最后更新于:2026年08月

⚠️ 重要声明:本文仅从技术研究角度介绍内网穿透技术的工程实现。请在遵守当地法律法规的前提下阅读和应用本文内容。

FRP 内网穿透完全指南
FRP:开源界最成熟的内网穿透方案

家里有 NAS、Home Lab、开发环境,但没有公网 IP?想从外面访问内网的 Nextcloud、Jellyfin、Home Assistant?SSH 反向隧道能用但不稳定,Cloudflare Tunnel 免费但依赖第三方——FRP(Fast Reverse Proxy) 是开源界最成熟的答案。

FRP 是用 Go 语言编写的反向代理工具,专注于内网穿透。它只需要一台有公网 IP 的 VPS 作为中转服务器,就能把内网的 TCP/UDP/HTTP/HTTPS 服务暴露到公网。单二进制部署、跨平台支持、内置 Web Dashboard、TLS 加密、多客户端负载均衡——功能强大但配置极简。

本文将从架构原理、服务端部署、客户端配置、多场景实战到安全加固,全面拆解 FRP v0.61 的生产级用法。


🧭 第一部分:FRP 是什么?

1.1 内网穿透问题

PLAINTEXT
┌──────────────────────────────────────────────────────────┐
│              内网穿透问题                                 │
│                                                          │
│  外部用户                 公网 VPS              你的内网   │
│  (手机/笔记本)            (有公网IP)            (NAS/Home Lab)│
│                                                          │
│  ┌────────┐                                    ┌──────┐ │
│  │ 手机   │──── 想访问 ────×─── NAT/防火墙 ──→│ NAS  │ │
│  └────────┘                 被阻断             └──────┘ │
│                                                          │
│  问题:内网没有公网 IP,外部无法直接访问                  │
│                                                          │
│  解决方案:FRP 反向代理                                  │
│                                                          │
│  ┌────────┐         ┌────────┐         ┌──────┐        │
│  │ 手机   │────────→│  VPS   │←────────│ NAS  │        │
│  └────────┘  公网   │frps    │  隧道   │frpc  │        │
│              访问   │(服务端)│  连接   │(客户端)│        │
│                     └────────┘         └──────┘        │
│                                                          │
│  NAS 主动连接 VPS 建立隧道                               │
│  外部访问 VPS → 隧道转发 → NAS                           │
└──────────────────────────────────────────────────────────┘

1.2 FRP 核心特性

PLAINTEXT
┌──────────────────────────────────────────────────────────┐
│                 FRP 核心特性                             │
│                                                          │
│  📦 极致轻量                                             │
│     ├── Go 语言编写(单二进制文件)                      │
│     ├── 零依赖(不需要运行时环境)                       │
│     ├── 跨平台(Linux/macOS/Windows/ARM)               │
│     └── 配置极简(一个 TOML 文件)                       │
│                                                          │
│  🔗 全协议支持                                           │
│     ├── TCP 代理(任意 TCP 服务)                        │
│     ├── UDP 代理(DNS/游戏/QUIC)                        │
│     ├── HTTP 代理(Web 服务 + 虚拟主机)                 │
│     ├── HTTPS 代理(TLS Web 服务)                       │
│     ├── STCP(安全 TCP,需密钥访问)                     │
│     └── XTCP(P2P 穿透,点对点连接)                     │
│                                                          │
│  ⚡ 高级功能                                             │
│     ├── 内置 Web Dashboard(实时监控)                   │
│     ├── TLS 加密(端到端安全)                           │
│     ├── 负载均衡(多客户端轮询)                         │
│     ├── 健康检查(自动剔除故障节点)                     │
│     ├── 带宽限制(QoS 控制)                             │
│     ├── 端口白名单(安全控制)                           │
│     └── 静态文件服务(HTTP 模式内置)                    │
│                                                          │
│  🛡️ 安全                                                │
│     ├── Token 认证(客户端鉴权)                         │
│     ├── TLS 传输加密                                     │
│     ├── OIDC 认证(企业级)                              │
│     ├── 端口范围限制                                     │
│     └── HTTP Basic Auth                                  │
└──────────────────────────────────────────────────────────┘

1.3 FRP vs 其他内网穿透方案

