Self-Hosting Behind CGNAT
Self-Hosting Behind CGNAT
在 CGNAT 环境下进行自托管
There is nothing more satisfying than owning, end to end, the software and the hardware you use without relying on abusive cloud corporations. Internet is us, not them. Break free from censorship. Learn how to self-host at home, and be truly libre.
没有什么比端到端地掌控你所使用的软件和硬件,且无需依赖那些滥用数据的云服务巨头更令人满足的了。互联网属于我们,而不是他们。摆脱审查,学习如何在家里进行自托管,真正实现自由。
In the past, self-hosting was easier. You just had to open a port on your router and forward it to any machine at home. A dynamic DNS service kept your domain pointing at the right public IP whenever your ISP rotated it. Nowadays, the shortage of IPv4 addresses means routers share the same IP across your neighborhood. Requests are routed using carrier-grade NAT (CGNAT), a second-layer NAT inside the carrier’s network, where your router’s address is private and translated by the carrier on the way out. The public address is the carrier’s, so port forwarding no longer works.
过去,自托管要容易得多。你只需要在路由器上打开一个端口,并将其转发到家里的任何机器即可。每当 ISP(互联网服务提供商)更换 IP 时,动态 DNS 服务会确保你的域名指向正确的公网 IP。如今,IPv4 地址的短缺意味着整个社区的路由器共享同一个 IP。请求通过运营商级 NAT (CGNAT) 进行路由,这是运营商网络内部的第二层 NAT,你的路由器地址是私有的,并在出口处由运营商进行转换。公网地址属于运营商,因此端口转发不再起作用。
Topology
网络拓扑
My services run on a mid-range machine in my mother’s basement in northern Spain, and are exposed to the Internet through a cheap VPS bridge in a French data center.
我的服务运行在西班牙北部我母亲地下室的一台中端机器上,并通过法国数据中心的一台廉价 VPS 网桥暴露在互联网上。
+-------------------------------------+
| public Internet |
+-------------------------------------+
^ ^ | inbound
v | |
+------------+ |
| bridge | | egress
+------------+ |
^^ || WireGuard
vv |
+-------------------------------------+
| homelab |
+-------------------------------------+
Code Snippet 1: Topology diagram. The homelab is exposed to the Internet through a WireGuard tunnel to a VPS bridge. 代码片段 1:拓扑图。家庭实验室通过 WireGuard 隧道连接到 VPS 网桥,从而暴露在互联网上。
A bidirectional WireGuard tunnel forwards all packets in all ports from the bridge to the homelab box, and vice versa. The beauty of this is that the tunnel is initiated by the homelab, so you don’t need a static dedicated IP at home. Buying a static IP from your ISP is a valid alternative, at around 20 euros a month in Spain. The penalty of the bridge is 39 ms of RTT.
双向 WireGuard 隧道将所有端口的所有数据包从网桥转发到家庭实验室机器,反之亦然。这种方案的妙处在于隧道是由家庭实验室主动发起的,因此你不需要家里的静态专用 IP。(从 ISP 购买静态 IP 是另一种可行方案,在西班牙每月大约需要 20 欧元)。使用网桥的代价是增加了 39 毫秒的往返延迟 (RTT)。
Tunnel configuration
隧道配置
Bridge’s wg0.conf.
网桥的 wg0.conf 配置:
[Interface]
Address = 10.0.0.1/24
PrivateKey = <bridge-private-key>
ListenPort = 51820
PostUp = ...
PostDown = ...
[Peer]
PublicKey = <homelab-public-key>
AllowedIPs = 10.0.0.2/32
PostUp sets up NAT and forwarding rules at the kernel level. The first two exclude ports 2222 for SSH, and 51820 for the VPN tunnel itself. The last three forward all traffic in all ports to the homelab. The destination is rewritten but not the source, so the homelab sees the real client IPs.
PostUp 在内核层面设置 NAT 和转发规则。前两条规则排除了用于 SSH 的 2222 端口和用于 VPN 隧道本身的 51820 端口。后三条规则将所有端口的所有流量转发到家庭实验室。目标地址被重写,但源地址保持不变,因此家庭实验室可以看到真实的客户端 IP。
iptables -t nat -A PREROUTING -i ens3 -p udp --dport 51820 -j RETURN
iptables -t nat -A PREROUTING -i ens3 -p tcp --dport 2222 -j RETURN
iptables -t nat -A PREROUTING -i ens3 -j DNAT --to-destination 10.0.0.2
iptables -A FORWARD -i wg0 -o ens3 -s 10.0.0.2 -j ACCEPT
iptables -A FORWARD -i ens3 -o wg0 -d 10.0.0.2 -j ACCEPT
Homelab’s wg0.conf.
家庭实验室的 wg0.conf 配置:
[Interface]
Address = 10.0.0.2/24
PrivateKey = <homelab-private-key>
Table = off
PostUp = ip route add default dev wg0 table 200
PostUp = ip rule add from 10.0.0.2 table 200
PostDown = ...
[Peer]
PublicKey = <bridge-public-key>
Endpoint = 213.32.19.229:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
Replies from the homelab have to go back down the tunnel. That is what the config is for, sending those replies through the bridge, while leaving the homelab’s own traffic on the home router. From then on, SSH to ssh.alvarezrosa.com at port 22 lands on the homelab, and port 2222 on the bridge.
来自家庭实验室的回复必须通过隧道返回。这就是上述配置的作用:将这些回复通过网桥发送,同时让家庭实验室自身的流量保持在家庭路由器上。此后,通过 22 端口 SSH 连接到 ssh.alvarezrosa.com 将会到达家庭实验室,而 2222 端口则会连接到网桥。
Resilience
韧性
Three pieces can fail: 三个环节可能会出现故障:
- Homelab. A cronjob in the homelab checks whether SSH is still working and, if it is not, reboots the box. 家庭实验室: 家庭实验室中的一个 cronjob 会检查 SSH 是否正常工作,如果不正常,则重启机器。
- Bridge. In case it fails, I recommend a backup entry point like a Cloudflare tunnel or Tailscale directly to the homelab. 网桥: 如果网桥失效,我建议设置一个备份入口点,例如 Cloudflare Tunnel 或直接连接到家庭实验室的 Tailscale。
- Tunnel. A short drop re-handshakes on its own. A longer one is covered by the two cases above. 隧道: 短暂的中断会自动重新握手。较长时间的中断则由上述两种情况覆盖。
Own your services. Be libre and have fun! 掌控你的服务。保持自由,享受乐趣!