DNS-over-QUIC для UDP-прокси и реализации клиента.
2019—2023 © НС1
Этот код выпущен под лицензией Apache License 2.0. Условия использования можно найти в файле ЛИЦЕНЗИИ.
Реализация соответствует RFC 9250: DNS через выделенные соединения QUIC.
Совместимость протокола 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 (публичный DNS Google) в качестве внутреннего сервера и будет прослушивать порт 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
Прокси-сервер поддерживает аутентификацию сертификата клиента. Чтобы включить эту функцию, укажите пакет сертификатов CA в формате PEM в качестве параметра прокси -mtls_ca_certs
.
Создайте тестовый сертификат ЦС:
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
Запустите прокси и включите mTLS, предоставив сертификат CA в виде пакета CA:
./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.