PLAINTEXT
┌──────────────────────────────────────────────────────────────┐
│        FRP vs Cloudflare Tunnel vs ngrok vs SSH 隧道        │
├──────────────────┬──────┬──────────┬───────┬────────────────┤
│ 特性             │ FRP  │ CF Tunnel│ ngrok │ SSH 隧道       │
├──────────────────┼──────┼──────────┼───────┼────────────────┤
│ 开源             │ ✅   │ ❌        │ 部分  │ ✅             │
│ 需要 VPS         │ ✅   │ ❌        │ ❌     │ ✅             │
│ 自主可控         │ ✅   │ ❌        │ ❌     │ ✅             │
│ TCP 代理         │ ✅   │ ❌        │ 付费  │ ✅             │
│ UDP 代理         │ ✅   │ ❌        │ ❌     │ ❌             │
│ HTTP 虚拟主机    │ ✅   │ ✅        │ ✅     │ ❌             │
│ P2P 穿透         │ ✅   │ ❌        │ ❌     │ ❌             │
│ 自动 HTTPS       │ ❌   │ ✅        │ ✅     │ ❌             │
│ Dashboard        │ ✅   │ ✅        │ ✅     │ ❌             │
│ 负载均衡         │ ✅   │ ❌        │ ❌     │ ❌             │
│ 带宽限制         │ ✅   │ 无限      │ 有限  │ 无             │
│ 延迟             │ 低   │ 中        │ 中    │ 低             │
│ 稳定性           │ 高   │ 高        │ 中    │ 中             │
│ 部署难度         │ ⭐⭐  │ ⭐        │ ⭐    │ ⭐             │
│ 适用场景         │ 通用 │ Web 服务 │ 临时  │ 临时/运维      │
└──────────────────┴──────┴──────────┴───────┴────────────────┘

选型建议:有 VPS 且需要全协议支持 → FRP;无 VPS 只需 Web 穿透 → Cloudflare Tunnel;临时演示 → ngrok;应急使用 → SSH 隧道。


📦 第二部分:安装 FRP

2.1 下载 FRP

BASH
# 查看最新版本
# https://github.com/fatedier/frp/releases

# 下载 FRP v0.61.0(2026年最新稳定版)
# Linux AMD64
wget https://github.com/fatedier/frp/releases/download/v0.61.0/frp_0.61.0_linux_amd64.tar.gz

# Linux ARM64(树莓派/ARM 服务器)
wget https://github.com/fatedier/frp/releases/download/v0.61.0/frp_0.61.0_linux_arm64.tar.gz

# macOS
wget https://github.com/fatedier/frp/releases/download/v0.61.0/frp_0.61.0_darwin_amd64.tar.gz

# Windows
# 从 GitHub Releases 下载 frp_0.61.0_windows_amd64.zip

# 解压
tar -xzf frp_0.61.0_linux_amd64.tar.gz
cd frp_0.61.0_linux_amd64

# 目录结构
# frps        # 服务端二进制
# frps.toml   # 服务端配置
# frpc        # 客户端二进制
# frpc.toml   # 客户端配置

2.2 服务端(frps)安装

BASH
# 复制到系统路径
sudo mkdir -p /etc/frp
sudo cp frps /usr/local/bin/
sudo cp frps.toml /etc/frp/

# 验证
frps --version
# 输出:0.61.0

2.3 客户端(frpc)安装

BASH
# 在内网机器上
sudo cp frpc /usr/local/bin/
sudo cp frpc.toml /etc/frp/

# 验证
frpc --version
# 输出:0.61.0

2.4 Docker 安装

BASH
# 服务端 Docker
docker run -d \
    --name frps \
    --restart=unless-stopped \
    --network=host \
    -v /etc/frp/frps.toml:/etc/frp/frps.toml \
    snowdreamtech/frps:latest

# 客户端 Docker
docker run -d \
    --name frpc \
    --restart=unless-stopped \
    --network=host \
    -v /etc/frp/frpc.toml:/etc/frp/frpc.toml \
    snowdreamtech/frpc:latest

⚙️ 第三部分:服务端配置(frps)

3.1 最简配置

TOML
# /etc/frp/frps.toml

# 服务端监听端口(客户端连接此端口)
bindPort = 7000

# 客户端认证 Token(必须设置!)
auth.token = "your-secret-token-here"

就这 3 行。启动服务端:

BASH
# 前台运行(调试)
frps -c /etc/frp/frps.toml

# 后台运行
nohup frps -c /etc/frp/frps.toml > /var/log/frps.log 2>&1 &

3.2 生产级配置

TOML
# /etc/frp/frps.toml

# === 基础配置 ===
bindPort = 7000                    # 客户端连接端口
bindAddr = "0.0.0.0"              # 监听地址

