22 KiB
#vps #caddy #frp #reverse-proxy #troubleshooting #cloudflare #ubuntu
思路:Cloudflare DNS 指向 公网上的一台VPS,VPS 上运行 Caddy;内网主机通过 frp 将服务暴露到 VPS(本地 127.0.0.1 或某个端口),VPS 反向代理到该端口。
- 在 VPS 上运行
frps(frp server)。 - 在每个内网设备运行
frpc(frp client),将本地服务映射到 VPS 上的独立端口或域名映射(frp 支持 http/https 映射,和 subdomain 映射需要 frp 企业/配置域名解析到 VPS)。 - VPS 上的 Caddy 反向代理到 frps 映射端口(127.0.0.1:xxxxx)。
frp 优点:专为内网穿透设计,支持 NAT、自动重连、Web 管理面板(可选)。推荐当你有多台设备和多端口时使用。
!
!
前置共识(已知条件)
-
域名:
ishenwei.online(在阿里云 DNS/Cloudflare 控制台管理) -
内网服务:
- NAS server:
192.168.3.17:5000(对应nas.ishenwei.online) - NAS mysql server:
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)
- NAS server:
-
你有一台公网 VPS(Ubuntu,可用于反代或做中继)IP:
192.227.222.142(固定)
🧭 目标
- 公网 VPS(Ubuntu,公网 IP =
192.227.222.142) - 内网 NAS (
192.168.3.17:5000) - 内网 Ubuntu (
192.168.3.47:5678) - 通过
frp建立安全的反向隧道 - 通过
Caddy在 VPS 上为每个子域名提供 HTTPS 域名访问:
| 域名 | 映射目标 |
|---|---|
| https://nas.ishenwei.online | → NAS 192.168.3.17:5000 |
| https://n8n.ishenwei.online | → Ubuntu 192.168.3.47:5678 |
| 公网VPS(frps服务端) | |
| ↓(公网端口转发) | |
| 192.227.222.142 | |
| ↓ | |
| 通过 frp 反向代理访问内网主机 | |
| ↓ | |
| 内网 Ubuntu (192.168.3.47) 启动 frpc | |
| ├─ n8n 服务 (5678) | |
| ├─ Transmission (9091) | |
| └─ Grafana (3000) |
🧱 拓扑图
Internet │ ▼ ┌──────────────────────────┐ │ VPS (192.227.222.142) │ │ - frps (监听 7000) │ │ - Caddy (80/443 TLS) │ │ ├─ nas.ishenwei.online → 127.0.0.1:15000 (映射NAS:5000) │ └─ n8n.ishenwei.online → 127.0.0.1:15678 (映射Ubuntu:5678) └──────────────────────────┘ ▲ ▲ │ frp tunnel │ frp tunnel ┌────────────┐ ┌────────────┐ │ NAS (192.168.3.17) │ │ Ubuntu (192.168.3.47) │ │ frpc.ini │ │ frpc.ini │ │ 映射5000→15000 │ │ 映射5678→15678 │ └────────────┘ └────────────┘
第 1 步:Cloudflare DNS 配置
| 主机记录 | 记录类型 | 记录值 | TTL |
|---|---|---|---|
| nas | A | 192.227.222.142 | 600 |
| n8n | A | 192.227.222.142 | 600 |
| Cloudflare Dashboard -> DNS | |||
!![]() |
保存即可。
验证命令(任意机器执行):
dig nas.ishenwei.online +short # 应返回 192.227.222.142
🧩 第 2 步:在 VPS 安装 Caddy + frps
1️⃣ 安装 Caddy
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
chmod o+r /usr/share/keyrings/caddy-stable-archive-keyring.gpg
chmod o+r /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy
cd Caddy 安装后会自动作为系统服务运行。
2️⃣ 安装 frp(frp 服务端)
# 在 VPS 与内网主机都执行(分别下载到 /opt/frp)
cd /opt
sudo mkdir frp && cd frp
FRP_VER=0.65.0 # 若有更新,可替换版本号
curl -LO https://github.com/fatedier/frp/releases/download/v${FRP_VER}/frp_${FRP_VER}_linux_amd64.tar.gz
tar xzf frp_${FRP_VER}_linux_amd64.tar.gz
sudo mv frp_${FRP_VER}_linux_amd64 /opt/frp
创建配置文件 /opt/frp/frps.ini:
[common]
bind_addr = 0.0.0.0
bind_port = 7000
---
title: 前置共识(已知条件)
author: shenwei
tags: [caddy, cloudflare, frp, reverse-proxy, troubleshooting, ubuntu, vps]
---
---
title: 前置共识(已知条件)
source:
author: shenwei
published:
created:
description:
tags: [caddy, cloudflare, frp, reverse-proxy, troubleshooting, ubuntu, vps]
---
# Dashboard
dashboard_addr = 0.0.0.0
dashboard_port = 7500
dashboard_user = admin
dashboard_pwd = StrongPassword123!
# 认证 Token
token = Gg8sqHJVgh42KQ0oTatMjl6AywWqAzaaT0B77a4qD46tXtoH9j9mXb2k1YitObhs
创建 systemd 单元 /etc/systemd/system/frps.service:
[Unit]
Description=frp server (frps)
After=network.target
[Service]
Type=simple
ExecStart=/opt/frp/frps -c /opt/frp/frps.ini
Restart=on-failure
[Install]
WantedBy=multi-user.target
启动:
sudo systemctl daemon-reload
sudo systemctl enable --now frps
验证:
sudo systemctl status frps
ss -ltnp | grep 7000
3️⃣ VPS 防火墙设置(允许必要端口)
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 7000/tcp # frp server 端口
sudo ufw allow 7050 # frp server dashboard
sudo ufw allow 60022 # Ubuntu1 SSH
sudo ufw allow 60023 # NAS SSH
sudo ufw allow 60024 # Ubuntu2 SSH
sudo ufw allow 65005 # webdav
sudo ufw allow 63306 # NAS mysql
sudo ufw allow 60080 # NAS web
sudo ufw enable
sudo ufw status verbose
运行结果:
To Action From
-- ------ ----
22/tcp (OpenSSH) ALLOW IN Anywhere
80/tcp ALLOW IN Anywhere
443/tcp ALLOW IN Anywhere
7000/tcp ALLOW IN Anywhere
7500/tcp ALLOW IN Anywhere
7050 ALLOW IN Anywhere
60022 ALLOW IN Anywhere
65005 ALLOW IN Anywhere
60023 ALLOW IN Anywhere
60021/tcp ALLOW IN Anywhere
60021/udp ALLOW IN Anywhere
63306 ALLOW IN Anywhere
60080 ALLOW IN Anywhere
60024 ALLOW IN Anywhere
22/tcp (OpenSSH (v6)) ALLOW IN Anywhere (v6)
80/tcp (v6) ALLOW IN Anywhere (v6)
443/tcp (v6) ALLOW IN Anywhere (v6)
7000/tcp (v6) ALLOW IN Anywhere (v6)
7500/tcp (v6) ALLOW IN Anywhere (v6)
7050 (v6) ALLOW IN Anywhere (v6)
60022 (v6) ALLOW IN Anywhere (v6)
65005 (v6) ALLOW IN Anywhere (v6)
60023 (v6) ALLOW IN Anywhere (v6)
60021/tcp (v6) ALLOW IN Anywhere (v6)
60021/udp (v6) ALLOW IN Anywhere (v6)
63306 (v6) ALLOW IN Anywhere (v6)
60080 (v6) ALLOW IN Anywhere (v6)
60024 (v6) ALLOW IN Anywhere (v6)
如果你想让 frp dashboard 从本地访问:ssh -L 7500:127.0.0.1:7500 ubuntu@192.227.222.142,然后本地打开 http://127.0.0.1:7500。
🧩 第 3 步:在 内网NAS服务器 与内网 Ubuntu服务器 安装 frpc
两台机器都执行以下步骤(路径、端口配置不同)
2️⃣ 安装 frp(frp 客户端)
# 在 VPS 与内网主机都执行(分别下载到 /opt/frp)
cd /opt
sudo mkdir frp && cd frp
FRP_VER=0.65.0 # 若有更新,可替换版本号
curl -LO https://github.com/fatedier/frp/releases/download/v${FRP_VER}/frp_${FRP_VER}_linux_amd64.tar.gz
tar xzf frp_${FRP_VER}_linux_amd64.tar.gz
sudo mv frp_${FRP_VER}_linux_amd64 /opt/frp
3️⃣ 内网 NAS(192.168.3.17)配置
创建 /opt/frp/frpc.ini:
[common]
server_addr = 192.227.222.142
server_port = 7000
token = Gg8sqHJVgh42KQ0oTatMjl6AywWqAzaaT0B77a4qD46tXtoH9j9mXb2k1YitObhs
# 每个本地服务一个 section
# nas 映射: 本地 5000 -> VPS 127.0.0.1:15000
[nas]
type = tcp
local_ip = 127.0.0.1
local_port = 5000
remote_port = 15000
# Navidrome: 本地 4533 -> VPS 127.0.0.1:4533
[navidrome]
type = tcp
local_ip = 127.0.0.1
local_port = 4533
remote_port = 14533
# Calibre: 本地 8083 -> VPS 127.0.0.1:18083
[calibre]
type = tcp
local_ip = 127.0.0.1
local_port = 8083
remote_port = 18083
[webdav]
type = tcp
local_ip = 127.0.0.1
local_port = 5005
remote_port = 65005
[miniflux]
type = tcp
local_ip = 127.0.0.1
local_port = 8080
remote_port = 18080
[zipline]
type = tcp
local_ip = 127.0.0.1
local_port = 3333
remote_port = 13333
[nas_ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22
[mysql]
type = tcp
local_ip = 127.0.0.1
local_port = 3307
remote_port = 63307
[nas_web]
type = tcp
local_ip = 127.0.0.1
local_port = 80
remote_port = 10080
创建 systemd 单元 /etc/systemd/system/frpc.service:
[Unit]
Description=frp client
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/opt/frp/frpc -c /opt/frp/frpc.ini
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
启动:
sudo systemctl daemon-reload
sudo systemctl enable --now frpc
sudo systemctl status frpc
如需重启
sudo systemctl restart frpc
3️⃣ 内网 Ubuntu(192.168.3.47)配置
创建 /opt/frp/frpc.ini:
[common]
server_addr = 192.227.222.142
server_port = 7000
token = Gg8sqHJVgh42KQ0oTatMjl6AywWqAzaaT0B77a4qD46tXtoH9j9mXb2k1YitObhs
# 每个本地服务一个 section
# n8n 映射: 本地 5678 -> VPS 127.0.0.1:15678
[n8n]
type = tcp
local_ip = 127.0.0.1
local_port = 5678
remote_port = 15678
# Transmission: 本地 9091 -> VPS 127.0.0.1:19091
[transmission]
type = tcp
local_ip = 127.0.0.1
local_port = 9091
remote_port = 19091
# Grafana: 本地 3000 -> VPS 127.0.0.1:13000
[grafana]
type = tcp
local_ip = 127.0.0.1
local_port = 3000
remote_port = 13000
# 🆕 SSH 映射
[ubuntu_ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = 60022
[homarr]
type = tcp
local_ip = 127.0.0.1
local_port = 7575
remote_port = 17575
[superset]
type = tcp
local_ip = 127.0.0.1
local_port = 8777
remote_port = 18777
[tk]
type = tcp
local_ip = 127.0.0.1
local_port = 8888
remote_port = 18888
创建 systemd 单元 /etc/systemd/system/frpc.service:
[Unit]
Description=frp client
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/opt/frp/frpc -c /opt/frp/frpc.ini
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
启动:
sudo systemctl daemon-reload
sudo systemctl enable --now frpc
sudo systemctl status frpc
如需重启
sudo systemctl restart frpc
🧩 第 4 步:VPS 上配置 Caddy 反向代理
编辑 /etc/caddy/Caddyfile:
# The Caddyfile is an easy way to configure your Caddy web server.
#
# Unless the file starts with a global options block, the first
# uncommented line is always the address of your site.
#
# To use your own domain name (with automatic HTTPS), first make
# sure your domain's A/AAAA DNS records are properly pointed to
# this machine's public IP, then replace ":80" below with your
# domain name.
:80 {
# Set this path to your site's directory.
root * /usr/share/caddy
# Enable the static file server.
file_server
# Another common task is to set up a reverse proxy:
# reverse_proxy localhost:8080
# Or serve a PHP site through php-fpm:
# php_fastcgi localhost:9000
}
transmission.ishenwei.online {
reverse_proxy 127.0.0.1:19091
#log {
# output file /var/log/caddy/transmission.access.log
# format single_field common_log
#}
}
grafana.ishenwei.online {
reverse_proxy 127.0.0.1:13000
#log {
# output file /var/log/caddy/grafana.access.log
# format single_field common_log
#}
}
nas.ishenwei.online {
reverse_proxy 127.0.0.1:15000
}
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
}
web.ishenwei.online {
reverse_proxy 127.0.0.1:10080
}
# Refer to the Caddy docs for more information:
# https://caddyserver.com/docs/caddyfile
如需重启 Caddy
sudo systemctl reload caddy
sudo systemctl status caddy
或者:
#彻底重启 Caddy 服务(强制方式)
sudo systemctl restart caddy
Caddy 会自动申请并更新 Let's Encrypt 证书,提供 HTTPS 访问。
如果 systemctl 无响应(Caddy 卡死或崩溃)
sudo systemctl stop caddy
sudo pkill -9 caddy # 杀掉所有残留进程 sudo systemctl start caddy
验证 Caddyfile 语法(最关键)
sudo caddy validate --config /etc/caddy/Caddyfile
如果返回:
Valid configuration
说明语法正确,可以重载。
如果报错,Caddy 会指明哪一行有问题,例如:
parse error: unknown directive at line 12
你需要根据提示修正。
🧩 第 5 步:测试验证
1️⃣ 在 VPS 上
curl http://127.0.0.1:15678
curl http://127.0.0.1:15000
curl http://127.0.0.1:19091
curl http://127.0.0.1:13000
ss -ltnp | egrep '15678|19091|13000|7000|60022'
root@racknerd-66f115a:~# ss -ltnp | egrep '15678|19091|13000|7000'
LISTEN 0 4096 *:19091 *:* users:(("frps",pid=59421,fd=10))
LISTEN 0 4096 *:13000 *:* users:(("frps",pid=59421,fd=8))
LISTEN 0 4096 *:15678 *:* users:(("frps",pid=59421,fd=9))
LISTEN 0 4096 *:7000 *:* users:(("frps",pid=59421,fd=6))
2️⃣ 在浏览器中
访问:
应能通过 HTTPS 打开对应服务。
🧩 第 6 步:可选安全加固
1️⃣ Caddy 基础认证
在 Caddyfile 的 n8n.ishenwei.online 段中加入:
basicauth /* { admin JDJhJDE0JDN3ZXVhV2YyZG9SY2hvYzVmZ2h3QUlVblpOMU4vS1ptcENrSlhySElMb3l5dytOMkh0Tk93 }
用
caddy hash-password生成密码散列。
2️⃣ 防火墙
只放行必要端口:
sudo ufw allow 22,80,443,7000/tcp
sudo ufw enable
🧩 第 7 步:Dashboard(可选)
访问:
http://192.227.222.142:7500
用户名:admin 密码:StrongPassword123!
你可以实时查看 frp 客户端的连接状态。
FRP 架构已经稳定运行(HTTP 反代验证通过),接下来要实现 通过域名 ubuntu1.ishenwei.online SSH 到内网的 Ubuntu (192.168.3.47:22)。
⚠️ 重点提醒(安全性)
SSH 穿透与 HTTP 不同,它是纯 TCP 流量,不经 Caddy(Caddy 只处理 HTTP/HTTPS),所以:
-
Caddy 不参与 SSH 的代理。
-
只用 frps + frpc 配置即可完成。
-
CaddyFile 无需修改。
🧭 拓扑关系
你(外部SSH客户端)
│
▼
ubuntu1.ishenwei.online:60022 (VPS公网)
│
▼
FRP Server (frps) on VPS
│
▼
FRP Client (frpc) on 192.168.3.47
│
▼
Local Ubuntu SSH (192.168.3.47:22)
🧩 VPS 端(frps)配置
编辑 /opt/frp/frps.ini:
不需要添加新的 section,这里只是定义基础参数。frps 会自动识别来自客户端的 TCP 映射。
🧩 内网 Ubuntu(192.168.3.47)端 frpc 配置
编辑 /opt/frp/frpc.ini,在现有配置文件中追加:
# SSH 映射
[ubuntu_ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = 60022
type = tcp表示这是纯 TCP 代理,不走 HTTP 协议remote_port = 60022是 VPS 上暴露的端口(外部 SSH 连接入口)
🔧 启动并验证
在内网机器上:
sudo systemctl restart frpc
sudo systemctl status frpc
验证日志中是否出现:
[ubuntu_ssh] start proxy success
🌐 在外部电脑上连接 SSH
从公网(任意地方)执行:
ssh -p 60022 user@ubuntu1.ishenwei.online
注意:DNS 只解析到 IP,SSH 的端口要显式指定为
-p 60022。
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 7000/tcp # frp server 端口
sudo ufw allow 7050
sudo ufw allow 60022
sudo ufw enable
sudo ufw status verbose
🔒 (可选)安全加固建议
-
不要直接使用 22 或常见端口,比如:
remote_port = 26222避免被扫描。
-
限制来源 IP(仅 VPS 防火墙开放指定来源):
sudo ufw allow from <your_home_ip> to any port 60022 proto tcp -
使用公钥认证禁用密码登录:
-
编辑
/etc/ssh/sshd_configPasswordAuthentication no -
重启 SSH:
sudo systemctl restart ssh
-
✅ 总结
| 组件 | 是否需要修改 | 说明 |
|---|---|---|
| Caddy | ❌ 无需修改 | 不处理 SSH |
| frps (VPS) | ✅ 保持默认端口即可 | |
| frpc (内网 Ubuntu) | ✅ 新增 [ubuntu_ssh] section |
|
| DNS | ✅ 添加 ubuntu1.ishenwei.online -> VPS公网IP |
|
| SSH 连接 | ✅ 使用 ssh -p 60022 user@ubuntu1.ishenwei.online |
错误排查 #troubleshooting
✔ 检查Server上配置的代理服务器可能会有冲突
NAS上安装的V2RayA 会对FRP有影响,需要停止代理服务器并重启FRPC
✔ 第 1 步:确认 frps 是否真的在监听端口(排除端口被占用/劫持)
ss -lntup | grep 7000
ss -lntup | grep frps
结果:
root@racknerd-66f115a:~# ss -lntup | grep 7000
tcp LISTEN 0 4096 *:7000 *:* users:(("frps",pid=413014,fd=6))
root@racknerd-66f115a:~# 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 在 LISTEN 但不是你期望的配置文件
✔ 第 2 步:确定 frps 进程读取的配置是否跟你想的一样
执行:
ps -ef | grep frps
你要看到类似:
root@racknerd-66f115a:~# ps -ef | grep frps
root 413014 1 0 02:23 ? 00:00:00 /opt/frp/frps -c /opt/frp/frps.ini
root 419007 414182 0 02:57 pts/1 00:00:00 grep --color=auto frps
如果看到:
- 路径不对
- 配置文件不对
- 或者正运行旧版本二进制
那 frps 实际载入的 token、bind_port 等信息就不匹配。
尤其要确认 token 是否是你以为的那个。
👉 很多人遇到的问题是:
他们编辑了 /opt/frp/frps.ini,但 systemd service 其实加载另一个路径,例如 /etc/frp/frps.ini。
✔ 第 3 步:确认防火墙是否把 7000 封了
在 VPS 执行:
sudo iptables -L -n
sudo ufw status
sudo firewall-cmd --list-all
你需要确保:
-
tcp 7000在 ACCEPT -
Cloudflare 没有影响你(你用的是直连 IP,不会影响)
-
Caddy/Nginx 没修改 nftables(某些 One-key 脚本会修改)
✔ 第 4 步:确认没有 Caddy/Nginx 误 proxy 了 TCP 7000
检查 Caddy 配置:
vi /etc/caddy/Caddyfile
是否存在以下配置:
:7000 { reverse_proxy ... }
如果有 → FRP 就没法直接监听这个端口。
✔ 第 5 步:确认 frps 日志是否有拒绝认证(token mismatch)
执行:
journalctl -u frps -n 100 --no-pager
如果你看到类似:
authentication failed token mismatch invalid login
那肯定是 token 和 frpc 不一致。
👉 很多人以为一样,但实际是空格、换行、编码问题导致不一致。
✔ 第 6 步:尝试手动 telnet 登录后观察 frps 日志变化
非常关键的诊断动作
你从任意 frpc 客户端执行:
telnet 192.227.222.142 7000
同时在 frps VPS 执行:
journalctl -u frps -f
正常情况下,你应该看到 frps 有日志反应:
- 有连接建立
- 有 login 请求
如果 frps 完全无反应:
➡ 说明请求没有到达 frps 进程 → 必然是端口被别的服务占用 / iptables 拦截 / SELinux 限制 / Caddy/Nginx 覆盖了端口
✔ 第 7 步:强制重启 frps 和 frpc
在 frps 机器上:
systemctl restart frps
确认状态:
systemctl status frps
在 frpc 机器上:
systemctl restart frpc
systemctl status frpc
journalctl -u frpc -n 50
如果 frpc 日志里直接报:
dial tcp 192.227.222.142:7000: connection reset
➡ 防火墙问题
如果报:
authentication failed
➡ token 不一致
如果:
wait until server ready
➡ frps 端口被劫持
