Files
nexus/knowledgebase/通过VPS+FRP+Caddy实现内网穿透域名访问.md
2026-06-04 15:43:50 +08:00

1169 lines
28 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: 通过 VPS + FRP + Caddy 实现内网穿透域名访问
author: shenwei
created: 2026-06-04
updated: 2026-06-04
tags: [vps, caddy, frp, reverse-proxy, cloudflare, aliyun, ubuntu, troubleshooting, toml]
---
#vps #caddy #frp #reverse-proxy #troubleshooting #cloudflare #aliyun #ubuntu #toml #frpc #frps
```table-of-contents
```
# 概述
**核心思路:** DNSCloudflare 或阿里云)将子域名指向公网 VPSVPS 上运行 Caddy 提供 HTTPS 反代;内网主机通过 frp 将本地服务以反向隧道方式暴露到 VPS 的 `127.0.0.1:<某端口>`Caddy 反代到该端口完成最终请求。
**架构组成:**
- **VPS** 运行 `frps`frp 服务端) + `Caddy`HTTPS 反代)
- **每台内网设备** 运行 `frpc`frp 客户端),将本地服务映射到 VPS 的独立端口
- **DNS** 把所有子域名 A 记录指向 VPS 公网 IP
**frp 的优势:** 专为内网穿透设计,支持 NAT 穿透、自动重连、Web Dashboard适合多设备多端口场景。
> ⚠️ **配置格式说明:** 本文档统一使用 frp **TOML 格式**`frps.toml` / `frpc.toml`),不再使用旧版 INI 格式。frp 自 v0.52 起将 TOML 作为推荐格式v0.65 完全采用。如果你旧配置是 `.ini`,请按本文档末尾的 [INI → TOML 迁移对照表](#-ini--toml-迁移对照表) 进行迁移。
---
# 前置共识(已知条件)
- **域名:** `ishenwei.online`DNS 在 Cloudflare 或阿里云控制台管理,本文以 Cloudflare 为主,阿里云步骤类似)
- **公网 VPS** Ubuntu固定公网 IP `192.227.222.142`
- **FRP 版本:** v0.65.0
- **统一 Token** `Gg8sqHJVgh42KQ0oTatMjl6AywWqAzaaT0B77a4qD46tXtoH9j9mXb2k1YitObhs`
- **内网服务清单:**
| 服务 | 内网地址 | 期望公网域名 |
|------|---------|------------|
| NAS DSM | `192.168.3.17:5000` | `nas.ishenwei.online` |
| NAS MySQL | `192.168.3.17:3306` | `mysql.ishenwei.online` |
| Ubuntu1 n8n | `192.168.3.47:5678` | `n8n.ishenwei.online` |
| Ubuntu1 Transmission | `192.168.3.47:9091` | `transmission.ishenwei.online` |
| Ubuntu1 Grafana | `192.168.3.47:3000` | `grafana.ishenwei.online` |
---
# 🧱 拓扑图
```
Internet
┌──────────────────────────────────────┐
│ VPS (192.227.222.142) │
│ - frps 监听 7000 │
│ - Caddy 80 / 443 (TLS) │
│ ├─ nas.ishenwei.online → 127.0.0.1:15000
│ ├─ n8n.ishenwei.online → 127.0.0.1:15679
│ └─ ... │
└──────────────────────────────────────┘
▲ ▲
│ frp tunnel │ frp tunnel
┌───────┴────────┐ ┌───────┴────────┐
│ NAS │ │ Ubuntu1 │
│ 192.168.3.17 │ │ 192.168.3.47 │
│ frpc.toml │ │ frpc.toml │
│ 5000 → 15000 │ │ 9091 → 19091 │
│ 4533 → 14533 │ │ 3000 → 13000 │
│ ... │ │ ... │
└────────────────┘ └────────────────┘
```
---
# 第 1 步DNS 配置
## Cloudflare 配置
进入 Cloudflare Dashboard → DNS
| 主机记录 | 记录类型 | 记录值 | 代理状态 | TTL |
|---------|---------|--------|---------|-----|
| nas | A | 192.227.222.142 | 🚫 DNS only | 600 |
| n8n | A | 192.227.222.142 | 🚫 DNS only | 600 |
| transmission | A | 192.227.222.142 | 🚫 DNS only | 600 |
| grafana | A | 192.227.222.142 | 🚫 DNS only | 600 |
| ubuntu1 | A | 192.227.222.142 | 🚫 DNS only | 600 |
⚠️ **重要:必须关闭 Cloudflare 代理(小灰云)**,使用 DNS only 模式,否则:
- Caddy 申请 Let's Encrypt 证书会失败
- SSH 等非 HTTP/HTTPS TCP 流量无法穿过 Cloudflare
## 阿里云 DNS 配置
进入阿里云控制台 → 域名解析,添加同样的 A 记录即可。
## 验证 DNS
任意机器执行:
```bash
dig nas.ishenwei.online +short
# 应返回 192.227.222.142
```
---
# 第 2 步VPS 安装 Caddy + frps
## 1. 安装 Caddy
```bash
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' \
| sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' \
| sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo chmod o+r /usr/share/keyrings/caddy-stable-archive-keyring.gpg
sudo chmod o+r /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy
```
Caddy 安装后自动注册为 systemd 服务并运行。
## 2. 安装 frp 服务端frps
```bash
cd /opt
sudo mkdir frp && cd frp
FRP_VER=0.65.0
sudo curl -LO https://github.com/fatedier/frp/releases/download/v${FRP_VER}/frp_${FRP_VER}_linux_amd64.tar.gz
sudo tar xzf frp_${FRP_VER}_linux_amd64.tar.gz
# 保留版本目录: /opt/frp/frp_0.65.0_linux_amd64/
```
> 💡 **路径约定**:本文按 [FRP 配置详细笔记](FRP%20配置详细笔记.md) 的约定,所有二进制和配置文件都放在 `/opt/frp/frp_0.65.0_linux_amd64/` 下。
## 3. 创建 `/opt/frp/frp_0.65.0_linux_amd64/frps.toml`
```toml
# ===== 监听配置 =====
bindAddr = "0.0.0.0"
bindPort = 7000
# ===== 认证(必须与所有 frpc 一致)=====
auth.method = "token"
auth.token = "Gg8sqHJVgh42KQ0oTatMjl6AywWqAzaaT0B77a4qD46tXtoH9j9mXb2k1YitObhs"
# ===== 日志 =====
log.to = "/var/log/frps.log"
log.level = "info"
log.maxDays = 7
# ===== 管理 Dashboard =====
webServer.addr = "0.0.0.0"
webServer.port = 7500
webServer.user = "admin"
webServer.password = "StrongPassword123!"
# ===== 安全限制(可选,推荐)=====
allowPorts = [
{ start = 10000, end = 65535 }
]
# 心跳超时(秒)
transport.heartbeatTimeout = 90
```
## 4. 创建 systemd 服务 `/etc/systemd/system/frps.service`
```ini
[Unit]
Description=frp server (frps)
After=network.target
[Service]
Type=simple
ExecStart=/opt/frp/frp_0.65.0_linux_amd64/frps -c /opt/frp/frp_0.65.0_linux_amd64/frps.toml
Restart=on-failure
RestartSec=10
LimitNOFILE=1048576
[Install]
WantedBy=multi-user.target
```
启动并验证:
```bash
sudo systemctl daemon-reload
sudo systemctl enable --now frps
sudo systemctl status frps
ss -ltnp | grep 7000
journalctl -u frps -f
```
## 5. VPS 防火墙配置
```bash
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp # Caddy HTTP
sudo ufw allow 443/tcp # Caddy HTTPS
sudo ufw allow 7000/tcp # frp server 端口
sudo ufw allow 7500/tcp # frp dashboard
sudo ufw allow 60022 # Ubuntu1 SSH
sudo ufw allow 60023 # NAS SSH
sudo ufw allow 60024 # Ubuntu2 SSH
sudo ufw allow 60026 # MacMini SSH
sudo ufw allow 65005 # WebDAV
sudo ufw allow 63307 # NAS MySQL
sudo ufw allow 10080 # NAS Web
sudo ufw allow 12222 # Gitea SSH
sudo ufw enable
sudo ufw status verbose
```
> 💡 如果只想从本地访问 frp dashboard无需开放 7500
> ```bash
> ssh -L 7500:127.0.0.1:7500 ubuntu@192.227.222.142
> ```
> 然后浏览器打开 `http://127.0.0.1:7500`。
---
# 第 3 步:内网设备安装 frpc
## 1. 安装 frp 客户端(每台内网设备执行)
```bash
cd /opt
sudo mkdir frp && cd frp
FRP_VER=0.65.0
# Linux amd64
sudo curl -LO https://github.com/fatedier/frp/releases/download/v${FRP_VER}/frp_${FRP_VER}_linux_amd64.tar.gz
sudo tar xzf frp_${FRP_VER}_linux_amd64.tar.gz
# macOS ARM64 (MacMini M 系列)
# sudo curl -LO https://github.com/fatedier/frp/releases/download/v${FRP_VER}/frp_${FRP_VER}_darwin_arm64.tar.gz
# sudo tar xzf frp_${FRP_VER}_darwin_arm64.tar.gz
```
## 2. 内网 NAS192.168.3.17)配置
创建 `/opt/frp/frp_0.65.0_linux_amd64/frpc.toml`
```toml
# ===== 服务器连接 =====
serverAddr = "192.227.222.142"
serverPort = 7000
auth.method = "token"
auth.token = "Gg8sqHJVgh42KQ0oTatMjl6AywWqAzaaT0B77a4qD46tXtoH9j9mXb2k1YitObhs"
# ===== 日志 =====
log.level = "info"
log.maxDays = 3
log.disablePrintColor = false
# ===== 客户端管理界面(可选)=====
webServer.addr = "127.0.0.1"
webServer.port = 7400
webServer.user = "admin"
webServer.password = "admin"
# ===== NAS DSM: 本地 5000 → VPS :15000 =====
[[proxies]]
name = "nas"
type = "tcp"
localIP = "127.0.0.1"
localPort = 5000
remotePort = 15000
# ===== Navidrome: 本地 4533 → VPS :14533 =====
[[proxies]]
name = "navidrome"
type = "tcp"
localIP = "127.0.0.1"
localPort = 4533
remotePort = 14533
# ===== Calibre: 本地 8083 → VPS :18083 =====
[[proxies]]
name = "calibre"
type = "tcp"
localIP = "127.0.0.1"
localPort = 8083
remotePort = 18083
# ===== WebDAV: 本地 5005 → VPS :65005 =====
[[proxies]]
name = "webdav"
type = "tcp"
localIP = "127.0.0.1"
localPort = 5005
remotePort = 65005
# ===== Miniflux: 本地 8080 → VPS :18080 =====
[[proxies]]
name = "miniflux"
type = "tcp"
localIP = "127.0.0.1"
localPort = 8080
remotePort = 18080
# ===== Zipline: 本地 3333 → VPS :13333 =====
[[proxies]]
name = "zipline"
type = "tcp"
localIP = "127.0.0.1"
localPort = 3333
remotePort = 13333
# ===== NAS SSH: 本地 22 → VPS :60023 =====
[[proxies]]
name = "nas_ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 60023
# ===== NAS MySQL: 本地 3307 → VPS :63307 =====
[[proxies]]
name = "mysql"
type = "tcp"
localIP = "127.0.0.1"
localPort = 3307
remotePort = 63307
# ===== NAS Web: 本地 80 → VPS :10080 =====
[[proxies]]
name = "nas_web"
type = "tcp"
localIP = "127.0.0.1"
localPort = 80
remotePort = 10080
# ===== Jellyfin: 本地 8096 → VPS :18096 =====
[[proxies]]
name = "jellyfin"
type = "tcp"
localIP = "127.0.0.1"
localPort = 8096
remotePort = 18096
# ===== Gitea Web (给 Caddy 反代): 本地 3000 → VPS :13001 =====
[[proxies]]
name = "gitea-web"
type = "tcp"
localIP = "127.0.0.1"
localPort = 3000
remotePort = 13001
# ===== Gitea SSH (直接暴露): 本地 2222 → VPS :12222 =====
[[proxies]]
name = "gitea-ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 2222
remotePort = 12222
```
## 3. 内网 Ubuntu1192.168.3.47)配置
创建 `/opt/frp/frp_0.65.0_linux_amd64/frpc.toml`
```toml
# ===== 服务器连接 =====
serverAddr = "192.227.222.142"
serverPort = 7000
auth.method = "token"
auth.token = "Gg8sqHJVgh42KQ0oTatMjl6AywWqAzaaT0B77a4qD46tXtoH9j9mXb2k1YitObhs"
# ===== 日志 =====
log.level = "info"
log.maxDays = 3
# ===== 客户端管理界面 =====
webServer.addr = "127.0.0.1"
webServer.port = 7400
webServer.user = "admin"
webServer.password = "admin"
# ===== Ubuntu1 SSH: 本地 22 → VPS :60022 =====
[[proxies]]
name = "ubuntu1-ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 60022
# ===== Transmission: 本地 9091 → VPS :19091 =====
[[proxies]]
name = "transmission"
type = "tcp"
localIP = "127.0.0.1"
localPort = 9091
remotePort = 19091
# ===== Grafana: 本地 3000 → VPS :13000 =====
[[proxies]]
name = "grafana"
type = "tcp"
localIP = "127.0.0.1"
localPort = 3000
remotePort = 13000
# ===== Homarr: 本地 7575 → VPS :17575 =====
[[proxies]]
name = "homarr"
type = "tcp"
localIP = "127.0.0.1"
localPort = 7575
remotePort = 17575
# ===== Superset: 本地 8777 → VPS :18777 =====
[[proxies]]
name = "superset"
type = "tcp"
localIP = "127.0.0.1"
localPort = 8777
remotePort = 18777
# ===== TK (生产): 本地 8888 → VPS :18888 =====
[[proxies]]
name = "tk"
type = "tcp"
localIP = "127.0.0.1"
localPort = 8888
remotePort = 18888
# ===== Portainer: 本地 9000 → VPS :19443 =====
[[proxies]]
name = "ubuntu1-portainer"
type = "tcp"
localIP = "127.0.0.1"
localPort = 9000
remotePort = 19443
# ===== STQ: 本地 5173 → VPS :15173 =====
[[proxies]]
name = "stq"
type = "tcp"
localIP = "127.0.0.1"
localPort = 5173
remotePort = 15173
# ===== STQ Admin: 本地 7000 → VPS :17000 =====
[[proxies]]
name = "stq-admin"
type = "tcp"
localIP = "127.0.0.1"
localPort = 7000
remotePort = 17000
# ===== STQ n8n: 本地 62000 → VPS :15678 =====
[[proxies]]
name = "stq-n8n"
type = "tcp"
localIP = "127.0.0.1"
localPort = 62000
remotePort = 15678
```
## 4. 内网 MacMinimacOS ARM64配置示例
创建 `/opt/frp/frp_0.65.0_darwin_arm64/frpc.toml`
```toml
serverAddr = "192.227.222.142"
serverPort = 7000
auth.method = "token"
auth.token = "Gg8sqHJVgh42KQ0oTatMjl6AywWqAzaaT0B77a4qD46tXtoH9j9mXb2k1YitObhs"
log.level = "info"
log.maxDays = 3
webServer.addr = "127.0.0.1"
webServer.port = 7400
webServer.user = "admin"
webServer.password = "admin"
[[proxies]]
name = "macmini-ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 60026
[[proxies]]
name = "n8n"
type = "tcp"
localIP = "127.0.0.1"
localPort = 5678
remotePort = 15679
[[proxies]]
name = "vaultwarden"
type = "tcp"
localIP = "127.0.0.1"
localPort = 5151
remotePort = 15151
[[proxies]]
name = "it-tools"
type = "tcp"
localIP = "127.0.0.1"
localPort = 8999
remotePort = 18999
[[proxies]]
name = "drawio"
type = "tcp"
localIP = "127.0.0.1"
localPort = 8085
remotePort = 18085
```
> 💡 **MacMini 一般通过 tmux 运行 frpc**(非 systemd见 [FRP 配置详细笔记](FRP%20配置详细笔记.md)。
## 5. 创建 frpc systemd 服务Linux
创建 `/etc/systemd/system/frpc.service`
```ini
[Unit]
Description=frp client
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/opt/frp/frp_0.65.0_linux_amd64/frpc -c /opt/frp/frp_0.65.0_linux_amd64/frpc.toml
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
```
启动:
```bash
sudo systemctl daemon-reload
sudo systemctl enable --now frpc
sudo systemctl status frpc
```
修改配置后重启:
```bash
sudo systemctl restart frpc
sudo journalctl -u frpc -n 50
```
---
# 第 4 步VPS 上配置 Caddy 反向代理
编辑 `/etc/caddy/Caddyfile`
```caddy
# 默认 :80 站点(可保留作为占位)
:80 {
root * /usr/share/caddy
file_server
}
# ============== 内网服务反代 ==============
nas.ishenwei.online {
reverse_proxy 127.0.0.1:15000
}
n8n.ishenwei.online {
reverse_proxy 127.0.0.1:15679
}
transmission.ishenwei.online {
reverse_proxy 127.0.0.1:19091
}
grafana.ishenwei.online {
reverse_proxy 127.0.0.1:13000
}
navidrome.ishenwei.online {
reverse_proxy 127.0.0.1:14533
}
calibre.ishenwei.online {
reverse_proxy 127.0.0.1:18083
}
dashboard.ishenwei.online {
reverse_proxy 127.0.0.1:17575
}
miniflux.ishenwei.online {
reverse_proxy 127.0.0.1:18080
}
zipline.ishenwei.online {
reverse_proxy 127.0.0.1:13333
}
superset.ishenwei.online {
reverse_proxy 127.0.0.1:18777
}
tk.ishenwei.online {
reverse_proxy 127.0.0.1:18888
}
tk-dev.ishenwei.online {
reverse_proxy 127.0.0.1:18889
}
jellyfin.ishenwei.online {
reverse_proxy 127.0.0.1:18096
}
vaultwarden.ishenwei.online {
reverse_proxy 127.0.0.1:15151
}
it-tools.ishenwei.online {
reverse_proxy 127.0.0.1:18999
}
drawio.ishenwei.online {
reverse_proxy 127.0.0.1:18085
}
# Gitea (需大文件支持以支持 git push)
gitea.ishenwei.online {
reverse_proxy 127.0.0.1:13001
request_body {
max_size 5GB
}
}
web.ishenwei.online {
reverse_proxy 127.0.0.1:10080
}
```
## 验证 Caddyfile 语法
```bash
sudo caddy validate --config /etc/caddy/Caddyfile
```
返回 `Valid configuration` 即成功;否则会指出具体行号。
## 重启 / 重载 Caddy
```bash
# 优雅重载(推荐)
sudo systemctl reload caddy
sudo systemctl status caddy
# 强制重启
sudo systemctl restart caddy
# Caddy 卡死时的强制清理
sudo systemctl stop caddy
sudo pkill -9 caddy
sudo systemctl start caddy
```
Caddy 会自动申请并续期 Let's Encrypt 证书,无需人工干预。
---
# 第 5 步:验证测试
## 1. 在 VPS 上验证 frp 隧道
```bash
# 测试本地端口连通
curl http://127.0.0.1:15679 # n8n
curl http://127.0.0.1:15000 # nas
curl http://127.0.0.1:19091 # transmission
curl http://127.0.0.1:13000 # grafana
# 查看 frps 是否在监听对应端口
ss -ltnp | egrep '15679|19091|13000|7000|60022'
```
预期:
```
LISTEN 0 4096 *:19091 *:* users:(("frps",pid=59421,fd=10))
LISTEN 0 4096 *:13000 *:* users:(("frps",pid=59421,fd=8))
LISTEN 0 4096 *:15679 *:* users:(("frps",pid=59421,fd=9))
LISTEN 0 4096 *:7000 *:* users:(("frps",pid=59421,fd=6))
```
## 2. 浏览器验证 HTTPS
访问:
- https://nas.ishenwei.online
- https://n8n.ishenwei.online
- https://transmission.ishenwei.online
- https://grafana.ishenwei.online
应能通过 HTTPS 正常打开,证书自动签发。
---
# 第 6 步SSH 穿透(特殊场景)
## 重要SSH 不经 Caddy
⚠️ SSH 是纯 TCP 流量,**Caddy 不参与代理**Caddy 只处理 HTTP/HTTPS。SSH 穿透仅由 `frps + frpc` 完成,**Caddyfile 无需修改**。
## SSH 拓扑
```
外部 SSH 客户端
ubuntu1.ishenwei.online:60022 ← VPS 公网入口
frpsVPS
frpc192.168.3.47
本地 SSH (192.168.3.47:22)
```
## 配置步骤
**1. `frpc.toml` 中已包含 SSH 映射段:**
```toml
[[proxies]]
name = "ubuntu1-ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 60022
```
**2. 重启 frpc 并验证:**
```bash
sudo systemctl restart frpc
sudo systemctl status frpc
sudo journalctl -u frpc -n 50 | grep "start proxy success"
```
成功日志:
```
[ubuntu1-ssh] start proxy success
```
**3. 外部 SSH 连接:**
```bash
ssh -p 60022 user@ubuntu1.ishenwei.online
```
> 注意DNS 只解析 IP**必须显式指定端口 `-p 60022`**。
**4. 推荐:配置 SSH config 简化连接**
`~/.ssh/config`
```
Host ubuntu1
HostName ubuntu1.ishenwei.online
Port 60022
User ishenwei
IdentityFile ~/.ssh/id_ed25519
```
之后直接 `ssh ubuntu1` 即可。
---
# 第 7 步frp Dashboard可选
浏览器访问:
```
http://192.227.222.142:7500
用户名admin
密码StrongPassword123!
```
可实时查看:
- 各 frpc 客户端的连接状态
- 每个代理隧道的流量统计
- 在线/离线状态
---
# 🔒 可选安全加固
## 1. Caddy 基础认证
在某个站点段中加入:
```caddy
n8n.ishenwei.online {
basicauth /* {
admin JDJhJDE0JDN3ZXVhV2YyZG9SY2hvYzVmZ2h3QUlVblpOMU4vS1ptcENrSlhySElMb3l5dytOMkh0Tk93
}
reverse_proxy 127.0.0.1:15679
}
```
生成密码 hash
```bash
caddy hash-password
```
## 2. SSH 安全加固
**(1) 不使用 22 等常见端口**(已用 60022/60023/60024/60026
**(2) 限制来源 IP**
```bash
sudo ufw allow from <your_home_ip> to any port 60022 proto tcp
```
**(3) 禁用密码登录,仅允许公钥认证**
编辑内网机器 `/etc/ssh/sshd_config`
```
PasswordAuthentication no
PubkeyAuthentication yes
```
重启 SSH
```bash
sudo systemctl restart ssh
```
## 3. frps 端口限制
通过 `allowPorts` 限制 frpc 可注册的端口范围,避免恶意 client 抢占低端口:
```toml
allowPorts = [
{ start = 10000, end = 65535 }
]
```
---
# ✅ 配置改动速查表
| 组件 | 是否需要修改 | 说明 |
|------|------------|------|
| **DNS** | ✅ 每个子域名添加 A 记录 → VPS 公网 IP | Cloudflare 必须 DNS only |
| **Caddy** | ✅ HTTP/HTTPS 服务需添加站点段;❌ SSH 不需要 | 不处理 TCP 非 HTTP 流量 |
| **frps (VPS)** | ✅ 一次性配置 `bindPort` + `auth.token` | 后续新增映射无需改 frps |
| **frpc (内网)** | ✅ 每个新服务新增一个 `[[proxies]]` 块 | 修改后 `systemctl restart frpc` |
| **VPS 防火墙** | ✅ 放行所有 `remotePort` | UFW 同时配置 IPv4/IPv6 |
---
# 🛠 错误排查 #troubleshooting
## ✔ 检查代理软件冲突
**NAS 上安装的 V2RayA / Clash 等代理软件可能劫持 frp 流量。**
排查:停止代理软件 → 重启 frpc → 观察日志。
```bash
# 停止代理V2RayA 示例)
sudo systemctl stop v2raya
sudo systemctl restart frpc
sudo journalctl -u frpc -f
```
## ✔ 第 1 步:确认 frps 在监听端口
```bash
ss -lntup | grep 7000
ss -lntup | grep frps
```
预期:
```
tcp LISTEN 0 4096 *:7000 *:* users:(("frps",pid=413014,fd=6))
tcp LISTEN 0 4096 *:7500 *:* users:(("frps",pid=413014,fd=3))
```
如果端口未监听,可能是:
- ❌ 端口被 Caddy/Nginx 占用
- ❌ frps 未绑定 `0.0.0.0`
- ❌ frps 在跑但配置不对
## ✔ 第 2 步:确认 frps 进程加载的配置文件
```bash
ps -ef | grep frps
```
预期:
```
root 413014 1 0 02:23 ? /opt/frp/frp_0.65.0_linux_amd64/frps -c /opt/frp/frp_0.65.0_linux_amd64/frps.toml
```
**常见坑:**
- 编辑了 `frps.toml`,但 systemd 加载的是 `frps.ini`(旧配置遗留)
- 编辑了 `/opt/frp/frps.toml`,但 systemd 实际加载 `/opt/frp/frp_0.65.0_linux_amd64/frps.toml`
- 确认 systemd unit 的 `ExecStart` 路径完全匹配
特别注意 **token 完全一致**(包括无多余空格/换行/编码差异)。
## ✔ 第 3 步:确认防火墙未阻塞 7000
```bash
sudo iptables -L -n
sudo ufw status
sudo firewall-cmd --list-all # 如果用 firewalld
```
需要确保:
- TCP 7000 在 **ACCEPT** 列表
- 没有 One-key 脚本擅自修改 nftables
- 直连 IP 不受 Cloudflare 影响
## ✔ 第 4 步:确认 Caddy 没误代理 7000
```bash
sudo grep -n "7000" /etc/caddy/Caddyfile
```
如存在 `:7000 { reverse_proxy ... }` → 必须删除,否则 frps 无法占用 7000。
## ✔ 第 5 步:检查 frps 日志 token 错误
```bash
sudo journalctl -u frps -n 100 --no-pager
tail -f /var/log/frps.log
```
如出现:
```
authentication failed
token mismatch
invalid login
```
→ token 不一致。重点检查 `frps.toml` 和 `frpc.toml` 的 `auth.token` 是否字符级相同。
## ✔ 第 6 步telnet + journalctl 联合诊断
从 frpc 客户端:
```bash
telnet 192.227.222.142 7000
```
同时在 VPS 上:
```bash
sudo journalctl -u frps -f
```
- **frps 有日志** → 网络通畅,问题在认证/配置层
- **frps 完全无反应** → 请求未到达进程,问题在端口占用 / iptables / SELinux / Caddy 抢端口
## ✔ 第 7 步:强制重启 + 看错误码
VPS
```bash
sudo systemctl restart frps
sudo systemctl status frps
```
内网:
```bash
sudo systemctl restart frpc
sudo systemctl status frpc
sudo journalctl -u frpc -n 50
```
**frpc 错误对照表:**
| 错误日志 | 原因 |
|---------|------|
| `dial tcp 192.227.222.142:7000: connection reset` | 防火墙拦截 |
| `authentication failed` | token 不一致 |
| `wait until server ready` | frps 端口被劫持 |
| `unmarshal config error` | TOML 语法错误(缩进、引号、`[[proxies]]` 双方括号) |
## ✔ 第 8 步TOML 配置语法快速校验
frp 支持直接校验配置:
```bash
/opt/frp/frp_0.65.0_linux_amd64/frpc verify -c /opt/frp/frp_0.65.0_linux_amd64/frpc.toml
/opt/frp/frp_0.65.0_linux_amd64/frps verify -c /opt/frp/frp_0.65.0_linux_amd64/frps.toml
```
输出 `success` 即语法正确。
---
# 🔄 INI → TOML 迁移对照表
如果你有旧的 `frpc.ini`,按下表对照迁移到 `frpc.toml`
| INI 写法 | TOML 写法 |
|---------|----------|
| `[common]` | (顶层,无需 section|
| `server_addr = 1.2.3.4` | `serverAddr = "1.2.3.4"` |
| `server_port = 7000` | `serverPort = 7000` |
| `token = xxx` | `auth.method = "token"`<br>`auth.token = "xxx"` |
| `[nas]` | `[[proxies]]`<br>`name = "nas"` |
| `type = tcp` | `type = "tcp"` |
| `local_ip = 127.0.0.1` | `localIP = "127.0.0.1"` |
| `local_port = 5000` | `localPort = 5000` |
| `remote_port = 15000` | `remotePort = 15000` |
| `dashboard_addr = 0.0.0.0` | `webServer.addr = "0.0.0.0"` |
| `dashboard_port = 7500` | `webServer.port = 7500` |
| `dashboard_user = admin` | `webServer.user = "admin"` |
| `dashboard_pwd = xxx` | `webServer.password = "xxx"` |
| `log_file = /var/log/frps.log` | `log.to = "/var/log/frps.log"` |
| `log_level = info` | `log.level = "info"` |
| `log_max_days = 7` | `log.maxDays = 7` |
**关键差异:**
1. TOML 字符串**必须用双引号**
2. TOML 字段名**驼峰命名**`serverAddr`,不是 `server_addr`
3. 每个代理用 `[[proxies]]`双方括号TOML 数组语法),不是 `[name]`
4. 代理的 `name` 现在是字段,不是 section 名
5. 同名字段使用点号:`auth.token`、`log.level`、`webServer.port`
6. 数字、布尔值不加引号;字符串必须加双引号
## 迁移完整示例
**旧版 frpc.ini**
```ini
[common]
server_addr = 192.227.222.142
server_port = 7000
token = MyToken123
[nas]
type = tcp
local_ip = 127.0.0.1
local_port = 5000
remote_port = 15000
[ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = 60022
```
**新版 frpc.toml**
```toml
serverAddr = "192.227.222.142"
serverPort = 7000
auth.method = "token"
auth.token = "MyToken123"
[[proxies]]
name = "nas"
type = "tcp"
localIP = "127.0.0.1"
localPort = 5000
remotePort = 15000
[[proxies]]
name = "ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 60022
```
## 迁移后必做事项
1. **更新 systemd 服务文件**:把 `ExecStart` 里的 `frpc.ini` 改成 `frpc.toml`
2. **执行 `daemon-reload`** 让 systemd 识别新路径:
```bash
sudo systemctl daemon-reload
sudo systemctl restart frpc
```
3. **校验配置**
```bash
/opt/frp/frp_0.65.0_linux_amd64/frpc verify -c /opt/frp/frp_0.65.0_linux_amd64/frpc.toml
```
4. **观察日志确认所有 proxy 启动成功**
```bash
sudo journalctl -u frpc -n 100 | grep "start proxy success"
```
5. **可选:备份并删除旧的 `.ini` 文件**,避免下次误改:
```bash
sudo mv /opt/frp/frpc.ini /opt/frp/frpc.ini.bak
```
---
# 📚 端口映射总表
> 详细参考 [FRP 配置详细笔记](FRP%20配置详细笔记.md) 中的端口汇总。
| 内网主机 | 内网端口 | VPS 公网端口 | 域名 | 服务 |
|---------|---------|------------|------|------|
| NAS | 5000 | 15000 | nas.ishenwei.online | DSM |
| NAS | 4533 | 14533 | navidrome.ishenwei.online | Navidrome |
| NAS | 8083 | 18083 | calibre.ishenwei.online | Calibre |
| NAS | 5005 | 65005 | — | WebDAV |
| NAS | 8080 | 18080 | miniflux.ishenwei.online | Miniflux |
| NAS | 3333 | 13333 | zipline.ishenwei.online | Zipline |
| NAS | 22 | 60023 | — | SSH |
| NAS | 3307 | 63307 | — | MySQL |
| NAS | 80 | 10080 | web.ishenwei.online | Web |
| NAS | 8096 | 18096 | jellyfin.ishenwei.online | Jellyfin |
| NAS | 3000 | 13001 | gitea.ishenwei.online | Gitea Web |
| NAS | 2222 | 12222 | — | Gitea SSH |
| MacMini | 22 | 60026 | — | SSH |
| MacMini | 5678 | 15679 | n8n.ishenwei.online | n8n |
| MacMini | 5151 | 15151 | vaultwarden.ishenwei.online | Vaultwarden |
| MacMini | 8999 | 18999 | it-tools.ishenwei.online | IT-Tools |
| MacMini | 8085 | 18085 | drawio.ishenwei.online | Drawio |
| Ubuntu1 | 22 | 60022 | — | SSH |
| Ubuntu1 | 9091 | 19091 | transmission.ishenwei.online | Transmission |
| Ubuntu1 | 3000 | 13000 | grafana.ishenwei.online | Grafana |
| Ubuntu1 | 7575 | 17575 | dashboard.ishenwei.online | Homarr |
| Ubuntu1 | 8777 | 18777 | superset.ishenwei.online | Superset |
| Ubuntu1 | 8888 | 18888 | tk.ishenwei.online | TK |
| Ubuntu1 | 9000 | 19443 | — | Portainer |
| Ubuntu1 | 5173 | 15173 | — | STQ |
| Ubuntu1 | 7000 | 17000 | — | STQ Admin |
| Ubuntu1 | 62000 | 15678 | — | STQ n8n |
| Ubuntu2 | 22 | 60024 | — | SSH |
| Ubuntu2 | 8888 | 18889 | tk-dev.ishenwei.online | TK Dev |
---
# 📎 References
- [frp 官方文档](https://github.com/fatedier/frp)
- [frp TOML 配置示例](https://github.com/fatedier/frp/blob/dev/conf/frpc_full_example.toml)
- [Caddy 官方文档](https://caddyserver.com/docs/)
- [Let's Encrypt](https://letsencrypt.org/)
- 内部文档:[FRP 配置详细笔记](FRP%20配置详细笔记.md)
- 内部文档:[Gitea 完整配置指南SSH + frp + Caddy](Gitea%20完整配置指南SSH%20+%20frp%20+%20Caddy.md)