# HTTP/HTTPS 代理端口(vhostHTTPPort)
vhostHTTPPort = 80                # HTTP 虚拟主机端口
vhostHTTPSPort = 443              # HTTPS 虚拟主机端口

# === 认证配置 ===
auth.token = "your-strong-secret-token-change-me"
# 或使用 OIDC 认证(企业级)
# auth.method = "oidc"
# auth.oidc.issuer = "https://your-oidc-provider"
# auth.oidc.audience = "frp"

# === TLS 配置 ===
transport.tls.force = true         # 强制客户端使用 TLS

# === Dashboard ===
webServer.addr = "0.0.0.0"
webServer.port = 7500
webServer.user = "admin"
webServer.password = "your-dashboard-password"
webServer.pprofEnable = false

# === 端口白名单(安全控制)===
# 只允许客户端映射 6000-6100 和 8080 端口
allowPorts = [
    { start = 6000, end = 6100 },
    { start = 8080, end = 8080 }
]

# === 日志 ===
log.to = "/var/log/frps.log"
log.level = "info"                 # trace/debug/info/warn/error
log.maxDays = 7

# === 性能优化 ===
transport.maxPoolCount = 5          # 最大连接池
transport.heartbeatTimeout = 90    # 心跳超时(秒)

3.3 systemd 服务

INI
# /etc/systemd/system/frps.service
[Unit]
Description=frp Server Service
After=network.target
Wants=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/frps -c /etc/frp/frps.toml
Restart=on-failure
RestartSec=5s
LimitNOFILE=1048576

[Install]
WantedBy=multi-user.target
BASH
# 启用并启动
sudo systemctl daemon-reload
sudo systemctl enable frps
sudo systemctl start frps

# 查看状态
sudo systemctl status frps

# 查看日志
sudo journalctl -u frps -f

3.4 防火墙配置

BASH
# 开放端口
# 7000: frps 客户端连接端口
# 7500: Dashboard 端口
# 6000-6100: 客户端映射端口范围
# 80/443: HTTP/HTTPS 虚拟主机

# UFW
sudo ufw allow 7000/tcp
sudo ufw allow 7500/tcp
sudo ufw allow 6000:6100/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# iptables
sudo iptables -A INPUT -p tcp --dport 7000 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 7500 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 6000:6100 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT

📱 第四部分:客户端配置(frpc)

4.1 最简配置

TOML
# /etc/frp/frpc.toml

# 服务端地址
serverAddr = "your-vps-ip"
serverPort = 7000

# 认证 Token(必须与服务端一致)
auth.token = "your-secret-token-here"

# 代理规则
[[proxies]]
name = "ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 6000

启动客户端:

BASH
# 前台运行
frpc -c /etc/frp/frpc.toml

# 验证连接
# 访问 your-vps-ip:6000 = 访问内网的 22 端口
ssh -p 6000 user@your-vps-ip

4.2 systemd 服务(客户端)

INI
# /etc/systemd/system/frpc.service
[Unit]
Description=frp Client Service
After=network.target
Wants=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/frpc -c /etc/frp/frpc.toml
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target
BASH
sudo systemctl daemon-reload
sudo systemctl enable frpc
sudo systemctl start frpc
sudo systemctl status frpc

🔧 第五部分:多场景实战

5.1 场景一:远程 SSH 访问

TOML
# frpc.toml - SSH 远程访问

serverAddr = "your-vps-ip"
serverPort = 7000
auth.token = "your-secret-token"

[[proxies]]
name = "nas-ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 6000

# 从外网连接
# ssh -p 6000 user@your-vps-ip

5.2 场景二:暴露 Web 服务(HTTP)

TOML
# frpc.toml - HTTP 服务

serverAddr = "your-vps-ip"
serverPort = 7000
auth.token = "your-secret-token"

# Nextcloud
[[proxies]]
name = "nextcloud"
type = "http"
localIP = "127.0.0.1"
localPort = 8080
customDomains = ["nextcloud.example.com"]

# Jellyfin
[[proxies]]
name = "jellyfin"
type = "http"
localIP = "127.0.0.1"
localPort = 8096
customDomains = ["jellyfin.example.com"]

# Home Assistant
[[proxies]]
name = "homeassistant"
type = "http"
localIP = "127.0.0.1"
localPort = 8123
customDomains = ["ha.example.com"]

# 访问方式:
# http://nextcloud.example.com → VPS:80 → 隧道 → 内网 8080
# 需要在 DNS 将 *.example.com 指向 VPS IP

5.3 场景三:HTTPS 服务

