内网穿透
发布于 May 3, 2023 • 2 分钟 阅读 • 251 字对于IPv4,可用的公网IPv4地址资源的越来越少,国内运营商为了节省公网IPv4地址资源,为用户宽带分配的基本都是内网IPv4地址,通过NAT(网络地址转换)实现多个宽带用户共享同一个公网IP地址资源。服务必须拥有公网IP才能被访问,如何将内网的服务暴露到公网中供其他人进行访问,这就是内网穿透技术该做的事情。
本文针对IPv4地址内网穿透情况进行讨论,IPv6地址资源丰富,需要内网穿透的场景还是比较少的。
这里介绍几种笔者了解到的内网穿透方案,各有各的优缺点。
NAT在将内网地址转换为公网地址的过程中会记录公网地址和端口与内网地址和端口的映射关系,只要内网机器向公网发起请求,NAT设备就会对映射关系开放一段时间。对于Full Cone NAT,只要对应关系被打开,公网上所有主机都可以通过该映射关系对内网机器发起请求。
基于Full Cone NAT的特点,UDP打洞的原理就是通过一个公网服务器提供客户端信息注册和打洞服务。服务器流程基本如下:客户端A和B向打洞服务器S注册客户端A和B信息,S记录A和B的公网信息。打洞服务器可以向客户端发送对端的端口信息,随后客户端A和B可直接通信,期间客户端A和B定期发送心跳包连接维持NAT映射关系。常见的开源实现有pwnat(原理有点不太一样,有兴趣的了解一下)、tailscale和zerotier。
frp中继是最稳定和最简单的方法,同时也是搭建低延迟内网穿透网络的最好方案。原理是通过一个含有公网IP的服务器对内网流量进行中转。最热门开源中继服务器项目即 frp
cf即cloudflare,是一家国外非常著名的云计算厂商。这里介绍的是他们家的Zero Trust Tunnel功能。通过他们的开源客户端 cloudflared, 可以将内网服务暴露到cloudflare的公网IP并使用域名进行访问。使用隧道服务必须将自己的域名DNS交由cloudflare托管。
Linux服务器可以使用curl -o文件名 "下载地址"
下载,选择合适cpu架构的可执行程序。下载地址可以浏览器中点击右键复制下载地址获得。
cp -a /path/to/your/frps/binary /usr/bin
if [ ! -d /etc/frp ]; then
mkdir -p /etc/frp
fi
cat >> /etc/frp/frps.ini << EOF
[common]
bind_port = 7000
token = frp通信密钥
EOF
cat >> /etc/systemd/system/frps.service << EOF
[Unit]
Description=frp server.
After=network.target
[Service]
Type=simple
Restart=always
ExecStart=/usr/bin/frps -c /etc/frp/frps.ini
[Install]
WantedBy=multi-user.target
EOF
systemctl enable frps
systemctl start frps
cp -a /path/to/your/frpc/binary /usr/bin
if [ ! -d /etc/frp ]; then
mkdir -p /etc/frp
fi
cat >> /etc/frp/frpc.ini << EOF
[common]
server_addr = frp服务器地址
server_port = 7000
admin_addr = 127.0.0.1
admin_port = 7400
token = frp通信密钥
[lxc-centos-ssh]
type = tcp
local_ip = 内网ip地址
local_port = 内网ip端口
remote_port = 远程端口
EOF
cat >> /etc/systemd/system/frpc.service << EOF
[Unit]
Description=frp clien.
After=network.target
[Service]
Type=simple
Restart=always
ExecStart=/usr/bin/frpc -c /etc/frp/frpc.ini
[Install]
WantedBy=multi-user.target
EOF
systemctl enable frpc
systemctl start frpc
Linux服务器可以使用curl -o文件名 "下载地址"
下载,选择合适cpu架构的可执行程序。下载地址可以浏览器中点击右键复制下载地址获得。
按照提示将终端生成的URL复制到浏览器中访问,完成登陆认证。登陆认证完成后客户端证书会自动下载到服务器。
cloudflared tunnel login
此操作cf会自动为你的域名创建子域名的CNAME记录,并将结果解析到cf的隧道主机。
cloudflared tunnel create 隧道名称
cloudflared tunnel route dns 隧道名称 子域名
#cloudflared tunnel route dns lxc-tunnel aaabbb.rubitcat.cn
cat >> ~/.cloudflared/config.yml << EOF
tunnel: 你的隧道ID 例如 58ef03bb-6d61-47e9-b903-b771550c02e6
credentials-file: 你的隧道认证文件 例如~/.cloudflared/58ef03bb-6d61-47e9-b903-b771550c02e6 .json
protocol: http2
originRequest:
connectTimeout: 30s
noTLSVerify: false
ingress:
- hostname: 服务子域名
service: 内网服务,该服务不一定需要部署在运行cloudflared的机器上,例如https://192.168.3.33:2300
- hostname: ... 多条服务开多个数组记录
service: ...
- service: http_status:404
EOF
cloudflared --config 隧道配置文件 tunnel run 隧道名