NAT后面的FTP SERVER终极篇
如果对于被动模式还有不同的意见,我们可以再看下这篇文章:
如果Ftp服务器和Ftp客户端都有公网ip,中间没有防火墙,没有Nat,或者两边都仅仅是1:1的NAT,则基本上没有什么问题。
Ftp服务比其他internet服务www,pop3,smtp,telnet复杂的地方在于它需要至少两个连接,一个控制命令连接,一个数据传输连接。控制命令连接一定是客户端发起的,目的指向服务器的21端口,这个没有什么问题。复杂在于数据传输连接,端口号事先不确定,是通过客户发起的21端口连接临时协商的,Tcp连接的发起者不确定,同样是临时协商的。麻烦在于正常情况下,虽然这个“协商”内容全部是通过两边路由器的,但是路由器不懂他们在说什么,当然也不会主动给与配合。
依据数据传输连接的发起方,Ftp传输模式分为两种,主动和被动模式,模式的划分是以服务器的角度来看的。如果是客户端发起的,称为被动模式,反之,服务器端发起的,称为主动模式。
只要路由器做了Nat,实际上就部分充当了防火墙的角色。如果使用主动模式,而客户机位于Nat后面,服务器发起数据连接,则客户端路由器会丢掉此连接请求。鉴于国内客户机在Nat后面的普遍性,研究被动模式更具有实际价值。如果使用被动模式,则客户端路由器一般不用设什么,因为内部网向外的连接请求通常默认是允许的(当然你也可以不允许某某上网,内容不在本文之列)
现在进入本文核心部分,如何设置路由器和客户端软件,以便位于Nat后面的Ftp Server能够接受被动模式的数据传输。重复一下,Ftp的被动模式连接过程,首先客户端发起一个指向服务器的端口为21的连接,然后客户机和Ftp服务器协商,大家一致同意接下来的数据传输由仍然由客户端发起,服务器的ip为111.111.111.111端口号为9999(111和999只是个例子,不是真实的),到这个时候双方都还没有问题,或者有问题还没有发现
我们来分析一下,如果服务器的网卡用的ip为172.18.1.1,假如服务器很笨,它不知道自己的公网ip,也不去查一下,直接告诉客户机自己的ip为172.18.1.1.碰巧这个客户端同样笨,并不认为172.18.1.1的地址有什么不妥,于是很高兴地发起另外一个端口为9999的连接,指向了172.18.1.1,客户端忘了自己先前发起21连接时根本就不是用的这个172.18.1.1.这个客户端怎么这么笨啊,告诉你吧,像这样笨的客户端多着呢.filezilla,leaftp,internet explorer莫不是这样笨。Ftp服务器软件怎么这么笨啊?同样笨的服务器端软件多着呢。
好了,先不管笨到什么程度,继续往下看。当客户机发起数据连接后,目标地址为172.18.1.1的TCP包进入到ISP的路由器,假如叫Router1,Router1一看目的地址是172.18.1.1,马上骂了,混账,172.18开头的地址我这里没有记录,对不起,扔掉。于是服务器最终得不到客户端发起的数据连接,苦苦守望了N久,终于放弃了此次连接,传输失败。
假如,假如服务器端ftp软件足够聪明,向客户报告自己的真实的公网ip 123.123.123.123,而不是私有ip 172.18.1.1,又或者,虽然服务器端软件很笨,但是客户端软件聪明,它发现了172.18.1.1,认识到服务器工作有疏忽,想起了自己先前的初始连接对方ip是123.123.123,于是主动用发起的对123.123.123.123而不是172.18.1.1的数据连接。现在假如新的目标端口为9999的连接已经到了服务器端的路由器Router2外网接口。
如果Router2里存在一个端口映射,将9999的端口映射到Ftp服务器,则连接最后成功。如果数据连接的请求到了Router2,Router2认为是个非法的连接请求,客户端的连接仍到不了则Ftp服务器。有一种方案是在Ftp服务器端设置限定一端连续的端口供被动模式时客户来连接,IIS,Serv-U等软件好像都可以设,然后在路由器上把这一段端口都映射到Ftp服务器。另一种思路是路由器使用支持动态端口打开的技术,使它能读懂21端口的客户端和服务器端的谈话内容,得知他们的行动后,主动打开他们要的数据连接端口并做好映射,数据传输完毕后再关掉。某些linux路由器支持这个功能,不过好像要重新编译内核。
附录
1 不那么"笨"的Ftp客户端
flashfxp,firefox ftp等能智能使用改用21端口的ip地址连接数据通道软件
flashfxp要在 快速连接-常规-对于被动模式使用连接站点ip
2 不那么“笨”的Ftp 服务器软件
用serv-U,filezilla server等支持内网发布的服务器端软件(能给客户回应外部ip而不是本机私有ip)
Serv-U好像可以设置查询自身的动态域名,filezilla server可以设一个固定外网ip.
3 "真理"
双方都在防火墙或者NAT后面,都不想开了端口等着对方来连接,都想主动连出去,这样防火墙才不会拦截.但是只要是TCP连接,就必须至少有一方是主动连接的,主动被动是看相对哪一方而言.