TOML
# 方式一:FRP 仅做 TCP 透传,HTTPS 由内网服务处理
[[proxies]]
name = "nextcloud-https"
type = "tcp"
localIP = "127.0.0.1"
localPort = 443
remotePort = 8443
# 访问 https://your-vps-ip:8443

# 方式二:FRP HTTPS 代理(需要证书)
[[proxies]]
name = "nextcloud-https-vhost"
type = "https"
localIP = "127.0.0.1"
localPort = 443
customDomains = ["nextcloud.example.com"]

# 方式三:FRP HTTP + 外部 Caddy/Nginx 处理 TLS
# Caddy 反向代理到 frps 的 vhostHTTPPort
# Caddy 处理 TLS,FRP 只做 HTTP 转发

配合 Caddy 自动 HTTPS

PLAINTEXT
# Caddyfile(VPS 上)
nextcloud.example.com {
    reverse_proxy localhost:80  # frps 的 vhostHTTPPort
}

jellyfin.example.com {
    reverse_proxy localhost:80
}

ha.example.com {
    reverse_proxy localhost:80
}
PLAINTEXT
# 数据流:
# 用户 → Caddy (443/TLS) → frps (80/HTTP) → 隧道 → frpc → 内网服务
# Caddy 负责自动 HTTPS,FRP 负责内网穿透

5.4 场景四:远程桌面(RDP / VNC)

TOML
# Windows RDP
[[proxies]]
name = "windows-rdp"
type = "tcp"
localIP = "127.0.0.1"
localPort = 3389
remotePort = 6001

# macOS VNC (Screen Sharing)
[[proxies]]
name = "macos-vnc"
type = "tcp"
localIP = "127.0.0.1"
localPort = 5900
remotePort = 6002

# 连接方式:
# Windows RDP: your-vps-ip:6001
# macOS VNC:   your-vps-ip:6002

5.5 场景五:UDP 服务(DNS / 游戏)

TOML
# DNS 服务
[[proxies]]
name = "dns"
type = "udp"
localIP = "127.0.0.1"
localPort = 53
remotePort = 6003

# Minecraft 游戏服务器
[[proxies]]
name = "minecraft"
type = "tcp"
localIP = "127.0.0.1"
localPort = 25565
remotePort = 6004

# WireGuard VPN(UDP)
[[proxies]]
name = "wireguard"
type = "udp"
localIP = "127.0.0.1"
localPort = 51820
remotePort = 6005

5.6 场景六:安全 TCP(STCP)

STCP(Secret TCP)比普通 TCP 更安全——访问者也需要运行 frpc 并提供密钥,否则无法连接。

TOML
# === 内网客户端 frpc.toml ===
serverAddr = "your-vps-ip"
serverPort = 7000
auth.token = "your-secret-token"

[[proxies]]
name = "secret-ssh"
type = "stcp"
localIP = "127.0.0.1"
localPort = 22
secretKey = "another-secret-key"   # 访问者需要此密钥

# === 访问者 frpc.toml(在另一台机器上)===
serverAddr = "your-vps-ip"
serverPort = 7000
auth.token = "your-secret-token"

[[visitors]]
name = "ssh-visitor"
type = "stcp"
serverName = "secret-ssh"          # 要访问的 STCP 代理名
secretKey = "another-secret-key"   # 必须与提供者一致
bindAddr = "127.0.0.1"
bindPort = 6000                    # 本地监听端口

# 访问者执行后:
# ssh -p 6000 user@127.0.0.1  →  隧道  →  内网 22 端口
# 没有密钥的第三方无法连接

5.7 场景七:P2P 穿透(XTCP)

XTCP 尝试 NAT 穿透建立点对点连接,不经过 VPS 中转,降低延迟和带宽消耗。如果穿透失败则回退到 STCP 模式。

TOML
# === 内网客户端 frpc.toml ===
[[proxies]]
name = "p2p-ssh"
type = "xtcp"
localIP = "127.0.0.1"
localPort = 22
secretKey = "p2p-secret-key"

# === 访问者 frpc.toml ===
[[visitors]]
name = "p2p-ssh-visitor"
type = "xtcp"
serverName = "p2p-ssh"
secretKey = "p2p-secret-key"
bindAddr = "0.0.0.0"
bindPort = 6001

# 注意:
# - XTCP 不保证穿透成功(取决于 NAT 类型)
# - 对称型 NAT(Symmetric NAT)通常无法穿透
# - 穿透失败时自动回退到 STCP 模式
# - 适合大流量场景(如文件传输、视频流)

5.8 场景八:负载均衡

多个内网客户端提供相同服务,FRP 自动负载均衡:

