NAT探珠

概要

NAT的全称是 Network Address Translation, 其实看英文名,就知道它的大概意思:网络地址转换。

严格来说,

  • 这个Address,包括了IP地址和端口。
  • 而这个Translation,则包括来来源地址和目的地址,以及来源端口和目的端口这4者之间的转换

那么NAT规则其实定义的就是这4者的映射关系,告诉路由器应该怎么去转换(Translation)

那么什么时候会用到NAT技术呢,答案是,从一个网络到另外一个网络,有一些文章在写NAT的时候,常讲的是外网(互联网)到私网(私域子网)的通信的时候,其实这只是其中一种场景,实际上,只要是两个网络间需要通信,都可以用NAT来做。

下面这个图讲的就是互联网和私网这个场景的NAT

    \ | /                  .                               /
   +---------------+  WAN     .           +-----------------+/
   |Regional Router|----------------------|Stub Router w/NAT|---
   +---------------+          .           +-----------------+\
                              .                      |        \
                              .                      |  LAN
                              .               ---------------
                        Stub border

        Figure 1: A typical NAT operation scenario

这个图是从NAT的规范rfc.2663 复制过来的,其中WAN就是广域网,LAN是一个局域网,LAN通过路由器连接到WAN,那么要在WAN和LAN之间通信,那就通过的在路由器里面做数据包的NAT转换。

NAT的地址转换技术有很多种类,但这些技术一般都具备下面这3个特征:

  • 透明地址分配,就是定义外网和内网的地址的映射关系
  • 通过地址转换进行透明路由(这里的路由指的是数据包的转发,而不是指交换路由信息)
  • ICMP的错误包的payload转换

那么透明地址分配的规则是这个这些技术里面的关键点,这种地址分配又分为:

  • 静态地址分配:这是一种one-to-one的映射关系,这种映射关系明确、简单,不需要在地址转换翻译的过程中管理会话,发出去和回复回来的数据包都有明确的关系。
  • 动态地址分配:非one-to-one的映射关系,一个或者少量的外网地址分配个一个私网的一堆主机,这种情况,则需要通过会话来明确这个映射关系,那么就需要管理会话,这样才知道回复的数据包对应的是哪台主机发出去的(通过会话来查找映射关系,映射关系会话开始的时候就确立了)

NAT的种类

NAT根据他的通信种类,又分为4类:

  • 传统NAT或出站NAT: 会话从私有网络发起,是单向的,出站方向的这种会话
  • 双向NAT:会话可以从无论是公有网络还是私有网络发起都行,是双向的
  • 两次NAT:两次NAT是NAT的一个变种,它在转换过程中,把数据包里面源地址和目标地址都给改了,这种情况是因为两个网络的地址有冲突,比如两个网络都是同一个网段,而且主机的地址都一样
  • 多宿主NAT:解决NAT路由的单点故障问题而衍生出来的一种NAT技术

这么多NAT,对我们最经常需要用到的是传统NAT(出站NAT),下面我们重点讲这种NAT技术

传统NAT(出站NAT)

而传统的NAT又分为:

  • Basic NAT,需要一个外部的IP池拿来和做转换,不需要端口参与,要求对每一个当前连接都要对应一个公网IP地址,这种NAT在转换的阶段,指修改IP、ip头的checksum以及一切更高级别和IP相关的checksum(如TCP、UDP、ICMP的header的checksum)的值(使数据包看起来合法),一般来讲你有足够多的外网ip可以用来对应你的内网主机,那就用这种,
  • NAPT, NAPT是Net Address Port Translation, 需要端口参与到映射关系里,为什么需要端口参数呢,因为你的外网ip数量不足以对应到你内网的主机数量,所以需要共享外网IP.

NAPT的技术有根据地址转换过程阶段分为

  • DNAT,数据包发出去的时候,修改的是目标IP地址,所以叫做Destination NAT,简称DNAT
  • SNAT, 数据包发出去的时候,修改的是源IP地址,所以叫做Source NAT,简称SNAT(但是只看缩写的话,SNAT会有很多其他的定义,有一些厂商,比如WatchGuard,SNAT代表的是Static NAT)

BASIC NAT

下面这个图分别演示了路由器在转换过程中的SNAT和DNAT

image

SNAT阶段:由于私网对外只有一个IP(一般是拨号拿来的或者运营商给静态分配的),私网的主机A在给公网发出去请求的给Web Server的时候,它的这个请求的数据包先经过路由器,路由器对会把它的地址改为私网对外的唯一的对外的公网地址202.20.65.5,然后在发给Web Server

DNAT阶段: Web Server收到请求后,开始响应,这个时候它响应的数据包的目标地址就变成了它私网的唯一的对外的公网地址202.20.65.5,但是,路由器收到这个数据包后,要把他转给这个包发起者192.168.1.2,就必须包目的地址改为192.168.1.2然后再发出去,这样主机A才会接受这个包(这里涉及同一个子网到数据链路层包广播的问题)

那么,这里又有一个问题,在DNAT阶段,路由器是怎么知道,这个报应该把他的目的地址转换位192.168.1.2呢?这里就涉及到上面所说会话管理的问题,路由器(或者说NAT网关)在会话开始的阶段,在第一个个包发出去,它就确认了会话的方向(第一个包的方向就是会话的方向)和对应关系(这里讲的会话的定义是,一小撮用来表达怎么用来完成一个转换的流量集合,这个集合定义为一个会话)

到这里,又涉及到一个概念是Session flow和packet low的对比(NAT用的Session flow),这里不细讲了,可以直接看rfc规范的这部分

