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 ...
随机推荐
- select中DISTINCT的应用-过滤表中重复数据
在表中,一个列可能会包含多个重复值,有时也许希望仅仅列出不同(distinct)的值. DISTINCT 关键词用于返回唯一不同的值. SQL SELECT DISTINCT 语法 SELECT DI ...
- MobaXterm/Xshell快速命令宏配置
背景:使用MobaXterm或者Xshell连接远程服务器时,添加常用的命令宏一键执行,能提高效率节约时间. 使用方法: MobaXterm: 1)左边菜单栏->Macros->Recor ...
- UBOOT编译--- UBOOT顶层Makefile中目标_all和all的关系及背景(四)
@ 目录 1. 前言 2. 概述 3. 老版本UBOOT(背景) 4. 新版本UBOOT 5. 参考 1. 前言 UBOOT版本:uboot2018.03,开发板myimx8mmek240. 2. 概 ...
- 【开发必备】单点登录,清除了cookie,页面还保持登录状态?
背景 本地搭建了一台认证服务器.两台资源服务器,看看请求的过程 开始 没登录,直接请求资源服务器,结果跳转到的登录页面 登录后,请求了认证服务器的登录接口,然后顿重定向,最后回到了资源服务器的接口,页 ...
- vue3 + element plus 使用字节跳动图标
使用场景: 提一下vue2 用法>> 下面回到正题 vue3 用法 1 安装包: npm install @icon-park/vue-next --save 2 字节跳动图标库取图地 ...
- Thrift RPC添加access log
前言: 当我们在部署web服务的时候,web容器通常都会记录来自客户端的访问日志.而当我们使用Thrift RPC服务的时候,Thrift服务则不会给我们自动记录客户端的访问日志. 通过这篇文章,你可 ...
- SpringBoot 自动装配的原理分析
关于 SpringBoot 的自动装配功能,相信是每一个 Java 程序员天天都会用到的一个功能,但是它究竟是如何实现的呢?今天阿粉来带大家看一下. 自动装配案例 首先我们通过一个案例来看一下自动装配 ...
- RocketMQ Connect 构建流式数据处理平台
本文作者:孙晓健,Apache RocketMQ Committer 01 RocketMQ Connect RocketMQ Connect 是一款可扩展的在 RocketMQ 与其他系统之间做流式 ...
- 连接MySql时提示%d format: a number is required, not str
代码: sql = "select * from appelementinfo" coon = pymysql.connect(user='root', password='', ...
- Django ValueError: HTTP status code must be an integer from 100 to 599.
程序执行后一直提示ValueError: HTTP status code must be an integer from 100 to 599. 遍历代码一切正常,然后开始调试代码,找出获取数据有问 ...