TOML
# === 客户端 A frpc.toml ===
[[proxies]]
name = "web-lb"
type = "tcp"
localIP = "127.0.0.1"
localPort = 8080
remotePort = 7001
loadBalancer.group = "web"
loadBalancer.groupKey = "web-lb-key"

# === 客户端 B frpc.toml ===
[[proxies]]
name = "web-lb"
type = "tcp"
localIP = "127.0.0.1"
localPort = 8080
remotePort = 7001
loadBalancer.group = "web"
loadBalancer.groupKey = "web-lb-key"

# === 客户端 C frpc.toml ===
[[proxies]]
name = "web-lb"
type = "tcp"
localIP = "127.0.0.1"
localPort = 8080
remotePort = 7001
loadBalancer.group = "web"
loadBalancer.groupKey = "web-lb-key"

# 效果:外部访问 VPS:7001
# FRP 轮询转发到 A、B、C 三台内网机器

5.9 场景九:健康检查

TOML
[[proxies]]
name = "web-with-healthcheck"
type = "tcp"
localIP = "127.0.0.1"
localPort = 8080
remotePort = 7002

# 健康检查
healthCheck.type = "tcp"           # tcp 或 http
healthCheck.timeoutSeconds = 3
healthCheck.maxFailed = 3          # 连续失败 3 次则标记为下线
healthCheck.intervalSeconds = 10   # 每 10 秒检查一次

# HTTP 健康检查
# healthCheck.type = "http"
# healthCheck.path = "/health"
# healthCheck.httpHeaders = ["Host: example.com"]

5.10 场景十:带宽限制

TOML
# 限制单个代理的带宽
[[proxies]]
name = "limited-web"
type = "tcp"
localIP = "127.0.0.1"
localPort = 8080
remotePort = 7003
transport.bandwidthLimit = "10MB"  # 限制 10 MB/s
transport.bandwidthLimitMode = "client"  # 限制客户端上行带宽

# 场景:限制 NAS 下载带宽,避免占满 VPS 带宽

🐳 第六部分:Docker Compose 部署

6.1 服务端 Docker Compose

YAML
# /opt/frp/docker-compose.yml
version: '3.8'

services:
  frps:
    image: snowdreamtech/frps:latest
    container_name: frps
    restart: unless-stopped
    network_mode: host
    volumes:
      - ./frps.toml:/etc/frp/frps.toml:ro
      - ./logs:/var/log/frp
    environment:
      - TZ=Asia/Shanghai
TOML
# /opt/frp/frps.toml
bindPort = 7000
vhostHTTPPort = 80
auth.token = "your-strong-token"
transport.tls.force = true

webServer.addr = "0.0.0.0"
webServer.port = 7500
webServer.user = "admin"
webServer.password = "dashboard-password"

allowPorts = [
    { start = 6000, end = 6100 }
]

log.to = "/var/log/frp/frps.log"
log.level = "info"
log.maxDays = 7

6.2 客户端 Docker Compose

YAML
# /opt/frp/docker-compose.yml
version: '3.8'

services:
  frpc:
    image: snowdreamtech/frpc:latest
    container_name: frpc
    restart: unless-stopped
    network_mode: host
    volumes:
      - ./frpc.toml:/etc/frp/frpc.toml:ro
    environment:
      - TZ=Asia/Shanghai
TOML
# /opt/frp/frpc.toml
serverAddr = "your-vps-ip"
serverPort = 7000
auth.token = "your-strong-token"
transport.tls.enable = true

[[proxies]]
name = "nas-ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 6000

[[proxies]]
name = "nas-web"
type = "http"
localIP = "127.0.0.1"
localPort = 5000
customDomains = ["nas.example.com"]

🔒 第七部分:TLS 加密配置

7.1 为什么需要 TLS?

PLAINTEXT
默认情况下,frpc ↔ frps 的隧道流量未加密
虽然 auth.token 提供了认证,但数据传输是明文的

启用 TLS 后:
  frpc ←── TLS 加密 ──→ frps
  
  外部无法嗅探隧道内的数据
  防止中间人攻击

7.2 启用 TLS

TOML
# === 客户端 frpc.toml ===
serverAddr = "your-vps-ip"
serverPort = 7000
auth.token = "your-secret-token"

# 启用 TLS
transport.tls.enable = true

