摘要: 做为很是古老的协议(1971年首次提出,1980年首次应用),FTP在目前依然占有一席之地,可是因为目前IT业发展的很是迅猛,它和如今的基础架构产生了一些水土不服,本文旨在经过平常常见的案例,来介绍如何在阿里云上搭建FTP Server和FTP Client。安全
做为很是古老的协议(1971年首次提出,1980年首次应用),FTP在目前依然占有一席之地,可是因为目前IT业发展的很是迅猛,它和如今的基础架构产生了一些水土不服,本文旨在经过平常常见的案例,来介绍如何在阿里云上搭建FTP Server和FTP Client。服务器
本文先从FTP的协议分析,重点阐述了其中控制通道的两种链接模式,进而说明在阿里云上搭建FTP服务器可能遇到的问题,如被动模式下服务器公网IP没法获取、主动模式下没法链接等状况。网络
在FTP协议中,一般有两个通道:控制通道和数据通道,前者用来传输控制命令,如协议握手、得到当前目录等操做,而数据通道顾名思义,就是用来传输文件数据之用,另外ls命令的结果一般也会经过数据通道来传输。架构
而被动模式和主动模式是针对如何创建数据通道而言的,这里的主动、被动是站在服务器的角度上描述的,他们的差异简单来讲就是数据通道的TCP链接创建是由谁发起的,主动模式下服务器主动向客户端创建数据通道,而被动模式下,服务器是等待客户端来链接的。网站
这两个模式你们听到比较多的应该是被动模式,一般网上的文章都会建议客户端使用被动模式来链接,下面简单来讲明一下二者的差异。this
主动模式的详细操做能够参考我以前写的一篇文章,这里节选部分信息:阿里云
如下是一次完整的交互,客户端为47.x.x.224,服务端为112.x.x.7。spa
对他的分析能够参考以后的一张交互图,须要重点说明的是交互图中标红的一行,这一行能够理解为数据通道的实际体现(抓包中倒数第4个包,因为我只过滤了FTP协议的包,TCP的控制包没有显示出来,这个包其实是创建了一个新的TCP流来传输的),在这以前PORT命令是由客户端发出的,这一条报文为code
PORT 47,x.x,224,39,16
其中前四个数字为十进制的IP地址,在主动模式下为客户端的IP地址,最后两个数字为端口,因为端口须要两个字节表示,因此在这里的计算方式为39x256+16=10000,那么这一条报文的意思就是告诉服务器,“我计划使用10000端口做为监听的端口,个人IP地址是47.x.x.224,你能够来链接我了进行数据传输了”。orm
而被动模式最显著地差异就是在于如何创建数据通道,主动模式下是服务端去链接客户端传输数据,而被动模式下,是客户端去发起链接,向服务器创建链接。
如下是一次被动模式下的交互,客户端为30.x.x.85,服务端为47.x.x.255。
能够看出最大的区别在于红框中的命令,这一次从PORT改成PASV,以后服务器回复一条被动模式的信息,其中一样是6个数字:IP地址+端口号(端口号的计算方法和主动模式中同样),只是这一次换作服务器告诉客户端,“你如今能够链接个人47.x.x.255的47185端口了”。
这里特别提示一下,从下面的抓包截图中能够看出服务器回复的PASV响应中IP地址并非上面提到的47.x.x.255,而是一个私网地址172.x.x.241,缘由咱们会在# 专有网络ECS内部署FTP Server #这一节中提到。
为什么会同时存在被动模式和主动模式呢?在互联网的初期,因为各个终端使用的都是标准的公网IP地址,彼此时间能够互相通讯,互相可见,因此在发起TCP链接时,无所谓是哪一方先发起。但随着互联网的高速发展,人们发现IP地址已经不够用了,进而诞生了NAT技术,这就在通讯的双方之间插入了一个中间人,在NAT设备以后的终端对于对方是不可见的,因此只能由它来发起链接。
因此为了迎合NAT技术,FTP协议里就出现了被动模式,并且因为目前大部分FTP客户端都是在NAT设备以后,因此绝大多数状况下只能使用被动模式(固然在一些特殊的架构里主动模式仍是有必定的用武之处,本文最后一节将会说起)
目前阿里云ECS的网络类型有两种:经典网络与专有网络。对于经典网络的ECS来讲,系统内有两张网卡:eth0和eth1,eth0为内网网卡,eth1为外网网卡。在系统内内网和外网的IP地址是静态写在配置文件里的,系统内能够直接看到。而专有网络的ECS系统内只有一张网卡eth0,全部的流量都由这张网卡出入,系统内部没法看到ECS自身的公网IP/弹性公网IP。
这就直接致使了一个问题:因为目前的网络环境下大部分客户端都会使用被动模式来链接,可是被动模式下服务器须要告诉客户端链接的IP地址,而专有网络下的ECS没法直接看到外网IP,那么就致使FTP Server将本身的私网IP告诉了客户端,客户端收到了一个私网IP天然就没法进行链接。而list、文件传输都须要走FTP协议的数据通道,因此最终致使了专有网络下搭建的FTP Server没法让客户端正常的传输数据。
解决办法也很简单:主动告知FTP Server程序系统的外网地址,因为市面上FTP Server众多,各家的设置方式不尽相同,如下说明几个常见的FTP服务器的设置方法:
在vsftpd的配置文件中,加入如下两行,其中替换为ECS的弹性公网地址:
listen_ipv6=NO pasv_address=<EIP>
打开IIS,选择服务器(注意不要选择“网站”下的ftp站点),打开右侧的“防火墙支持”,在“防火墙的外部IP地址”其中填入ECS的弹性公网地址便可。
打开管理控制台,依次选择“域”-》[对应的域]-》“域详细信息”-》“监听器”-》21端口的监听器,点击“编辑”,将ECS的弹性公网地址填入弹出的对话框中
在撰写本文时,我发现一些客户端彷佛已经提供了智能化的规避方案,如lftp提供如下参数,当出现相似的问题时会尝试使用控制通道的服务器IP地址进行数据通道的链接。
ftp:fix-pasv-address (boolean) if true, lftp will try to correct address returned by server for PASV command in case when server address is in public network and PASV returns an address from a private network. In this case lftp would substitute server address instead of the one returned by PASV command, port number would not be changed. Default is true.
另外,FileZilla也默认开启了修正被动模式下数据通道IP地址的功能:
阿里云上的安全组至关于一个方向墙,相似iptables或Windows防火墙,能够根据协议、源/目的IP、源/目的端口来实现特定流量的放行、拦截。在# 被动模式和主动模式 #一节中咱们已经提到了FTP除了21端口之外,根据不一样的模式在数据通道下还会使用到特定的端口,因此须要在ECS的安全组中放行。
关于FTP两种模式下的报文交互,前文已经作了阐述,但还未说明程序是如何选择端口的,下面简单说明一下:
- | 控制通道 | 数据通道 |
---|---|---|
客户端 | 主动链接服务器,随机选择本地源端口 | 主动链接服务器,随机选择本地源端口 |
服务端 | 被动接受客户端链接,本地默认监听21端口 | 被动接受客户端链接,本地随机监听端口 |
注:被动模式下服务端数据通道监听的端口理论上能够经过FTP程序的配置文件修改
- | 控制通道 | 数据通道 |
---|---|---|
客户端 | 主动链接服务器,随机选择本地源端口 | 等待服务器的连接,本地监听一个随机的端口(注) |
服务端 | 被动接受客户端链接,本地默认监听21端口 | 主动连接客户端,随机选择本地源端口 |
注:主动模式下客户端数据通道监听的端口理论上能够经过FTP程序的配置文件修改
那么能够得出在ECS上部署FTP Server,若对于安全组有严格的进出限制,那么须要放行:
这里依然以常见的FTP程序为例:
pasv_enable=YES pasv_min_port=10000 pasv_max_port=10020
前文提到在一些特定的场景下,确实只能使用主动模式,好比说IDC和银行侧相连,银行出于安全考虑仅容许21端口入方向的流量,其他的端口都是封禁的,那么就没法使用被动模式,只能退而求其次使用主动模式。那么此时对于客户端的要求能够总结为下列几点:
关于第2、3、四点,其实和被动模式下PASV命令的响应相似,都须要在程序中做相应的配置才行,但因为这个场景下这个需求确实比较小众,我只收集了少许的客户端配置方法,其余的客户端配置方法请和程序的提供商寻求技术支持。
ftp:passive-mode (boolean) sets passive FTP mode. This can be useful if you are behind a firewall or a dumb masquerading router. In passive mode lftp uses PASV command, not the PORT command which is used in active mode. In passive mode lftp itself makes the data connection to the server; in active mode the server connects to lftp for data transfer. Passive mode is the default. ftp:port-ipv4 (ipv4 address) specifies an IPv4 address to send with PORT command. Default is empty which means to send the address of local end of control connection. ftp:port-range (from-to) allowed port range for active mode. Format is min-max, or `full' or `any' to indicate any port. Default is `full'.