点赞
评论
收藏
分享
举报
Nginx FTP 协议支持
发表于2020-06-17 08:56

浏览 3.8k

文章标签

授权协议:
Apache License 2.0
原作者联系方式:
jkpei@hotmail.com
功能说明:
nginx stream ftp alg 支持

概述 

Nginx  1.9.0 开始加入了 stream 模块支持四层的代理,转发和负载均衡。但是,stream 模块的功能相对简单。对需要 ALG 处理的协议比如 FTP 的支持也远远不够。

我试着去修改了 Nginx 的源代码,添加了alg模块。使之支持了 FTP 主动模式和被动模式下的 ALG 功能。 Github 的源码地址为 https://github.com/pei-jikui/nginx-alg代码本身不困难,困难的是如何把代码模块化,有机地融入nginx原有的框架结构中,尽量少地修改已有的框架代码。而后者,需要对stream模块乃至nginx本身的框架和代码有一定的熟悉程度。

pic1.png

 1: FTP被动模式 数据连接 

pic2.png

图2 : FTP主动模式 数据连接

可能大家会说,Passive 模式不需要ALG 。准确的说,Passive 模式下,如果ftp client server 路由可达,可以不需要ALG 。但是在client server 路由不可达的情况下,Passive 模式也必须有ALG 的支持。


FTP ALG


FTP 协议

FTP File Transfer Protocol ,文件传输协议) 是TCP/IP 协议组中的协议之一,也属于典型的客户端服务器结构。

FTP 客户端和服务器之间需要建立两条TCP 连接,一条是控制连接,用来发送控制指令,另外一条是数据连接,真正的文件传输是通过数据连接来完成的。 比如在 ftp 客户端输入ls 命令,ls 命令本身是通过控制连接发送的,而ls 得到的内容是通过数据连接发送的。

pic3.png

图3 : FTP 主动连接

pic4.png

图4 FTP 被动连接  

如上图对于两种传输模式来说,控制连接的建立过程都是一样,均为服务器监听 21 号端口,客户端向服务器的该端口发起TCP 连接。

对于数据连接, FTP 有两种工作方式,一种是主动方式(Port 方式)另外一种是被动方式(Passive 方式。 这两种工作方式的命名是以服务器的视角来区分的。主动方式就是数据连接是服务器主动来连接客户端。被动方式是服务器被动地等待客户端来连接。 主动模式服务器通过控制连接知道客户端监听的端口后,使用自己的 20 号端口作为源端口,“ 主动” 发起TCP 数据连接。

而被动模式服务器监听 1024-65535 的一个随机端口,并通过控制连接将该端口告诉客户端,客户端向服务器的该端口发起TCP 数据连接,这种情况下数据连接的建立相当于服务器是“ 被动” 的。


FTP NAT

FTP 协议 出现时, Internet 规模还没有如此庞大。IPV4 的地址足够每一个客户端使用。所以,FTP 在那时工作的很好。

随着 Internet 的飞速发展,IPV4 的地址已经远远不够。为了解决这一问题,NAT 技术就出现了。NAT 技术使得多个client 可以使用同一个IP 进行Internet 访问。但是NAT 技术只会改变报文头部的IP 地址,并不会改变数据报文里面的内容。这使得FTP 协议在NAT 环境下,数据连接会出现问题。

pic5.png


图5 FTP 主动模式经过NAT

pic6.png


图6 :FTP 被动模式经过NAT

如上图, 常见的 FTP 使用场景,客户端在内网,服务器在外网。客户端访问服务需要经过NAT 

客户端的报文经过了路由器 NAT 之后,服务器端看到的报文的客户端的报文的IP 源地址和端口都已经被改变了,当然对于控制连 接来说这没有影响,因为有网关或者路由器的NAT 模块在中间做管理。

对于正要通过控制连接建立的数据连接就有问题了,因为 NAT 改变的仅仅是IP 报文 头,而对于因为报文中PORT PASV 命令中包含的地址和端口信息没有做任何改动,这样对与PORT 模式服务器是无法和一个内部地址建立连接的。对于PASV 模式,而且客户端和服务路由不可达的情况下,客户端无法直接和Server 建立连接。所以这个时候就出现了ALG 这个功 能。


ALG

ALG Application Layer Gateway 的简称。它的功能就是在发现如果报文头做了NAT ,在这个时候如果发现这个是一个FTP 的连接的时候,就需要同时改变PORT PASV 命令中的地址和端口。从而让client server 之间可以正确连接。在这个过程中,ALG 不仅需要监听,修改控制连接的报文,还需要代理转发数据连接的报文。  


代码改动的原理

原始的Nginx Stream 模块对于协议只是进行了简单的两端数据交换。本身不会对协议包内容进行任何的监听和修改。

  

pic7.png

图7 ALG ftp 的支持

PASV模式代码的修改原理是,

1)         监听 ftp 控制连接上的数据,如果发现server client 方法PASV 命令。修改报文中的IP地址和端口。把IP 改写成自己的IP 地址,同时用一个新port N 代替原来报文里面的PORT 

