概述
1. 为什么需要内网穿透
要想说清楚为什么需要内网穿透, 需要先说清楚什么是内网, 什么是公网
内网和公网是计算机网络中两个常用的概念,它们指的是不同的网络范围的访问权限.
- 内网: 内网是指由一个组织或机构内部使用的私有网络。它通常用于组织内部的通信、数据共享和资源访问。内网可以包括办公室、学校、企业等组织内部的局域网LAN或广域网WAN。内网中的设备通常具有私有IP地址,并通过路由器、防火墙等网络设备与外部网络(即互联网)隔离。
- 公网: 公网是指公共互联网,即全球范围的互联网。它是由各种网络和设备连接而成的全球性网络,用于连接全球的计算机和设备,提供各种互联网服务和资源。外网是公共的,任何连接到互联网的设备都可以通过网络协议进行通信和访问外部资源。
私有网段地址
- 10.0.0.0/8 (可支持16,777,214个主机地址)
- 172.16.0.0/12 (可支持1,048,574个主机地址)
- 192.168.0.0/16 (可支持65,534个主机地址)
现状
由于IPV4使用32位来表示, 大约总空间约42.9亿(包括了私有地址), 导致出现IPV4地址稀缺的情况, 从而就延申出了另外一个技术NAT, NAT技术的出现大大缓解了IPV4地址不够的情况, 但是由于NAT技术的特点是在一个大的局域网中共享一个公网IP(后面详细介绍NAT技术), 所以又延申出来一个新问题, 也就是我们个人的IP地址基本上都是192.168这个私有网段, 从而导致不能够被外部直接访问. 内网不能够被直接访问, 就需要借助今天的主角内网穿透来解决这个问题.
2. 内网穿透应用场景
- P2P场景, 例如机器A想要直接和机器B通信,不想借助中间商, 在高实时性通信中P2P拥有绝对的优势
- 内网有一个服务, 希望外部也可以访问
- 跨局域网使用 SSH, 微软RDP
- 私有化
- 等等
NAT技术
内网穿透有很多别名,比如打洞, 其中有一个别名就是NAT穿透, 既然是要对NAT进行穿透, 避免不了先了解NAT技术
NAT的全称是 Network Address Translation(网络地址转换), 主要负责将内部的私有IP地址转换成可以在公网使用的公网IP, NAT技术除了可以有效的节省IPV4公网地址, 还可以用来隐藏其内网IP, 来提供安全性.
(图片来自网络)
NAT 实现方式
NAT实现方式分为
- 静态NAT
- 动态NAT
- NAPT
静态NAT
静态NAT是指一个公网IP地址对应一个私有IP地址,是一对一的转换.
内网IP | 外网IP |
---|---|
192.168.21.20 | 120.152.168.222 |
192.168.21.21 | 120.152.168.223 |
192.168.21.22 | 120.152.168.224 |
192.168.21.23 | 120.152.168.225 |
NAPT
在基础NAT中,私有地址和公网地址是一对一的转换关系, 它只解决了公网和私网的通信问题,但是没有解决公网地址不足的问题
NAPT的全称是(Network Address Port Translation), 可以看到多了一个Port, 也就是在做转换时会将IP地址和Port号同时进行转换.
NAT表
(图片来源于网络)
看一个实际的例子:
当前环境
- 私网主机A (10.0.0.1/24)
- 公网服务器地址 (61.144.249.229)
- 路由器RT上配置 NAPT, 地址池 219.134.180.11 - 219.134.180.20
A → Server
(图片来源于网络)
- A向公网服务器地址(简称Server)发送报文, 网关是RT( 10.0.0.254/23), 目的地址和端口号是61.144.249.229:80, 源地址和端口号是10.0.0.1/24
(图片来源于网络)
- RT 收到 IP 报文后,查找路由表,将 IP 报文转发至出接口,由于出接口上配置了 NAPT ,因此 RT 需要将源地址 10.0.0.1:1024 转换为公网地址和端口。
- RT 从地址池中查找第一个可用的公网地址 219.134.180.11 ,用这个地址替换数据包的源地址,并查找这个公网地址的一个可用端口,例如 2001 ,用这个端口替换源端口。转换后的数据包源地址为 219.134.180.11:2001 ,目的地址和端口不变。同时 RT 在自己的 NAT 表中添加一个表项,记录私有地址 10.0.0.1:1024 到 公网地址 219.134.180.11:2001 的映射。RT 再将报文转发给目的地址 61.144.249.229 。
如果 B 也要访问 Server ,则 RT 会从地址池中分配同一个公网地址 219.134.180.11 ,但分配另一个端口 3001 ,并在 NAT 表中添加一个相应的表项,记录 B 的私有地址 10.0.0.2:1024 到公网地址 219.134.180.12:3001 的映射关系。
(图片来源于网络)
NAPT的主要类型
NAPT主要被分为了两大类型: 锥型NAT和对称型NAT, 其中锥型NAT又分了几种,总结下来NAPT被分为了以下类型:
- 完全锥型
- 受限锥形
- 端口受限锥型
- 对称型NAT
注意所有类型在最新的RFC 5780都拥有两种行为 Mapping(映射), Filtering(过滤), 其中映射是值私网访问外部,NAT服务器做的一个关系映射, 过滤是指外部访问内部时NAT服务器做的一层过滤(主要是如何转发到内网,以及是否允许转发到内网), 其中前三中类型的映射规则都是一样的, 只有对称型NAT映射规则不一样
完全锥型NAT
特点 | 映射规则 | 过滤规则 |
---|---|---|
IP和端口都不受限 | 所有主机A访问的外部部服务都被映射到同一公网IP和端口 | 将私有网络的源IP地址和端口映射到公网IP某个端口,只要是这个私有网络的源IP地址和端口号都将被映射到这个公网IP和端口,也就是如果外部知道这个映射的公网IP和端口,就可以通过这个公网IP和端口和私有网络的源IP和端口进行通信 |
受限锥形
特点 | 映射规则 | 过滤规则 |
---|---|---|
IP受限,端口不受限 | 所有主机A访问的外部部服务都被映射到同一公网IP和端口 | 在公网映射端口后,并不允许所有的IP对该端口的访问, 如果想要访问这个内部主机,就必须是内部主机有对这个外部主机进行过访问, 如果现在内部主机访问了外部主机A,但是没有访问外部主机B, 那通过主机A是可以访问内部主机的,但是通过主机B是访问不到内部主机的. |
端口受限锥型
特点 | 映射规则 | 过滤规则 |
---|---|---|
IP和端口都受限 | 所有主机A访问的外部部服务都被映射到同一公网IP和端口 | 相较于受限锥形它会更加严格,不仅仅对IP地址增加限制, 还会对端口号增加限制, 比如主机A访问了外部主机A的80端口, 那么只有外部主机A的80端口可以与这个主机A进行通信, 如果使用的是8080将直接被NAT丢弃 |
对称型NAT
特点 | 映射规则 | 过滤规则 |
---|---|---|
IP和端口都受限 | 主机A内部的访问不同服务都会被映射成不同的公网IP和端口, | 过滤规则与端口受限型一样 |
NAT穿透
NAT穿透也被称为打洞, 也就是我在NAT上开一个小洞, 只要是通过这个洞外部就可以主动与私网进行通信
打洞的简单逻辑如下:
让私网机器主动通过NAT访问服务器, 服务器就可以记住NAT映射后的公网IP地址和端口号, 后续可以将这个IP地址和端口号告知其他私网机器, 使得私网机器可以访问其他私网机器
完整逻辑:
解释:
- 通过打洞服务器收集到私网机器A和私网机器B的公网IP地址和端口号, 由于打洞服务器处理公网,所以私有机器是可以主动访问打洞服务器的, 并且主动访问完成之后会在各自内网的NAT表上记录一个映射地址.
- 打洞服务器收集到A和B的公网IP和端口号之后, 将数据进行交换, 把A的公网IP地址和端口给到B, B的公网IP地址和端口给到A
- 当A知道了B的公网IP和端口之后, 会尝试着去和这个公网IP和端口进行通信, 这一步的目的主要是由于除了完全锥型NAT之外其他的NAT类型的过滤规则都会去检测接收到的数据包的源IP地址是否在自己NAT映射表中存在. 比如 A机器主动通过B的公网IP和端口发送数据之后, 就会在A机器的NAT映射表中记录上B机器的公网IP和端口号, 相当于是自己给B机器的公网IP和端口号开了一个口子, 使其B机器使用自己的公网IP和端口号可以与A进行通信
- 当B知道了A的公网IP和端口之后, 会同步上面的步骤, 也会给A在自己的NAT映射表中开一个口子,使其A能够通过这个IP地址和A的公网IP地址直接访问到B
- 当A和B都给自己开了一个口子之后, A和B就可以进行P2P通信了
不同NAT类型的打洞对比
Peer A | Peer B | 是否可以打洞 |
---|---|---|
完全锥型 | 完全锥型 | 是 |
完全锥型 | 受限锥形 | 是 |
完全锥型 | 端口受限锥型 | 是 |
完全锥型 | 对称型NAT | 是 |
受限锥形 | 受限锥形 | 是 |
受限锥形 | 端口受限锥型 | 是 |
受限锥形 | 对称型NAT | 是 |
端口受限锥型 | 端口受限锥型 | 是 |
端口受限锥型 | 对称型NAT | 否 |
对称型NAT | 对称型NAT | 否 |
为什么对称型和对称型 & 端口受限型和对称型打洞不能成功?
对称型的特点:
访问外部的不同服务都会被映射到不同的IP地址或者端口号, 那我们先看第一步, 服务去获取双方的公网IP之后双方的NAT映射表是什么情况, 假设机器A的私网IP是10.0.0.1, 机器B的私网IP是10.0.0.2, 打洞服务器获取到的A的公网IP和端口是3.3.3.3:1000, 获取到B的公网IP和端口是4.4.4.4:2000, 打洞服务器自身的公网IP和端口是5.5.5.5:3000, 获取完成之后NAT映射表如下:
机器名 | 源 | 目的 |
---|---|---|
A | 3.3.3.3:1000 | 5.5.5.5:3000 |
B | 4.4.4.4:2000 | 5.5.5.5:3000 |
在服务器获取完公网IP并在A和B之间交换了公网IP, 现在A和B需要进行互相访问, 来进行打洞, 互相访问完成之后A和B的NAT映射表如下(A和B是对称型和对称型):
机器名 | 源 | 目的 |
---|---|---|
A | 3.3.3.3:1000 | 5.5.5.5:3000 |
3.3.3.3:1002 | 4.4.4.4:2000 | |
B | 4.4.4.4:2000 | 5.5.5.5:3000 |
4.4.4.4:2002 | 3.3.3.3:1000 |
按照对称型的筛选原则, 源和目的的端口IP必须完美匹配, 也就是如果A想要访问B, 并且被B接收到数据, 那就是必须访问B的4.4.4.4:2002 (但是由于这个端口生成规则是B的映射表自动生成的, A不可能知道), B想要访问A就必须访问A的3.3.3.3:1000(但是由于这个端口生成规则是A的映射表自动生成的. B不可能知道). 好了陷入了一个死循环.
为什么对称型和受限锥形&完全锥型可以打洞?
还是和上面一样的流程, A是对称型NAT B是完全锥型NAT, 在执行完前面的流程后, A和B的映射表如下
机器名 | 源 | 目的 |
---|---|---|
A | 3.3.3.3:1000 | 5.5.5.5:3000 |
3.3.3.3:1002 | 4.4.4.4:2000 | |
B | 4.4.4.4:2000 | 5.5.5.5:3000 |
4.4.4.4:2000 | 3.3.3.3:1000 |
不同点在于B的NAT映射表里的两条数据中的源都是4.4.4.4:2000, 并且这个公网IP和端口号A是知道的(通过打洞服务器交换了各自的IP和端口号), 那现在A给B发送数据B是可以收到的, 比如B收到了3.3.3.3:1002发送来的数据, 就可以直接使用给3.3.3.3:1002回送消息了.
内网穿透之反向代理
说完了NAT穿透, 发现有几种NAT类型组合之后会存在穿透失败的情况. 为了解决内网穿透的100%成功率, 有一个反向代理的技术可以实现. 要说反向代理可以先说清楚代理
代理技术在我们日常使用中经常使用到, 常用的代理模式有三种
- 正向代理
- 反向代理
- 透明代理 (透明代理和正向代理基本一直,区别在于访问者不需要知道代理服务器的存在, 完全透明)
正向代理
正向代理也是日常使用中接触最多的一种代理模式, 正向代理是指机器A想要访问某个服务, 需要经过某个代理服务器. 通过我们需要在机器A上配置代理服务器的地址和端口, 我们现在用的大多数翻墙软件就是使用的正向代理.
应用场景:
- 机器通过正向代理访问原本不可访问的服务
- 通过正向代理服务器进行出口管控
- 隐藏访问者行踪( 代理服务器变成一个肉鸡)
反向代理
应用场景:
- 负载均衡
- 内网穿透
FRP介绍
官方介绍:
- frp is a fast reverse proxy that allows you to expose a local server located behind a NAT or firewall to the Internet. It currently supports TCP and UDP , as well as HTTP and HTTPS protocols, enabling requests to be forwarded to internal services via domain name.
简单介绍就是FRP通过反向代理实现将内部服务(处于NAT或者防火墙背后的本地服务) 暴露Internet
架构
frps:部署在公网的内网穿透服务器(反向代理服务器)
fpsc:部署在内网的客户端
要想利用Frp实现内网穿透,必须要拥有一个公网IP地址,将Frps程序部署在公网IP地址的服务器上,其中Frps提供反向代理能力,公网IP是需要提供给外部用户访问的入口,frps通过和frpc建立连接,将安装frpc客户端机器的内网服务代理到frps中,从而实现内网穿透。
参考链接
一文带大家,彻底了解,NAT技术 - 知乎 (zhihu.com)
RFC 2663 - IP Network Address Translator (NAT) Terminology and Considerations (ietf.org)
RFC 5389 - Session Traversal Utilities for NAT (STUN) (ietf.org)
RFC 5780 - NAT Behavior Discovery Using Session Traversal Utilities for NAT (STUN) (ietf.org)