发布于
1427 字 · 8 分钟

内网穿透

AI 摘要

作者
  • avatar
    姓名
    Corner430
    社交账号
题图

没有公网 IP 时,内网穿透是从外网访问家中设备的必备技术。本文介绍几种主流方案的配置方法。

1 frp

frp 是一款高性能反向代理工具,支持 TCP/UDP/HTTP/HTTPS 协议转发,也支持基于 xtcp 的点对点(P2P)穿透。

1.1 服务端配置(frps)

在有公网 IP 的服务器上部署 frps,配置文件 frps.ini

[common]
bind_port = 7000
token = password
dashboard_port = 7500
dashboard_user = admin
dashboard_pwd = password
vhost_http_port = 10080
vhost_https_port = 10443

启动服务端:

frps -c frps.ini

# 输出示例:
# 2019/01/12 15:22:39 [I] [service.go:130] frps tcp listen on 0.0.0.0:7000
# 2019/01/12 15:22:39 [I] [service.go:172] http service listen on 0.0.0.0:10080
# 2019/01/12 15:22:39 [I] [service.go:193] https service listen on 0.0.0.0:10443
# 2019/01/12 15:22:39 [I] [service.go:216] Dashboard listen on 0.0.0.0:7500
# 2019/01/12 15:22:39 [I] [root.go:210] Start frps success

1.2 客户端配置(frpc)

在内网设备上部署 frpc,配置文件 frpc.ini

[common]
server_addr = 1.1.1.1
server_port = 7000
token= password

[RDP]
type = tcp
local_ip = 127.0.0.1
local_port = 3389
remote_port = 7001

[VNC]
type = tcp
local_ip = 127.0.0.1
local_port = 5900
remote_port = 7002

[SMB]
type = tcp
local_ip = 127.0.0.1
local_port = 445
remote_port = 7003

启动客户端:

./frpc -c frpc.ini

# 输出示例:
# 2019/01/12 16:14:56 [I] [service.go:205] login to server success, get run id [2b65b4e58a5917ac]
# 2019/01/12 16:14:56 [I] [control.go:143] [smb] start proxy success
# 2019/01/12 16:14:56 [I] [control.go:143] [rdp] start proxy success

1.3 开机自启动

Windows:

创建 .vbs 脚本,放入启动文件夹(shell:startup):

set ws=wscript.createobject("wscript.shell")
ws.run "cmd /c C:\frp_0.51.3_windows_amd64\frpc.exe -c C:\frp_0.51.3_windows_amd64\frpc.ini",0

Linux:

创建 systemd 服务:

sudo vim /etc/systemd/system/frpc.service
[Unit]
Description=Frp client
After=network.target

[Service]
Type=simple
ExecStart=/path/to/your/frpc -c /path/to/your/frpc.ini
Restart=always
RestartSec=3

[Install]
WantedBy=multi-user.target

启用服务:

sudo systemctl daemon-reload
sudo systemctl enable frpc.service
sudo systemctl start frpc.service

2 ZeroTier

ZeroTier 是一个虚拟局域网(VLAN)工具,将分布在不同网络的设备组成一个虚拟局域网,实现直连通信。

2.1 安装与加入网络

# 安装
curl -s https://install.zerotier.com | sudo bash

# 加入网络
sudo zerotier-cli join <NETWORK_ID>

# 在 ZeroTier 官网控制台授权该设备

# 查看网络状态
sudo zerotier-cli listnetworks

# 设置开机自启
sudo systemctl enable zerotier-one.service

2.2 部署 Moon(加速节点)

使用 Docker 部署 Moon 服务器,降低中转延迟:

services:
  zerotier-moon:
    image: seedgou/zerotier-moon
    container_name: 'zerotier-moon'
    restart: always
    ports:
      - '9993:9993/udp'
    volumes:
      - ./config:/var/lib/zerotier-one
    entrypoint:
      - /startup.sh
      - '-4'
      - 1.2.3.4 # 替换为服务器的公网 IP

启动后进入容器加入网络:

# 进入容器
docker exec -it zerotier-moon /bin/sh
# 加入网络
zerotier-cli join <NETWORK_ID>
# 在官网授权后退出容器
# 到 ./config 目录下查看 moon.json,复制 id 字段
# 各客户端加入 Moon:
zerotier-cli orbit <MOON_ID> <MOON_ID>

注意:Win11 版本的 ZeroTier 可能存在闪退问题。

2.3 路由器配置(OpenWrt)

现版本 ZeroTier 会自动允许客户端 NAT,无需手动设置防火墙。直接配置路由表,加入 Moon,打上允许自动 NAT 的标签即可。

  1. 创建新接口 创建接口

  2. 设定防火墙 防火墙设置

  3. 配置 ZeroTier 作用域的防火墙 ZeroTier 防火墙

  4. 新增一条防火墙通信规则 通信规则

