1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > 如何快速的自建 DoH ( DNS over HTTPS) 服务

如何快速的自建 DoH ( DNS over HTTPS) 服务

时间:2022-01-15 10:59:37

相关推荐

如何快速的自建 DoH ( DNS over HTTPS) 服务

公众号关注「奇妙的 Linux 世界」

设为「星标」,每天带你玩转 Linux !

1. 前言

DoH(DNS over HTTPS),顾名思义,使用HTTPS协议执行DNS查询,除了最常用的UDP外,还有DoT(DNS over TLS),DNS over HTTP(服务提供商自定义)等方案,对比如下:

移动端的DNS优化已经有很多实践,最常见的是DNS over HTTP,通过加密的HTTP请求规避运营商对DNS的UDP包劫持,从而优化App访问服务器的延迟。但这个方案并没有形成统一的标准,通常需要内嵌DNS服务提供商的SDK,通过访问固定的 BGP或任播IP获取DNS响应。

大概是意识到DNS在移动互联网中的扮演越来越重要的角色,在DoT和DoH的规范相继推出后,许多DNS服务提供商都跟进了部署,国内的阿里云、DNSPod,国外的谷歌、Cloudflare等目前已经推出了免费的DoT和DoH服务。

客户端方面,常用的Chrome、FireFox已经支持了自定义DoH服务器,macOS、iOS也可通过配置文件设置系统范围的默认DoH服务器。

笔者也正好有一个自定义DNS的需求:

需要针对一些域名的DNS查询仅返回IPv4记录

使用的某某路由器系统的自定义DNS服务仅支持设置UDP和DoH

UDP模式默认使用53端口,不可修改,UDP包容易遭受干扰

DoH可自定义域名、端口且使用HTTP2作为传输协议,稳定性更强

综上,只有自建DoH服务了,于是就有了下面的折腾,最后测试时发现这个傻瓜路由器系统只支持一些特定的DoH服务商如阿里云DNS、DNSPod等,不支持自建的DoH服务。

2. 部署方案

DoH本质上就是一个HTTP请求,只是目前协议定义要求启用TLS与HTTP/2。最初没有跑通coredns的DoH时,使用了nginx作为前端转发DoH请求到doh-server,然后doh-server使用本地的coredns服务作为上游。

最近再仔细研究了下文档,发现coredns已经支持了DoH服务,可直接对外暴露服务,或者通过nginx转发来复用已经部署好的web服务。

2.1 nginx + doh-server + coredns

/m13253/dns-over-https 是一个提供 DNS over HTTP 的服务,需要一个web前端和一个DNS后端,可用的docker镜像地址为:[satishweb/doh-server](/r/satishweb/ doh-server),使用doh-server时,DNS请求流转如下:

HTTPService->doh-server->DNSServer

RFC8484中指定使用/dns-query路径作为默认查询路径,因此只需要将该路径前缀的请求转发到doh-server即可,如下:

nginx配置(已配置好TLS与HTTP2)

