提到多对多、多对一的NAT(多个私网地址转换为多个或一个公网地址),就不能回避公网地址利用率的问题。 “华为防火墙一个公网IP突破了65535端口限制,理论上能够无限制进行NAT转换”这个结论在江湖上已经广为流传,接触过华为防火墙的兄弟可能早有耳闻,几天前提起源NAT也有兄弟跳起来指出。这正是华为防火墙十年前申请的一项专利技术的应用。
至此处,原谅强叔回忆下此专利发明人的大牛风采。几前路遇隐居的大牛下山,强叔敬仰地双手抱拳:“哥你已不在江湖多年,江湖中仍然流传着哥的传说。”——强叔还被称为小强之时,大牛已经名满防火墙。此时大牛仍然腼腆一笑,道声旧日小事飘然去也,唯强叔口水流了一地。之后,强叔又马不停蹄至襄阳,请教如今的NAT传人后,才算对此专利解读稍有眉目。围观兄弟且看,强叔接下来揭密华为防火墙NAT地址复用技术。 

在《源NAT》一节,强叔提到:“防火墙在应用源NAT功能时就是从地址池中挑选出一个公网IP,然后对私网IP进行转换。挑选哪个公网IP是随机的,和配置时的顺序、IP大小等因素都没有关系。”这其实就是我们看到的外部招式,所谓内功心法不外露的。

那么在进行源NAT时,究竟是怎样从地址池中挑选出公网IP地址资源进行分配的呢?
请允许强叔引入Hash算法的概念,这应该是大家常听说的一种广泛应用于程序编写的方法。一句话解释,就是把一种任意长度的信息进行压缩映射,成为某一固定长度的信息。例如,把3000个私网IP映射成100个公网IP,也就是从地址池挑选出公网IP地址资源进行分配的过程,资料中也偶尔会提到的“基于源地址Hash”。

Hash的具体规则或者说算法是什么呢?很灵活,自行设定,但是根据要达成的目标和计算结果,可以优选。在这里,我们使用的算法也比较简单取模运算。
估计很多不写代码兄弟的数学都已经还给老师了,但是提起求余运算应该都知道,思路如下:

示例如下:
内网用户10.1.1.1-10.10.10.1,NAT地址池202.169.1.1-202.169.1.5
X=5
Y=10.1.1.1
10.1.1.1----->00001010 00000001 00000001 00000001----->167837953
不用计算可目测余数为3,选择地址池的第四个资源即202.169.1.4。

至此,内网用户的源IP地址已经可以全部被分配了对应的地址池中的公网IP地址资源,并且保证了每个内网的IP地址每次访问外部网络时始终转换为同一个公网IP地址。
按照上述运算后,一部分内网用户就会被分配相同的公网IP地址资源。

 

下一步,我们来研究下如何分配端口资源。
其实强叔对于将复杂一点的数学运算表达清楚没有太多信心,决定到最后不得已的时候再引出来,下面端口分配先从防火墙的实现原理讲起,定性区分出端口分配带来的影响。
在《源NAT》一节中,我们已介绍了NAPT情况建立的会话表。
例如,内网10.1.1.1和10.1.1.2用户分别ping 220.180.20.50服务器,在USG上通过公网地址202.169.1.1进行NAT转换,查询会话表显示如下:
<USG9000> display firewall session table 
 Current total sessions: 2                                                                                 
 Slot: 5 CPU: 1                                                                                            
 icmp ×××: public --> public 10.1.1.1:1280[202.169.1.1:10298] --> 220.180.20.50:2048                          
 icmp ×××: public --> public 10.1.1.2:1280[202.169.1.1:6103] --> 220.180.20.50:2048   
由于内网不同用户的IP地址和端口必不相同,仅使用“源地址+源端口”二元组信息在USG上即可标识一条数据流,来建立正向NAT地址转换。而进行反向地址还原时,使用“源地址+源端口+目的地址+目的端口+协议”五元组信息唯一标识一条数据流。
那么,根据会话表实现机制,只要内网不同用户访问“目的地址+目的端口+协议”三元组中的任一参数不同时,即使将地址池中同一公网地址的同一端口同时分配给内网多个用户时,也不会产生冲突。
示例如下:

编号

内网源地址

内网源端口

NAT地址

NAT端口

目的地址

目地端口

协议

1

10.1.1.1

80

202.169.1.1

8080

www.baidu.com

80

http

2

10.1.1.2

80

202.169.1.1

8080

www.sohu.com

80

http

 

因此,只要内网不同用户访问“目的地址+目的端口+协议”三元组中的任一参数不同时,唯一的NAT地址和端口可以反复利用,不受65535端口的限制。此时无论端口如何分配,都不会产生问题。

围观兄弟接下来肯定就有问题等着强叔了:在地址池只有一个公网IP情况下,如果访问相同的“目的地址+目的端口+协议”三元组时怎么办?现实可能就是这么残酷……
在内网不同用户访问相同的“目的地址+目的端口+协议”三元组时,不能被分配给相同的NAT地址和端口资源,这是因为一旦完全相同,访问的目的主机会发现出现同样的“源地址+源端口”访问本主机的同一“目的地址+端口+协议”,目的主机无法正确回应甚至可能会判定为受到***。

关键点来了!因此,保证内网不同用户、访问相同的“目的地址+目的端口+协议”三元组时,不能被分配到相同地址的相同端口资源是关键。这就要引入冲突检测机制。
其实在分配端口的法则上,我们仍然使用Hash算法,使得在内存占用合理情况下、尽可能保证被分配到相同公网地址的用户、其被分配的端口尽量不一致,简化的基本思路如下:

这就保证了,不同内网户访问相同的 “目的地址+目的端口+协议”三元组,不会被分配到相同的NAT地址的端口资源。而且会话表是会实时老化的,被分配过的端口在会话表老化后会重新被利用,因此,概率上端口也不会受到限制。
除非最极端的情况发生:超过64k的内网用户,同一时刻、向外网同一目的主机的同一端口、采用同样协议发起链接。不过兄弟们觉不觉得很面熟,这看起来就是发起了传统而典型的DDoS***了吧-_-

好了,揭密到此,强叔已经全盘兜出了,大家是否已经了然于胸了?
其实原专利本身是晦涩难懂的,华为防火墙也在这么多年的发展中进行着不断演进,强叔只是对其基本实现原理进行了简单大意解读。若有对原专利感兴趣的小伙伴可自行谷歌:CN1567907A 一种网络地址资源的利用方法。