#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


---
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`：
``` 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 <your_home_ip> 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 端口被劫持
