tl;dr
桌面端的同学,也可以看看:
在 Chrome 中配置安全 DNS (DNS over HTTPS) 以解决校园网对 xjtu.men 的 DNS 污染和 DNS 劫持问题(哪怕你设置了使用校外的 DNS,依然会给你错误的解析结果):
-
下载安装 Chrome,若是 Android 可直接点击 Chrome.apk。
-
启用安全 DNS。移动端请参考后面的截图。PC 可直接设置中搜索
DNS
,找到安全 DNS
设置项,复制到导航栏打开:
chrome://settings/security?search=dns
然后选择 cloud flare(1.1.1.1), 如果不可用,可输入自定安全 DNS URL,有以下多种选择:
https://1.12.12.12/dns-query
- Ali 安全 DNS 的 URL 为:
https://dns.alidns.com/dns-query
(其实还有 1.1.1.1, 9.9.9.9 等多种选择,详情请 Google)
Mobile 操作步骤如下:
隐私与安全 → 使用安全 DNS → 另选一个提供商 → 自定义
前情提要
症状描述
校园网环境下浏览器无法访问本站,而 4G 网络下可以正常访问。
故障排查
先用ipconfig /all
查看网络信息(personal information redacted):
再 nslookup
看看这几个校园网自动配置的 DNS 服务器是否能进行正常域名解析:
[root@ubuntu ~]# nslookup xjtu.app 10.6.39.2
Server: 10.6.39.2
Address: 10.6.39.2#53
** server can't find xjtu.app: REFUSED
[root@ubuntu ~]# nslookup xjtu.app 202.117.0.20
Server: 202.117.0.20(陕西省西安市西安交通大学教育网)
Address: 202.117.0.20(陕西省西安市西安交通大学教育网)#53
** server can't find xjtu.app: REFUSED
[root@ubuntu ~]# nslookup xjtu.app 1.1.1.1
Server: 1.1.1.1(AS13335 Cloudflare Inc. 1.1.1.0/24 美国 APNIC&CloudFlare 公共 DNS 服务器)
Address: 1.1.1.1(AS13335 Cloudflare Inc. 1.1.1.0/24 美国 APNIC&CloudFlare 公共 DNS 服务器)#53
** server can't find xjtu.app: REFUSED
可以看到,校园网默认配置的 DNS 服务器拒绝解析 xjtu.app
,甚至向校外 1.1.1.1 的解析请求也被劫持从而无法正常解析。然而此时其他域名的解析正常。
下面来看基于 DNS over HTTPS (DoH) 的 localhost DNS 服务器的结果:
[root@ubuntu ~]# nslookup xjtu.app 127.0.0.1
Server: 127.0.0.1
Address: 127.0.0.1#53
Non-authoritative answer:
Name: xjtu.app
Address: 104.21.47.144(美国 CloudFlare 节点)
Name: xjtu.app
Address: 172.67.171.83(美国 CloudFlare 节点)
Name: xjtu.app
Address: 2606:4700:3030::ac43:ab53(全球 Cloudflare Inc Anycast 网段)
Name: xjtu.app
Address: 2606:4700:3036::6815:2f90(全球 Cloudflare Inc Anycast 网段)
所以答案很简单,DNS 污染。
当你浏览器键入 xjtu.men 域名的时候后台在发生什么
域名到 IP 的转换(DNS 解析)
- 浏览器会自动把你输入的补全成
https://xjtu.app
(如果域名在 HSTS preload list 里,有些浏览器会补全成https://xjtu.app
)。 - 做 DNS 解析,查询域名对应的 IP。
- 对于配置了
network.trr.mode=3 或 2
的 Firefox,会通过 HTTPS 进行加密的解析 - 对于一般的浏览器,会通过操作系统配置的 DNS 进行解析,如果 DNS 的 IP 不在本机,那么查询请求会以明文的形式在网络上传播,中间的任何一个节点都可以窥探并篡改到你查询的域名。
例如假设你要到8.8.8.8
这个 DNS 服务器上查询:
- 对于配置了
[root@ubuntu ~]# traceroute 8.8.8.8
traceroute to 8.8.8.8(美国加利福尼亚州圣克拉拉县山景市谷歌公司 DNS 服务器), 30 hops max, 60 byte packets
1 <redacted>
2 <redacted>
3 <redacted>
4 <redacted>
5 <redacted>
6 206.72.211.148.any2ix.coresite.com (206.72.211.148(美国加利福尼亚州洛杉矶 CoreSite Any2Exchange)) 9.922 ms 10.65.1.237 (10.65.1.237) 0.494 ms 206.72.211.148.any2ix.coresite.com (206.72.211.148(美国加利福尼亚州洛杉矶 CoreSite Any2Exchange)) 10.051 ms
7 108.170.247.129(美国加利福尼亚州圣克拉拉县山景市谷歌公司) 10.973 ms 108.170.247.161(美国加利福尼亚州圣克拉拉县山景市谷歌公司) 11.184 ms 206.72.211.148.any2ix.coresite.com (206.72.211.148(美国加利福尼亚州洛杉矶 CoreSite Any2Exchange)) 9.967 ms
8 108.170.247.161(美国加利福尼亚州圣克拉拉县山景市谷歌公司) 11.043 ms 108.170.247.129(美国加利福尼亚州圣克拉拉县山景市谷歌公司) 10.733 ms 142.251.60.99(美国加利福尼亚州圣克拉拉县山景市谷歌公司) 9.712 ms
9 dns.google (8.8.8.8(美国加利福尼亚州圣克拉拉县山景市谷歌公司 DNS 服务器)) 9.963 ms 10.838 ms 9.971 ms
那么从 1
到9
的所有 IP 上的主机都能看到并篡改这个域名的 DNS 查询结果,一般是 IP。所以在这个环节污染正常的 DNS 解析过程,让你获取不到正确的 IP,即可封网站。
对于这种最低级的方法,解决方案有很多:
- 更换网络环境
- 安装 DNS over HTTPS (DoH) 软件,例如 Cloudflare 1.1.1.1, dnscrypt-proxy。
- 修改电脑的 hosts 文件,例如:
<IP> xjtu.app
注意,请用 nslookup
/ ping
/ https://bgp.he.net/dns/xjtu.app#_ipinfo 获取最新 IP,替换 <IP>
。
如果你有 IPv6 的话也可以加上下面一行
2604:a880:4:1d0::305:e000 xjtu.men
通过传输协议 HTTP(S) 向位于该 IP 的 (Web) 服务器请求内容
- 首次访问本站时,对于 HTTP 请求,由于 HTTP 是不安全的,跟 DNS 类似,传输路径上的任何主机都看到并篡改你的访问请求和返回的内容,例如这是一个 Web 服务器的日志:
127.0.0.1 - - [05/Jun/2023:20:36:10 +0800] "GET /http/transfer/is/naked HTTP/1.1" 404 385 "" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36"
提示你的请求至少泄露了这些信息:
- 你请求的路径
/http/transfer/is/naked
- 你的 IP:
127.0.0.1
- 你的浏览器的 User Agent 信息:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36
由于 HTTP 非常不安全,负责地配置的服务器一般会向浏览器回复这样的内容:
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="https://xjtu.app/">here</A>.
</BODY></HTML>
提示浏览器改用 HTTPS 协议。
在这个环节封网站也很简单,随便篡改响应头,返回404之类的。
解决方案是使用现代浏览器,或者人工输入域名前面的 https。
- 由于本站加入了 HTTPS 预加载列表, Chrome, Firefox, Safari, Edge 会自动且只能采用 HTTPS 连接本站,无需上一步的过程且必须验证 SSL 证书的正确性。
- 要在服务器和浏览器之间建立端到端加密的 HTTPS 连接,必须进行 TLS 握手,需要两者来回发送几次数据,下面是 CloudFlare 画的一张示意图:
中间的过程涉及公私钥非对称加密的内容,比较复杂,这里只谈怎么在这个环节封网站。
TLS 握手时,浏览器向服务器发送的客户端 Hello 包含 Server Name Indication (SNI),这时你要访问的网站的域名可以被传输路径中途的主机窥探到。
比如你的浏览器地址栏是 https://subdomain.xjtu.app/my/little/secret
,那么路径中的主机知道你想访问subdomain.xjtu.app
这个域名(但是不知道你请求的路径/my/little/secret
)。通过 TLS 的这个缺陷可以封网站。
解决方案:
让中间主机无法看到你访问的域名。比如使用 加密/安全 SNI,或者更先进的 加密客户端 Hello (ECH),或者把你的网络流量包在其他协议里。
可以到 这个网站 测试你的浏览器支持哪些安全功能。
在 TLS 握手的过程中,网站会发送证明身份的证书给浏览器,TLS1.2 协议不加密证书,而证书会泄露域名信息,解决方案是:采取激进的 TLS 设置,只使用 TLS1.3,不支持 TLS1.2。
另外,如果传输路径上有干扰,把服务器返回的流量给篡改了,比如返回的证书的 CA 不受信任,或者域名不是你请求访问的域名, \ldots\ldots ,那么也会失败,通过这个也可以封网站。解决方案只有把你的网络流量包在其他协议里。
- 在 TLS 握手成功后,进行 HTTPS 流量传输,这时候中间路径上的主机只能看到你和远方的服务器之间传输加密流量,可知的只有你们双方的 IP 和端口号。
要封网站,只需中间路径上的主机把数据包全给扔掉。
可以选择性封锁,常见的比如封锁某些 IP 到你的所有流量,或者某些端口,或者某些协议如 UDP 的流量。
解决方法:
- 对于服务器:使用大公司的 CDN 服务,即:要么不封 IP,只要封就把这个 CDN 服务商的所有 IP 给封了。
- 把你的网络流量包在其他协议里。