Coding 的痕迹

一位互联网奔跑者的网上日记

0%

网站安全的一点思考

最近看到清华大学树洞项目的 搭建指南,里面特别强调了主机安全:

【warning必须采取的安全措施】:请务必确保时刻没有子域名DNS解析到服务器真实IP,并且服务器真实IP必须始终保密!

服务器的 IP 如果泄露, DDoS 等情况就有可能发生,同时还会极大地增加攻击面。因此,服务器的HTTP流量必须始终通过 CDN(比如Cloudflare CDN)。在 https://securitytrails.com/dns-trails 网站上,一个域名的全部子域名和 DNS 历史记录都可以轻松查到,因此不能有任何时刻让服务器真实 IP 暴露在外。

于是在 SecurityTrails 上检查了自己的域名 sunnysab.cn,发现有些仅自己使用、或给同学使用的,未公开的域名也赫然在列,令人不解。

域名解析

回忆所学过的 DNS 服务查询流程,就以本博客的域名来说,客户端会首先向根域名服务器(.)查询 cn. 的名称服务器,再向 cn. 的名称服务器查询到 sunnysab.cn 所属的的名称服务器,最终得到该域名对应的 A/AAAA 记录 (IP 地址),按理说不会暴露子域名的情况。

这里修正一下,通过 Wireshark 抓包我们可以发现:

  1. 查询时会携带期望得到的记录,如正常查询时会请求对应域名的 A 记录。
  1. 客户端会首先查询根域名服务器列表,并从中选择一个;此后,它向所有遇到的服务器查询 sunnysab.cn 所对应的 A 记录。根域名服务器自然不知道,于是返回了 cn 对应的名称服务器(NS 记录)a.dns.cnb.dns.cn 等等;紧接着,它向 a.dns.cn 查询 sunnysab.cn 所对应 A 的记录,以此类推。

  2. 接第二条,如果我查询一个三级域名,如 a.b.example.com,就要看哪一级别的名称服务器存储了对应的记录。

域名解析流程如下,它也被称为迭代查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
$ dig +trace sunnysab.cn

; <<>> DiG 9.18.0 <<>> +trace sunnysab.cn
;; global options: +cmd
. 329177 IN NS a.root-servers.net.
. 329177 IN NS c.root-servers.net.
. 329177 IN NS i.root-servers.net.
. 329177 IN NS l.root-servers.net.
. 329177 IN NS b.root-servers.net.
. 329177 IN NS j.root-servers.net.
. 329177 IN NS h.root-servers.net.
. 329177 IN NS k.root-servers.net.
. 329177 IN NS f.root-servers.net.
. 329177 IN NS d.root-servers.net.
. 329177 IN NS m.root-servers.net.
. 329177 IN NS g.root-servers.net.
. 329177 IN NS e.root-servers.net.
;; Received 267 bytes from 192.168.31.1#53(192.168.31.1) in 6 ms

cn. 172800 IN NS a.dns.cn.
cn. 172800 IN NS b.dns.cn.
cn. 172800 IN NS c.dns.cn.
cn. 172800 IN NS d.dns.cn.
cn. 172800 IN NS e.dns.cn.
cn. 172800 IN NS f.dns.cn.
cn. 172800 IN NS g.dns.cn.
cn. 172800 IN NS ns.cernet.net.
cn. 86400 IN DS 57724 8 2 5D0423633EB24A499BE78AA22D1C0C9BA36218FF49FD95A4CDF1A4AD 97C67044
cn. 86400 IN RRSIG DS 8 1 86400 20220422050000 20220409040000 47671 . Ecc7/2n1m4EGcDGsilV4h8Dq+jHAx2UN6KhJC9QrTGGfyqdxTaiKQvDp llcpdMvF5G07McmLR2X4Z6/z9Af+n22X9fhxJL25JYPwvmb9feZuVo51 FEQ6EFiRgODb6NxqeOGSEpPzr4ERT5zA+hBRTboGQv/8G77pXMEn9vkU FlBwIBVVZhuyLPnliIRsy1scdRNJf92s8ExSh4R3roK0PVdZNcdJdmgm sdTRiihRyZa8wAaVc3wgXA9JAxHsmC64K7UUAxzhZDHLzn+Qr3OhMjAS mbqRNJOBTuQNvJK7tsKERZvwdNMfDnTZYaRiIQe8p0aS2I/MBd5IFdzj 9x6Dmw==
;; Received 702 bytes from 199.7.83.42#53(l.root-servers.net) in 16 ms

sunnysab.cn. 86400 IN NS f1g1ns1.dnspod.net.
sunnysab.cn. 86400 IN NS f1g1ns2.dnspod.net.
3QDAQA092EE5BELP64A74EBNB8J53D7E.cn. 21600 IN NSEC3 1 1 10 AEF123AB 3QHKTF6LTFG8AAFUUAJSR8RVAJP99SFU NS SOA RRSIG DNSKEY NSEC3PARAM
3QDAQA092EE5BELP64A74EBNB8J53D7E.cn. 21600 IN RRSIG NSEC3 8 2 21600 20220421020437 20220322010437 38388 cn. h8l0G9BHCfmmihReDucaiq7ZGQVaLbZMg00XJW0S0ueVhyvgFGtobZrS zAw4TgiKkQ4RzVMIaQDCpl9Ndj1gvhGvK9tmO3DxRLMTs2EfhbS4oaAW J5ZPgtNZWe9UnmNYShX1a7BvWLAuF+yx4ZhP/pxd5LLbdpIO4FLGBIkl JKE=
460MA1KN9RCS318KUU45F11O2MJGT558.cn. 21600 IN NSEC3 1 1 10 AEF123AB 46F805934J5U26CSL3LRD98GD3IJC8R8 NS DS RRSIG
460MA1KN9RCS318KUU45F11O2MJGT558.cn. 21600 IN RRSIG NSEC3 8 2 21600 20220421020437 20220322010437 38388 cn. hfaIKR67Vm4pnSy8ScHFEJ55K1hjG2u49euVOJ7W6d1N5GnLF6Tn5JxF X/BfScthNSnLCQl/5c3AE//pUTuviDQePG4syifn58ljjV/hSV1ARprG PY+DA+VPLE6bVX1RV5P7kcGtHIFZxHWhHnGgB5irC6PuEkqWrx9RM1QX fWg=
;; Received 585 bytes from 203.119.27.1#53(c.dns.cn) in 6 ms

