谢喜仁的《计算机网络》只要求掌握NAT的概念(内外部IP地址和端口的映射),其他详细的工作原理和种类都不作要求。
概念
——NAT的工作就是:在你的主机A到另一台主机N的传输路径上,有一台NAT box,它的IP地址是X。当你向B发送数据报时,数据包通过内部接口经过NAT box时,NAT box将会把数据包中的【主机A的IP地址】替换为【NAT box的IP地址X】,再通过外部接口转发出去。这样,看起来就像是NAT box发出的数据报,而不是主机A发出的。B给A回复数据报时,也要先通过外部接口经过NAT box,将【目的IP地址X】修改为【主机A的IP地址】,然后通过内部接口转发给主机A。
——典型的NAT box是家庭用的无线路由器。可以有很多台设备连接到无线路由中。当这些设备往外传输数据时,都得经过NAT box,将它们各自的IP地址统一转换为NAT box的IP地址,然后再转发出去。
优点:它对外隐藏了内部网络的IP地址,在一定程度上起到了防火墙的作用
——NAT给它内部接口连接的内部网络里面的主机各自分配一个私有IP地址,而私有IP地址都是10.x.x.x的格式。不同NAT旗下可能有相同的私有IP地址值,但对应的肯定不是同一台主机。
数据报经过NAT box发出去时,除了要修改【源IP地址】,还要修改【源端口】,因为发送端和接收端不能使用相同的端口(为什么?)。
——NAT如何实现这种IP地址和端口修改,如何实现这种映射关系?
——当NAT得到来自内部网络的某台主机的【发往外部网络的】数据报时,才产生这种映射关系。收到该数据报后,NAT根据这个创建的映射关系进行修改,然后才发出去。当接收方返回数据报时,NAT也会查找这个映射关系,又进行修改,发给内部网络对应的那台主机。
分类
——NAT有很多种实现方式,但它也是在构建应用程序时的一个复杂因素。
——实现NAT时,要考虑两个基本问题:
1.NAT怎样、什么时候创建和分配这种映射关系?
2.NAT应该允许什么样的分组进行这种映射关系?
RFC 3489中有NAT的一些分类和术语
1.full cone NAT
——它是表现最好的一种。只要【外部端口收到的】数据报的【目的IP地址、目的端口】同时满足,就对该数据报进行映射修改。
2.restricted cone NAT
——它基于IP地址,对数据报进行过滤。只有【外部端口收到的】数据报的【目的IP地址、目的端口、源IP地址】同时满足,才对该数据报进行映射修改。
3.port restricted NAT
——只有【外部端口收到的】数据报的【目的IP地址、目的端口、源IP地址、源端口】同时满足,才对该数据报进行映射修改。
4.对称NAT
——简单来说就是:内部与外部的映射关系是一对多,一个内部的IP地址和端口可以映射成多种IP地址和端口,用于发给不同的接收方
NAT算是一种违背了strong end-to-end 原则的设计。以最后一种对称NAT为例,如果突然改变了NAT的端口(例如从图中的6641切换为9821,而实际对应的主机A不变),会导致一下子掉线。虽然有优点,但是给网络设计添加了复杂性,难以管理和考虑。有关NAT的设计,TCP的在RFC5382、UDP的在RFC4787中都有具体的设计方案。
如果主机A已经在NAT上创建了一个【A映射的IP地址和端口】,同一内部网络下的主机B往这个【A映射的IP地址和端口】发送数据的话,在A的角度看来,源IP地址和源端口是【主机B的IP地址和端口】还是【A映射的IP地址端口】?
——这两个乍一想的答案都不对。应该一步一步来分析:
B的包发给【A映射的IP地址和端口】,该包在NAT翻译之前应该是这样的:源:B的IP地址:B的端口
目的:A映射的IP地址:A映射的端口NAT翻译后:
源:B映射的IP地址:B映射的端口
目的:A的IP地址:A的端口如果A回复数据时,在经过NAT时,翻译的过程是和上面反过来,即:
NAT翻译前:源:A的IP地址:A的端口
目的:B映射的IP地址:B映射的端口NAT翻译后:
源:A映射的IP地址:A映射的端口
目的:B的IP地址:B的端口如果不进行这样的翻译,A回复的包将会无法到达B
——如果只按照上面讲的机制,即:映射关系只能由内部网络的主机主动创建,那么假如外部网络的主机想要主动与内部网络的主机进行传输,到达NAT时,会因为没有创建内部网络的主机的映射关系,导致数据不知道发给谁,也就是:外部网络的主机无法主动创建内部网络主机的映射关系,导致无法主动与内部网络的主机传输,最终外部网络的主机只会收到ICMP。
——解决方法1:connection reversal。
————以上面的例子来讲,外部网络的主机B想要主动和内部网络的主机A传输,必须往一个集合服务发送请求,让集合服务器转发这个请求给A。A收到来自集合服务器的请求以后,就会主动和B建立连接,进而由A主动建立映射关系。这里的reversal指的就是:外部B想主动和内部A建立连接,就要通过一个集合服务转发请求,反过来变成A主动和B建立连接
实现
1.IP地址和端口的映射
——考虑一个内部IP地址和TCP端口(X:X),它启动了连接到外部(Y1:Y1)元组的TCP连接。假设NAT为这个连接分配的映射为(X1‘:X1’)。此后不久,端点从同一个地址(X:X)启动到外部地址(Y2:Y2)的连接,并获取NAT上的映射(X2‘:X2’)。如果(X1‘:X1’)对于(Y2:Y2)的所有值等于(X2‘:X2’)(即:如果内部IP地址和端口无论和谁建立TCP连接,经过NAT映射得到的外部IP地址和端口都是一样的),那么NAT被定义为具有端点独立映射”行为。如果(X1‘:X1’)只有在Y2等于Y1时才等于(X2‘:X2’),那么NAT被定义为具有“地址依赖映射”行为。
——要求1:NAT必须具有TCP的“端点独立映射”行为。
2.从内部启动TCP连接
——要求2:NAT必须支持所有有效的TCP数据包序列(定义在[RFC 0793]中)(特别是SYN,ACK,SYN+ACK),以便【在NAT允许连接时】在内部和外部启动连接。特别要强调的是:NAT除了能够处理TCP 3次握手连接发起模式外,NAT还必须能够处理TCP同时打开的连接初始化模式(即同时给对方发SYN,同时给对方回复SYN+ACK)。
3.从外部启动TCP连接
——NAT将内部端点发起的第一个连接的映射分配到外部端点。与以前一样,当一个内部IP地址和端口(X:X)启动到外部连接(Y1:y1)时,该地址和端口(X:X)被分配(或重用)映射(X1‘:x1’)。
——在某些情况下,NAT策略可能允许将此映射用于从外部启动到内部端点的连接。外部端点(Y2:y2)试图通过向(X1‘:x1’)发送SYN来启动与内部端点的连接。NAT可以选择允许建立连接,也可以不允许连接。
————如果NAT选择允许连接,它会翻译入站SYN并按照现有映射将其路由到(X:x)。它还翻译(X:x)在响应中生成的SYN-ACK,并将其路由到(Y2:y2),以此类推。或者,NAT可以通过过滤入站SYN来禁止连接。
——如果NAT的安全策略允许,NAT可以允许外部发起的连接重用现有映射。有几种不同的策略是可能的,如[bem-udp]中所描述的那样。如果NAT允许从所有(Y2:y2)发起连接,则定义为具有“端点无关筛选”行为。如果NAT仅在Y2等于Y1时才允许连接初始化,则NAT被定义为具有“与地址相关的筛选”行为。如果NAT只在(Y2:y2)等于(Y1:y1)时才允许连接初始化,那么NAT被定义为具有“地址和端口相关的筛选”行为(只有在【第一个连接终止后不久,但映射仍处于活动状态】才可能实现这三种行为)。
——本文档中定义的另一种筛选行为是NAT不允许来自外部的任何连接初始化;在这种情况下,NAT被定义为具有“连接相关过滤”行为。“地址和端口相关过滤”和“连接相关过滤”行为的区别在于,前者允许在第一个连接的time_WAIT状态期间进入SYN,以启动一个新连接,而后者不允许。
——要求3:如果应用程序透明性是最重要的,建议NAT对TCP具有“端点无关的过滤”行为。如果更严格的过滤行为是最重要的,建议NAT具有“与地址相关的过滤”行为。a)过滤行为可以是NAT管理员可配置的选项。(B)TCP的过滤行为可能与UDP的过滤行为无关。
——要求4:NAT在收到数据包后至少6秒钟内不能响应未经请求的入站SYN数据包。如果在此间隔期间,NAT接收并翻译连接的出站SYN,NAT必须静默删除原始的未经请求的入站SYN数据包。否则,NAT应该为原始SYN发送一个ICMP【端口不可访问】的错误(即类型3,代码3),除非使用以下规则:如果发送响应违反NAT的安全策略,NAT必须悄悄丢弃原始SYN数据包。
————理由:此要求的目的是允许【同时开放】在NAT存在的情况下可靠地工作,并在未请求的SYN出现错误时迅速发出错误信号。在编写这份备忘录时,这两者都不可能实现;因此,这一要求是一种妥协。NAT应该容忍TCP同时打开的出站SYN中的一些延迟,这可能是由于网络拥塞或端点之间的松散同步造成的。如果未请求的SYN不是同时打开的尝试的一部分,并且是错误的,NAT应该努力按照[RFC 1122]发出错误信号。