20 KiB
#vps #caddy #frp #reverse-proxy #troubleshooting #cloudflare
思路:Aliyun 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 控制台管理) -
内网服务:
-
NAS:
192.168.3.17:5000(对应nas.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)
-
-
你有一台公网 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 步:阿里云 DNS 配置
进入阿里云控制台 → 域名解析:
| 主机记录 | 记录类型 | 记录值 | TTL |
|---|---|---|---|
| nas | A | 192.227.222.142 | 600 |
| n8n | A | 192.227.222.142 | 600 |
保存即可。
验证命令(任意机器执行):
`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
Caddy 安装后会自动作为系统服务运行。
2️⃣ 安装 frps(frp 服务端)
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
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, log, reverse-proxy, troubleshooting, vps]
---
---
title: 前置共识(已知条件)
source:
author: shenwei
published:
created:
description:
tags: [caddy, cloudflare, frp, log, reverse-proxy, troubleshooting, 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 # Ubuntu SSH
sudo ufw allow 60023 # NAS 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
如果你想让 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️⃣ 安装 frps(frp 服务端)
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
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 = 60055
创建 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
创建 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
}
n8n.ishenwei.online {
reverse_proxy 127.0.0.1:15678
#log {
# output file /var/log/caddy/n8n.access.log
# format single_field common_log
#}
}
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
}
# 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
✔ 第 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 端口被劫持