1. vsftp的安装
    分为本地用户、虚拟用户两种模式,今天就不在此过多介绍怎么分别启用不同的模式,以后再单独一篇安装的文章。
    yum install -y vsftpd
    配置文件:/etc/vsftpd/vsftpd.conf
    启动:systemctl start vsftpd

  2. vsftp客户端
    服务启动后,使用客户端连接,常用的方式有windows地址栏中输入ftp://x.x.x.x 或者下载安装FileZilla输入服务端IP,端口默认21测试连接。

  3. 主动模式、被动模式介绍
    从FileZilla中我们可以发现,ftp连接有3种模式:默认、主动、被动。在服务端其实只有两种主动和被动,经过实测,客户端(含windows地址栏连接)默认连接方式是被动模式。下面来说说主动模式跟被动模式的区别吧。
    我们重温一下FTP的工作过程。客户端连接服务端TCP 21端口建立命令通道后,输入用户名密码完成登录;随后的每一次数据传输都需要另外建立数据通道进行; 如果数据通道由客户端发起,服务端接受,我们称之为被动模式;反之,如果数据通道由服务端发起,客户端接受,则称之为主动模式。
    主动模式:
    aws上的vsftp服务的坎坷经历_第1张图片
    被动模式:
    aws上的vsftp服务的坎坷经历_第2张图片

  4. AWS遇到的问题,其实是NAT的问题。
    铺垫了这么久,以下进入正题。除了ftp有NAT的问题,还有其他一些服务也存在,如VOIP服务。
    我们在共有云购买的机器现在网卡上都是只有一块内网网卡,然后通过NAT绑定公网IP对外提供公网服务。(PS:老早前公网地址是可以启动在云主机的网卡上的,这样就没有NAT问题),这时主动模式的连接不会受影响,原因请自行领悟。这里只介绍会出现问题的被动模式。
    以被动模式内网访问时,完美!顺利!
    aws上的vsftp服务的坎坷经历_第3张图片
    以被动模式公网访问时,糟糕!
    aws上的vsftp服务的坎坷经历_第4张图片
    这里连接超时,显而易见,FTP服务端发送给客户端的IP地址是服务端的私有地址。位于Internet上的客户端无法建立与位于VPC内部的私有地址10.0.0.10直接通讯。

  5. 解决这个问题有多种方法,我们由简单到复杂分别叙述
    ①增强协议适配NAT
    FTP协议针对NAT和其他因素,对协议进行了增强,提供了增强版的被动模式EPSV命令。服务端不再显式指定IP地址,只提供数据通道的端口号。客户端默认与控制通道相同的IP地址建立数据通道。
    aws上的vsftp服务的坎坷经历_第5张图片
    可以看到,解决方案很优雅。当然这需要客户端和服务端都支持增强的协议才能达成;如果我们不修改协议,能否解决这个问题呢。

②服务端适配
有些时候,修改协议和实现需要多方协调和很长的时间才能完成。在RFC2428标准化之前,一些FTP实现就已经通过修改实现来适配基本NAT,而非修改协议。
以vsftpd为例,它允许通过配置文件vsftpd.conf中的配置项 pasv_address=x.x.x.x 告知服务端,在PASV被动模式下,应当指示客户端连接到配置项指定的IP(而不是服务端的私有IP)来适配基本NAT。
题外话:其他的一些常见应用例如VoIP类应用,也有类似的机制去适配基本NAT;例如引入STUN/TURN/ICE等方式适配各种更加复杂的NAT穿越场景(多年前搞过VOIP)

③啥都不改(此法慎用)适用于精通网络的高手
#从EC2 实例元数据服务获取本实例的公网IP(如有)、私网IP

      public_ipv4=`curl -s http://169.254.169.254/latest/meta-data/public-ipv4`

      local_ipv4=`curl -s http://169.254.169.254/latest/meta-data/local-ipv4`

#配置私网地址段,这里应为EC2实例所在VPC的地址范围

      local_net=10.0.0.0/16

      if [ “x${public_ipv4}” == “x” ]

      then

      echo “No public IPv4 address available for this instance, abort.”

      exit 1

      else

#如果EC2实例的公网IP不为空,则将该公网地址添加到eth0上

      ip address add ${public_ipv4}/32 dev eth0

#本地接受的连接,如果来源不是本VPC,那么将IP包的目的地址改写为公网IP

      iptables -t nat -A PREROUTING ! -s ${local_net} -d ${local_ipv4} -i eth0 -j DNAT --to ${public_ipv4}

#本地发起的连接,如果出方向流量的源IP地址是公网地址,那么需要改写为私网IP

      iptables -t nat -A POSTROUTING -s ${public_ipv4} -o eth0 -j SNAT --to ${local_ipv4}

      fi

验证脚本执行结果:
首先检查本实例的公网IP是否已经正确配置到eth0上。

~ # ip addr show dev eth0

然后检查iptables的NAT规则是否正确配置

~ # iptables -t nat -nvL
最后分别从VPC内部和Internet连接到服务,验证结果

~ $ ss -nt

此法不建议生产使用,维护门槛比较高。

最后:附上清测可以使用的vsftpd.conf,注意需要把20、21、pasv_min~pasv_max这些端口在安全组中配置开放访问策略
anonymous_enable=NO
local_enable=YES
write_enable=YES
local_umask=022
dirmessage_enable=YES
xferlog_enable=YES
connect_from_port_20=YES
xferlog_std_format=YES
idle_session_timeout=300
pam_service_name=vsftpd
userlist_enable=YES
tcp_wrappers=YES
max_clients=65530
max_per_ip=65530
reverse_lookup_enable=NO
pasv_address=x.x.x.x
pasv_enable=YES
pasv_max_port=65535
pasv_min_port=64000