#vps #caddy #frp #reverse-proxy #troubleshooting #cloudflare ```table-of-contents ``` 思路: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](https://nas.ishenwei.online) | → NAS `192.168.3.17:5000` | | [https://n8n.ishenwei.online](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 ``` 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 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 服务端) ``` 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 sudo mv frp_${FRP_VER}_linux_amd64/* /opt/frp/ ``` 创建配置文件 `/opt/frp/frps.ini`: ``` bash [common] bind_addr = 0.0.0.0 bind_port = 7000 # 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`: ``` bash [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 防火墙设置(允许必要端口) ``` bash 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 服务端) ``` 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 sudo mv frp_${FRP_VER}_linux_amd64/* /opt/frp/ ``` ### 3️⃣ 内网 NAS(192.168.3.17)配置 创建 `/opt/frp/frpc.ini`: ``` bash [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`: ``` bash [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 ``` 启动: ``` bash sudo systemctl daemon-reload sudo systemctl enable --now frpc sudo systemctl status frpc ``` 如需重启 ``` bash sudo systemctl restart frpc ``` ### 3️⃣ 内网 Ubuntu(192.168.3.47)配置 创建 `/opt/frp/frpc.ini`: ``` bash [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`: ``` bash [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 ``` 启动: ``` bash sudo systemctl daemon-reload sudo systemctl enable --now frpc sudo systemctl status frpc ``` 如需重启 ``` bash sudo systemctl restart frpc ``` ## 🧩 第 4 步:VPS 上配置 Caddy 反向代理 编辑 `/etc/caddy/Caddyfile`: ``` bash # 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 ``` bash sudo systemctl reload caddy sudo systemctl status caddy ``` 或者: ``` bash #彻底重启 Caddy 服务(强制方式) sudo systemctl restart caddy ``` Caddy 会自动申请并更新 Let's Encrypt 证书,提供 HTTPS 访问。 如果 systemctl 无响应(Caddy 卡死或崩溃) ``` bash 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 上 ``` bash 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://nas.ishenwei.online](https://nas.ishenwei.online) - [https://n8n.ishenwei.online](https://n8n.ishenwei.online) 应能通过 HTTPS 打开对应服务。 ## 🧩 第 6 步:可选安全加固 ### 1️⃣ Caddy 基础认证 在 Caddyfile 的 `n8n.ishenwei.online` 段中加入: ``` bash basicauth /* { admin JDJhJDE0JDN3ZXVhV2YyZG9SY2hvYzVmZ2h3QUlVblpOMU4vS1ptcENrSlhySElMb3l5dytOMkh0Tk93 } ``` > 用 `caddy hash-password` 生成密码散列。 ### 2️⃣ 防火墙 只放行必要端口: ``` bash sudo ufw allow 22,80,443,7000/tcp sudo ufw enable ``` ## 🧩 第 7 步:Dashboard(可选) 访问: ``` bash 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 无需修改**。 ## 🧭 拓扑关系 ``` bash 你(外部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`,在现有配置文件中追加: ``` bash # 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 --- ## 🔒 (可选)安全加固建议 1. **不要直接使用 22 或常见端口**,比如: `remote_port = 26222` 避免被扫描。 2. **限制来源 IP**(仅 VPS 防火墙开放指定来源): `sudo ufw allow from to any port 60022 proto tcp` 3. **使用公钥认证禁用密码登录**: - 编辑 `/etc/ssh/sshd_config` `PasswordAuthentication 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 是否真的在监听端口(排除端口被占用/劫持) ``` bash ss -lntup | grep 7000 ss -lntup | grep frps ``` 结果: ``` bash 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 进程读取的配置是否跟你想的一样 执行: ``` bash ps -ef | grep frps ``` 你要看到类似: ``` bash 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 配置: ``` bash 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 客户端执行: ``` bash telnet 192.227.222.142 7000 ``` 同时在 frps VPS 执行: ``` bash 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 端口被劫持