<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>折腾 on E7Coding</title><link>https://www.e7coding.com/categories/%E6%8A%98%E8%85%BE/</link><description>Recent content in 折腾 on E7Coding</description><generator>Hugo</generator><language>zh-cn</language><managingEditor>Joy</managingEditor><webMaster>Joy</webMaster><lastBuildDate>Tue, 16 Jun 2026 13:00:00 +0800</lastBuildDate><atom:link href="https://www.e7coding.com/categories/%E6%8A%98%E8%85%BE/index.xml" rel="self" type="application/rss+xml"/><item><title>把设备接进自建 Headscale：从 tailscale up 登录到 headscale-ui 管理</title><link>https://www.e7coding.com/posts/tailscale-device-join/</link><pubDate>Tue, 16 Jun 2026 13:00:00 +0800</pubDate><author>Joy</author><guid>https://www.e7coding.com/posts/tailscale-device-join/</guid><description>&lt;blockquote&gt;
&lt;p&gt;折腾背景：&lt;a href="https://www.e7coding.com/posts/tailscale-intro/"&gt;序章&lt;/a&gt;讲了原理，&lt;a href="https://www.e7coding.com/posts/headscale-ui-setup/"&gt;headscale-ui&lt;/a&gt; 配好了管理界面，&lt;a href="https://www.e7coding.com/posts/self-hosted-derp/"&gt;自建 DERP&lt;/a&gt; 也把中继搬到了国内。这是系列收尾——把最日常的一环讲清楚：&lt;strong&gt;一台新设备怎么用 Tailscale 客户端登录进自建 Headscale，并在 headscale-ui 里管理它&lt;/strong&gt;。下面文字配模拟截图走一遍。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="整体流程"&gt;整体流程&lt;/h2&gt;
&lt;p&gt;接入一台设备就五步，控制面在 Headscale，登录指向它，设备入网后在 Web 界面里管：&lt;/p&gt;

&lt;pre class="mermaid"&gt;
flowchart TD
 A["① 装 Tailscale 客户端"] --&gt; B["② tailscale up&lt;br/&gt;--login-server=自建地址"]
 B --&gt; C["③ 终端输出 register 链接&lt;br/&gt;（含 nodekey）"]
 C --&gt; D["④ headscale-ui 批准设备&lt;br/&gt;归到某个 user"]
 D --&gt; E["⑤ 设备上线&lt;br/&gt;分到 100.64.x.x"]
 E --&gt; F["⑥ 日常管理&lt;br/&gt;路由 / Tag / 过期 / 删除"]

 style B fill:#ffe9d5,stroke:#b71d18
 style D fill:#ffe9d5,stroke:#b71d18
