在 Linux 上使用 Cloudflare DoH 绕过服务商限制

0、前言

大部分提供 HKT、HKBN、HiNet 等家宽 VPS 的服务商一般都会做一些限制,例如禁止访问政府网站、购物网站。这当然可以理解,毕竟如果有人租用家宽来破坏政府网站、在购物平台恶意刷单、刷点数,将会给服务商带来麻烦。但是我最近买的一台 HiNet NAT VPS 居然屏蔽当地的流媒体平台(LiTV 和 KKTV),这让我无法理解,遂着手研究绕过方法。

1、原理分析

首先进行流媒体测试,推荐我 自主研发 二次开发 的 Golang 流媒体解锁检测脚本:

MediaUnlockTest with Golang
https://github.com/HsukqiLee/MediaUnlockTest

执行:

Bash
1
bash <(curl -Ls unlock.icmp.ing/scripts/test.sh)

测试结果显示:

Text
1
2
3
4
5
6
7
8
9
10
11
[ Taiwan ] ==================
KKTV                      NO  (Network Err)
LiTV                      NO  (Network Err)
MyVideo                   YES
4GTV                      YES
LineTV                    YES
Hami Video                YES
CatchPlay+                YES (Region: TW)
Bahamut Anime             YES (Region: TW)
HBO GO Asia               YES (Region: TW)
Bilibili Taiwan Only      YES

以 LiTV 为例,进行 curl 测试,发现卡在解析这一步。尝试进行 NSLookUp:

Bash
1
2
root@server:/root# nslookup litv.tv
;; connection timed out; no servers could be reached

显然请求被阻止。尝试更换 DNS:

Bash
1
2
root@server:/root# nslookup litv.tv 1.1.1.1
;; connection timed out; no servers could be reached

结果相同,看来有 DNS 劫持。

尝试在 https://dns.google 获得正确 IP,用 curl --resolve 指定 IP 访问,请求成功,可判断没有 IP/HTTP 层面的阻断。

2、解决方法

最简单的解决方法就是使用 DoH。以 Cloudflared Proxy DNS 为例:

2.1、安装

执行:

Bash
1
curl -o /usr/bin/cloudflared -L "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64"

如果是其他架构可自行替换链接,例如 ARM64改为:

Bash
1
curl -o /usr/bin/cloudflared -L "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm64"

2.2、测试

先开一个 screen 或用其他方法,在后台保持运行:

Bash
1
cloudflared proxy-dns --port 5553

然后在另一个 session 中执行:

Bash
1
dig +short @127.0.0.1 -p5553 cloudflare.com AAAA

如果输出类似:

Bash
1
2
2606:4700::6810:84e5
2606:4700::6810:85e5

则表示成功,可以停止程序运行,进行下一步。

2.3、配置

添加 systemd 服务,即在:

/etc/systemd/system/cloudflared-proxy-dns.service

写入:

Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
echo '[Unit]
Description=DNS over HTTPS (DoH) proxy client
Wants=network-online.target nss-lookup.target
Before=nss-lookup.target

[Service]
AmbientCapabilities=CAP_NET_BIND_SERVICE
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
DynamicUser=yes
ExecStart=/usr/local/bin/cloudflared proxy-dns

[Install]
WantedBy=multi-user.target

然后启动:

Bash
1
sudo systemctl enable --now cloudflared-proxy-dns

修改系统 DNS:

Bash
1
echo 'nameserver 127.0.0.1' > /etc/resolv.conf

注意:
systemd-resolved 等软件会锁定 DNS 为配置文件中的地址,请自行查询修改方法。

安装成功!

再次测试,发现……所有域名都解析不了了 XD。

2.4、自定义上游

简单排查发现,Cloudflared 无法解析域名。默认的上游服务器地址是:

https://1.1.1.1/dns-query
https://1.0.0.1/dns-query

测试发现这两个地址也被屏蔽了(仅屏蔽 HTTP/HTTPS,UDP 53 的请求会被劫持),尝试换成其他 DoH 地址,测试正常。

故修改配置文件如下:

Text
1
2
3
4
5
6
7
8
9
10
11
12
13
[Unit]
Description=DNS over HTTPS (DoH) proxy client
Wants=network-online.target nss-lookup.target
Before=nss-lookup.target

[Service]
AmbientCapabilities=CAP_NET_BIND_SERVICE
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
DynamicUser=yes
ExecStart=/usr/local/bin/cloudflared proxy-dns --upstream  "DoH_SERVER_1" --upstream  "DoH_SERVER_2"

[Install]
WantedBy=multi-user.target

然后重启服务:

Bash
1
2
systemctl daemon-reload
systemctl restart cloudflared-proxy-dns

再次测试就正常啦!

3、缺陷

首先,DoH/DoT 这类加密 DNS 的速度肯定没有 UDP 53 快,但是实测解析速度没什么直观影响,可能因为 Cloudflare 机房近,并且 DNS 可以缓存。

其次,这个方法只能用于 DNS 劫持的屏蔽方法。后面测试时,我发现运营商(意料之中地)屏蔽了虾皮,但是屏蔽方法不一样,即使正确解析也无法连接。后面发现虾皮只有一个 IP 143.92.82.21,只要这个 IP 阻断了,VPS 就完全无法连接,除非使用代理(可是这样就不是家宽 IP 了啊 XD)。

在 Linux 上使用 Cloudflare DoH 绕过服务商限制

https://blog.tsinbei.com/tw/archives/1844/

文章作者
Hsukqi Lee
发布于

2024-11-19

修改于

2024-11-19

许可协议

CC BY-NC-ND 4.0

评论

昵称
邮箱
网址
暂无