# 可选:指定 TLS 证书(默认使用自动生成的)
# transport.tls.certFile = "/path/to/client.crt"
# transport.tls.keyFile = "/path/to/client.key"
# transport.tls.trustedCaFile = "/path/to/ca.crt"
# transport.tls.serverName = "frps.example.com"
TOML
# === 服务端 frps.toml ===
# 强制所有客户端使用 TLS(拒绝非 TLS 连接)
transport.tls.force = true

# 可选:指定 TLS 证书
# transport.tls.certFile = "/path/to/server.crt"
# transport.tls.keyFile = "/path/to/server.key"
# transport.tls.trustedCaFile = "/path/to/ca.crt"

7.3 使用自签证书

BASH
# 生成 CA 密钥和证书
openssl genrsa -out ca.key 2048
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt \
    -subj "/CN=FRP-CA"

# 生成服务端密钥和证书
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr \
    -subj "/CN=frps.example.com"
openssl x509 -req -days 3650 -in server.csr -CA ca.crt -CAkey ca.key \
    -CAcreateserial -out server.crt

# 生成客户端密钥和证书
openssl genrsa -out client.key 2048
openssl req -new -key client.key -out client.csr \
    -subj "/CN=frpc-client"
openssl x509 -req -days 3650 -in client.csr -CA ca.crt -CAkey ca.key \
    -CAcreateserial -out client.crt
TOML
# 服务端
transport.tls.force = true
transport.tls.certFile = "/etc/frp/certs/server.crt"
transport.tls.keyFile = "/etc/frp/certs/server.key"
transport.tls.trustedCaFile = "/etc/frp/certs/ca.crt"

# 客户端
transport.tls.enable = true
transport.tls.certFile = "/etc/frp/certs/client.crt"
transport.tls.keyFile = "/etc/frp/certs/client.key"
transport.tls.trustedCaFile = "/etc/frp/certs/ca.crt"
transport.tls.serverName = "frps.example.com"

📊 第八部分:Dashboard 监控

8.1 启用 Dashboard

TOML
# frps.toml
webServer.addr = "0.0.0.0"
webServer.port = 7500
webServer.user = "admin"
webServer.password = "your-dashboard-password"

8.2 Dashboard 功能

PLAINTEXT
访问 http://your-vps-ip:7500

Dashboard 显示:
  ├── 概览
  │   ├── 客户端数量
  │   ├── 代理数量
  │   ├── 流量统计(上行/下行)
  │   └── 连接数
  │
  ├── 代理列表
  │   ├── 代理名称
  │   ├── 类型(TCP/HTTP/UDP/STCP/XTCP)
  │   ├── 状态(在线/离线)
  │   ├── 本地地址
  │   ├── 远程端口
  │   ├── 流量使用
  │   └── 健康检查状态
  │
  └── 客户端列表
      ├── 客户端名称
      ├── 连接时间
      ├── 版本
      └── 代理数量

8.3 客户端 Admin UI

TOML
# frpc.toml - 客户端也可启用本地管理界面
webServer.addr = "127.0.0.1"
webServer.port = 7400
webServer.user = "admin"
webServer.password = "client-admin-password"

# 访问 http://127.0.0.1:7400 查看客户端状态

🛡️ 第九部分:安全加固

9.1 安全配置清单

TOML
# frps.toml - 安全加固配置

# 1. 强制 TLS 加密
transport.tls.force = true

# 2. 设置强 Token
auth.token = "use-a-random-32-char-string"

# 3. 端口白名单(限制客户端可映射的端口)
allowPorts = [
    { start = 6000, end = 6100 }
]

# 4. Dashboard 密码
webServer.addr = "127.0.0.1"      # 仅本地访问(配合 Nginx 反代)
webServer.port = 7500
webServer.user = "admin"
webServer.password = "strong-password"

# 5. 禁用不安全的特性
# 不使用 HTTP 代理(改用 Caddy/Nginx 处理 TLS)
# vhostHTTPPort = 0  # 如果不需要 HTTP 虚拟主机

# 6. 日志审计
log.to = "/var/log/frps.log"
log.level = "info"
log.maxDays = 30

9.2 Dashboard 安全

BASH
# 方案一:Dashboard 只监听 localhost,通过 SSH 隧道访问
# frps.toml
# webServer.addr = "127.0.0.1"

# SSH 隧道访问
ssh -L 7500:127.0.0.1:7500 user@your-vps-ip
# 然后浏览器访问 http://localhost:7500

# 方案二:Caddy/Nginx 反向代理 + Basic Auth
PLAINTEXT
# Caddyfile
frp-dashboard.example.com {
    basic_auth {
        admin $2a$14$...
    }
    reverse_proxy localhost:7500
}

9.3 HTTP 代理安全