2)          port N 上启一个监听socket. 同时把修改后的报文传给client.

3)         Client 收到新的报文以后就会往Nginx port N 上进行连接。

4)         建立连接以后, Nginx 再向server 原来的地址和port 发起连接。

等两端连接建立起来以后, client server 的数据通道就可以打通了。  


ACTIVE模式的修改原理和上述PASV修改的原理差不多。

整个过程中,需要解决的问题是:

1) 如何建立起控制层面和数据层面的联系。在多个 upstream服务器的场景下,数据连接和控制连接需要连接到同一个upstream server中。

2) 动态按需创建socket用来处理数据连接。


结语

通过修改 Nginx 代码支持FTP 的port模式和passive 模式的ALG ,可以进一步学习和理解Nginx 的原理和代码,从而进一步掌握Nginx 的内部运行机理。

 


已修改于2023-03-08 02:03
创作不易,留下一份鼓励
皮皮鲁

暂无个人介绍

关注



写下您的评论
发表评论
全部评论(0)

按点赞数排序

按时间排序

关于作者
皮皮鲁
这家伙很懒还未留下介绍~
85
文章
2
问答
42
粉丝
相关文章
使用配置方式:install./configure--add-module={module_dir}&&make&&makeinstallconfserver{ listen80; client_max_body_size100m; location/{ roothtml/upload; } #Uploadformshouldbesubmittedtothislocation location/upload{ #Passalteredrequestbodytothislocation upload_pass/example.php; #Storefilestothisdirectory #Thedirectoryishashed,subdirectories0123456789shouldexist
点赞 3
浏览 2.8k
使用方法:1.创建tableCREATETABLE oauth_access_token (id int(10)NOTNULLAUTO_INCREMENT,access_token varchar(255)DEFAULTNULL,expires_in int(10)NOTNULL,last_used_time int(10)NOTNULL,PRIMARYKEY(id),KEY ACCESS_TOKEN (access_token))ENGINE=InnoDBDEFAULTCHARSET=utf8;2.安装Oauth模块cd/work/nginx-1.8.0&&./configure--add-module=/work/nginx-http-oauth-module&&make3.添加配置请参照源码连接中的nginx.conf 4.使用Oauth模块a)创建访问tokenhttp://192.168.1.104/token?appid=
点赞 3
浏览 2.1k
模块配置使用:=================example================== >curlhttp://yourip/metric_status {"1xx":0,"2xx":21715,"3xx":48,"4xx":94,"5xx":2,"total":21859,"avg_time":0.036,"min_time":0.001,"max_time":10.484} =================nginx.conf=============== metric_zonesize=10Mmin_time=10msmax_time=10s; metricon; server{ listen80; location/{ roothtml; } location/metric_status{ metric_statuson; metricoff; } location/me
点赞 3
浏览 1.9k