背景

作为程序员,应该都听说过NAT(Network Address Transfer,网络地址转换)这一技术名词,并或多或少大概知道其原理与作用--NAT是用于解决IPv4地址不够用,保证我们能够在IPv6普及前依然可以正常使用互联网而广泛使用的一个技术,其原理正如其名称所示:其可以将私网IP通过网关(可以是路由器也可以是自身防火墙)转换为公网IP而实现与互联网的正常通信。

粗看下来这个理解已经说透了NAT的用途与原理,但是如果进一步问出以下几个问题,不少人(包括曾经的博主)就很难说清楚了,这里记录一下自己的思考总结,如有不对欢迎勘正。

NAT && NAPT之灵魂拷问

  1. NAT是将一个私网IP映射为一个公网IP与外网进行通信,那一个公网IP可以映射绑定多个私网IP吗?如果可以,怎么识别目的为网关公网IP的网络包实际属于哪个私网IP呢?
  2. NAT与NAPT是什么关系?
  3. NAPT通过IP+port的方式解决私网IP到公网IP的多对一绑定问题,但是port其实是传输层概念,对于TCP/UDP协议包我们很好理解可以根据其port实现单一公网IP到不同私网IP的绑定,那对于网络层协议如ICMP其并没有port的概念,其目的地址仅由IP标识,那网关能够识别出同一目的公网IP 的ICMP包对应的实际私网IP吗?能的话又是怎么做到的呢?

NAT

上面三个问题其实是层层递进的关系,先来理清NAT到底是什么,wikipedia上NAT定义如下:

网络地址转换(英语:Network Address Translation,缩写:NAT;又称网络掩蔽、IP掩蔽)在计算机网络中是一种在IP数据包通过路由器或防火墙时重写来源IP地址或目的IP地址的技术。这种技术被普遍使用在有多台主机但只通过一个公有IP地址访问互联网的私有网络中。它是一个方便且得到了广泛应用的技术。当然,NAT也让主机之间的通信变得复杂,导致了通信效率的降低。

正如前面简述,NAT本质上就是通过发送时重写来源IP(私网IP->公网IP),接收时重写目的IP(公网IP->私网IP)实现多台主机复用同一公网IP的目的。

Basic NAT

基本NAT(Basic NAT)只对IP地址进行了转换,不支持端口映射,所以一个公网IP不能同时被两个私网IP绑定,而只能被一个私网IP绑定,多个私网IP只能分不同时段独占式绑定同一公网IP。

Basic NAT又称静态NAT,实际对于解决IPv4地址不足并无助益,因为其支持同时上网的私有主机数最大也只能等于公网IP池的IP个数。

Basic NAT 使用场景

这种NAT的使用场景较少,目前能想到的实际应用场景是各云厂商的弹性IP技术(EIP, Elastic IP)技术,其实质就是一个Basic NAT的使用。

NAPT

现在大家一般提到的NAT其实都是NAPT(Netwoard Address Port Transfer, 网络地址端口转换),即同时会转换IP+Port,这样就可以做到多个私网IP同时使用一个公网IP对外通信了--网关通过维护一个私网IP+port <->公网IP + Port的映射表来识别同一目的公网IP但不同Port对应的实际私网IP+port。

网络层协议怎么Transfer?

正如问题3中提到的,Port是传输层才有的概念,多个私有主机IP的TCP、UDP连接通信通过不同的IP+Port组合同时使用同一公网IP与互联网进行通信,但是网络层协议如ICMP是没有Port的,NAPT怎么处理这种情况呢?没有Port难道不支持多个私有主机使用ICMP协议与公网通信?

实际验证当然是可以的,那么NAPT是怎么解决没有Port的ICMP协议包的多个目的私有IP识别呢?

举一个具体样例如下:

私有主机Private0、Private1同时使用ping命令向公网IP 8.8.8.8 发送ICMP回送请求包,在通过网关时对应私网Private0/1会被转换成公网IP Public0, 当网关收到8.8.8.8的回包时,发现其目的IP的Public0,怎么判定这个包到底是回给Private0还是Private1的呢?

仔细思考这一样例,会发现其本质和同一台主机上多个进程同时向8.8.8.8发送ICMP回送请求包的场景本质上是一样的,即:主机M0上开启两个进程Process0、Process1分别使用ping命令向8.8.8.8发送ICMP回送请求,当M0收到来自8.8.8.8的回包时,怎么判断这个回包应该属于Process0还是Process1?

要回答这个问题,需要从ICMP回送请求包的格式本身来寻找答案,ICMP包是封装在IP包之中的,其完整的IP数据包格式如下(以下图片引自20 张图解: ping 的工作原理, 感谢小林):



对应ICMP回送请求包其ICMP头格式如下:



如上图,ICMP回送请求包中包含一个标识符字段,用以区分是哪个应用程序发 ICMP 包,比如可以用进程 PID 作为标识符,这样当M0收到来自8.8.8.8的回包时,其根据标识符就能知道该包到底属于哪个进程了。

同理 公网网关在处理Private0、Private1的ICMP请求报时,也会根据标识符字段建立一个映射关系,当收到8.8.8.8的回包时,根据回包的标识符就能在之前建立的映射关系中确定回包实际所属的私网IP到底是Private0还是Private1了。

转载请注明出处,原文地址: https://www.cnblogs.com/AcAc-t/p/nat_napt_icmp_thinking.html

参考

https://zh.wikipedia.org/wiki/网络地址转换

https://www.cnblogs.com/xiaolincoding/p/12571184.html

https://www.cnblogs.com/AcAc-t/p/nat_napt_icmp_thinking.html

https://www.alibabacloud.com/help/zh/elastic-ip-address/latest/what-is-an-eip

最新文章

  1. AngularJS 指令(使浏览器认识自己定义的标签)
  2. Java List的深度克隆
  3. Python函数,参数,变量
  4. 【BZOJ】【3856】Monster
  5. angularjs中的directive
  6. Qt: 把内容写进字符串中与C++很相似(使用QTextStream包装QString)
  7. Android 动态Tab分页效果
  8. 新浪SAE快速上手教程
  9. 【C语言探索之旅】 第二部分第一课:模块化编程
  10. 办理康卡迪亚大学(本科)学历认证『微信171922772』Concordia学位证成绩单使馆认证Concordia University
  11. Proxy SwitchySharp chrome网络代理【转】
  12. iOS https请求 NSURLSessionDataTask
  13. Struts2学习(五)———— s标签和国际化
  14. BN(Batch Normalization)
  15. Spark实现K-Means算法
  16. React native 开发如何使用阿里的icon
  17. Asp.Net支付宝手机网站支付接口API之C#版
  18. jersey学习笔记
  19. Golang 写一个端口扫描器
  20. 嵌入式C语言自我修养 09:链接过程中的强符号和弱符号

热门文章

  1. 更改DataFrame列顺序
  2. 什么是ForkJoin?看这一篇就能掌握!
  3. 二、redis介绍
  4. 【Azure 环境】Azure 云环境对于OpenSSL 3.x 的严重漏洞(CVE-2022-3602 和 CVE-2022-3786)的处理公告
  5. AI音乐创作,让每一个人都成为音乐家
  6. Webpack前端源码泄露漏洞
  7. Windows自带管理工具
  8. 聊聊如何让办公网络直连Kubernetes集群PodIP/ClusterIP/Service DNS等
  9. 大前端html基础学习02
  10. Go | 函数注意事项