NAPT网络结构下TCP/UDP/ICMP访问外网原理思考
背景
作为程序员,应该都听说过NAT(Network Address Transfer,网络地址转换)这一技术名词,并或多或少大概知道其原理与作用--NAT是用于解决IPv4地址不够用,保证我们能够在IPv6普及前依然可以正常使用互联网而广泛使用的一个技术,其原理正如其名称所示:其可以将私网IP通过网关(可以是路由器也可以是自身防火墙)转换为公网IP而实现与互联网的正常通信。
粗看下来这个理解已经说透了NAT的用途与原理,但是如果进一步问出以下几个问题,不少人(包括曾经的博主)就很难说清楚了,这里记录一下自己的思考总结,如有不对欢迎勘正。
NAT && NAPT之灵魂拷问
- NAT是将一个私网IP映射为一个公网IP与外网进行通信,那一个公网IP可以映射绑定多个私网IP吗?如果可以,怎么识别目的为网关公网IP的网络包实际属于哪个私网IP呢?
- NAT与NAPT是什么关系?
- 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访问外网原理思考的更多相关文章
- OpenStack创建网络和虚拟机、dhcp设备、虚拟路由器、虚拟机访问外网原理分析
创建网络和虚拟机流程: 1.创建网络和子网 背后发生了什么: Neutron让控制节点上针对此子网的dhcp(虚拟设备)启动,用于给该子网下的实例分配ip 2.生成虚拟机 背后发生了什么: 用户通过G ...
- 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网络知识 第十五节课 ...
- virtualbox下安装的纯净版centOS7,无法访问外网
virtualbox下安装的纯净版centOS7,网络设置如下: 需要在/etc/sysconfig/network-scripts/下编辑ifcfg-enp0s3,其中,NOBOOT设置成也是,就可 ...
- VMware安装Ubuntu配置NAT模式下静态IP,解决访问外网问题
安装好VMware后,打开网络连接可以看到有VMware Network Adapter VMnet1和VMware Network Adapter VMnet8两个网络适配器,VMnet1是针对桥接 ...
- 本地虚拟机NAT模式下怎么设置才可以访问外网
记:因为我要在本机虚拟机上安装Docker,结果发现虚拟机环境不能上网,是主机模式.我要调成net模式下才可以访问外网,这就需要怎么设置.下面文章记录一下. 在本机安装VMware软件后,系统中会自动 ...
- 在VMWare下为CentOS设置静态IP通过NAT访问外网
一.背景 安装好的CentOS系统默认是通过DHCP自动分配地址来共享主机的IP以达到访问外网的目的,但是因为莫名的原因无法访问外网.只好改为通过静态IP的方式访问外网. 二.操作步骤 2.1 确认开 ...
- 本地虚拟机在NAT网络连接模式下如何设置才可以访问外网以及使用Xshell远程连接
本文演示环境: 笔记本电脑系统:windows 7 虚拟机系统:CentOS 7 虚拟化软件:VMware Workstation 12 远程连接工具:Xshell 5 第一步: 打开虚拟网络编辑器 ...
- Neutron:访问外网
instance 如何与外部网络通信? 这里的外部网络是指的租户网络以外的网络. 租户网络是由 Neutron 创建和维护的网络. 外部网络不由 Neutron 创建. 如果是私有云,外部网络通 ...
- 阿里云CentOS 7无外网IP的ECS访问外网(配置网关服务器)
说明: 1.必须要有一台机器具有外网IP的ECS. 2.如果不想配置具有外网IP的ECS时,可以购买NAT网关,但需要钱,贵.下面会说明NAT网关的配置. 3.最后吐槽一下阿里云VPC网关导致不能按照 ...
- OpenStack Neutron配置虚拟机访问外网
配置完成后的网络拓扑如下: 当前环境: X86服务器1台 Ubuntu 16.04 DevStack搭建OpenStack 网络拓扑: 外部网络:192.168.98.0/24 内部网络:10.0.0 ...
随机推荐
- c语言求输入的任一整数的各位数之和
c语言求解代码: # include<stdio.h> int main(void){ int a,i=0,sum=0; scanf("%d",&a); if( ...
- Python基础之面向对象:3、继承与派生
面向对象 一.三大特征之继承 python三大特征: 封装.继承.多态 三者中继承最为核心,实际应用对,感受较为直观 封装和多态略微抽象 1.继承的概念 继承的含义: 在现实生活中,继承表示人与人 ...
- 畅联新增物联网设备接入协议:精华隆的NB一键报警
这个是有点时间了,这里记录一下! ----------------------------------------------------------------------------------- ...
- ui自动化测试数据复原遇到的坑——1、hibernate输出完整sql
公司老项目使用SSH+informix+weblogic+IE开发,我们要做ui自动化测试,其中的测试数据复原,我打算通过hibernate输出sql,然后把插入.更新的sql改为delete或upd ...
- 2022-11-08 Acwing每日一题
本系列所有题目均为Acwing课的内容,发表博客既是为了学习总结,加深自己的印象,同时也是为了以后回过头来看时,不会感叹虚度光阴罢了,因此如果出现错误,欢迎大家能够指出错误,我会认真改正的.同时也希望 ...
- UBOOT编译--- include/config/auto.conf、 include/config/auto.conf.cmd、 include/generated/autoconf.h (二)
1. 前言 UBOOT版本:uboot2018.03,开发板myimx8mmek240. 2. 背景 在编译构建目标时(如 make xxx),顶层 Makefile 的 dot-config 变量值 ...
- MVC开发单元测试小工具 —— 搜寻还没写单元测试的方法
方法比较笨,有更好的建议可以提. 写这个工具呢,因为要写单元测试,保证代码质量,方便修改维护.一切为了自己方便.当然这个算是个人开发的项目 1.MVC中控制器建立个基类(这个光明正大的抄袭的),控制往 ...
- 重学c#系列——逆变和协变[二十四]
前言 简单整理一下逆变和协变. 正文 什么是逆变和协变呢? 首先逆变和协变都是术语. 协变表示能够使用比原始指定的派生类型的派生程度更大的类型. 逆变表示能够使用比原始指定的派生类型的派生程度更小的类 ...
- linux deb系 apache 配置解析php文件
安装apache服务器和php服务 sudo apt-get install apache2 php 然后其实一般来说什么也不用安装了就可以成功解析php文件了 制作一个测试文件,test.php放到 ...
- 8.一个项目实战(下载CSDN博客文章)
专栏地址 ʅ(‾◡◝)ʃ 前言 要写一个下载器,首先要实现一个接口函数,而这个函数可以对请求的数据进行处理也就是爬虫,其次才是写图形化界面 接口的实现 其实CSDN的浏览器页面的接口很复杂,是直接通过 ...