server{listen443sslhttp2fastopen=256reuseport;listen[::]:443sslhttp2fastopen=256reuseport;...location/dns-query{proxy_redirectoff;proxy_http_version1.1;proxy_set_headerHost$http_host;#showrealIPproxy_set_headerX-Real-IP$remote_addr;proxy_set_headerX-Forwarded-For$proxy_add_x_forwarded_for;proxy_passhttp://127.0.0.1:8053;}}

doh-server

使用hostNetwork模式启动服务,监听8053端口

dockerrun-d--restartunless-stopped--networkhost--namedoh-server\-eUPSTREAM_DNS_SERVER="udp:127.0.0.1:53"\-eDOH_HTTP_PREFIX="/dns-query"\-eDOH_SERVER_LISTEN="127.0.0.1:8053"\-eDOH_SERVER_TIMEOUT="10"\-eDOH_SERVER_TRIES="3"\-eDOH_SERVER_VERBOSE="true"\satishweb/doh-server

coredns

coredns配置文件如下

➜~tree/etc/coredns//etc/coredns/└──Corefile0directories,1files➜cat/etc/coredns/Corefile.:53{bind127.0.0.1forward.1.1.1.11.0.0.1logerrorscache}

使用hostNetwork模式启动服务,监听53端口

dockerrun-d--restartunless-stopped--networkhost--namecoredns\-v/etc/coredns:/etc/coredns\coredns/coredns\-conf/etc/coredns/Corefile

服务启动后,我们可以得到一个自定义的DoH服务:/dns-query

2.2 coredns

目前coredns支持作为DoH服务端,不支持连接上游DoH服务器,上游服务器可使用UDP和DoT。

直接对外暴露服务需要使用有效的TLS证书,coredns配置文件及证书位置如下:

➜~tree/etc/coredns//etc/coredns/├──Corefile├──tls.crt└──tls.key0directories,3files➜cat/etc/coredns/Corefilehttps://.:443{tls/etc/coredns/tls.crt/etc/coredns/tls.keybind0.0.0.0forward.1.1.1.11.0.0.1logerrorscache}

使用hostNetwork模式启动服务,监听443端口

dockerrun-d--restartunless-stopped--networkhost--namecoredns\-v/etc/coredns:/etc/coredns\coredns/coredns\-conf/etc/coredns/Corefile

服务启动后,我们可以得到一个自定义的DoH服务:/dns-query

2.3 nginx + coredns

直接暴露coredns服务到公网需要占用端口,coredns在未配置TLS证书时,可使用nginx作为前端来复用web服务,如下:

nginx配置(已配置好TLS与HTTP2)

server{listen443sslhttp2fastopen=256reuseport;listen[::]:443sslhttp2fastopen=256reuseport;...location/dns-query{proxy_redirectoff;proxy_http_version1.1;proxy_set_headerHost$http_host;#showrealIPproxy_set_headerX-Real-IP$remote_addr;proxy_set_headerX-Forwarded-For$proxy_add_x_forwarded_for;proxy_passhttp://127.0.0.1:8053;}}

coredns

coredns配置文件如下

➜~tree/etc/coredns//etc/coredns/└──Corefile0directories,1files➜cat/etc/coredns/Corefilehttps://.:8053{bind127.0.0.1forward.1.1.1.11.0.0.1logerrorscache}

使用hostNetwork模式启动服务,监听8053端口

dockerrun-d--restartunless-stopped--networkhost--namecoredns\-v/etc/coredns:/etc/coredns\coredns/coredns\-conf/etc/coredns/Corefile

服务启动后,我们可以得到一个自定义的DoH服务:/dns-query

3. 测试

使用谷歌浏览器配置DoH服务:Settings -> Secutiry and Privacy -> Secutiry -> Advanced -> Use secure DNS

使用Go代码测试:/mikumaycry/example/blob/main//doh/main.go

packagemainimport("encoding/base64""fmt""/miekg/dns""io/ioutil""net/http""os")funcmain(){query:=dns.Msg{}query.SetQuestion(".",dns.TypeA)msg,_:=query.Pack()b64:=base64.RawURLEncoding.EncodeToString(msg)resp,err:=http.Get("/dns-query?dns="+b64)iferr!=nil{fmt.Printf("Sendqueryerror,err:%v\n",err)os.Exit(1)}deferresp.Body.Close()bodyBytes,_:=ioutil.ReadAll(resp.Body)response:=dns.Msg{}response.Unpack(bodyBytes)fmt.Printf("Dnsansweris:%v\n",response.String())}

本文转载自:「 Wbuntu 的博客」,原文:/deploy-a-doh-service/ ,版权归原作者所有。欢迎投稿,投稿邮箱: editor@hi-。

最近,我们建立了一个技术交流微信群。目前群里已加入了不少行业内的大神,有兴趣的同学可以加入和我们一起交流技术,在「奇妙的 Linux 世界」公众号直接回复「加群」邀请你入群。

你可能还喜欢

点击下方图片即可阅读

如何优雅的用 Nginx 在公网上快速搭建一个加密数据通道

点击上方图片,『美团|饿了么』外卖红包天天免费领

更多有趣的互联网新鲜事,关注「奇妙的互联网」视频号全了解!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。