NAT面对FTP该如何下手

Sina WeiboBaiduLinkedInQQGoogle+RedditEvernote分享




最简单的NAT只需要修改IP头里面的IP地址,不过大多数的NAT还需要传输层里面的端口。而这里我们仅仅考虑后者。在这个时候,存在着一个问题,那就是如果应用层需要使用IP地址或者端口,该怎么办?

当然,这仅仅是一个假设,许多应用不会用到网络层以及传输层里面的信息;还有一些应用会在应用层携带者IP或者端口信息,比如迅雷,但是没有它,天也不会塌下来;不过还有一些应用,非常需要它,如果没有它的话,当然天倒不会塌下来,但是一碰到NAT它却有可能没法活了,这些应用比如有FTP,PPTP,VoIP等。。。。。。此时就需要NAT从中忽悠了,这个被称为ALG(Application Layer Gateway)。

有人会有疑问,那既然这样,别在应用层数据里面使用IP或者端口信息,世界不就安宁了吗?当然,这是一个很好的建议,不过这在FTP是不可行的,因为FTP是在1985年的时候就诞生了(RFC 959),可是NAT是在1994年成为标准(RFC 1631)。但是还有很多应用比如PPTP是在1994年之后成为标准的,但是为何却不肯向NAT妥协呢?请读者讨论(当然,最好能够先问问PPTP等其他协议的作者,当时具体是如何思考这件事情的)。

FTP为何需要做ALG

FTP在进行NAT穿透的时候,根据不同的场合而有不同的结果(甚至有时候NAT不需要做任何事情):

  • 客户端是在NAT内网,还是在外网(俗称NAT静态映射);
  • 是PORT模式还是PASV模式。

根据FTP协议,FTP会使用一条数据连接来传输数据,并且这条连接的IP和端口是在控制连接里面协商的结果。而决定是否需要做ALG的,就是要看在协商的时候是携带了内网IP和内网端口信息,如果是的话,就需要做ALG。以下分四种情况讨论。

客户端在内网,使用PASV模式

比如我现在以IP为192.168.16.5,源端口为1315,然后通过firefox直接FTP到www.kernel.org。首先会建立一条控制连接:

image

那么在这条连接里面,双方会协商数据传输的端口,在这里采用的是PASV模式:

image

注意后面的(149,20,20,133,127,85),这个就是本文的灵魂所在(NAT就是需要对这一串数字知根知底,顺便提一下《LOST》里面的4, 8, 15, 16, 23, 42)。在PASV模式下其实就是服务端告诉客户端其IP地址以及其开放的端口,通过以下方式运算得到:

  • 前面4个字节代表的是IP,逗号是分隔符,这里是:

image

转换成IP其实就是149.20.20.133,就是服务器的IP

  • 后面两个代表的是端口,这里是:

image

即为32597

PASV模式意味着,服务端打开了数据端口,这里是开启了32597端口,所以接下来了客户端会向服务端的32597端口发起连接:

image

在这种情况下,由于IP和端口是公网的,所以不需要做ALG了。一般的FTP客户端都是使用了这样PASV的方式,所以应用上一般都没有异常。

客户端在内网,使用PORT模式

我使用Firefox的一个插件FireFTP作为FTP客户端,并且设置为PORT模式,仍然FTP到149.20.20.133,并且传输了一个文件:

image
这个时候,我们可以看到,情况有点不一样了,此时是客户端直接把自己的IP和开放的端口告诉给了服务端了,在这里IP是192.168.16.5,端口是2230。服务端能够向192.168.16.5的2230端口发起数据请求吗?答案是否定的。这个时候NAT需要勇敢的站出来了!

  • 首先不管怎么说,NAT得把192.168.16.5这个内网的IP修改成公网的IP,这里是116.238.184.142,以便149.20.20.133能够访问得到;
  • 端口呢?端口是否需要修改?这得分情况,如果说NAT出去的端口中没有2230这个端口,那么可以不修改;但是如果这个端口已经被占用了,那么就必须得修改,否则就会出现一台主机(NAT设备)出现两个相同的端口,比如现在我们将其修改成12345,修改之后还必须要添加一条NAT会话(相当于作了一条静态映射),以便服务端发起数据连接的时候能够匹配到;
  • 还有一个事情必须得记住,那就是这些IP信息和端口信息是以ASCII码传输的,所以可能会造成数据包修改前后,长度发生了变化!比如从192,168,16,5,8,182修改成116,238,184,142,48,57就是从18个字节增加到了21个字节了。所以这个数据包的修改需要同时更新IPLEN字段,并且你得记住你的长度变化(这里是3个字节),因为服务端响应的是后面修改的数据,所以ACK会比客户端预期的多3,当ACK从服务端过来的时候,NAT要把ACK减掉3,以便让192.168.16.5认识。事情还没有完,由于ACK减少了,这样客户端发送出来的SEQ就是这个被减少了的ACK,这样服务端也不干啊,所以针对客户端发送出去的SEQ,NAT需要加上3。以后在这条连接上面,NAT需要做这样的事情over and over again去忽悠客户端和服务端;
  • 最后别忘了更新IP校验和,以及TCP校验和。

客户端在外网,使用PASV模式

如果在NAT设备内网搭建了一台FTP服务器,客户端在外网来对其进行访问,结果将和前面的不一样。首先需要映射FTP服务器的端口,标准是FTP/21。而此时由于是服务端报告自己的IP和端口信息,并且传输给客户端,由于服务端的IP信息是内网的,所以NAT需要对其进行修改,如何修改呢?留给读者去分析。

客户端在外网,使用PORT模式

呵呵,想想看看,这个是客户端(外网)报告自己的IP和端口信息,哦,不用动。。。。。。

后记

