tunnel-internals

内网穿透原理详解:花生壳 vs Cloudflare 隧道

本文解释本项目实际使用的两条通道各自是怎么工作的完整过程是什么
为什么速度差了 3 倍,以及安全性上有什么差别与风险

最后更新:2026-09-12 | 所有数据来自本机实测


目录

  1. 先搞清楚要解决什么问题
  2. 方案 A:花生壳 HTTPS 映射
  3. 方案 B:Cloudflare 命名隧道
  4. 完整过程逐步对比
  5. 为什么速度差 3 倍
  6. 全面对比表
  7. 安全性对比
  8. 结论:什么时候用哪个

一、先搞清楚要解决什么问题

问题:你家电脑「没有地址」

互联网上的设备要能被访问,需要一个公网 IP。但现实是:

互联网
   │
   ▼
运营商(中国移动/电信)
   │
   ▼
多层 NAT 网关          ← 这里把公网 IP 转换成了私有 IP
   │
   ▼
你家路由器 192.168.44.1
   │
   ▼
你的电脑 192.168.44.4   ← 这个地址只在局域网内有效

192.168.44.4 这个地址在整个互联网上毫无意义——全世界有几亿台设备用着同样的地址段。
外面的请求根本找不到你。

传统解法(本项目不适用)

方法 为什么不用
申请公网 IP 运营商多数已不提供,或要额外付费
路由器端口映射 前提是你已经有公网 IP
云服务器中转 要花钱、要维护、要考虑备案

内网穿透的核心思路

既然「外面进不来」,那就让「里面主动出去」。

① 你的电脑主动连出去,连到一个有公网 IP 的服务器
② 这条连接建立后一直保持不断(长连接)
③ 有人访问那个服务器的某个地址时,服务器顺着这条已建立的连接
   把请求「反向」送回来

这个「反向送回来」就是内网穿透(也叫反向隧道)。

关键点:因为连接是你的电脑主动发起的,所以:

  • 不需要公网 IP ✓
  • 不需要改路由器 ✓
  • 防火墙通常也不会拦(出站连接一般放行)✓

花生壳和 Cloudflare 都是这个思路,差别在于「中间那台服务器」是谁的、在哪、用什么协议。


二、方案 A:花生壳 HTTPS 映射

2.1 角色分工

你的电脑                    花生壳服务器(阿里云·杭州)           手机
─────────                   ──────────────────────              ─────
HskDDNS 客户端  ──长连接──►  115.236.153.177
                             证书: *.vicp.fun (DigiCert)
                             地址: xxx.vicp.fun

2.2 建立阶段(只需一次,之后一直保持)

1. 你在电脑上启动「花生壳客户端」并登录
2. 客户端读到配置:映射 127.0.0.1:51194 → https://xxx.vicp.fun
3. 客户端主动向花生壳服务器发起 TCP 长连接(心跳保活)
4. 花生壳服务器登记:「这条连接对应 xxx.vicp.fun」
5. 花生壳把 xxx.vicp.fun 的 DNS 解析指向自己的服务器

这一步完成后,通道就「架」好了——之后只要客户端不退出,通道一直在。

实测观察:客户端进程 HskDDNS.exe 只在本地有回环连接,实际的长连接
由配套服务进程维持。用 Get-NetTCPConnection 看不到明显的对外连接,
但公网确实可达——说明它用的是自己的一套保活机制。

2.3 访问阶段(每次请求都走一遍)

 手机                花生壳服务器              你的电脑
  │                     │                      │
  │ ① DNS 查询           │                      │
  │ xxx.vicp.fun ───────►│                      │
  │ ◄─── 115.236.153.177 │                      │
  │                     │                      │
  │ ② TLS 握手(在这里终止)                     │
  │ ◄══════════════════►│  *.vicp.fun 证书      │
  │                     │                      │
  │ ③ HTTPS 请求         │                      │
  │ GET /api/health ───►│                      │
  │                     │ ④ 顺着已建的长连接     │
  │                     │    反向转发 HTTP 请求  │
  │                     │─────────────────────►│
  │                     │                      │ ⑤ 转发到
  │                     │                      │  127.0.0.1:51194
  │                     │                      │
  │                     │◄─────────────────────│ ⑥ 响应
  │ ◄───────────────────│ ⑦ 原路返回            │