TOML
# 为 HTTP 代理添加 Basic Auth
[[proxies]]
name = "protected-web"
type = "http"
localIP = "127.0.0.1"
localPort = 8080
customDomains = ["protected.example.com"]

[proxies.http]
httpUser = "webuser"
httpPassword = "webpassword"

9.4 监控与告警

BASH
# 简单的 FRP 连接监控脚本
#!/bin/bash
# /opt/frp/monitor.sh

FRPS_PORT=7000
ALERT_EMAIL="admin@example.com"

# 检查 frps 是否运行
if ! systemctl is-active --quiet frps; then
    echo "FRPS is down!" | mail -s "FRP Alert" $ALERT_EMAIL
    systemctl restart frps
fi

# 检查端口是否监听
if ! ss -tlnp | grep -q ":$FRPS_PORT "; then
    echo "FRPS port $FRPS_PORT not listening!" | mail -s "FRP Alert" $ALERT_EMAIL
fi

# 添加到 cron
# */5 * * * * /opt/frp/monitor.sh

🌍 第十部分:社区反馈与实战经验

10.1 Reddit 社区讨论摘要

根据 Reddit 相关讨论(r/selfhosted, r/homelab, r/networking, r/sysadmin 等板块)中关于 FRP 的用户反馈整理:

r/selfhosted 用户 u/homelab_builder(2025年底)

“FRP is the gold standard for self-hosted NAT traversal. I’ve been running it for 2 years with zero downtime. The setup is trivial — one TOML file for the server, one for the client. I expose my Nextcloud, Jellyfin, and Home Assistant through a single FRP server. The Dashboard is great for monitoring which proxies are active. The only thing I wish it had was built-in HTTPS (I use Caddy in front for that).”

r/homelab 用户 u/nas_enthusiast(2026年初)

“Tried Cloudflare Tunnel, ngrok, and FRP. FRP wins for full protocol support. Cloudflare Tunnel only does HTTP/HTTPS — can’t do RDP, VNC, or UDP. FRP handles everything. I run frpc on my Synology NAS via Docker, and it just works. The STCP mode is brilliant for sensitive services — only machines with the secret key can connect.”

r/networking 用户 u/network_tinkerer(2026年中)

“The XTCP P2P mode is a hidden gem. When it works (depends on NAT type), you get direct peer-to-peer connection without routing through the VPS. This means zero bandwidth cost on your VPS and lower latency. It doesn’t work with symmetric NAT (common on cellular), but for home broadband it’s usually fine. Falls back to STCP automatically when P2P fails.”

r/sysadmin 用户 u/infra_engineer(2025年底)

“We use FRP for remote access to IoT devices in the field. Each device runs frpc and connects to our frps server. The load balancer feature lets us distribute traffic across multiple devices. Health checks automatically remove failed devices from the pool. The Go binary is perfect for embedded systems — no runtime dependencies, cross-compiled for ARM out of the box.”

10.2 常见使用场景

PLAINTEXT
来自社区的实际使用场景:

1. 家庭 NAS 远程访问
   "Synology NAS + frpc Docker = 从外面访问文件/照片/视频"
   "配合 Caddy 实现 HTTPS,完美替代 QuickConnect"

2. Home Lab 暴露
   "Proxmox VE Web UI、Home Assistant、Grafana 全部通过 FRP 暴露"
   "一个 VPS + FRP = 所有家庭服务的统一入口"

3. 远程开发
   "公司电脑跑 frpc,家里通过 VSCode Remote SSH 连接"
   "比 VPN 更轻量,只暴露需要的端口"

4. IoT 设备管理
   "树莓派 + frpc = 远程 SSH 访问"
   "多个 IoT 设备通过 FRP 负载均衡"

5. 游戏服务器
   "Minecraft 服务器跑在家里,通过 FRP UDP 代理暴露"
   "朋友连接 VPS IP 即可加入游戏"

6. 代理节点中转
   "国内 VPS 跑 frps,海外节点跑 frpc"
   "通过 FRP TCP 代理中转代理流量"

10.3 社区推荐的最佳实践

PLAINTEXT
1. 必须设置 auth.token(不要用默认配置)
2. 启用 TLS 加密(transport.tls.force = true)
3. 设置 allowPorts 端口白名单
4. Dashboard 不要直接暴露到公网
5. HTTP 服务配合 Caddy/Nginx 处理 TLS
6. 敏感服务使用 STCP 模式
7. 大流量场景尝试 XTCP P2P 穿透
8. 启用健康检查自动剔除故障节点
9. 配置带宽限制避免占满 VPS 带宽
10. 定期检查 Dashboard 中的异常连接

