问题起因🌲

最近在做一个web项目,前两周打开前端调试突然发现网站渲染失败,F12查看发现部分CSS和JS的CDN资源加载不出来,均来自于cdnjs.cloudflare.com这个域名,当时刚好碰上Cloudflare出现了重大事故(详见Cloudflare 刚刚这波挂得挺惨的Cloudflare outage on June 21, 2022),于是当时想着可能是Cloudflare的问题,过几天应该就好了吧?😄

结果昨天晚上去看还是加载失败,就开始自己定位问题。😓

问题定位🔍

Ping

首先看看域名能不能ping通

1
2
3
4
5
6
7
8
9
10
11
$ ping cdnjs.cloudflare.com
PING cdnjs.cloudflare.com (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.048 ms
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.063 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.113 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.195 ms
64 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.201 ms
^C
--- cdnjs.cloudflare.com ping statistics ---
5 packets transmitted, 5 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.048/0.124/0.201/0.064 ms

这个域名居然被解析到本地回环地址127.0.0.1,好奇怪啊!看上去像是DNS解析出错了。接着查看本机网络配置的DNS服务器,发现DNS地址是192.168.1.1,emmmmm,和网关地址一样,看来这个地址是DHCP动态下发的我没改过,理论上是没有问题的,整个局域网内的设备都从网关获取DNS既方便修改也有利于DNS缓存命中。

DNS resolve

理所当然,先确认一下是不是DNS解析的问题。

运行一下nslookup命令

1
2
3
4
5
6
7
$ nslookup cdnjs.cloudflare.com
Server: 192.168.1.1
Address: 192.168.1.1#53

Non-authoritative answer:
Name: cdnjs.cloudflare.com
Address: 127.0.0.1

或运行一下dig命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ dig cdnjs.cloudflare.com

; <<>> DiG 9.10.6 <<>> cdnjs.cloudflare.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 7424
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;cdnjs.cloudflare.com. IN A

;; ANSWER SECTION:
cdnjs.cloudflare.com. 300 IN A 127.0.0.1

;; Query time: 11 msec
;; SERVER: 192.168.1.1#53(192.168.1.1)
;; WHEN: Mon Jul 04 19:36:14 CST 2022
;; MSG SIZE rcvd: 54

果然,都是解析到了127.0.0.1。注意看Server都是192.168.1.1网关地址,这里有一个疑惑,是不是网关上面的DNS配错了呢?

我用的网关是深圳电信的天翼网关3.0,浏览器打开192.168.1.1登录天翼智能网关web页面进去看配置,翻了个底朝天也没发现DNS配置在哪,我记得这里是可以配置DNS的啊(怀疑人生中…),上知乎搜了一圈发现有些老哥在喷电信说3.0版本不能修改DNS配置了(存疑,姑且信了…)。

但是还是要确认是DNS服务器的原因,怎么办呢?很简单,既然网关找不到配置,那就上网搜索一下深圳电信这个片区的DNS服务器地址是多少,然后指明这个服务器地址再测试一下即可。

Query Specific Name Server

中国广东电信DNS服务器IP地址​查到深圳电信的DNS服务器地址为202.96.134.133,接下来指明server参数测试:

nslookup命令

1
2
3
4
5
6
$ nslookup cdnjs.cloudflare.com 202.96.134.133
Server: 202.96.134.133
Address: 202.96.134.133#53

Name: cdnjs.cloudflare.com
Address: 127.0.0.1

dig命令(注意dig的server参数要加上@,很容易忘掉然后错误地用/etc/resolv.conf里面的默认server去查两个记录了)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ dig cdnjs.cloudflare.com @202.96.134.133

; <<>> DiG 9.10.6 <<>> cdnjs.cloudflare.com @202.96.134.133
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 62035
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;cdnjs.cloudflare.com. IN A

;; ANSWER SECTION:
cdnjs.cloudflare.com. 300 IN A 127.0.0.1

;; Query time: 8 msec
;; SERVER: 202.96.134.133#53(202.96.134.133)
;; WHEN: Mon Jul 04 20:09:52 CST 2022
;; MSG SIZE rcvd: 54

🪨🔨🌶️,铁证如山呐,深圳电信DNS把cdnjs.cloudflare.com解析到了127.0.0.1

做个对比,测了一下老家安徽电信的DNS(61.132.163.68)和公共的阿里云DNS(223.5.5.5),解析结果如下

1
2
3
4
5
6
7
8
9
$ nslookup cdnjs.cloudflare.com 61.132.163.68
Server: 61.132.163.68
Address: 61.132.163.68#53

Non-authoritative answer:
Name: cdnjs.cloudflare.com
Address: 104.17.25.14
Name: cdnjs.cloudflare.com
Address: 104.17.24.14
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ dig cdnjs.cloudflare.com @223.5.5.5

; <<>> DiG 9.10.6 <<>> cdnjs.cloudflare.com @223.5.5.5
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 7837
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;cdnjs.cloudflare.com. IN A

;; ANSWER SECTION:
cdnjs.cloudflare.com. 98 IN A 104.17.25.14
cdnjs.cloudflare.com. 98 IN A 104.17.24.14

;; Query time: 9 msec
;; SERVER: 223.5.5.5#53(223.5.5.5)
;; WHEN: Mon Jul 04 20:10:15 CST 2022
;; MSG SIZE rcvd: 70

可见安徽电信和阿里云的DNS均可以正确解析出ip为104.17.24.14104.17.25.14👍

解决办法🔧

换成国内CDN

昨晚的第一反应是把cloudflare CDN换成国内的bootCDN,见Github Commit - Line 13

如果用户主要是国外的那另说,其实国内用还是优先上国内的CDN,速度上确实快不少,而且相对来说稳定性也好一点。我每次偷懒直接从官方文档里面复制粘贴CDN地址就没管过前端代码了😓。

附国内常见的CDN:

修改hosts

上面用公共DNS server已经查到对应的ip地址了,直接在hosts中把cdnjs.cloudflare.com解析到104.17.24.14,hosts里面配置的优先级高于一般走的DNS解析流程,肯定可以解决问题。

sudo vi /etc/hosts

添加下面这一行

104.17.24.14 cdnjs.cloudflare.com

即可

修改DNS server

修改hosts是改动最小的做法,但是如果未来还有别的网址解析失败就很麻烦了,不好维护。所以更方便的做法改DNS server,而且最好是改网关的DNS server(前文已经说了,天翼网关3.0貌似改不了),那只能退而求其次改本机的了。

一般来说越近的DNS server越快,所以运营商的是最快的(架不住运营商有时候干点恶心人的事情),再慢一点就是国内公共DNS,最慢的是国外的。于是找了几个公共DNS server出来ping了一下,比如阿里、腾讯、百度、114、谷歌的,发现延迟最小的是阿里云的223.5.5.5

删掉hosts里面的记录然后把本机器的DNS server改成223.5.5.5,也能解决问题。

经验总结📖

  1. 主体目标用户在国内的话用国内CDN;
  2. DNS server最好配置成公共DNS;

有待进一步了解🎯

参考💼