DNS-over-QUIC 到 UDP 代理和客户端实现。
2019—2023 © NS1
此代码根据 Apache License 2.0 发布。您可以在许可证文件中找到条款和条件。
该实现遵循 RFC 9250:基于专用 QUIC 连接的 DNS。
QUIC 协议兼容性取决于 quic-go 库。
构建 DoQ 代理和测试客户端。
go build ./cmd/proxy
go build ./cmd/client
为代理服务器生成测试密钥和自签名证书。
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -pkeyopt ec_param_enc:named_curve -out server.key
openssl req -x509 -days 30 -subj "/CN=DNS-over-QUIC Test" -addext "subjectAltName=DNS:localhost,IP:127.0.0.1,IP:::1" -key server.key -out server.crt
启动代理。默认情况下,服务器从上面生成的文件加载 TLS 密钥和证书,将使用 8.8.4.4(Google 公共 DNS)作为后端服务器,并将侦听 UDP 端口 853(草案中的实验端口)。使用命令行选项修改默认行为。请注意,使用默认端口需要以超级用户身份启动代理。
sudo ./proxy
使用测试实用程序查询代理。客户端与服务器建立 QUIC 会话,并通过专用流发送每个查询。在上游,XFR 请求通过 TCP 发送,所有其他请求通过 UDP 发送。回复按完成顺序打印:
./client ns1.com A ns1.com AAAA
;; opcode: QUERY, status: NOERROR, id: 25849
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1
;; QUESTION SECTION:
;ns1.com. IN AAAA
;; ANSWER SECTION:
ns1.com. 195 IN AAAA 2606:4700:10::6814:31b6
ns1.com. 195 IN AAAA 2606:4700:10::6814:30b6
ns1.com. 195 IN RRSIG AAAA 13 2 200 20190325121641 20190323121641 44688 ns1.com. m17G7sGkXNhBiKINI2LuQLvUL0Qb+l6LMUmKSoVo2TP5sw3Yd27L44QOZhVU1GS//tD1e6YVOVsMrW3arlk/bQ==
;; ADDITIONAL SECTION:
;; OPT PSEUDOSECTION:
; EDNS: version 0; flags: do; udp: 512
;; opcode: QUERY, status: NOERROR, id: 26044
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1
;; QUESTION SECTION:
;ns1.com. IN A
;; ANSWER SECTION:
ns1.com. 25 IN A 104.20.49.182
ns1.com. 25 IN A 104.20.48.182
ns1.com. 25 IN RRSIG A 13 2 26 20190325121645 20190323121645 44688 ns1.com. xJK5DhMiFqxWx/gC7gHQXM8wkVFDyocIF3Zuehqa+S92zAq3yOtZMrqVRXxsKNw2lfCMQXLHr7hVUDm5H4B5eA==
;; ADDITIONAL SECTION:
;; OPT PSEUDOSECTION:
; EDNS: version 0; flags: do; udp: 512
代理服务器支持客户端证书认证。为了启用该功能,请提供 PEM 格式的 CA 证书包作为代理参数-mtls_ca_certs
。
生成测试 CA 证书:
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -pkeyopt ec_param_enc:named_curve -out ca.key
openssl req -x509 -days 30 -subj "/CN=DNS-over-QUIC Test CA" -addext "basicConstraints=critical,CA:true,pathlen:0" -key ca.key -out ca.crt
生成服务器和客户端证书并使用 CA 证书对其进行签名:
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -pkeyopt ec_param_enc:named_curve -out server.key
openssl req -x509 -CA ca.crt -CAkey ca.key -days 30 -subj "/CN=server" -addext "subjectAltName=DNS:localhost,IP:127.0.0.1,IP:::1" -key server.key -out server.crt
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -pkeyopt ec_param_enc:named_curve -out client.key
openssl req -x509 -CA ca.crt -CAkey ca.key -days 30 -subj "/CN=client" -key client.key -out client.crt
运行代理并通过提供 CA 证书作为 CA 捆绑包来启用 mTLS:
./proxy -mtls_ca_certs ca.crt
通过提供客户端证书来运行查询。 CA 捆绑包启用服务器证书验证:
./client -ca_certs ca.crt -cert client.crt -key client.key ns1.com. AAAA
请注意,这是建立在实验协议之上的实验代码。
此存储库中的服务器和客户端使用相同的 QUIC 库,因此它们应该兼容。但是,如果使用不同的客户端,版本协商时握手可能会失败。当客户端无法连接时,建议先检查抓包情况。
代理还记录有关已接受的连接和流的信息,这些信息可用于检查事件的顺序:
$ sudo ./proxy -listen 127.0.0.1:853 -cert cert.pem -key key.pem -backend 8.8.4.4:53
ts=2019-03-24T10:31:32.408891Z msg="listening for clients" addr=127.0.0.1:853
ts=2019-03-24T12:16:45.048583Z client=127.0.0.1:52212 msg="session accepted"
ts=2019-03-24T12:16:45.050231Z client=127.0.0.1:52212 stream_id=0 msg="stream accepted"
ts=2019-03-24T12:16:45.050278Z client=127.0.0.1:52212 stream_id=4 msg="stream accepted"
ts=2019-03-24T12:16:45.091568Z client=127.0.0.1:52212 stream_id=4 msg="stream closed"
ts=2019-03-24T12:16:45.104623Z client=127.0.0.1:52212 stream_id=0 msg="stream closed"
ts=2019-03-24T12:16:45.110261Z client=127.0.0.1:52212 msg="session closed"
该项目得到维护。
欢迎提出请求和问题。有关详细信息,请参阅 NS1 贡献指南。