📋 第十一部分:故障排除

11.1 常见问题

PLAINTEXT
问题1:客户端无法连接服务端
  原因:
    - VPS 防火墙未开放 7000 端口
    - auth.token 不一致
    - TLS 配置不匹配(服务端 force=true 但客户端未启用)
  解决:
    - 检查防火墙:sudo ufw status
    - 核对 token
    - 客户端添加 transport.tls.enable = true

问题2:TCP 代理无法访问
  原因:
    - remotePort 被占用
    - remotePort 不在 allowPorts 范围内
    - 内网服务未运行
  解决:
    - 检查端口占用:ss -tlnp | grep PORT
    - 检查 allowPorts 配置
    - 确认本地服务可用:curl localhost:localPort

问题3:HTTP 代理 404
  原因:
    - customDomains 未正确解析到 VPS
    - customDomains 配置错误
  解决:
    - DNS 检查:dig example.com
    - 确认域名指向 VPS IP
    - 检查 frpc.toml 中的 customDomains

问题4:连接不稳定/频繁断开
  原因:
    - 心跳超时太短
    - 网络不稳定
  解决:
    - 增加心跳超时:transport.heartbeatTimeout = 90
    - 使用 systemd 自动重启

问题5:XTCP P2P 穿透失败
  原因:
    - 对称型 NAT(Symmetric NAT)
    - 防火墙阻止 UDP
  解决:
    - XTCP 会自动回退到 STCP 模式
    - 检查防火墙是否阻止 UDP
    - 尝试在不同网络环境下使用

11.2 调试命令

BASH
# 前台运行查看日志
frps -c /etc/frp/frps.toml
frpc -c /etc/frp/frpc.toml

# 调试模式
frps -c /etc/frp/frps.toml --log-level debug
frpc -c /etc/frp/frpc.toml --log-level debug

# 查看日志
tail -100 /var/log/frps.log
journalctl -u frps -f
journalctl -u frpc -f

# 检查端口监听
ss -tlnp | grep frp

# 测试连接
# 从客户端测试 VPS 端口
nc -zv your-vps-ip 7000

# 测试代理
curl -v http://your-vps-ip:6000

# 检查 TLS 连接
openssl s_client -connect your-vps-ip:7000

# 验证配置文件
frps verify -c /etc/frp/frps.toml
frpc verify -c /etc/frp/frpc.toml

📋 最佳实践清单

PLAINTEXT
服务端部署:
□ 设置强 auth.token(32+ 字符随机字符串)
□ 启用 transport.tls.force = true
□ 配置 allowPorts 端口白名单
□ Dashboard 设置强密码或仅监听 localhost
□ 配置日志和日志轮转
□ 注册为 systemd 服务
□ 配置防火墙规则

客户端配置:
□ auth.token 与服务端一致
□ 启用 transport.tls.enable = true
□ 只暴露必要的端口
□ 敏感服务使用 STCP 模式
□ 大流量服务配置带宽限制
□ 注册为 systemd 服务或 Docker 容器

安全加固:
□ 使用 TLS 加密隧道
□ Dashboard 不直接暴露公网
□ HTTP 服务配合 Caddy/Nginx 处理 TLS
□ 定期检查 Dashboard 异常连接
□ 设置监控告警
□ 定期更新 FRP 版本

性能优化:
□ 启用健康检查
□ 多节点使用负载均衡
□ 大流量场景尝试 XTCP P2P
□ 配置心跳保活
□ 合理设置连接池大小
□ 限制不必要的带宽占用

运维管理:
□ 配置 systemd 自动重启
□ 定期检查日志
□ 监控 VPS 带宽使用
□ 准备备用 VPS
□ 记录所有代理配置
□ 定期更新到最新版本

结语

FRP 是内网穿透领域最成熟的开源方案——Go 语言单二进制、全协议支持、STCP/XTCP 安全模式、负载均衡、健康检查、Dashboard 监控,功能完整且稳定。配合 Caddy 自动 HTTPS,可以构建一个完全自主可控的远程访问系统。

核心要点回顾:

内网穿透方案选择:

相关文章:

再次提醒:本文仅作技术研究与学习参考,请遵守所在国家和地区的法律法规。内网穿透暴露内网服务到公网时,务必配置 TLS 加密和访问控制。

版权声明

作者: 易邦

链接: https://blog.e8k.net/posts/frp-nat-traversal-complete-guide/

许可证: 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。