sunnysab.cn. 600 IN A 106.15.182.107
sunnysab.cn. 86400 IN NS f1g1ns2.dnspod.net.
sunnysab.cn. 86400 IN NS f1g1ns1.dnspod.net.
;; Received 120 bytes from 58.251.121.111#53(f1g1ns2.dnspod.net) in 36 ms

于是 Google 了一下,在一篇 Reddit 的帖中 (How does the SecurityTrails subdomain finder work?) 找到了一丝线索:

If you’re running SSL on those domains but don’t have a wildcard cert, it’s probably grabbing them from certificate transparency logs. https://crt.sh is a nice place to look things up (though updates have stopped for a month due to ongoing backend changes).

一查发现果然如此,看来子域名信息是在 SSL 证书颁发时公告出去了。 crt.sh 是一个个人的、开源的站点,旨在收集当前网络上的 SSL 证书公告,这儿有一篇介绍:《crt.sh: what is? Let’s gather certificate information 》

Crt.sh is a site where you could find all the SSL or TLS certificates of the particular targeted domain. And the site is open-source to monitor the certificates.

The site is in a GUI format and it is really very easy to gather the information and the motive of the site is to keep the certificate logs very transparently.

Even you could find the certificates algorithms in a ciphertext format. The crt.sh stands for “certificates.Saint Helena”

为了保证小程序和 App 的后端服务不被侧面攻击(包括旁站、暴露端口等方式的攻击),一般需要完全隐藏源站的真实地址。于是开通了阿里云的全站加速服务,将网站放置于 CDN 后面。操作后发现并不能完全解决问题,当使用 IP 访问源站时,nginx 会默认返回当前网站内容,攻击这可以依赖一类互联网空间搜索平台(如 ZoomEyes)通过网站内容反向检索到源站真实 IP 地址。

屏蔽直接 IP 访问

树洞配置指南中给出的方法是只允许 CDN (文中是 Cloudflare)服务器访问源站 Web 端口,但阿里云并未提供他们的 CDN 服务器列表,只提供了一个查询接口:

本想试试对阿里云 CDN 的 IP 反向域名解析一波,看看是否存在阿里云 CDN 的特征,但是好像没有什么有用的信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
root@kiteserver:~# dig -x 101.133.199.29

; <<>> DiG 9.16.1-Ubuntu <<>> -x 101.133.199.29
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 20917
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;29.199.133.101.in-addr.arpa. IN PTR

;; Query time: 0 msec
;; SERVER: 127.0.0.53#53(127.0.0.53)
;; WHEN: Sat Apr 09 21:35:25 CST 2022
;; MSG SIZE rcvd: 56

转换思路,可以设置 nginx 拒绝用户通过 IP 地址访问:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
server {
listen 80 default_server;
server_name _;

return 403;
}

server {
listen 443 ssl http2 default;
server_name _;

ssl_certificate /data/self-cert/server.pem;
ssl_certificate_key /data/self-cert/server.key;

return 403;
}

其中,服务器证书可以通过自签名的方式随便生成(见参考资料2),这里不再赘述,但要注意我使用的 nginx 版本要求密钥长度至少为 2048bit,否则启动时将报错:

1
2
3
4
5
6
7
# journalctl -r -u nginx

Apr 09 19:15:18 kiteserver systemd[1]: Failed to start nginx - high performance web server.
Apr 09 19:15:18 kiteserver systemd[1]: nginx.service: Failed with result 'exit-code'.
Apr 09 19:15:18 kiteserver systemd[1]: nginx.service: Control process exited, code=exited, status=1/FAILURE
Apr 09 19:15:18 kiteserver nginx[50970]: nginx: [emerg] SSL_CTX_use_certificate("/data/self-cert/server.crt") failed (SSL: error:140AB18F:SSL routines:SSL_CTX_use_certificate:ee key too small)
Apr 09 19:15:17 kiteserver systemd[1]: Starting nginx - high performance web server...

网上有解决方案,但是尝试无果,只得老老实实地重新生成了一个证书。

后记

其他常见的追溯源站 IP 地址的方法还有:

  • 查询 DNS 历史解析记录
  • 网站邮件头信息
  • 利用国外主机解析域名

为了服务器的安全,应当保证站点独立使用 IP,这些以及其他溯源方式读者可以自行了解。对于私人使用的、常见的域名,应当在本地通过修改 /etc/hosts 文件的方式设置,实现良好的安全性。

参考资料

  1. DNS通识
  2. openssl生成自签名证书(完整版)
  3. 绕过CDN寻找真实IP的8种方法

欢迎关注我的其它发布渠道