使用主动FTP模式而不是被动模式的风险

在服务器上,我正在使用一个Perl脚本,它定期从另一台服务器使用FTP下载几个文件。 不幸的是,Perl FTP模块中存在一些问题,导致脚本不时地意外终止。 我发现这个问题很容易通过从被动模式切换到主动模式来解决。

如果我正确理解这两种FTP模式之间的区别,使用主动模式意味着我需要在防火墙内打开某个端口范围。 我认为这带有一些安全风险。 所以我的问题是是否有一些解决方法或一个很好的做法,所以我可以在我的服务器上使用主动模式,而不会导致任何额外的风险。

简而言之:

  • FTP连接由两个stream组成:命令(控制)和数据
  • 当打开套接字并且代码没有显式绑定到端口时,操作系统将在其临时端口范围内使用高编号的端口( sysctl -a | grep ip_local_port_range
  • 非根进程必须使用端口> 1024

活动模式FTP

客户端通过端口21连接到服务器,并build立命令stream:

client:32198 -> server:21

客户端必须发送或接收一些数据,所以它通知服务器在某个端口上连接它。 要做到这一点,它发送一个类似于这样的PORT命令:

PORT 1,2,3,4,5,6

这是客户端通知服务器,服务器可以连接回客户端(地址为1.2.3.4端口(5 * 256)+ 6 = 1286)。

server:20 -> client:1286

通常,这是您看到活动模式FTP会话死亡的地方; 就防火墙和负载平衡器而言,通常会从客户端 – >服务器stream量,但服务器向客户端发起的连接往往被拒绝(负载平衡器通常足够聪明,可以将该数据stream与现有的命令stream相关联)。

您了解需要在防火墙上打开端口范围以促进此行为是绝对正确的。

被动模式FTP

在这种情况下,客户端像以前一样build立一个命令会话:

client:56221 -> server:21

但是当数据通信时,客户端发送一个PASV命令原语。 服务器响应客户端应该连接的一个IP:Port组合(与之前的PORT请求类似的格式),然后客户端连接到服务器,如下所示:

client:12347 -> server:4566

这绕过了上面描述的活动模式的防火墙问题,因为连接是以传统和预期的方式build立的。

被动模式的缺点是它在服务器上消耗更多的套接字。 在负载较重的环境中发出频繁的PASV原语可能最终导致端口耗尽。 (套接字在TIME_WAIT状态下会持续一段OS定义的时间(我认为在Redhat系统上需要2分钟左右)。

关于你的问题

除非你真的苦于港口枯竭的问题,被动模式将失败并且主动模式更经常成功是非常罕见的。 通常情况是相反的。 如果您能够发布更多关于您偶尔收到的错误,我们可以进一步debugging。

我会build议尽可能使用被动模式,所以我会build议寻find被动模式具体失败find你的问题的根本原因之前,承认使用主动模式FTP。

在主动模式下,客户端连接到端口21上的服务器以获得控制通道,然后当下载开始时,客户端开始监听服务器连接的随机端口号超过1024的套接字。

为了允许主动模式FTP,客户端的防火墙需要允许所有高于端口1024的传入通信量,这违背了防火墙的目的

被动模式意味着服务器在端口20上侦听,客户端启动连接。

您应该始终使用FTP的被动模式。 或者更好的是,不要使用FTP。 如果您正在下载文件,最好使用HTTP。 如果您需要上传文件,仍然使用HTTP(或其他协议,如scp)。

这个问题与Perl本身无关。 更重要的是,设置主动FTP连接而不是被动连接的解决scheme就是certificate。

实际上,上面的问题在尝试列出FTP目录的内容时会发生,而不是在连接或上传/下载时发生。 因此,这个问题与防火墙有关。

你必须检查你的防火墙是否允许被动的FTP连接通过,阅读上面的loopforever的优秀描述。

如果使用基于Linux的防火墙,则可以卸载nf_conntrack_ftp内存。