&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;关键就两处（标橙）：&lt;strong&gt;登录时把 &lt;code&gt;--login-server&lt;/code&gt; 指向自己的 Headscale&lt;/strong&gt;，以及&lt;strong&gt;入网要在 headscale-ui 里批准&lt;/strong&gt;——官方 Tailscale 是自动的，自建则要这一步人工确认，这正是「自己掌控」的体现。&lt;/p&gt;</description></item><item><title>自建 DERP 中继：让 Headscale 打洞失败也能稳连国内 20ms</title><link>https://www.e7coding.com/posts/self-hosted-derp/</link><pubDate>Tue, 16 Jun 2026 12:00:00 +0800</pubDate><author>Joy</author><guid>https://www.e7coding.com/posts/self-hosted-derp/</guid><description>&lt;blockquote&gt;
&lt;p&gt;折腾背景：我用 Headscale 自建了一套私有组网，大部分设备能 WireGuard P2P 直连。但有几台在对称型 NAT / 运营商大内网后面的机器始终打洞失败，流量只能走中继——而 Tailscale 官方的 DERP 中继节点都在境外，延迟动辄 100ms 起步，看着就难受。于是自己在国内搭了一台 DERP，延迟直接压到 &lt;strong&gt;20ms 级&lt;/strong&gt;。这篇把全过程连同三个坑一起记下来。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="先搞清楚derp-到底在干嘛"&gt;先搞清楚：DERP 到底在干嘛&lt;/h2&gt;
&lt;p&gt;WireGuard 组网的理想状态是两台设备&lt;strong&gt;点对点直连&lt;/strong&gt;（P2P）。但现实里大量设备藏在 NAT 后面，打洞（NAT 穿透）并不总能成功。一旦直连建立不起来，流量就得找个公网中继转一道——这个中继就是 &lt;strong&gt;DERP&lt;/strong&gt;（Designated Encrypted Relay for Packets）。&lt;/p&gt;</description></item><item><title>给 Headscale 配个 Web 界面：headscale-ui 安装折腾记</title><link>https://www.e7coding.com/posts/headscale-ui-setup/</link><pubDate>Tue, 16 Jun 2026 11:00:00 +0800</pubDate><author>Joy</author><guid>https://www.e7coding.com/posts/headscale-ui-setup/</guid><description>&lt;blockquote&gt;
&lt;p&gt;折腾背景：&lt;a href="https://www.e7coding.com/posts/tailscale-intro/"&gt;序章&lt;/a&gt;里我把 Tailscale / 自建 Headscale 的原理讲过了，假设你已经有一套 Headscale 跑起来。但 Headscale 原生&lt;strong&gt;只有命令行&lt;/strong&gt;——加节点、批准设备、建用户、配子网路由，全得 SSH 上去敲 &lt;code&gt;headscale&lt;/code&gt; 命令。设备一多就烦。&lt;a href="https://github.com/gurucomputing/headscale-ui" target="_blank" rel="noopener noreferrer"&gt;headscale-ui&lt;/a&gt; 是社区做的一个纯静态 Web 前端，直接调 Headscale 的 API，把这些操作搬进浏览器。这篇记一下它的安装和两个反代/登录的坑。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="它是怎么工作的"&gt;它是怎么工作的&lt;/h2&gt;
&lt;p&gt;headscale-ui 本身&lt;strong&gt;没有后端&lt;/strong&gt;，就是一堆静态 HTML/JS。它在你浏览器里，拿着你填的 &lt;strong&gt;API Key&lt;/strong&gt; 直接去敲 Headscale 的 HTTP API。所以部署的核心其实是两件事：&lt;/p&gt;</description></item><item><title>Tailscale 是什么：一篇看懂这套 P2P 内网穿透神器（折腾系列·序章）</title><link>https://www.e7coding.com/posts/tailscale-intro/</link><pubDate>Tue, 16 Jun 2026 10:00:00 +0800</pubDate><author>Joy</author><guid>https://www.e7coding.com/posts/tailscale-intro/</guid><description>&lt;blockquote&gt;
&lt;p&gt;这是我「Tailscale 折腾系列」的第一篇。后面会一篇篇动手搭自建控制面、配 Web 界面、自建国内中继——但在敲命令之前，先用一篇把&lt;strong&gt;原理&lt;/strong&gt;讲透。搞懂它怎么工作，后面折腾时遇到问题才知道是哪一环出了岔子，而不是照着命令瞎抄。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="先说痛点我们到底想解决什么"&gt;先说痛点：我们到底想解决什么&lt;/h2&gt;
&lt;p&gt;场景很常见：人在外面，想连家里的 NAS、回公司内网、用一台云服务器中转流量。传统方案各有各的难受：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;端口转发 / DDNS&lt;/strong&gt;：要有公网 IP，还把服务直接暴露在公网上，不安全。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;frp / 反向代理&lt;/strong&gt;：能穿透，但每加一个服务就要配一条规则，运维琐碎。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;传统 VPN（OpenVPN/IPsec）&lt;/strong&gt;：中心化网关，配置重，所有流量绕一圈，慢。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;它们的共同问题是：&lt;strong&gt;要么依赖公网 IP，要么流量被迫绕中心节点，要么配置繁琐&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;Tailscale 的思路完全不同：让你所有设备&lt;strong&gt;登录同一个账号就自动组成一张虚拟局域网&lt;/strong&gt;，设备之间&lt;strong&gt;点对点直连&lt;/strong&gt;，像插在同一台交换机上一样——不需要公网 IP，不用挨个配端口。&lt;/p&gt;
&lt;h2 id="核心原理控制面与数据面分离"&gt;核心原理：控制面与数据面分离&lt;/h2&gt;
&lt;p&gt;Tailscale 基于 &lt;strong&gt;WireGuard&lt;/strong&gt;（现代、快、内核级的 VPN 协议）。它真正聪明的地方，是把网络拆成了&lt;strong&gt;两个面&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;控制面（Control Plane）&lt;/strong&gt;：协调中心。负责设备认证、分发各设备的公钥、下发访问策略（ACL）。它&lt;strong&gt;只协调、不碰你的数据&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;数据面（Data Plane）&lt;/strong&gt;：设备之间用 WireGuard &lt;strong&gt;直接点对点加密通信&lt;/strong&gt;，数据不经过任何中心服务器。&lt;/li&gt;
&lt;/ul&gt;

&lt;pre class="mermaid"&gt;
flowchart TD
 C["控制面 / Control Plane&lt;br/&gt;认证 · 分发公钥 · 下发 ACL"]

 A["设备 A&lt;br/&gt;手机"]
 B["设备 B&lt;br/&gt;家里 NAS"]
 D["设备 C&lt;br/&gt;公司电脑"]

 C -. "只协调，不碰数据" .-&gt; A
 C -. "只协调，不碰数据" .-&gt; B
 C -. "只协调，不碰数据" .-&gt; D

 A == "WireGuard P2P 直连" === B
 A == "WireGuard P2P 直连" === D
 B == "WireGuard P2P 直连" === D

 style C fill:#dbe9ff,stroke:#2563eb,stroke-width:2px
&lt;/pre&gt;
&lt;p&gt;控制面帮设备们「互相认识」，之后它们就甩开控制面自己直连了。这也是为什么 Tailscale 又快又安全——&lt;strong&gt;流量从不经过中间服务器&lt;/strong&gt;。&lt;/p&gt;</description></item></channel></rss>