在传输层里面:

  1. 如果是TCP协议,每个TCP会话的第一个数据包尝试建立一个会话 并包含连接启动信息。(这里涉及到3次握手的过程。TCP Session的确立,是在第一个包含这SYN标志位,而有没有ACK标志位出现后就确认,在TCP的协议里,除了第一个SYNC包,除了其他的包都必须包含ACK标志位)

2. 如果是UDP又是另外一码事,这里不细讲,看rfc规范吧

还有关于TCP和UDP详细的会话结束的定义和生命周期,看rfc规范这里

总的来讲,就是NAT会建立一个session或者connection 跟踪的机制,来跟踪哪个报应该转换到内部的哪个个主机IP

image

这个track table 如果,是外网IP足够多的话,那就用静态分配技术,使内外网IP一对一,如果外网IP不够多,那就用动态分配,如何根据这个对照表来动态转换

NAPT

大家看上面这个图很快就会发现另外一个问题,如果内网里面有两个主机同时请求Web Server,那怎么转换呢,这个时候,可以把端口作为额外信息加入这个映射表,这个就是NAPT了

image

看上图,即使主机A和主机B请求的源端口一样,路由器也可以将他们转换成不一样的的端口,如何在发出去,如何收到Server回复的数据包的时候,再按照转换的规则,原路转换回去就好

docker和wireshark抓包实例演示

下面我们用docker建一个有子网络位192.168.5.0的子网的容器,如何在容器它里面去访问一个网站,并通过wireshark来抓这个包看具体是怎么转换的

# 新建一个桥接子网
docker network create -d bridge --subnet 192.168.5.0/24 --gateway 192.168.5.1 test_bridge1

# 新建一个名位box 1的容器,并加入这个网络
docker run --name box1 -p 8082:80 -it --rm  --network=test_bridge1 busybox sh

如何我们在宿主机,看看这个私有网络的网卡是哪个

route -n
内核 IP 路由表
目标            网关            子网掩码        标志  跃点   引用  使用 接口
192.168.5.0     0.0.0.0    255.255.255.0   U     0      0        0 br-6edc31410314

接着,用wireshark监控这个网卡

并在box 1这个容器里面区去访问外网

wget www.baidu.com

然后下面这个截图是wireshark的抓包信息

image

可以看到,前面是访问dns,如何接下来就是建立TCP连接,最后是发起http的Get请求

可以看到info里面是49982->80,这个就是NAPT,主机box1用的端口是49982去访问百度的80

可以展开这个握手包的传输层看看:

image

然后服务器发回握手的第二个包是确认包,我们再看看他的传输层:

image

server返回来的包的目的端口是49982,这个就是NAT的映射关系

实际上,上面这个例子,有几层的NAT,有容器到子网,如何子网到物理机的无线网卡,那么即使你在分别抓这3个地方的包,他们的端口映射是一样的。

上面这个端口的情况,下面我们来看一下ping 百度的其中一个ip

ping 182.61.200.6

抓容器的包和子网网桥的包和以及宿主机的包对比一下

image
image
image

容器本身和网桥里面抓包的source ip 是一样的(这个是容器的veth pair实现的机制所致),IP是192.168.5.2(容器IP)

而宿主机发出去的source ip以及被NAT网关转换成192.168.3.3,同时也可以看到,回复的ICMP包的地址也同样被按原路转换回去了

查看宿主机的NAT规则

上面我们创建容器的时候,绑定了容器box1的80端口到宿主机的8082端口

docker run --name box1 -p 8082:80 -it --rm  --network=test_bridge1 busybox sh

那这个绑定是怎么回事呢?为什么这样绑定,发给宿主机的8082端口的数据包就会发到容器呢?答案就是NAT,严格来说是宿主机在它的iptables里面增加了DNAT规则,告诉宿主机的iptable,碰到8082的包就发给宿主机的80吧,下面就是这条规则

> sudo iptables -S -t nat | grep 8082
-A DOCKER ! -i br-6edc31410314 -p tcp -m tcp --dport 8082 -j DNAT --to-destination 192.168.5.2:80

上面是规则,下面把路由表格列出来

> sudo iptables -L -t nat
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
KUBE-SERVICES  all  --  anywhere             anywhere             /* kubernetes service portals */
DOCKER     all  --  anywhere             anywhere             ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
KUBE-SERVICES  all  --  anywhere             anywhere             /* kubernetes service portals */
DOCKER     all  --  anywhere            !localhost/8          ADDRTYPE match dst-type LOCAL
...
Chain DOCKER (2 references)
target     prot opt source               destination         
RETURN     all  --  0.0.0.0/0            0.0.0.0/0                 
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:27017 to:172.18.0.2:27017
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:8081 to:172.17.0.2:80
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:8082 to:192.168.5.2:80
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:8083 to:192.168.5.3:80
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:8085 to:192.168.6.3:80
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:8084 to:192.168.5.4:80

用conntrack看当前链接的映射关系

sudo conntrack -L         
tcp      6 32841 ESTABLISHED src=192.168.3.3 dst=49.51.200.100 sport=58710 dport=443 src=49.51.200.100 dst=192.168.3.3 sport=443 dport=58710 [ASSURED] mark=0 use=1
tcp      6 74 TIME_WAIT src=10.1.1.1 dst=10.1.1.32 sport=33634 dport=8082 src=10.1.1.32 dst=10.1.1.1 sport=8082 dport=33634 [ASSURED] mark=0 use=1
tcp      6 31706 ESTABLISHED src=192.168.3.3 dst=49.51.200.100 sport=55282 dport=443 src=49.51.200.100 dst=192.168.3.3 sport=443 dport=55282 [ASSURED] mark=0 use=1
...

扩展阅读:

新手该如何选择云服务器
个人玩家和中小企业云服务器选择对比

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容