如果只要实现DOH那很简单,CoreDNS本身就可以整一个出来。但是关键是如何避免被扫描到而被滥用、避免被扫描到然后被枪毙。之前看到过一个reddit老哥分享的方法,就是用很长的字符串替换标准DOH的/dns-query
uri来充当password,实现避免除了自己人都无法访问这个DOH服务器的效果。
假设要用sF5FWjUk
来作为URI,那么nginx中需要配置一个Location块:
1
2
3
4
5
6
7
8
9
location /sF5FWjUk {
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
# show real IP
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:8443/dns-query;
}
就是说匹配/sF5FWjUk
的访问,都转发(proxy_pass)到监听在127.0.0.1的8443端口的CoreDNS所提供的DOH服务上。而CoreDNS的文档里有说明,CoreDNS提供一种特殊的DOH模式:CoreDNS自己不作为TLS终点,也就是CoreDNS虽然提供DOH服务但是不对请求进行HTTPS加解密,而是让另一个软件(比如nginx)负责这个工作。因此CoreDNS的配置文件只需要这样写:
1
2
3
4
https://.:8443 {
bind 127.0.0.1
forward . 127.0.0.1:8053
}
简简单单,功能类似于:把接收到的DoH请求转换成普通DNS请求,转发给监听在8053端口的dnscrypt-proxy。
所以整个流程下来就实现了:
- 非公开DoH,防止被探测和滥用
- DoH服务
- dnscrypt-proxy所提供的ECS、加密DNS请求、中国域名分流请求
等功能。其实dnscrypt-proxy那一部份不是必要的,如果不需要edns-client-subnet之类的功能,对于log也不是特别在意的话,把CoreDNS的forward写成比如forward . 8.8.8.8:53
就完事了。