DNS-over-QUIC から UDP プロキシおよびクライアントへの実装。
2019—2023 © NS1
このコードは、Apache License 2.0 に基づいてリリースされています。契約条件は LICENSE ファイルにあります。
実装は RFC 9250: DNS over D dedicated QUIC Connections に従います。
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 Public 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 貢献ガイドライン」を参照してください。