背景

作为程序员,应该都听说过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

NAPT网络结构下TCP/UDP/ICMP访问外网原理思考的更多相关文章

  1. OpenStack创建网络和虚拟机、dhcp设备、虚拟路由器、虚拟机访问外网原理分析

    创建网络和虚拟机流程: 1.创建网络和子网 背后发生了什么: Neutron让控制节点上针对此子网的dhcp(虚拟设备)启动,用于给该子网下的实例分配ip 2.生成虚拟机 背后发生了什么: 用户通过G ...

  2. centos Linux系统日常管理2 tcpdump,tshark,selinux,strings命令, iptables ,crontab,TCP,UDP,ICMP,FTP网络知识 第十五节课

    centos  Linux系统日常管理2  tcpdump,tshark,selinux,strings命令, iptables ,crontab,TCP,UDP,ICMP,FTP网络知识 第十五节课 ...

  3. virtualbox下安装的纯净版centOS7,无法访问外网

    virtualbox下安装的纯净版centOS7,网络设置如下: 需要在/etc/sysconfig/network-scripts/下编辑ifcfg-enp0s3,其中,NOBOOT设置成也是,就可 ...

  4. VMware安装Ubuntu配置NAT模式下静态IP,解决访问外网问题

    安装好VMware后,打开网络连接可以看到有VMware Network Adapter VMnet1和VMware Network Adapter VMnet8两个网络适配器,VMnet1是针对桥接 ...

  5. 本地虚拟机NAT模式下怎么设置才可以访问外网

    记:因为我要在本机虚拟机上安装Docker,结果发现虚拟机环境不能上网,是主机模式.我要调成net模式下才可以访问外网,这就需要怎么设置.下面文章记录一下. 在本机安装VMware软件后,系统中会自动 ...

  6. 在VMWare下为CentOS设置静态IP通过NAT访问外网

    一.背景 安装好的CentOS系统默认是通过DHCP自动分配地址来共享主机的IP以达到访问外网的目的,但是因为莫名的原因无法访问外网.只好改为通过静态IP的方式访问外网. 二.操作步骤 2.1 确认开 ...

  7. 本地虚拟机在NAT网络连接模式下如何设置才可以访问外网以及使用Xshell远程连接

    本文演示环境: 笔记本电脑系统:windows 7 虚拟机系统:CentOS 7 虚拟化软件:VMware Workstation 12 远程连接工具:Xshell 5 第一步: 打开虚拟网络编辑器 ...

  8. Neutron:访问外网

    instance 如何与外部网络通信?   这里的外部网络是指的租户网络以外的网络.  租户网络是由 Neutron 创建和维护的网络. 外部网络不由 Neutron 创建. 如果是私有云,外部网络通 ...

  9. 阿里云CentOS 7无外网IP的ECS访问外网(配置网关服务器)

    说明: 1.必须要有一台机器具有外网IP的ECS. 2.如果不想配置具有外网IP的ECS时,可以购买NAT网关,但需要钱,贵.下面会说明NAT网关的配置. 3.最后吐槽一下阿里云VPC网关导致不能按照 ...

  10. OpenStack Neutron配置虚拟机访问外网

    配置完成后的网络拓扑如下: 当前环境: X86服务器1台 Ubuntu 16.04 DevStack搭建OpenStack 网络拓扑: 外部网络:192.168.98.0/24 内部网络:10.0.0 ...

随机推荐

  1. 前后端分离项目(九):实现"添加"功能(后端接口)

    好家伙,来了来了,"查"已经完成了,现在是"增" 前端的视图已经做好了,现在我们来完善后端 后端目录结构   完整代码在前后端分离项目(五):数据分页查询(后端 ...

  2. PCA降维的原理及实现

    PCA可以将数据从原来的向量空间映射到新的空间中.由于每次选择的都是方差最大的方向,所以往往经过前几个维度的划分后,之后的数据排列都非常紧密了, 我们可以舍弃这些维度从而实现降维 原理 内积 两个向量 ...

  3. Java多线程-ThreadPool线程池(三)

    开完一趟车完整的过程是启动.行驶和停车,但老司机都知道,真正费油的不是行驶,而是长时间的怠速.频繁地踩刹车等动作.因为在速度切换的过程中,发送机要多做一些工作,当然就要多费一些油. 而一个Java线程 ...

  4. 前端html和css总结

    1.html知识总结 1.1 表格的的相关属性 属性 表示 border-collapse 设置表格的边框是否被合并为一个单一的边框 cellpadding 单元格边距 cellspacing 单元格 ...

  5. 「浙江理工大学ACM入队200题系列」问题 L: 零基础学C/C++52——计算数列和2/1,3/2,5/3,8/5......

    本题是浙江理工大学ACM入队200题第五套中的L题 我们先来看一下这题的题面. 题面 题目描述 有一分数序列:2/1,3/2,5/3,8/5,13/8,21/13,-- 计算这个数列的前n项和.注意: ...

  6. 记录redis集群连接超时问题及解决方案

    下午同事反馈,某业务场景性能测试过程中,出现异常,提供日志报: Redis command timed out 1. 先看下日志 org.springframework.dao.QueryTimeou ...

  7. 【笔记】CF1607F Robot on the Board 2 及相关

    题目传送门 记忆化搜索 首先,这题 \(10000\) 组 \(2000\times 2000\) 的数据直接爆搜肯定会超时.想到,如果一个点的答案已经被更新过,之后走到这个点能再多走的点也就确定了, ...

  8. 倍福Ads协议通信测试

    测试环境:vs2015 + TC31-Full-Setup.3.1.4022.30.exe 首先需要安装TC31-Full-Setup.3.1.4022.30.exe 本例子是用本机作测试,如果使用远 ...

  9. 方法的重载(Overload)+ println重载

    方法的重载(Overload) package cn.day01; /*方法的重载(Overload):多个方法的名称一样,但是参数列表不一样. * 好处:只需要记住唯一一个方法名称,就可以实现类似多 ...

  10. ubuntu undefined reference to

    温馨提示,请使用ctrl+F进行快速查找 libdl.so undefined reference to `dlsym' undefined reference to `dlopen' undefin ...