DNS

DNS

根据 RFC,所有 domain 的 FQDN (fully qualified domain name) 以 "." 结尾。如 google.com 的 FQDN 是 "google.com." 。但现在通常习惯省略域名末尾的 "." 。

末尾带 . 和不带 . 的域名都可以出现在 URL 的 hostname 部分,但两者本质上是不同东西。HTTPS 证书的 Common Name,浏览器同源策略(CORS)的 origin 等会区分带 . 的和不带 . 的为不同域名。

一些网站支持带 . 的域名访问,通常会重定向到不带 . 的域名。例如:

# curl -I https://google.com.
HTTP/2 301 
location: https://www.google.com/

顶级域名也可以有 A 记录,例如: http://ai./。由于只有1个层级的域名会和局域网设备 hostname 混淆,在浏览器等地方可能需要末尾带 . 才能访问。

公共 DNS 服务器

DoT 使用 tcp/853 端口。

  • Google DNS: 8.8.8.8 / 8.8.4.4
    • tls://8.8.8.8:853, tls://8.8.4.4:853
    • 注:Google DNS 最傻逼的是 TTL 时间见鬼的长。改个 NS 服务器可能需要几个小时才能反映在 Google DNS 里。而 Cloudflare 只需几分钟。
    • 傻逼 Google 自从阿三当 CEO 后越来越傻逼。
  • Cloudflare DNS: 1.1.1.1, 1,0,0,1
    • tls://1.1.1.1:853, tls://1.0.0.1:853
    • https://1.1.1.1/dns-query, https://1.0.0.1/dns-query
  • 阿里 dns (Docs)
    • 223.5.5.5, 223.6.6.6
    • tls://223.5.5.5:853, tls://223.6.6.6:853
    • 2400:3200::1, 2400:3200:baba::1
    • DoH: https://dns.alidns.com/dns-query, https://223.5.5.5/dns-query , https://223.6.6.6/dns-query
    • 证书 的Common Name 是 *.alidns.com。使用 IP 地址访问时,较旧版本的某些工具(例如 curl 和使用 libcurl 的程序)测试证书报错(不识别证书里的 Certificate Subject ALternative Name / IP Address 类型字段)。

DoH

OpenWrt

  • smartdns 直接支持 DoH upstream。
  • https-dns-proxy 这个轻量的 opkg 包(需要 overlay 可用空间 40KB )可以将上游 DoH 转为本地 udp DNS 端口,通常配合 dnsmasq 使用。

https-dns-proxy

Docs

https-dns-proxy is configured with Google DNS and Cloudflare DNS by default. You can change it to Google DNS or any other DoH provider. Use resolvers supporting DNSSEC validation if necessary. Specify several resolvers to improve fault tolerance.

默认的 uci 配置: (uci show | grep https-dns-proxy)

https-dns-proxy.config=main
https-dns-proxy.config.update_dnsmasq_config='*'
https-dns-proxy.config.force_dns='1'
https-dns-proxy.config.force_dns_port='53' '853'
https-dns-proxy.@https-dns-proxy[0]=https-dns-proxy
https-dns-proxy.@https-dns-proxy[0].bootstrap_dns='1.1.1.1,1.0.0.1'
https-dns-proxy.@https-dns-proxy[0].resolver_url='https://cloudflare-dns.com/dns-query'
https-dns-proxy.@https-dns-proxy[0].listen_addr='127.0.0.1'
https-dns-proxy.@https-dns-proxy[0].listen_port='5054'
https-dns-proxy.@https-dns-proxy[0].user='nobody'
https-dns-proxy.@https-dns-proxy[0].group='nogroup'
https-dns-proxy.@https-dns-proxy[1]=https-dns-proxy
https-dns-proxy.@https-dns-proxy[1].bootstrap_dns='8.8.8.8,8.8.4.4'
https-dns-proxy.@https-dns-proxy[1].resolver_url='https://dns.google/dns-query'
https-dns-proxy.@https-dns-proxy[1].listen_addr='127.0.0.1'
https-dns-proxy.@https-dns-proxy[1].listen_port='5053'
https-dns-proxy.@https-dns-proxy[1].user='nobody'
https-dns-proxy.@https-dns-proxy[1].group='nogroup'
# Configure DoH provider
while uci -q delete https-dns-proxy.@https-dns-proxy[0]; do :; done
uci set https-dns-proxy.dns="https-dns-proxy"
uci set https-dns-proxy.config.update_dnsmasq_config="-"
uci set https-dns-proxy.config.force_dns="0"
uci set https-dns-proxy.dns.bootstrap_dns="8.8.8.8,8.8.4.4"
uci set https-dns-proxy.dns.resolver_url="https://dns.alidns.com/dns-query"
uci set https-dns-proxy.dns.listen_addr="127.0.0.1"
uci set https-dns-proxy.dns.listen_port="5053"
uci commit https-dns-proxy
/etc/init.d/https-dns-proxy restart

Debug:

https-dns-proxy -r https://dns.alidns.com/dns-query -a 0.0.0.0 -p 5053 -b 8.8.8.8,8.8.4.4 -4 -l https-dn
s.log -v debug

