最近在开发支付系统,在和第三方支付渠道联调时碰到一个问题:我的电脑是在公司的内网中,无法收到渠道发出的异步回调通知。要想解决这个问题,就需要进行内网穿透,于是在内网穿透工具 frp 的帮助下,成功的解决了这个问题。
什么是内网
网络中进程怎么通信
我们知道,IP 地址相当于计算机在网络中的唯一编号,端口号(Port)则是运行在这台计算机中进程的唯一编号。利用 IP + Port 就能在互联网中实现进程间的通信。
私有 IP 地址
在互联网的地址架构中,有一些 IP 地址是 私有 IP 地址 ,这些地址无法直接连接互联网。与公网 IP 相比,私有 IP 是免费的,同时节省了 IP 地址资源,适合在局域网使用。
IPv4 私有地址
IP 地址区块 | 最大 CIDR 区块(子网掩码) | IP 数量(允许的主机数量) |
---|---|---|
10.0.0.0 - 10.255.255.255 | 10.0.0.0/8(255.0.0.0) | 1677 7216 |
172.16.0.0 - 172.31.255.255 | 172.16.0.0/12(255.240.0.0) | 104 8576 |
192.168.0.0 - 192.168.255.255 | 192.168.0.0/16(255.255.0.0) | 6 5536 |
Mac 电脑上可以用 ifconfig
命令来查看自己的 IP 地址。
展示出来的有 en0 en1 en2 en3 en4。到底那个才是我正在使用的 IP 地址呢,运行一下命令:
1 | networksetup -listallhardwareports |
IP 数据报
每个 IP 数据报都包含了源 IP 地址和目的 IP 地址,用来标识数据报的发送主机和接收主机。
IPv4 datagram format
问题 1
假设我现在要访问 Google 的搜索服务(216.58.200.36),那么由我发送出的每个 IP 报文中的源 IP 地址就是 10.100.21.4,目的 IP 地址就是 216.58.200.36。但 10.100.21.4 是一个私有 IP 地址,无法直接和互联网相连,那么我们又是怎么上网的呢?(假设路由器的内网 IP 地址为 10.100.20.254,公网 IP 地址为 118.184.5.17。)
怎么穿透
这就要用到 NAT(Network Address Translation)技术,它是一种在 IP 数据报通过路由器或防火墙时重写源 IP 地址或目的 IP 地址的技术。
Basic NAT
它的功能比较简单,仅支持地址转换(不支持端口映射)。Basic NAT 要求每一个连接都要对应一个公网 IP 地址。Basic NAT 要维护一个 IP 转换表:
内网 IP | 公网 IP |
---|---|
192.168.1.220 | 169.254.34.148 |
192.168.1.221 | 169.254.34.149 |
192.168.1.222 | 169.254.34.150 |
缺点是:很多时候我们没有大量的公网 IP 地址,无法做到一一映射。
NAPT
网络地址端口转换(Network Address Port Translation),这种方式支持端口映射,允许多台主机共享一个公网 IP 地址。NAPT 要维护一个 IP + Port 的转换表:
内网 IP | 公网 IP |
---|---|
192.168.1.220:7788 | 169.254.34.148:10001 |
192.168.1.221:80 | 169.254.34.149:10002 |
192.168.1.222:443 | 169.254.34.150:10003 |
回答 1
当我向 Google 的搜索服务(216.58.200.36:80)发送的 IP 数据报到达路由器时,它会将报文中的源 IP 地址改为它自己的公网 IP 地址(118.184.5.17),并且随机分配一个未被占用的端口号 9102(1024-65535),最后在转换表中插入一条这样的记录:
内网 IP | 公网 IP |
---|---|
… | … |
10.100.21.4:2048 | 118.184.5.17:9102 |
当 IP 数据报到达 Google 的搜索服务之后,Google 给我们回复的 IP 数据报中的源 IP 地址就为 216.58.200.36:80,而目的 IP 地址就是我们路由器的 IP 地址 118.184.5.17:9102。而路由器接收到这份报文之后,根据转换表中的记录,将数据报中的目的 IP 地址替换成 10.100.21.4:2048,这样就能正确地转发 IP 数据报到我的主机上了。
小结一下
完成内网穿透的三要素:
- 一台内网中的主机。
- 一台拥有公网 IP 的 NAT 服务器。
- 一台公网中的主机。
内网穿透工具
很多工具都能实现内网穿透,像 nogrok、花生壳、frp 等,这里使用的是 frp。
step0
建议先看一下 README.md。
step1
去 github 上下载 RELESAE 包。
先利用 ssh 命令登录到公网 Linux 服务器,然后按顺序执行以下命令:
1 | wget https://github.com/fatedier/frp/releases/download/v0.24.1/frp_0.24.1_linux_amd64.tar.gz |
解压之后的目录
step3
修改 frps.ini 文件。
1 | #frps.ini |
启动 frps。
1 | ./frps -c frps.ini |
frps 启动成功日志
step4
修改 frpc.int 文件,假设 Linux 服务器的公网 IP 为 45.77.99.210。
1 | #frpc.ini |
启动 frpc。
1 | ./frpc -c frpc.ini |
frpc 日志
frps 日志
启动过程中可能会遇到的问题:
- 服务器/客户端指定的端口已经被占用。
- Linux 通过
netstat -nap | grep 7000
命令查看 7000 端口是否已经被占用。 - Mac 通过
netstat -nap tcp | grep 8080
命令查看 8080 端口是否已经被占用。
- Linux 通过
- 服务器的 7000 端口没有开放。
- 用
firewall-cmd --query-port=7000/tcp --zone=public
命令看看是否已经打开。 - 如果关闭着,用
firewall-cmd --zone=public --add-port=7000/tcp --permanent
命令打开,然后重启服务器。
- 用
- 其它问题。
step5
至此,你已经成功的建立起了一个 NAT 映射,快去验证一下吧。