在使用FTP的时候,并且处于NAT的环境之下,如果出现异常的话,就可以怀疑怀疑是否是ALG功能失效导致。

(4个打分, 平均:4.75 / 5)

雁过留声

“NAT面对FTP该如何下手”有23个回复

  1. Stone 于 2010-03-07 7:06 下午

    弱弱的说一句:发表这种文章,大大降低了弯曲评论的档次。

  2. wenlujon 于 2010-03-07 7:23 下午

    我相信这样的文章会有人需要。也正体现了首席所讲的“草根精神”(NAT,FTP应用的广泛性楼上不可不知)。

  3. 六楼的 于 2010-03-07 7:37 下午

    又来科普文章啦

  4. 1help1 于 2010-03-07 8:45 下午

    喜欢这样的文章.说实话,一个人不可能cover所有的领域. 有些文章在某些人看来是科普文章,可是对于另外一个领域的人来说就正对胃口.

  5. wenlujon 于 2010-03-07 8:50 下午

    赞同三楼的,但和一般的科普不同的是,此本讲述的是why, how而不是what.

  6. appleleaf 于 2010-03-07 9:04 下午

    FTP ALG并非仅此而已,楼主可以扩展一下。
    例如IPv6对于FTP的扩展。
    例如如何handle RFC 2228,FTP安全扩展等等。

    本文科普,但是对于不了解FW的观众我觉得还是挺好的。

    另外,作者是原创,且描述问题的规模值得写一篇文章,因此表示鼓励。如果作者对于所有ALG都能分类描述一下,笔者还是很期待的。

  7. appleleaf 于 2010-03-07 9:05 下午

    “笔者”用惯了,应该是“本观众还是很期待的”。

  8. wenlujon 于 2010-03-07 9:19 下午

    非常感激1help1兄的支持。本来花了一天的时间整这篇文章(装fireFTP,抓包,还有整图片,发现两个问题,如果图片大于600px就会导致文字都超出后边的限制,还有一个是使用左移8位会出现一个笑脸,后来就搞成截图),结果被批,都有一丝丝的伤心了。有1help1兄的支持,豁然开朗<<8

  9. wenlujon 于 2010-03-07 9:29 下午

    to appleleaf兄:说实话,ftp的扩展,以及ipv6小弟也没有接触,目前我所写的是我非常有把握的,以后如果接触的话,一定找机会实践一把,并且奉上文章。
    呵呵,所有的ALG中实践过有PPTP,H.323,TFTP,ESP。
    这些后续如果有需要的话,我会花时间慢慢补充。

  10. 陈怀临 于 2010-03-08 7:23 上午

    图的width好像lmit是580.我今天与高主编商量一哈。吧这些限制写在“投稿与建议”中。

    wenlujon,ALG是网络安全里非常重要的一块。你的文章很好。继续努力。某公司的许多人都在读你的这篇文章并开展热烈讨论呢。。。

  11. 帅云霓 于 2010-03-08 7:28 上午

    首席是在说坐我附近的一票人么…

  12. 陈怀临 于 2010-03-08 9:16 上午

    咔咔,感情是两个公司的人都在学习弯曲评论:-)

  13. ASR1k 于 2010-03-08 10:53 上午

    ALG倒是一个不错的东西, 特别是语音协议, 例如323 和 sip一类的…不过很多公司都做的不好. 语音一类协议消息太多, ALG并不光是改地址那么简单的.

  14. wenlujon 于 2010-03-08 4:44 下午

    多谢首席夸奖。我会继续努力的,下次打算奉上PPTP的ALG。

  15. xtang 于 2010-03-08 11:03 下午

    H323的ALG确实不好弄。关键是其伞下协议太多,而且有不少文档还不完全公开。要想在控制通道上分析找到内网IP,恐怕几百行程序都打不住。

    当年玩IPFilter的时候只好搞了个笨算法,强行扫描整个数据包,搜索并替换内网IP。:) 理论上这个东西漏洞太多,实践上在自己家里的网关上用用还是很有成效的。而且这个简单算法对323伞下的协议全有效。一石n鸟,哈哈。

  16. appleleaf 于 2010-03-09 3:20 上午

    “恐怕几百行程序都打不住”,几百行就写一下吗。

  17. xtang 于 2010-03-09 7:44 上午

    “偷懒才能进步”,呵呵。主要传统协议栈上的ALG,还是运行在协议栈的context里的,时间花太久对协议栈性能影响还是挺大的。

  18. wenlujon 于 2012-06-20 3:46 上午

    呵呵,好久没来,发现上弯曲推荐了,窃喜一把,以后有时间要多写写啊。弯曲推荐这一栏啥时候出来的东东?

  19. 狐说 于 2012-07-03 11:23 下午

    没有ALG怎么办?

  20. nsgreen 于 2012-07-08 4:15 上午

    什么时候可以看到“NAT面对SIP该如何下手”?

  21. multiCore 于 2012-07-09 1:33 上午

    花了一个月时间,在Octeon上实现了一个NAT/NAPT的人飘过,不包括ALG,不过我我已经定义了相关的接口函数,做ALG的时候直接调用就行了;NAT这个东西看着简单,做起来还是蛮复杂的,我当时参考的是一个思科的手册上的参数。想想当时随便就答应了,真是划不来,唉。。。。。。

  22. netqvq 于 2012-07-13 2:00 上午

    做网络的有责任加快IPv6的普及。我更希望看些v6相关的技术

  23. 瀚云 于 2012-07-15 11:31 下午

    V6的协议匹配确实是个难点,尤其设计到ASIC中,关键是IPv6协议设计的时候,报文头里面多个option的长度不固定,并且N个报文头可以有也可以没有,还可以嵌套~~~当然四层以上变化可以忽略不计。

发表评论