注明:

  • https-dns-proxy 文档
  • 测试 OpenWrt 版 https-dns-proxy 使用 "https://223.5.5.5/dns-query" TLS 证书错误,无法工作。
  • update_dnsmasq_config : 对应 https-dns-proxy 配置里的 dnsmasq_config_update。设为 "-" 则 https-dns-proxy 启动和停止时不会修改 dnsmasq 配置——将 dnsmasq 上游设为 https-dns-proxy ( server=127.0.0.1#5053 ),同时添加 Canary domain (use-application-dns.net)的特殊解析记录。
  • 如果 force_dns 为 1 (初始配置), https-dns-proxy 启动时会在 iptables nat/zone_lan_prerouting 链添加规则劫持 DNS 解析请求 REDIRECT 到自己监听端口。

smartdns

smartdns 直接支持使用 DoH 上游服务器。

server-https 1.0.0.1 -no-check-certificate
  • 部分编译版本的 smartdns DoH 和 / 或 DoT 有问题,可能解析失败。

use-application-dns.net

To signal that their local DNS resolver implements special features that make the network unsuitable for DNS-over-HTTPS (DoH), network administrators may configure their networks to modify DNS requests for the following special-purpose domain, called a canary domain: use-application-dns.net.

Mozilla 提出的标准。如果本地网络的默认 DNS 对 use-application-dns.net 的 A 记录解析返回 NXDOMAIN (或没有任何 A / AAAA 结果记录),则设备会自动禁用本地配置的 DoH 服务器。这个域名是 Mozilla 注册的。

这玩意意义不明,有什么用?。

_esni

ESNI 使用 _esni. 子域名的 TXT 记录存储客户端连接对应域名时用来加密 SNI 的公钥 base64。

ESNI 已经被 ECH 取代。

# 2023-10 测试以下记录已经无效
$ dig _esni.crypto.dance TXT +short
"/wGuNThxACQAHQAgXzyda0XSJRQWzDG7lk/r01r1ZQy+MdNxKg/mAqSnt0EAAhMBAQQAAAAAX67XsAAAAABftsCwAAA="

HTTPS (type65) / SVCB (type64) record

文档

HTTPS DNS record (type65, 又称 SVCB, service binding) 允许定义应用层的协议(HTTPS / h2 / h3),ECH (Encrypted Client Hello) 密钥和其它信息。

dig crypto.cloudflare.com type65 +short

1 . alpn="http/1.1,h2" ipv4hint=162.159.137.85,162.159.138.85 ech=AEX+DQBB2gAgACAnkIw2/4kebHPs0aL+X9TsrT4ZYOkpZUtzq3SSEoxMFQAEAAEAAQASY2xvdWRmbGFyZS1lY2guY29tAAA= ipv6hint=2606:4700:7::a29f:8955,2606:4700:7::a29f:8a55

结果字段:

  • 第一个数字: priority. 数字越小优先级越高。客户端进行负载均衡/错误重试。0为特殊值,表示为 alias 记录(类似 CNAME)。
  • ipv4hint / ipv6hint : 等效于 A / AAAA 记录。避免客户端需要重复发出 HTTPS 和 A/AAAA 两种查询。
    • These addresses can be used by a client in case the addresses of an endpoint are not already known. If the adresses are already known, the hints from the HTTPS record should not be used
  • alpn : TLS 的 Application-Layer Protocol 的 id。指示客户端使用的协议。避免了传统方式使用 h2 / h3 需要先建立 http/1.1 会话然后再 upgrade(注:TLS连接里ServerHello的ALPN字段包含了服务器支持的应用层协议列表,如["h2", "http1.1"],所以客户端实际上也会直接选择 h2 连接)。
    • h2: HTTP/2 over TLS
    • h2c: HTTP/2 over TCP
    • h3: HTTP/3
    • http/1.1: HTTP/1.1
  • ech : 指示客户端该域名的 Web 服务器 ECH 的公钥。值为 ECHConfigList, 包括 base64 形式的服务器公钥。
  • port : 配置(非标的)服务器TCP/UDP端口。

When a website has deployed an HTTPS DNS record and Chrome receives it, Chrome will always connect to the website via HTTPS. 所以 DNS 的 type65 record 等效于 HSTS ?

CloudFlare 托管的所有域名支持(并默认启用) type65 记录?

Chrome v118+ 默认检测网站域名的 HTTPS record 并在 alpn 支持 h3 时自动使用 QUIC (h3) 协议连接网站。

HTTPS vs SVCB

  • The HTTPS record (type65) is a special version of the SVCB record
  • The SVCB record (type64) is the generalized version of the HTTPS record (type65)
  • SVCB encodes a service name (as an Attrleaf naming pattern, RFC 8552 and RFC 8553)
    • _service.domain.tld. or _ssh.example.com.
  • The service label can be pretended with a Attrleaf label for a non-standard port: _4422._ssh.example.net. (Service ssh on port 4422)

Debug

nslookup (Windows) 只会使用唯一的第一优先级 DNS 作为指定服务器,不带失败回退和尝试其他可用服务器机制的。而系统和其他的软件是会在首选服务器失败后尝试查询其他可用服务器的。

Linux 版的 nslookup / dig 等命令行工具应该也是如此。


Last update: 2024-01-19 08:45:47 UTC