docs: 家庭内网远程访问设计方案(frp反向隧道×pangolin×分流DNS) + 文档索引
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>NAS 文档索引</title>
|
||||
<style>
|
||||
:root{
|
||||
--bg:#0f1117; --panel:#171a22; --panel2:#1d2129; --fg:#e6e8ee; --fg2:#a8afbd;
|
||||
--accent:#e0884f; --accent2:#5fb0c9; --ok:#5ec27a; --bad:#e06a6a; --warn:#e0b84f;
|
||||
--border:#272c36; --mono:"SF Mono",ui-monospace,Menlo,Consolas,monospace;
|
||||
--sans:-apple-system,"PingFang SC","Helvetica Neue",Arial,sans-serif;
|
||||
}
|
||||
*{box-sizing:border-box}
|
||||
body{margin:0;background:var(--bg);color:var(--fg);font-family:var(--sans);line-height:1.7;font-size:15px}
|
||||
.wrap{max-width:960px;margin:0 auto;padding:48px 24px 96px}
|
||||
h1{font-size:30px;line-height:1.3;margin:0 0 8px;letter-spacing:-.01em}
|
||||
.sub{color:var(--fg2);font-size:15px;margin:0 0 32px}
|
||||
h2{font-size:21px;margin:44px 0 14px;padding-bottom:8px;border-bottom:1px solid var(--border)}
|
||||
table{width:100%;border-collapse:collapse;margin:16px 0;font-size:14px}
|
||||
th,td{text-align:left;padding:9px 12px;border-bottom:1px solid var(--border);vertical-align:top}
|
||||
th{color:var(--fg2);font-weight:600;font-size:13px}
|
||||
a{color:var(--accent2)}
|
||||
.tag{display:inline-block;font-size:12px;font-weight:600;padding:2px 9px;border-radius:999px;vertical-align:middle}
|
||||
.tag.ok{background:rgba(94,194,122,.16);color:var(--ok)}
|
||||
.tag.warn{background:rgba(224,184,79,.16);color:var(--warn)}
|
||||
code{font-family:var(--mono);font-size:.86em;background:var(--panel2);padding:1px 6px;border-radius:5px;color:#f0d9c4}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrap">
|
||||
<h1>NAS 文档索引</h1>
|
||||
<p class="sub">Synology DS925+(192.168.3.200)运维文档单一入口 · 仓库 <code>~/code/nas</code></p>
|
||||
|
||||
<h2>设计方案</h2>
|
||||
<table>
|
||||
<tr><th>文档</th><th>状态</th><th>说明</th></tr>
|
||||
<tr>
|
||||
<td><a href="remote-access-frp.html">家庭内网远程访问 —— frp 反向隧道 × pangolin × 分流 DNS</a></td>
|
||||
<td><span class="tag warn">待评审</span></td>
|
||||
<td>内外同域名访问 NAS/Windows:frpc(NAS)→frps(pangolin1) 反向隧道 + split-horizon DNS + pangolin 客户端分流</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h2>知识库 / 运维</h2>
|
||||
<table>
|
||||
<tr><th>文档</th><th>状态</th><th>说明</th></tr>
|
||||
<tr>
|
||||
<td><a href="public-access.md">NAS 公网访问(Tailscale 方案)</a></td>
|
||||
<td><span class="tag ok">已上线</span></td>
|
||||
<td>Tailscale 部署记录与踩坑(mihomo fake-ip 劫持等);frp 方案上线后保留作应急后门与部署跳板</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,424 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>家庭内网远程访问方案 —— frp 反向隧道 × pangolin × 分流 DNS</title>
|
||||
<style>
|
||||
:root{
|
||||
--bg:#0f1117; --panel:#171a22; --panel2:#1d2129; --fg:#e6e8ee; --fg2:#a8afbd;
|
||||
--accent:#e0884f; --accent2:#5fb0c9; --ok:#5ec27a; --bad:#e06a6a; --warn:#e0b84f;
|
||||
--border:#272c36; --mono:"SF Mono",ui-monospace,Menlo,Consolas,monospace;
|
||||
--sans:-apple-system,"PingFang SC","Helvetica Neue",Arial,sans-serif;
|
||||
}
|
||||
*{box-sizing:border-box}
|
||||
body{margin:0;background:var(--bg);color:var(--fg);font-family:var(--sans);line-height:1.7;font-size:15px}
|
||||
.wrap{max-width:960px;margin:0 auto;padding:48px 24px 96px}
|
||||
h1{font-size:30px;line-height:1.3;margin:0 0 8px;letter-spacing:-.01em}
|
||||
.sub{color:var(--fg2);font-size:15px;margin:0 0 32px}
|
||||
h2{font-size:21px;margin:44px 0 14px;padding-bottom:8px;border-bottom:1px solid var(--border)}
|
||||
h3{font-size:16px;margin:24px 0 8px;color:var(--fg)}
|
||||
p{margin:10px 0}
|
||||
code{font-family:var(--mono);font-size:.86em;background:var(--panel2);padding:1px 6px;border-radius:5px;color:#f0d9c4}
|
||||
pre{background:#0a0c11;border:1px solid var(--border);border-radius:10px;padding:14px 16px;overflow-x:auto;font-family:var(--mono);font-size:12.5px;line-height:1.55;color:#cdd3df}
|
||||
pre code{background:none;padding:0;color:inherit}
|
||||
.c{color:#6a7385}
|
||||
.k{color:#5fb0c9}
|
||||
.s{color:#9ec97f}
|
||||
.tag{display:inline-block;font-size:12px;font-weight:600;padding:2px 9px;border-radius:999px;vertical-align:middle}
|
||||
.tag.ok{background:rgba(94,194,122,.16);color:var(--ok)}
|
||||
.tag.warn{background:rgba(224,184,79,.16);color:var(--warn)}
|
||||
.tag.info{background:rgba(95,176,201,.16);color:var(--accent2)}
|
||||
.tag.bad{background:rgba(224,106,106,.16);color:var(--bad)}
|
||||
.card{background:var(--panel);border:1px solid var(--border);border-radius:12px;padding:16px 20px;margin:14px 0}
|
||||
.card h3{margin-top:0;color:var(--accent2)}
|
||||
.files{font-family:var(--mono);font-size:12px;color:var(--fg2);margin:6px 0 10px}
|
||||
table{width:100%;border-collapse:collapse;margin:16px 0;font-size:14px}
|
||||
th,td{text-align:left;padding:9px 12px;border-bottom:1px solid var(--border);vertical-align:top}
|
||||
th{color:var(--fg2);font-weight:600;font-size:13px}
|
||||
ul,ol{padding-left:22px;margin:8px 0}
|
||||
li{margin:5px 0}
|
||||
.lead{background:linear-gradient(180deg,rgba(224,136,79,.10),transparent);border:1px solid var(--border);border-radius:12px;padding:18px 20px;margin:0 0 8px}
|
||||
.small{color:var(--fg2);font-size:13px}
|
||||
a{color:var(--accent2)}
|
||||
.back{display:inline-block;margin-bottom:24px;font-size:13px}
|
||||
b{color:#fff}
|
||||
.phase{font-size:19px;margin:40px 0 6px;color:var(--accent);font-weight:700}
|
||||
.diagram{background:var(--panel);border:1px solid var(--border);border-radius:12px;padding:12px;margin:16px 0;overflow-x:auto}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrap">
|
||||
<a class="back" href="index.html">← 文档索引</a>
|
||||
<h1>家庭内网远程访问方案<br>frp 反向隧道 × pangolin × 分流 DNS</h1>
|
||||
<p class="sub">2026-07-15 · <span class="tag warn">设计方案 · 待评审</span> · 相关:<a href="public-access.md">Tailscale 公网访问(现状,保留作应急后门)</a></p>
|
||||
|
||||
<div class="lead">
|
||||
<b>目标:</b>①在家直连内网、不出外网;②在外<b>开着 pangolin</b> 就能穿透回家(不装第二个 VPN 客户端);③内外用<b>同一套地址</b>——<code>git.yanmeiai.com</code>(Forgejo)、<code>nas.yanmeiai.com</code>(DSM/Photos)、<code>win.yanmeiai.com</code>(Windows RDP/SSH)。<br>
|
||||
<b>核心思路:</b>NAS 上的 frpc 主动外连 pangolin1 上的 frps 建反向隧道(家里零开放端口、不暴露家庭 IP);同一批域名<b>公网解析到 pangolin1、家内 DNS 解析到内网 IP</b>(split-horizon);pangolin 客户端配置加一条「这几个域名走本地 DNS、私网结果直连」的分流规则,保证 pangolin 常开时内外自动走对路。
|
||||
</div>
|
||||
|
||||
<h2>1 · 现状盘点(事实依据)</h2>
|
||||
<table>
|
||||
<tr><th>对象</th><th>现状</th><th>与本方案的关系</th></tr>
|
||||
<tr><td><b>NAS</b>(DS925+)</td><td><code>192.168.3.200</code>;跑 Forgejo(<code>:3000</code> HTTP / <code>:2222</code> SSH)、mihomo 透明代理(<code>:53</code> fake-ip DNS / TUN)、Tailscale(<code>100.95.151.13</code>)</td><td>装 frpc;mihomo 加 hosts 覆盖;Tailscale 作本次部署跳板</td></tr>
|
||||
<tr><td><b>Windows</b></td><td><code>192.168.3.88</code>,网关/DNS 均指向 NAS;有 OpenSSH server(<code>ssh windows</code>)</td><td>基本不改;frpc 从 NAS 直接转发其 RDP/SSH</td></tr>
|
||||
<tr><td><b>pangolin1</b></td><td><code>103.119.13.48</code>,Debian 12,2C/1G;<code>:443</code> sing-box REALITY、<code>:8080</code> 控制面(仅 127.0.0.1)、<code>:9443</code> gRPC、cloudflared 出站隧道;ufw 默认拒入站</td><td>装 frps(~20MB 内存);<code>7000/2222/3000/3389/5001/10022/10023</code> 均空闲无冲突</td></tr>
|
||||
<tr><td><b>家宽</b></td><td>有真实公网 IP(动态),路由器无端口映射</td><td>保持零开放端口,不做 DDNS</td></tr>
|
||||
<tr><td><b>DNS</b></td><td><code>yanmeiai.com</code> 在 Cloudflare(管理走 <code>cf-api</code>);<code>git.51yanmei.com</code> 公网 A 记录指 <code>192.168.3.200</code>(仅家内可达)</td><td>新增 3 条 DNS-only A 记录;旧 git 域名可选迁移</td></tr>
|
||||
</table>
|
||||
|
||||
<h2>2 · 架构总览</h2>
|
||||
<div class="diagram">
|
||||
<svg viewBox="0 0 900 470" width="100%" font-family="-apple-system,'PingFang SC',sans-serif" font-size="13">
|
||||
<!-- ===== 在外场景 ===== -->
|
||||
<text x="20" y="28" fill="#e0884f" font-weight="700" font-size="15">在外(pangolin 开)</text>
|
||||
<rect x="20" y="44" width="130" height="52" rx="8" fill="#1d2129" stroke="#272c36"/>
|
||||
<text x="85" y="66" fill="#e6e8ee" text-anchor="middle">Mac / 手机</text>
|
||||
<text x="85" y="84" fill="#a8afbd" text-anchor="middle" font-size="11">pangolin TUN</text>
|
||||
|
||||
<line x1="150" y1="70" x2="255" y2="70" stroke="#e0884f" stroke-width="2"/>
|
||||
<polygon points="255,70 246,65 246,75" fill="#e0884f"/>
|
||||
<text x="202" y="60" fill="#e0884f" text-anchor="middle" font-size="11">REALITY 隧道</text>
|
||||
|
||||
<rect x="258" y="30" width="240" height="130" rx="10" fill="#171a22" stroke="#e0884f"/>
|
||||
<text x="378" y="52" fill="#e6e8ee" text-anchor="middle" font-weight="600">pangolin1 · 103.119.13.48</text>
|
||||
<rect x="274" y="64" width="98" height="36" rx="6" fill="#1d2129" stroke="#272c36"/>
|
||||
<text x="323" y="87" fill="#e6e8ee" text-anchor="middle" font-size="12">sing-box</text>
|
||||
<rect x="386" y="64" width="98" height="36" rx="6" fill="#1d2129" stroke="#272c36"/>
|
||||
<text x="435" y="87" fill="#e6e8ee" text-anchor="middle" font-size="12">frps</text>
|
||||
<line x1="372" y1="82" x2="386" y2="82" stroke="#5fb0c9" stroke-width="2"/>
|
||||
<polygon points="386,82 378,78 378,86" fill="#5fb0c9"/>
|
||||
<text x="378" y="125" fill="#5fb0c9" text-anchor="middle" font-size="11">机内回环(hairpin):出口连自己</text>
|
||||
<text x="378" y="143" fill="#a8afbd" text-anchor="middle" font-size="11">业务端口 ufw 不开放 → 外网扫不到</text>
|
||||
|
||||
<line x1="498" y1="82" x2="610" y2="82" stroke="#5fb0c9" stroke-width="2" stroke-dasharray="6 4"/>
|
||||
<polygon points="502,82 511,77 511,87" fill="#5fb0c9"/>
|
||||
<text x="554" y="72" fill="#5fb0c9" text-anchor="middle" font-size="11">frp 反向长连接</text>
|
||||
<text x="554" y="100" fill="#a8afbd" text-anchor="middle" font-size="10">(家里主动拨出,TLS+token)</text>
|
||||
|
||||
<rect x="612" y="30" width="268" height="150" rx="10" fill="#171a22" stroke="#5ec27a"/>
|
||||
<text x="746" y="52" fill="#e6e8ee" text-anchor="middle" font-weight="600">家庭内网 192.168.3.0/24</text>
|
||||
<rect x="628" y="64" width="110" height="52" rx="6" fill="#1d2129" stroke="#272c36"/>
|
||||
<text x="683" y="84" fill="#e6e8ee" text-anchor="middle" font-size="12">NAS .200</text>
|
||||
<text x="683" y="102" fill="#a8afbd" text-anchor="middle" font-size="10">frpc·git·DSM·DNS</text>
|
||||
<rect x="754" y="64" width="110" height="52" rx="6" fill="#1d2129" stroke="#272c36"/>
|
||||
<text x="809" y="84" fill="#e6e8ee" text-anchor="middle" font-size="12">Windows .88</text>
|
||||
<text x="809" y="102" fill="#a8afbd" text-anchor="middle" font-size="10">RDP 3389 · SSH 22</text>
|
||||
<line x1="738" y1="90" x2="754" y2="90" stroke="#5ec27a" stroke-width="2"/>
|
||||
<polygon points="754,90 746,86 746,94" fill="#5ec27a"/>
|
||||
<text x="746" y="168" fill="#a8afbd" text-anchor="middle" font-size="11">路由器零端口映射,家庭 IP 不出现在公网 DNS</text>
|
||||
|
||||
<!-- ===== 在家场景 ===== -->
|
||||
<text x="20" y="250" fill="#5ec27a" font-weight="700" font-size="15">在家(pangolin 照样开)</text>
|
||||
<rect x="20" y="266" width="130" height="52" rx="8" fill="#1d2129" stroke="#272c36"/>
|
||||
<text x="85" y="288" fill="#e6e8ee" text-anchor="middle">Mac / 手机</text>
|
||||
<text x="85" y="306" fill="#a8afbd" text-anchor="middle" font-size="11">pangolin TUN</text>
|
||||
|
||||
<rect x="240" y="252" width="300" height="80" rx="10" fill="#171a22" stroke="#272c36"/>
|
||||
<text x="390" y="276" fill="#e6e8ee" text-anchor="middle" font-weight="600">客户端分流规则(BuildClientConfig 下发)</text>
|
||||
<text x="390" y="298" fill="#a8afbd" text-anchor="middle" font-size="11">这 3 个域名 → 本地 DNS 解析 → 得内网 IP</text>
|
||||
<text x="390" y="316" fill="#5ec27a" text-anchor="middle" font-size="11">私网地址命中 LAN 直连规则 → 不进隧道</text>
|
||||
|
||||
<line x1="150" y1="292" x2="240" y2="292" stroke="#5ec27a" stroke-width="2"/>
|
||||
<polygon points="240,292 231,287 231,297" fill="#5ec27a"/>
|
||||
|
||||
<line x1="540" y1="292" x2="640" y2="292" stroke="#5ec27a" stroke-width="2"/>
|
||||
<polygon points="640,292 631,287 631,297" fill="#5ec27a"/>
|
||||
<text x="590" y="282" fill="#5ec27a" text-anchor="middle" font-size="11">纯局域网直连</text>
|
||||
|
||||
<rect x="642" y="252" width="238" height="80" rx="10" fill="#171a22" stroke="#5ec27a"/>
|
||||
<text x="761" y="280" fill="#e6e8ee" text-anchor="middle">NAS .200 / Windows .88</text>
|
||||
<text x="761" y="302" fill="#a8afbd" text-anchor="middle" font-size="11">mihomo hosts 把 3 个域名</text>
|
||||
<text x="761" y="318" fill="#a8afbd" text-anchor="middle" font-size="11">解析成内网 IP</text>
|
||||
|
||||
<!-- ===== DNS 分流对照 ===== -->
|
||||
<rect x="20" y="366" width="860" height="84" rx="10" fill="#0a0c11" stroke="#272c36"/>
|
||||
<text x="40" y="392" fill="#a8afbd" font-size="12">同一个域名,两处答案(split-horizon):</text>
|
||||
<text x="40" y="416" fill="#e6e8ee" font-size="12" font-family="ui-monospace,Menlo,monospace">git.yanmeiai.com</text>
|
||||
<text x="220" y="416" fill="#5fb0c9" font-size="12">公网 DNS(Cloudflare)→ 103.119.13.48(pangolin1/frps)</text>
|
||||
<text x="220" y="438" fill="#5ec27a" font-size="12">家内 DNS(NAS mihomo)→ 192.168.3.200(直连)</text>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<h2>3 · 统一地址与端口规划</h2>
|
||||
<p>选端口的原则:<b>内外端口号一致</b>(同一个 URL 全球通用)。唯一例外是裸 SSH——<code>:22</code> 在 pangolin1 上被它自己的 sshd 占用,只能错位到 10022/10023,由 <code>~/.ssh/config</code> 别名消化(见 §7)。</p>
|
||||
<table>
|
||||
<tr><th>服务</th><th>统一地址</th><th>frpc 转发目标(家内)</th><th>pangolin1 remotePort</th><th>备注</th></tr>
|
||||
<tr><td>Forgejo Git SSH</td><td><code>ssh://git@git.yanmeiai.com:2222</code></td><td><code>127.0.0.1:2222</code></td><td>2222</td><td>内外一致 ✓</td></tr>
|
||||
<tr><td>Forgejo Web</td><td><code>http://git.yanmeiai.com:3000</code></td><td><code>127.0.0.1:3000</code></td><td>3000</td><td>内外一致 ✓</td></tr>
|
||||
<tr><td>DSM / Photos</td><td><code>https://nas.yanmeiai.com:5001</code></td><td><code>127.0.0.1:5001</code></td><td>5001</td><td>内外一致 ✓;Photos App 填这个地址</td></tr>
|
||||
<tr><td>Windows RDP</td><td><code>win.yanmeiai.com:3389</code></td><td><code>192.168.3.88:3389</code></td><td>3389</td><td>内外一致 ✓</td></tr>
|
||||
<tr><td>NAS SSH</td><td>外:<code>nas.yanmeiai.com:10022</code><br>家:<code>192.168.3.200:22</code></td><td><code>127.0.0.1:22</code></td><td>10022</td><td>端口错位,ssh alias 兜底</td></tr>
|
||||
<tr><td>Windows SSH</td><td>外:<code>win.yanmeiai.com:10023</code><br>家:<code>192.168.3.88:22</code></td><td><code>192.168.3.88:22</code></td><td>10023</td><td>端口错位,ssh alias 兜底</td></tr>
|
||||
</table>
|
||||
<p class="small">不转发的:SMB/445(协议不适合过公网,文件走 Synology Drive/Photos 或 git);DSM 5000(明文 HTTP,只留 5001 HTTPS);mihomo 9090 管理口(有需要时临时经 NAS SSH 端口转发)。</p>
|
||||
|
||||
<h2>4 · 安全模型(三层)</h2>
|
||||
<div class="card">
|
||||
<h3>第一层:业务端口对公网「隐形」(关键设计)</h3>
|
||||
<p>pangolin1 的 ufw 默认拒绝入站。<b>frps 的业务端口(2222/3000/3389/5001/10022/10023)一条 allow 规则都不加。</b>你在外面走 pangolin 时,流量从 sing-box 出站连 <code>103.119.13.48</code>——目的地是本机自己的公网 IP,内核走 <b>loopback 回环(hairpin)</b>送达,而 ufw 对 <code>lo</code> 接口默认全放行。效果:<b>这些端口只有「连着 pangolin 的你」能访问</b>,公网扫描器看到的是全拒。RDP 这种绝不能裸奔的服务因此是安全的。</p>
|
||||
<p class="small">验证兜底:若实测 hairpin 未走 lo(§9 验收步骤 P1-4 会测),补一条 <code>ufw allow from 103.119.13.48</code> 等价实现,语义不变。</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>第二层:frp 控制通道加固</h3>
|
||||
<p><code>:7000</code> 是唯一新开的公网端口(frpc 从家里拨入用,家宽 IP 动态、无法限源)。加固:<code>auth.token</code>(32 字节随机,存 Bitwarden)+ <code>transport.tls.force = true</code>(强制 TLS,未握手连接直接断)。</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>第三层:业务自身认证不放松</h3>
|
||||
<p>Forgejo 密钥登录、DSM 账号 2FA + 自动封锁、Windows RDP 强密码/NLA——原有认证全部保留,隧道只是网络通路。Tailscale 保留不动,作为 frp 链路故障时的应急后门。</p>
|
||||
</div>
|
||||
|
||||
<h2>5 · pangolin1 怎么配(装 frps)</h2>
|
||||
<p class="files">机器:<code>ssh pangolin1</code> · 人在外也能直接做(公网可达)</p>
|
||||
<h3>5.1 生成 token(本机 Mac 上)</h3>
|
||||
<pre><code><span class="c"># 生成 32 字节随机 token,存进 Bitwarden(条目名:frp home-tunnel)</span>
|
||||
openssl rand -hex 32
|
||||
rbw add "frp home-tunnel" <span class="c"># 密码字段贴上面的输出;两端配置从这里取,不落明文文件</span></code></pre>
|
||||
<h3>5.2 安装 frps 二进制 + systemd</h3>
|
||||
<pre><code><span class="c"># ssh pangolin1 之后(root)。VER 以 frp releases 最新版为准,下例为示意</span>
|
||||
VER=0.61.1
|
||||
curl -LO https://github.com/fatedier/frp/releases/download/v${VER}/frp_${VER}_linux_amd64.tar.gz
|
||||
tar xzf frp_${VER}_linux_amd64.tar.gz
|
||||
install -m 755 frp_${VER}_linux_amd64/frps /usr/local/bin/frps
|
||||
mkdir -p /etc/frp</code></pre>
|
||||
<p><code>/etc/frp/frps.toml</code>(<span class="tag warn">token 不入 git</span>,与 <code>/etc/pangolin*</code> 密钥同规矩):</p>
|
||||
<pre><code><span class="k">bindAddr</span> = <span class="s">"0.0.0.0"</span>
|
||||
<span class="k">bindPort</span> = 7000
|
||||
<span class="k">auth.method</span> = <span class="s">"token"</span>
|
||||
<span class="k">auth.token</span> = <span class="s">"<Bitwarden: frp home-tunnel>"</span>
|
||||
<span class="k">transport.tls.force</span> = true <span class="c"># 拒绝非 TLS 的 frpc</span>
|
||||
<span class="c"># 不开 dashboard;业务端口按 frpc 请求动态监听</span>
|
||||
<span class="k">allowPorts</span> = [
|
||||
{ <span class="k">start</span> = 2222, <span class="k">end</span> = 2222 }, { <span class="k">start</span> = 3000, <span class="k">end</span> = 3000 },
|
||||
{ <span class="k">start</span> = 3389, <span class="k">end</span> = 3389 }, { <span class="k">start</span> = 5001, <span class="k">end</span> = 5001 },
|
||||
{ <span class="k">start</span> = 10022, <span class="k">end</span> = 10023 },
|
||||
] <span class="c"># 白名单锁死,token 泄露也开不了别的口</span></code></pre>
|
||||
<p><code>/etc/systemd/system/frps.service</code>:</p>
|
||||
<pre><code>[Unit]
|
||||
Description=frp server (home reverse tunnel)
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/local/bin/frps -c /etc/frp/frps.toml
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
User=nobody <span class="c"># 非特权端口,无需 root</span>
|
||||
LimitNOFILE=65536
|
||||
<span class="c"># 1G 小机安全带:内存超限就重启,绝不拖垮 sing-box/控制面</span>
|
||||
MemoryMax=128M
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target</code></pre>
|
||||
<pre><code>chmod 600 /etc/frp/frps.toml && chown nobody /etc/frp/frps.toml
|
||||
systemctl daemon-reload && systemctl enable --now frps
|
||||
ufw allow 7000/tcp comment 'frp control (frpc dial-in from home)'
|
||||
<span class="c"># 验证:只多了 7000 这一个对外口</span>
|
||||
systemctl status frps --no-pager | head -5
|
||||
ss -tlnp | grep frps</code></pre>
|
||||
<p class="small">⚠️ 台账提醒:pangolin1 续费到期 <b>2026-07-19</b>(baize <code>billing.renew_at</code>)——动工前先确认已续费。</p>
|
||||
|
||||
<h2>6 · DNS 怎么配(Cloudflare + 家内 mihomo)</h2>
|
||||
<h3>6.1 公网侧:Cloudflare 加 3 条 A 记录(本机 Mac,cf-api)</h3>
|
||||
<p><b>必须 DNS only(灰云,<code>proxied:false</code>)</b>——git SSH / RDP 是任意 TCP,CF 橙云只代理 HTTP。zone id 见 baize:<code>2325730de45276d87180a8b66bd4cca0</code>。</p>
|
||||
<pre><code>cf-api -X POST "/zones/2325730de45276d87180a8b66bd4cca0/dns_records" \
|
||||
--data '{"type":"A","name":"nas","content":"103.119.13.48","proxied":false,"ttl":300}'
|
||||
cf-api -X POST "/zones/2325730de45276d87180a8b66bd4cca0/dns_records" \
|
||||
--data '{"type":"A","name":"git","content":"103.119.13.48","proxied":false,"ttl":300}'
|
||||
cf-api -X POST "/zones/2325730de45276d87180a8b66bd4cca0/dns_records" \
|
||||
--data '{"type":"A","name":"win","content":"103.119.13.48","proxied":false,"ttl":300}'</code></pre>
|
||||
<p class="small">代价说明:灰云记录会暴露 pangolin1 的 IP——它本来就是 VPN 数据面入口(客户端 endpoint 直连该 IP),无新增暴露。改完回写 baize <code>domains.yaml</code>。</p>
|
||||
<h3>6.2 家内侧:NAS mihomo 加 hosts 覆盖</h3>
|
||||
<p><code>/volume1/docker/proxy/mihomo/config.yaml</code> 两处改动(仓库 <code>docker/proxy/mihomo/config.yaml</code> 同步改):</p>
|
||||
<pre><code><span class="k">hosts</span>: <span class="c"># ① 家内答案:直接给内网 IP</span>
|
||||
<span class="k">nas.yanmeiai.com</span>: <span class="s">192.168.3.200</span>
|
||||
<span class="k">git.yanmeiai.com</span>: <span class="s">192.168.3.200</span>
|
||||
<span class="k">win.yanmeiai.com</span>: <span class="s">192.168.3.88</span>
|
||||
<span class="k">git.51yanmei.com</span>: <span class="s">192.168.3.200</span> <span class="c"># 兼容既有 git remote(可选,见 §10)</span>
|
||||
|
||||
<span class="k">dns</span>:
|
||||
<span class="k">fake-ip-filter</span>: <span class="c"># ② 追加:不给这几个域名发 fake-ip,走 hosts 真实值</span>
|
||||
<span class="c"># ……既有条目保持不动(含 +.tailscale.com 等)……</span>
|
||||
- <span class="s">nas.yanmeiai.com</span>
|
||||
- <span class="s">git.yanmeiai.com</span>
|
||||
- <span class="s">win.yanmeiai.com</span>
|
||||
- <span class="s">git.51yanmei.com</span></code></pre>
|
||||
<pre><code><span class="c"># 热重载(不重启容器),沿用仓库既有做法</span>
|
||||
ssh nas "curl -s -X PUT 'http://127.0.0.1:9090/configs?force=true' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{\"path\":\"/root/.config/mihomo/config.yaml\"}'"
|
||||
<span class="c"># 验证:家内解析应返回 192.168.3.200</span>
|
||||
ssh nas "nslookup git.yanmeiai.com 127.0.0.1"</code></pre>
|
||||
<h3>6.3 路由器:DHCP 的 DNS 指到 NAS(回家后做)</h3>
|
||||
<p>Windows 已手动指 NAS;要让 Mac/手机在家也吃到 hosts 覆盖,把路由器 DHCP 下发的 DNS 改为 <code>192.168.3.200</code>(一处改动、全家生效)。<span class="tag warn">取舍</span>:NAS 由此成为家内 DNS 单点——不要配第二个公共 DNS 兜底(客户端会随机用它,覆盖时灵时不灵);NAS 重启的几分钟内家里断解析,可接受。</p>
|
||||
|
||||
<h2>7 · NAS 怎么配(装 frpc)</h2>
|
||||
<p class="files">仓库新增:<code>docker/frp/docker-compose.yml</code> + <code>docker/frp/frpc.toml</code> + <code>docker/frp/.env.example</code> · NAS 路径:<code>/volume1/docker/frp/</code></p>
|
||||
<p>沿用本仓库 docker-compose 惯例(forgejo/proxy 同款)。<code>wangjia</code> 不在 docker 组,部署用 <code>sudo</code> 或 Container Manager UI。</p>
|
||||
<p><code>docker-compose.yml</code>:</p>
|
||||
<pre><code><span class="k">services</span>:
|
||||
<span class="k">frpc</span>:
|
||||
<span class="k">image</span>: <span class="s">snowdreamtech/frpc:0.61</span> <span class="c"># 多架构维护镜像;版本与 frps 对齐</span>
|
||||
<span class="k">container_name</span>: frpc
|
||||
<span class="k">network_mode</span>: host <span class="c"># 需直达 127.0.0.1 各服务 + 192.168.3.88</span>
|
||||
<span class="k">restart</span>: unless-stopped
|
||||
<span class="k">volumes</span>:
|
||||
- <span class="s">./frpc.toml:/etc/frp/frpc.toml:ro</span></code></pre>
|
||||
<p><code>frpc.toml</code>(token 同样不入 git,仓库放 <code>frpc.toml.example</code> 占位):</p>
|
||||
<pre><code><span class="k">serverAddr</span> = <span class="s">"103.119.13.48"</span>
|
||||
<span class="k">serverPort</span> = 7000
|
||||
<span class="k">auth.method</span> = <span class="s">"token"</span>
|
||||
<span class="k">auth.token</span> = <span class="s">"<Bitwarden: frp home-tunnel>"</span>
|
||||
<span class="k">transport.tls.enable</span> = true
|
||||
|
||||
[[<span class="k">proxies</span>]]
|
||||
<span class="k">name</span> = <span class="s">"git-ssh"</span>
|
||||
<span class="k">type</span> = <span class="s">"tcp"</span>
|
||||
<span class="k">localIP</span> = <span class="s">"127.0.0.1"</span>
|
||||
<span class="k">localPort</span> = 2222
|
||||
<span class="k">remotePort</span> = 2222
|
||||
|
||||
[[<span class="k">proxies</span>]]
|
||||
<span class="k">name</span> = <span class="s">"git-web"</span>
|
||||
<span class="k">type</span> = <span class="s">"tcp"</span>
|
||||
<span class="k">localIP</span> = <span class="s">"127.0.0.1"</span>
|
||||
<span class="k">localPort</span> = 3000
|
||||
<span class="k">remotePort</span> = 3000
|
||||
|
||||
[[<span class="k">proxies</span>]]
|
||||
<span class="k">name</span> = <span class="s">"dsm"</span>
|
||||
<span class="k">type</span> = <span class="s">"tcp"</span>
|
||||
<span class="k">localIP</span> = <span class="s">"127.0.0.1"</span>
|
||||
<span class="k">localPort</span> = 5001
|
||||
<span class="k">remotePort</span> = 5001
|
||||
|
||||
[[<span class="k">proxies</span>]]
|
||||
<span class="k">name</span> = <span class="s">"nas-ssh"</span>
|
||||
<span class="k">type</span> = <span class="s">"tcp"</span>
|
||||
<span class="k">localIP</span> = <span class="s">"127.0.0.1"</span>
|
||||
<span class="k">localPort</span> = 22
|
||||
<span class="k">remotePort</span> = 10022
|
||||
|
||||
[[<span class="k">proxies</span>]]
|
||||
<span class="k">name</span> = <span class="s">"win-rdp"</span>
|
||||
<span class="k">type</span> = <span class="s">"tcp"</span>
|
||||
<span class="k">localIP</span> = <span class="s">"192.168.3.88"</span> <span class="c"># 同网段代转 Windows,一个 frpc 管全家</span>
|
||||
<span class="k">localPort</span> = 3389
|
||||
<span class="k">remotePort</span> = 3389
|
||||
|
||||
[[<span class="k">proxies</span>]]
|
||||
<span class="k">name</span> = <span class="s">"win-ssh"</span>
|
||||
<span class="k">type</span> = <span class="s">"tcp"</span>
|
||||
<span class="k">localIP</span> = <span class="s">"192.168.3.88"</span>
|
||||
<span class="k">localPort</span> = 22
|
||||
<span class="k">remotePort</span> = 10023</code></pre>
|
||||
<pre><code><span class="c"># 部署(经 Tailscale 跳板 ssh 到 NAS 后)</span>
|
||||
sudo mkdir -p /volume1/docker/frp && cd /volume1/docker/frp
|
||||
<span class="c"># (把仓库里的两个文件放进来,frpc.toml 填真 token)</span>
|
||||
sudo docker compose up -d
|
||||
sudo docker logs frpc --tail 20 <span class="c"># 应见 "login to server success" + 6 个 proxy 启动成功</span></code></pre>
|
||||
<h3>Mac 的 ssh 别名收尾(<code>~/.ssh/config</code>)</h3>
|
||||
<pre><code><span class="c"># 既有 Host nas / windows(内网 IP 直连)保持不动,家里继续用</span>
|
||||
Host nas-r <span class="c"># 在外用:ssh nas-r</span>
|
||||
HostName nas.yanmeiai.com
|
||||
Port 10022
|
||||
User wangjia
|
||||
|
||||
Host win-r <span class="c"># 在外用:ssh win-r</span>
|
||||
HostName win.yanmeiai.com
|
||||
Port 10023
|
||||
User wangjia</code></pre>
|
||||
|
||||
<h2>8 · Windows 怎么改(几乎不用)</h2>
|
||||
<table>
|
||||
<tr><th>项</th><th>动作</th><th>说明</th></tr>
|
||||
<tr><td>网络</td><td><span class="tag ok">不改</span></td><td>网关/DNS 已指 NAS,天然吃到 hosts 覆盖</td></tr>
|
||||
<tr><td>RDP</td><td>确认已启用(设置 → 系统 → 远程桌面),保持 NLA 开启</td><td>frpc 从 NAS(同网段 .200)连入,默认防火墙「专用网络」范围即放行</td></tr>
|
||||
<tr><td>OpenSSH server</td><td><span class="tag ok">已有</span>(<code>ssh windows</code> 在用),确认服务设为自动启动</td><td>同上,无需改防火墙</td></tr>
|
||||
<tr><td>防火墙</td><td>仅当连不通时检查:RDP/SSH 入站规则的作用域含本地子网</td><td>不需要也不要开「任意来源」</td></tr>
|
||||
</table>
|
||||
|
||||
<h2>9 · pangolin 客户端分流(BuildClientConfig,让家里直连成立)</h2>
|
||||
<p class="files">代码:<code>server/internal/httpapi/clientconfig.go::BuildClientConfig</code> · 单独一刀,四端零改动(配置服务端渲染下发)</p>
|
||||
<p>pangolin TUN 的首条路由规则是 <code>hijack-dns</code>,所有 DNS 都被劫去隧道解析——家里也会拿到公网 IP、绕道外网。解法是给这几个域名开「本地解析 + 按结果路由」的侧门:</p>
|
||||
<pre><code><span class="c">// 伪代码示意。域名清单走 server 配置(env PRIVATE_SPLIT_DOMAINS),默认空 = 行为不变,</span>
|
||||
<span class="c">// 不影响其他用户。</span>
|
||||
<span class="c">// ① dns.servers 增本地解析器</span>
|
||||
{ <span class="s">"tag"</span>: <span class="s">"dns-local"</span>, <span class="s">"address"</span>: <span class="s">"local"</span>, <span class="s">"detour"</span>: <span class="s">"direct"</span> }
|
||||
<span class="c">// ② dns.rules 前插:这 3 个域名用本地 DNS(家=mihomo hosts→内网IP;外=公网DNS→pangolin1)</span>
|
||||
{ <span class="s">"domain"</span>: [<span class="s">"nas.yanmeiai.com"</span>,<span class="s">"git.yanmeiai.com"</span>,<span class="s">"win.yanmeiai.com"</span>], <span class="s">"server"</span>: <span class="s">"dns-local"</span> }
|
||||
<span class="c">// ③ route.rules 在 hijack-dns 之后插:先解析再按 IP 匹配后续规则</span>
|
||||
{ <span class="s">"domain"</span>: [<span class="s">"…同上…"</span>], <span class="s">"action"</span>: <span class="s">"resolve"</span> }
|
||||
<span class="c">// ④ 解析结果为私网 → 命中既有 LAN 直连规则 → 家里直连;</span>
|
||||
<span class="c">// 公网 IP(pangolin1)→ 不匹配 → 走默认代理出口 → 机内 hairpin 到 frps</span></code></pre>
|
||||
<p><span class="tag warn">实现时必须验证</span>:<code>action: resolve</code> 是 sing-box ≥ 1.11 语法——先确认四端内嵌 libbox 版本;不够就先升 libbox(<code>scripts/build-libbox.sh</code> 重编,产物 gitignore 需各端重新放置)。按仓库惯例先在 macOS 端端到端验证,再推 iOS/Android/Windows。</p>
|
||||
<p class="small">此刀未落地前的过渡用法:在外一切正常(隧道 DNS 拿公网 IP 本来就该走隧道);<b>在家</b>访问这几个域名会绕外网一圈(功能可用、不满足目标①),或临时关 pangolin 直连。</p>
|
||||
|
||||
<h2>10 · 执行顺序(人在外,现在就能开工)</h2>
|
||||
<p class="phase">P0 · 前置(5 分钟)</p>
|
||||
<ul>
|
||||
<li>确认 pangolin1 已续费(<b>2026-07-19 到期</b>)</li>
|
||||
<li>生成 token 存 Bitwarden「frp home-tunnel」(§5.1)</li>
|
||||
</ul>
|
||||
<p class="phase">P1 · pangolin1 装 frps(直接可做,§5.2)</p>
|
||||
<ul>
|
||||
<li>装二进制 + 配置 + systemd 拉起,<code>ufw allow 7000/tcp</code></li>
|
||||
<li>验证:<code>ss -tlnp | grep frps</code> 只见 7000;<b>P1-4 hairpin 实测</b>——pangolin1 本机 <code>curl --max-time 3 http://103.119.13.48:7000</code> 通(说明本机对自己公网 IP 走 lo),外网机器(如 ali)<code>nc -zw3 103.119.13.48 2222</code> 必须<b>不通</b></li>
|
||||
</ul>
|
||||
<p class="phase">P2 · Cloudflare 加 3 条灰云 A 记录(直接可做,§6.1)</p>
|
||||
<ul>
|
||||
<li>验证:<code>dig +short git.yanmeiai.com @1.1.1.1</code> → <code>103.119.13.48</code></li>
|
||||
</ul>
|
||||
<p class="phase">P3 · 经 Tailscale 跳板配 NAS(§6.2 + §7)</p>
|
||||
<ul>
|
||||
<li>Mac:断 pangolin → 连 Tailscale →(若登录卡住:Tailscale 登录要过 Google,可先在 pangolin 开着时完成浏览器授权再切换)</li>
|
||||
<li><code>ssh wangjia@100.95.151.13</code>:部署 frpc compose、改 mihomo(hosts + fake-ip-filter)并热重载</li>
|
||||
<li>验证:<code>docker logs frpc</code> 见 6 个 proxy 成功;<code>nslookup git.yanmeiai.com 127.0.0.1</code> → 192.168.3.200</li>
|
||||
<li>Mac:断 Tailscale → 恢复 pangolin</li>
|
||||
</ul>
|
||||
<p class="phase">P4 · 在外端到端验收(pangolin 开着)</p>
|
||||
<ul>
|
||||
<li><code>git ls-remote ssh://git@git.yanmeiai.com:2222/wangjia/nas.git</code> ✓</li>
|
||||
<li>浏览器 <code>http://git.yanmeiai.com:3000</code> 出 Forgejo 登录页 ✓</li>
|
||||
<li><code>https://nas.yanmeiai.com:5001</code> 出 DSM(证书告警属预期,见 §12 增强)✓</li>
|
||||
<li>Microsoft Remote Desktop 连 <code>win.yanmeiai.com</code> ✓;<code>ssh nas-r</code> / <code>ssh win-r</code> ✓</li>
|
||||
<li>反证:<b>关掉 pangolin</b> 后上述地址应全部超时(ufw 隐形生效)</li>
|
||||
</ul>
|
||||
<p class="phase">P5 · 回家后收尾(§6.3)</p>
|
||||
<ul>
|
||||
<li>路由器 DHCP DNS → 192.168.3.200;Mac 重新拿 DHCP</li>
|
||||
<li>验证:<code>dig +short git.yanmeiai.com</code> → 192.168.3.200;关 pangolin 时 <code>git ls-remote</code>/DSM 直连均通且 traceroute 一跳</li>
|
||||
</ul>
|
||||
<p class="phase">P6 · pangolin 分流规则(单独一刀,§9)</p>
|
||||
<ul>
|
||||
<li>确认 libbox 版本 → 改 <code>BuildClientConfig</code> + 单测 → macOS 端在家实测「pangolin 开着直连内网」→ 推其余三端</li>
|
||||
</ul>
|
||||
<p class="phase">P7 · 台账与文档回写</p>
|
||||
<ul>
|
||||
<li>baize <code>domains.yaml</code>(3 条新记录 + expected_resolution);nas 仓 <code>CLAUDE.md</code>(frp 服务 + 端口清单);<code>~/.ssh/config</code>(nas-r/win-r);todo 登记</li>
|
||||
</ul>
|
||||
|
||||
<h2>11 · 风险与回滚</h2>
|
||||
<table>
|
||||
<tr><th>风险</th><th>影响</th><th>缓解 / 回滚</th></tr>
|
||||
<tr><td>NAS 成家内 DNS 单点</td><td>NAS 挂 → 全家断解析</td><td>接受(NAS 稳定);应急把路由器 DHCP DNS 改回运营商</td></tr>
|
||||
<tr><td>token 泄露</td><td>他人可向 frps 注册代理</td><td><code>allowPorts</code> 白名单锁死端口范围;业务端口本就 ufw 隐形;换 token 重启两端即失效</td></tr>
|
||||
<tr><td>frps 占用拖累 1G 小机</td><td>控制面/数据面受影响</td><td>systemd <code>MemoryMax=128M</code>,超限自杀重启,隔离爆炸半径</td></tr>
|
||||
<tr><td>hairpin 假设不成立</td><td>在外连不上业务端口</td><td>P1-4 提前实测;兜底 <code>ufw allow from 103.119.13.48</code></td></tr>
|
||||
<tr><td>pangolin1 迁移/换 IP</td><td>公网侧全断</td><td>frps 配置随 deploy 脚本走;改 3 条 A 记录即恢复;家内直连不受影响</td></tr>
|
||||
<tr><td>libbox 版本不支持 resolve</td><td>P6 延期</td><td>P1–P5 不依赖 P6;过渡期家里关 pangolin 或接受绕行</td></tr>
|
||||
<tr><td>整体回滚</td><td>—</td><td>NAS:<code>docker compose down</code>;pangolin1:<code>systemctl disable --now frps</code> + 删 ufw 7000;CF 删 3 条记录;mihomo 还原备份重载。全程不动业务服务</td></tr>
|
||||
</table>
|
||||
|
||||
<h2>12 · 可选增强(不阻塞主线)</h2>
|
||||
<ul>
|
||||
<li><b>旧 git 域名兼容</b>:把 <code>git.51yanmei.com</code> 公网 A 记录(阿里云)从 192.168.3.200 改指 103.119.13.48——既有仓库 remote 在外也能用,家内靠 §6.2 的 hosts 覆盖。或者反过来:全量迁 remote 到 <code>git.yanmeiai.com</code>,旧域名退役。</li>
|
||||
<li><b>DSM 正经证书</b>:DSM 用 Let's Encrypt DNS-01(CF API)给 <code>nas.yanmeiai.com</code> 签证书,消掉 5001 的浏览器告警。</li>
|
||||
<li><b>Forgejo ROOT_URL</b>:app.ini 的 DOMAIN/SSH_DOMAIN/ROOT_URL 改为 <code>git.yanmeiai.com</code>(对应 CLAUDE.md 里既有 TODO),web 页面上的 clone 地址就会是新域名。</li>
|
||||
<li><b>监控</b>:pangolin-monitor(bootstrap 自带 Telegram 通道)加一条 frps 存活/7000 端口探测;NAS 侧 frpc 掉线重连靠 docker restart 策略兜底。</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user