注意第 ② 步:TLS(HTTPS 加密)是在花生壳的服务器上终止的。

也就是说:手机到花生壳服务器这一段是加密的,花生壳服务器到你家电脑那一段
是他们自己的通道
。所以花生壳在技术上「看得见」你的明文 HTTP 流量
(虽然他们声称不做记录)。

2.4 关键特征

特征 说明
连接方向 你的电脑 → 花生壳服务器(出站)
中间节点 1 跳,国内阿里云杭州
传输协议 私有协议(TCP 长连接 + 心跳)
TLS 终止点 花生壳服务器
证书 他们的泛域名证书 *.vicp.fun(DigiCert 签发)
域名归属 花生壳(你只是用它的子域)
公网端口 443(固定)

三、方案 B:Cloudflare 命名隧道

3.1 角色分工

你的电脑                        Cloudflare 边缘网络             手机
─────────                      ──────────────────────         ─────
cloudflared ──QUIC──►  任播 IP (172.67.x / 104.21.x)
                       全球数百个节点,就近接入
                       证书: 你的域名 (Let's Encrypt)

3.2 建立阶段

1. 你运行 cloudflared tunnel run yunzhangben
2. cloudflared 读取配置:
     隧道 ID  7d02623e-45a4-4eb9-b55c-6fcff81f7ad7
     入口     jz.dlink.work → http://127.0.0.1:51194
3. cloudflared 主动向 Cloudflare 边缘发起 **4 条 QUIC 连接**
     (UDP 7844 端口,出站)
     实测注册到:lax05 / lax08 / lax10 / lax11 / sjc05 / sjc07 ...
4. Cloudflare 登记:「隧道 7d02623e... 的入口是 jz.dlink.work」
5. 之前已通过 API 建好的 DNS 记录生效:
     jz.dlink.work  CNAME → 7d02623e-....cfargotunnel.com

为什么是 4 条连接? 冗余。某条抖动时流量自动切到其他连接,不用重连。

为什么用 QUIC(UDP)而不是 TCP?第五节

3.3 访问阶段

 手机              Cloudflare 边缘(就近节点)        你的电脑
  │                     │                             │
  │ ① DNS 查询           │                             │
  │ jz.dlink.work ──────►│                             │
  │ ◄── 任播 IP(就近)   │                             │
  │                     │                             │
  │ ② TLS 握手(边缘终止) │                             │
  │ ◄══════════════════►│ 你的域名证书                  │
  │                     │                             │
  │ ③ HTTPS 请求         │                             │
  │ GET /api/health ───►│                             │
  │                     │ ④ 按 Host 找到隧道            │
  │                     │    走已建的 QUIC 连接         │
  │                     │────────────────────────────►│
  │                     │                             │ ⑤ 转发到
  │                     │                             │  127.0.0.1:51194
  │                     │◄────────────────────────────│ ⑥ 响应
  │ ◄───────────────────│ ⑦ 原路返回                   │

结构上和花生壳几乎一样,差别全在细节:

  • 中间节点从「1 台国内服务器」变成「全球任播网络」
  • 传输协议从「TCP 私有协议」变成「QUIC」
  • TLS 终止点从「花生壳」变成「Cloudflare 边缘(同样不是你的电脑)」

3.4 关键特征

特征 说明
连接方向 你的电脑 → Cloudflare 边缘(出站)
中间节点 就近接入,但你的流量被分到了美国节点
连接数 4 条 QUIC 连接(冗余)
传输协议 QUIC(基于 UDP)
TLS 终止点 Cloudflare 边缘
证书 你自己的域名,Let's Encrypt 自动签发 + 90 天自动续期
域名归属
公网端口 443

四、完整过程逐步对比

以「手机打开 https://xxx/api/health」为例,把两条路的每一步并排列出来:

步骤 花生壳 Cloudflare 差异
0. 准备工作 客户端登录 → 建映射 tunnel logincreateroute dns → 写 config.yml Cloudflare 步骤多,但要配一次
1. 通道建立 客户端连花生壳服务器 cloudflared 连边缘(4 条 QUIC) 都是出站连接
2. DNS 解析 115.236.153.177(阿里云·杭州) 172.67.186.66(Cloudflare 任播) 解析速度都很快(<50ms)
3. 就近接入 固定一台服务器 任播,理论上就近 ⚠️ 实测被分到 lax/sjc(美国)
4. TLS 握手 花生壳服务器终止 Cloudflare 边缘终止 结构相同,都在中间终止
5. 证书 *.vicp.fun(他们的) dlink.work(你的) 浏览器都显示 🔒
6. 请求转发 走私有长连接回国 走 QUIC 跨境到美国 ⚠️ 这一步决定了延迟差异
7. 回源 127.0.0.1:51194 127.0.0.1:51194 完全相同
8. 响应返回 原路回国 原路跨境 ⚠️ 同上
9. 数据落地 你本机 SQLite 你本机 SQLite 完全相同

结论:两条路的结构几乎一模一样,都是「出站长连接 + 中间终止 TLS + 反向转发」。
真正的差别只有两点:

  1. 中间节点在哪(国内 vs 被分到美国)
  2. 用什么协议(TCP 长连接 vs QUIC)

五、为什么速度差 3 倍

实测数据

通道 平均延迟 最快
花生壳 0.452s 0.351s
Cloudflare 1.04s 0.948s
本机直连 0.013s

原因 1:物理距离(主因)

一次请求的完整路径长度:

花生壳:
  手机 → 阿里云杭州 → 你家电脑 → 阿里云杭州 → 手机
        └─ 全程国内,单程约 20~40ms

Cloudflare:
  手机 → 美国 lax/sjc → 你家电脑 → 美国 lax/sjc → 手机
        └─ 跨境,单程约 150~250ms

光速是有限的。跨境链路一来一回,光在光纤里跑就要多花几百毫秒——
这不是技术问题,是物理问题。

实测佐证:花生壳解析到 115.236.153.177(阿里云杭州),
Cloudflare 注册的边缘是 location=lax08 / sjc05(洛杉矶 / 圣何塞)。

原因 2:TCP 与 QUIC 的握手开销

花生壳 Cloudflare
传输层 TCP(已建立的长连接,无需重新握手) QUIC(同样已建立)
首次连接 一次 TCP + TLS 握手 QUIC 自带 TLS 1.3,1-RTT 建连
后续请求 复用长连接,0 额外握手 复用 QUIC 连接,0 额外握手

两者都复用了长连接,所以这一步差别不大。
实测也能看出来:花生壳第 1 次 0.58s,第 2、3 次降到 0.31s(建连开销被摊掉了)。

原因 3:CDN 就近调度没有生效

Cloudflare 的理论优势是「全球任播,用户就近接入」。
但本项目的源站(你的电脑)在中国,而 Cloudflare 在中国大陆没有节点
所以请求最终被调度到了美国。

这样一来就绕了个大圈:

请求:手机(中国) → 美国边缘 → 你家电脑(中国)
响应:你家电脑(中国) → 美国边缘 → 手机(中国)

跨境发生了 2 次(一去一回各 2 段)

对「源站在国内」的场景,Cloudflare 的全球网络反而是负担。

什么情况下 Cloudflare 会更快?

  • 源站在海外、用户也在海外 → Cloudflare 就近接入会明显更快
  • 用户分散在全球 → Cloudflare 优势巨大
  • 本项目的情况(源站在国内、用户在国内)→ 花生壳更优

六、全面对比表

性能

花生壳 Cloudflare 命名隧道
实测延迟 0.31 ~ 0.58 秒 🏆 1.0 ~ 1.2 秒
边缘节点位置 阿里云·杭州 lax08 / sjc05(美国)
带宽 1 Mbps/映射 不限速(受线路影响)
月流量 1 GB 不限
并发连接 5 不限
掉线重连 60 秒(免费版) 自动,多连接冗余
连接冗余 单连接 4 条 QUIC 连接

成本与归属

花生壳 Cloudflare
年成本 ¥0.01(促销价 ¥10(域名)
涨价风险 ⚠️ (促销价不保证) 低(域名价格稳定)
域名 花生壳的子域 你自己的
隧道/映射有效期 按年续费 永久
证书 他们的泛域名证书 你自己的域名证书
证书续期 自动 自动(90 天)

配置与维护

花生壳 Cloudflare
上手难度 ⭐ 图形界面,点几下 ⭐⭐⭐ 命令行 + 域名 + NS 配置
需要域名
需要注册账号 贝锐账号 Cloudflare 账号 + 邮箱验证
需要实名 (国内注册域名)
需要备案
配置文件 客户端里 ~/.cloudflared/config.yml
是否要管理员权限

安全

花生壳 Cloudflare
传输加密 TLS 1.3 TLS 1.3
TLS 终止点 花生壳服务器 Cloudflare 边缘
中间方能否看到明文 理论上可以 理论上可以
是否记录流量 未公开 未公开
数据存储位置 只在你本机 只在你本机

两者在这一点上完全相同:中间方都只转发请求,账本数据始终在你电脑的
data/book.db 里。项目本身做了额外的安全加固(强密码、限流、令牌不进 URL 等)。


七、安全性对比

7.1 先看攻击面:你到底暴露了什么

暴露到公网的:
  ✅ 登录页(用户名 + 密码输入框)
  ✅ 全部 REST API(但都需要令牌)
  ❌ 数据库        —— 不在公网,只在你本机
  ❌ 其他服务      —— 隧道只转发 51194 这一个端口
  ❌ 你的真实 IP   —— 隧道隐藏了家庭宽带 IP

一个容易被忽略的好处:隧道隐藏了你的真实 IP
攻击者只能看到花生壳 / Cloudflare 的 IP,看不到你家宽带的 IP,
也就无法对家庭网络发起直接攻击(端口扫描、DDoS 打你家宽带)。

可发现性对比

花生壳 Cloudflare + 自己的域名
地址 随机子域 1298sg5zx1280.vicp.fun jz.dlink.work
能否被猜到 极难(16 位随机) 子域名 jz 较容易被猜
是否进 CT 日志 ❌ 否(用的是 *.vicp.fun 泛域名证书) ⚠️
隐蔽性 靠「难猜」 靠「密码 + 限流」

什么是 CT 日志:自 2018 年起,所有公开可信 CA 签发的证书必须登记到
公开的 Certificate Transparency 日志,任何人都能查(如 crt.sh)。
你的域名用了 Let's Encrypt 证书,所以 jz.dlink.work 会被公开记录
别人搜 dlink.work 就能发现这个子域。

这不是漏洞,是 HTTPS 的固有特性(任何公开网站都这样)。
但它说明一件事:不能把「域名没人知道」当作安全措施。

7.2 传输链路安全(逐段分析)

两条路都是「三段两跳」:

   手机  ──①──►  中间服务器  ──②──►  你的电脑
         加密                加密
花生壳 Cloudflare
① 手机 → 中间 TLS 1.3(实测) TLS 1.3(实测)
② 中间 → 你的电脑 私有协议加密 QUIC(自带 TLS 1.3)
证书 *.vicp.fun / DigiCert-RapidSSL dlink.work / Let's Encrypt
浏览器警告
证书续期 自动 自动(90 天)

两段都加密,链路上不会被中间人窃听或篡改。

7.3 中间方信任模型:谁能看到什么

手机 ══加密══► 中间服务器 ══加密══► 你的电脑
                    ▲
              在这里解密,能看到明文

因为 TLS 在中间服务器终止,中间方在技术上可以拿到:

  • 你访问了哪些路径(/api/transactions/api/budget/...
  • 请求体内容(记账金额、备注、日期)
  • 登录时提交的用户名和密码(HTTPS 解密后即为明文)

这是所有「中间人转发」架构的共性,不是哪一家的缺陷。

花生壳 Cloudflare
中间方 上海贝锐(国内) Cloudflare(美国)
法律管辖 中国 美国
是否记录流量 未公开说明 未公开说明
账本数据留存 只在你本机 只在你本机

关键区别:中间方能看到「经过的请求」,但看不到你的历史账本 ——
数据始终在你电脑的 data/book.db,只有你主动发起的请求才会经过它们。

如果完全不能接受中间方解密,唯一解法是自建:用云服务器跑 frp,
或者直接把应用部署到自己的服务器上,让 TLS 在你自己机器上终止。
参考 docs/deployment-analysis.md

7.4 ⚠️ 最被忽视的风险:平台账号被盗

这一条比「密码被破解」危险得多,但绝大多数人没想到。

攻击者拿到你的花生壳账号后:
  ① 登录花生壳控制台
  ② 把 xxx.vicp.fun 的映射改成指向「他自己的服务器」
  ③ 他的服务器放一个和云账本一模一样的登录页
  ④ 你打开网址 → 输入密码 → 密码直接进了他手里
  ⑤ 他用真密码登录你的真账本

你完全无法分辨 —— 地址栏、证书(*.vicp.fun 泛域名,换后端照样有效)、
页面外观全都对。

Cloudflare 同理:账号被盗 → 改隧道路由 → 同样可以做钓鱼页。

所以:平台账号的安全等级 ≥ 你的账本密码。

平台 必须做的事
花生壳(贝锐) 强密码 + 开启两步验证(贝锐令牌 App)
Cloudflare 强密码 + 开启 2FA(强烈建议)
阿里云(域名) 强密码 + 开启 2FA + 开启域名转移锁

相关风险:域名过期被抢注。 dlink.work 到期未续费,别人可以注册它 ——
虽然不能直接接管你的隧道(凭证在你手里),但可以搭钓鱼站。
建议开启域名自动续费。

7.5 ⚠️ 局域网侧的明文暴露

这是当前配置里一个真实的、容易被忽略的风险。

云账本监听在 0.0.0.0:51194,即所有网卡。实测:

curl http://192.168.44.4:51194/api/health   # -> HTTP 200,明文 HTTP!

这意味着:电脑连到任何网络,同网段的其他人都能用明文 HTTP 访问云账本
登录密码也是明文传输

场景 风险
家里 Wi-Fi / 自己的手机热点 🟢 低(都是自己的设备)
公司 / 学校网络 🟡 中(同事、IT 可见)
咖啡厅 / 酒店 / 机场 Wi-Fi 🔴 高(同网段有陌生人)

缓解办法(二选一)

# 当前模式:局域网也能访问
双击 start.cmd

# 更安全:只监听 127.0.0.1,局域网访问不到,外部只能走隧道
双击 deploy\start-tunnel.cmd

建议:平时只用手机通过隧道访问的话,start-tunnel.cmd 更安全
需要在电脑上记账时,http://localhost:51194 依然可用。

附带说明:局域网模式下,同一 Wi-Fi 的手机也能用
http://192.168.44.4:51194 绕过 HTTPS 访问
,密码走明文。
在家无所谓,在外面要注意。

7.6 访问控制能力对比

能力 花生壳免费版 Cloudflare 免费版
IP 白名单 ❌ 需付费配件 ✅ 可配(WAF 规则 / Access)
访问密码二次校验 ✅ 可配(Cloudflare Access)
按地区限制
基础 DDoS 防护 ❓ 未说明 ✅ 有
速率限制 ❌(只有映射级 1 Mbps 总带宽) ✅ 可配 Rate Limiting
Bot 防护 ✅ 基础版
隐藏源站 IP

结论Cloudflare 在访问控制上明显更强 —— 免费版就能做 IP 白名单、
邮箱验证登录(Access)、速率限制;花生壳这些基本都要付费。

进阶做法:给 Cloudflare 通道加一层 Cloudflare Access(Zero Trust)
实现「先通过身份验证,才能看到云账本的登录页」——
这样即使密码泄露,攻击者也进不来。

7.7 应用自身做了哪些加固

通道只是「路」,门锁在应用自己身上。 本项目已实现:

加固项 说明
密码散列 scrypt(N=16384, r=8, p=1)+ 随机盐,不可逆
时序攻击防护 timingSafeEqual 比对
密码长度 最小 12 位;拒绝超长输入(防 scrypt DoS)
会话令牌 32 字节随机,数据库只存 SHA-256 散列
令牌不进 URL 只走 Authorization 头,避免落入浏览器历史 / 代理日志 / Referer
登录限流(按 IP) 10 分钟 10 次
登录限流(全局) 10 分钟 50 次,防轮换 IP 绕过
不信任 X-Forwarded-For 防伪造来源绕过限流
安全响应头 CSP / X-Frame-Options / Referrer-Policy / nosniff
CORS 默认同源,不发任何跨域头
审计日志 记录每个写操作(谁、何时、做了什么)
登录设备管理 可查看所有会话并远程下线
自动备份 恢复前还会自动存快照

7.8 风险清单与缓解(按实际可能性排序)

# 风险 可能性 影响 缓解措施 状态
1 密码太弱被暴力破解 🔴 高 12 位以上强密码;应用已有双层限流兜底 ⚠️ 待处理
2 花生壳 / CF 账号被盗 → 钓鱼 🔴 高 平台开两步验证;定期核对映射配置 ⚠️ 待处理
3 局域网明文访问 🟡 中 不需要局域网时改用 start-tunnel.cmd ⚠️ 待处理
4 域名过期被抢注 🟡 中 开启自动续费 + 转移锁 ⚠️ 建议处理
5 中间方记录流量 🟡 中 架构决定,无法缓解;敏感场景改自建 ℹ️ 接受
6 电脑被物理接触 🔴 高 系统登录密码;data\ 目录权限 ✅ 已控制
7 端口被扫描发现 🟢 低 有密码 + 限流;隧道隐藏源站 IP ✅ 已控制
8 子域被 CT 日志公开 🟢 低 不可控,靠密码防护 ℹ️ 已知

7.9 加固清单

按重要性排序,建议逐条完成:

7.10 安全结论

维度 花生壳 Cloudflare 谁更好
传输加密 TLS 1.3 TLS 1.3 平手
隐藏源站 IP 平手
地址可发现性 随机子域,难猜 子域进 CT 日志,可被搜到 花生壳
访问控制(免费版) ❌ 几乎没有 ✅ IP 白名单 / Access / 限速 Cloudflare
DDoS 防护 ❓ 未说明 Cloudflare
账号被盗后的钓鱼风险 平手
中间方可解密 是(国内) 是(美国) 看你的信任偏好
账本数据归属 只在你本机 只在你本机 平手

一句话总结

传输安全上两者相当;访问控制上 Cloudflare 明显更强(能加 IP 白名单和二次验证);
隐蔽性上花生壳更好(子域不进 CT 日志)。

但两者最大的共同风险不在通道技术,而在「密码强度」和「平台账号安全」——
这两点无论用哪条通道、无论用不用隧道,都必须处理。


八、结论:什么时候用哪个

一句话对比

花生壳 = 国内单跳中继,快;Cloudflare = 全球任播网络,稳且自主。

选择建议

你的情况 推荐
人、电脑都在国内,追求速度 花生壳
想要自己的域名、不依赖第三方 Cloudflare
担心第三方涨价/到期 Cloudflare(隧道永久有效)
不想碰命令行、想要开箱即用 花生壳
想要双保险 两个都留(本项目当前做法)

本项目当前做法

主力:花生壳      https://1298sg5zx1280.vicp.fun   0.31 秒
备用:Cloudflare  https://jz.dlink.work            1.07 秒

两个都配了开机自启,互为备用。 花生壳快一倍所以当主力;
一旦花生壳涨价到无法接受,直接切到自己的域名,不会出现「突然用不了」


附:术语表

术语 含义
NAT 网络地址转换,让多台设备共用一个公网 IP,代价是外部无法主动访问内网
公网 IP 互联网上唯一可路由的地址
反向隧道 由内网主动向公网建立连接,再借助这条连接反向传输数据
内网穿透 让外部访问到没有公网 IP 的内网服务
TLS 终止 在哪里解密 HTTPS 流量
任播(Anycast) 同一个 IP 在全球多个节点宣告,用户自动连到最近的
QUIC 基于 UDP 的新一代传输协议,自带加密,建连更快,多路复用无队头阻塞
CNAME DNS 记录类型,把一个域名指向另一个域名
NS 记录 指明某个域名的权威 DNS 服务器是谁
CFargotunnel.com Cloudflare 隧道的内部域名后缀
心跳保活 定期发小包维持长连接不被中间设备断开
posted @ 2026-09-12 12:07  omig001  阅读(8)  评论(0)    收藏  举报