此时内网设备可以访问外部网络。如果是 IPv6,这条规则不用写,关闭 ZeroTier 的「自动允许客户端 NAT」即可。

  1. 在 ZeroTier Web 控制台写一条路由表 路由表配置

2.4 部署 Planet(自建控制器)

放行端口:3000/tcp3443/tcp9994/tcp9994/udp

services:
  myztplanet:
    image: xubiaolin/zerotier-planet:latest
    container_name: ztplanet
    ports:
      - 9994:9994
      - 9994:9994/udp
      - 3443:3443
      - 3000:3000
    environment:
      - IP_ADDR4=[IPv4 地址]
      - IP_ADDR6=
      - ZT_PORT=9994
      - API_PORT=3443
      - FILE_SERVER_PORT=3000
    volumes:
      - ./data/dist:/app/dist
      - ./data/ztncui:/app/ztncui
      - ./data/one:/var/lib/zerotier-one
      - ./data/config:/app/config
    restart: unless-stopped

配置步骤:

  1. 访问 http://ip:3443 进行配置,初始账号密码 admin/password
  2. 创建网络后通过 Easy Setup 配置 IP 范围
  3. 使用服务端 ./data/dist/planet 替换各客户端的 planet 文件:
    • WindowsC:\ProgramData\ZeroTier\One\planet
    • Linux/var/lib/zerotier-one/planet
    • macOS/Library/Application Support/ZeroTier/One/planet
    • OpenWrt/etc/config/zero/planet
    • Android:使用 ZerotierFix
    • iOS:通过 Android 设备开路由中转
  4. 加入网络并授权

如果已开通 IPv6 且自建 Planet 只支持 IPv4,建议不自建 Planet,改为自建 Moon。

2.5 常见问题

  1. 无法卸载 ZeroTier

    # Ubuntu
    sudo apt remove zerotier-one
    sudo dpkg -P zerotier-one
    sudo rm -rf /var/lib/zerotier-one/
    
    # macOS
    brew uninstall zerotier-one
    sudo rm -rf /Library/Application Support/ZeroTier
    rm -rf ~/Library/Application\ Support/ZeroTier/
    
  2. 踢出后无法重进

    sudo zerotier-cli leave <NETWORK_ID>
    

    然后彻底卸载,重新安装并加入网络。

  3. 切换网络后无法连接 — 搭建 Planet 服务器可解决。

  4. 设备更换后无法连接 — 目前无解,需要创建新的 ZeroTier 网络重新加入。


3 Tailscale

Tailscale 基于 WireGuard 协议,配置比 ZeroTier 更简单。

3.1 路由器运行 Tailscale

tailscale up --netfilter-mode=off --advertise-routes=局域网网段 --accept-routes

配置完成后在路由器上设置防火墙规则。

3.2 自建 DERP 中转服务器

当 Tailscale 官方中转节点延迟较高时,可以自建 DERP 服务器:

# 安装依赖
apt update && apt upgrade
apt install -y wget git openssl curl

# 安装 Go(下载最新版本:https://go.dev/dl/)
wget https://go.dev/dl/go1.20.5.linux-amd64.tar.gz
rm -rf /usr/local/go && tar -C /usr/local -xzf go1.20.5.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin
echo "export PATH=$PATH:/usr/local/go/bin" >> /etc/profile
source /etc/profile

# 配置 Go 环境
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct

# 安装 derper
go install tailscale.com/cmd/derper@main
# 注释掉源码中的域名验证后重新编译
go build -o /etc/derp/derper

# 生成自签名证书
openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes \
  -keyout /etc/derp/derp.myself.com.key \
  -out /etc/derp/derp.myself.com.crt \
  -subj "/CN=derp.myself.com" \
  -addext "subjectAltName=DNS:derp.myself.com"

创建 systemd 服务:

[Unit]
Description=TS Derper
After=network.target
Wants=network.target

[Service]
User=root
Restart=always
ExecStart=/etc/derp/derper -hostname derp.myself.com -a :33445 -http-port 33446 -certmode manual -certdir /etc/derp
RestartPreventExitStatus=1

[Install]
WantedBy=multi-user.target

在 Tailscale ACL 中添加 DERP 配置:

"derpMap": {
    "OmitDefaultRegions": true,
    "Regions": {
        "901": {
            "RegionID": 901,
            "RegionCode": "Myself",
            "RegionName": "Myself Derper",
            "Nodes": [
                {
                    "Name": "901a",
                    "RegionID": 901,
                    "DERPPort": 33445,
                    "IPv4": "服务器IP",
                    "InsecureForTests": true
                }
            ]
        }
    }
}

4 Moonlight + Sunshine(远程串流)

Sunshine 是服务端,Moonlight 是客户端,两者配合可实现低延迟的远程游戏串流。

配合内网穿透工具(如 ZeroTier 或 Tailscale),即使不在同一局域网也能实现远程串流。

版权声明

除非另有说明,本文内容采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处。