什么是 DNS 解锁
实际上就是一种结合了 DNS 劫持 (DNS Hijacking) 与 SNI 代理 (SNI Proxy) 的流量重定向(Traffic Redirection)架构。其核心是通过一个定制的 分离解析 DNS (Split-horizon DNS) 服务器,对特定域名请求返回代理服务器自身的 IP 地址(A 记录),从而诱导客户端连接。随后,部署在同一台服务器上的 SNI 感知反向代理 (SNI-aware Reverse Proxy) 捕获入站流量,通过解析 TLS 握手中的 服务器名称指示 (Server Name Indication) 头部来识别客户端的真正目标,最终将数据包中继(Relay)到上游的原始服务器,实现透明代理和访问控制。
准备
- (A)一台 VPS
- (B)一台解锁漂亮的 VPS (需要有 docker)
步骤1
登录 VPS(B)
|
|
当前的文件树应该是这样的:
.
├── .env
├── .env.save
├── .git
├── .github
├── compose.yml
├── dnsmasq
├── proxy-domains.txt
├── readme.md
└── sniproxy
我们只需要关注 proxy-domains.txt, .env 即可。
proxy-domains.txt中是我们需要解锁的域名地址, 你可以随意的更改, 比如你想解锁gemini,就在其中填入gemini.google.com..env直接收两个变量, 分别是PUBLIC_IP,ALLOWED_IPS,前者是我们当前VPS的IP地址,后者是我们希望哪个IP可以通过我们进行代理,填入需要被解锁的VPS的IP即可。
之后我们启动容器,先不分离到后台,因为我们需要看一下日志:
|
|
不如意外的话,控制台会显示错误:
Error response from daemon: failed to set up container networking: driver failed programming external connectivity on endpoint dns-dnsmasq-1 (bb7cd1e4e43f631336d1dc4f9819be2a254d5cf217544075eb51e637cb2a94ae): failed to bind host port for 0.0.0.0:53:172.18.0.3:53/tcp: address already in use
意思其实就是 你的 VPS(B) 上的 53 端口已经被占用了。 dnsmasq 容器需要使用 53 端口(DNS 服务的标准端口),但 VPS(B)已经有另一个程序在占用它。在大多数现代 Linux 系统(如 Ubuntu)上,这个程序几乎肯定是 systemd-resolved,它是系统内置的 DNS 缓存服务。
接下来我们解决它:
|
|
大概率会是以下的情况:
UNCONN 0 0 127.0.0.54:53 0.0.0.0:* users:(("systemd-resolve",pid=285,fd=19))
UNCONN 0 0 127.0.0.53%lo:53 0.0.0.0:* users:(("systemd-resolve",pid=285,fd=17))
接着去取消它:
|
|
找到 #DNSStubListener=yes 这一行(它可能被注释掉了)。把他修改为:DNSStubListener=no。重启一下 systemd-resolved 服务。
|
|
再次启动 docker 服务:
|
|
观察一下日志,如果显示以下结果就证明没问题了。:
dnsmasq-1 | 正在使用 proxy-domains.txt 文件更新配置...
dnsmasq-1 | 启动 dnsmasq 服务...
步骤2
现在我们登录 VPS(A),我们只需要修改一下原来的 DNS 为我们VPS(B)的IP地址即可。
|
|
把所有 nameserver 行都注释掉,添加:
nameserver 2.2.2.2 # VPS(B) 的IP
最后在VPS(A)上进行一下测试,来测试我们的规则是否已经启用:
|
|
之后会返回一个结果:
;; SERVER: x.x.x.x#53(x.x.x.x) (UDP)
如果这个 x.x.x.x 是你的 VPS(B)的地址,那么恭喜你,DNS解锁已经成功了。