ПоднимаСм свой DNS-over-HTTPS сСрвСр

Π Π°Π·Π»ΠΈΡ‡Π½Ρ‹Π΅ аспСкты эксплуатации DNS ΡƒΠΆΠ΅ Π½Π΅ΠΎΠ΄Π½ΠΎΠΊΡ€Π°Ρ‚Π½ΠΎ Π·Π°Ρ‚Ρ€Π°Π³ΠΈΠ²Π°Π»ΠΈΡΡŒ Π°Π²Ρ‚ΠΎΡ€ΠΎΠΌ Π² рядС статСй ΠΎΠΏΡƒΠ±Π»ΠΈΠΊΠΎΠ²Π°Π½Π½Ρ‹Ρ… Π² Ρ€Π°ΠΌΠΊΠ°Ρ… Π±Π»ΠΎΠ³Π°. ΠŸΡ€ΠΈ этом, основной Π°ΠΊΡ†Π΅Π½Ρ‚ всСгда дСлался Π½Π° ΠΏΠΎΠ²Ρ‹ΡˆΠ΅Π½ΠΈΠ΅ бСзопасности этого ΠΊΠ»ΡŽΡ‡Π΅Π²ΠΎΠ³ΠΎ для всСго Π˜Π½Ρ‚Π΅Ρ€Π½Π΅Ρ‚ сСрвиса.

ПоднимаСм свой DNS-over-HTTPS сСрвСр

Π”ΠΎ послСднСго Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ, нСсмотря Π½Π° ΠΎΡ‡Π΅Π²ΠΈΠ΄Π½ΠΎΡΡ‚ΡŒ уязвимости DNS Ρ‚Ρ€Π°Ρ„ΠΈΠΊΠ°, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ, Π΄ΠΎ сих ΠΏΠΎΡ€, ΠΏΠΎ большСй части, пСрСдаётся Π² ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚ΠΎΠΌ Π²ΠΈΠ΄Π΅, для Π·Π»ΠΎΠ½Π°ΠΌΠ΅Ρ€Π΅Π½Π½Ρ‹Ρ… дСйствий со стороны ΠΏΡ€ΠΎΠ²Π°ΠΉΠ΄Π΅Ρ€ΠΎΠ², стрСмящихся ΠΏΠΎΠ²Ρ‹ΡΠΈΡ‚ΡŒ своих Π΄ΠΎΡ…ΠΎΠ΄Ρ‹ Π·Π° счёт встраивания Ρ€Π΅ΠΊΠ»Π°ΠΌΡ‹ Π² ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚, государствСнных силовых ΠΎΡ€Π³Π°Π½ΠΎΠ² ΠΈ Ρ†Π΅Π½Π·ΡƒΡ€Ρ‹, Π° Ρ‚Π°ΠΊΠΆΠ΅ просто прСступников, процСсс усилСния Π΅Π³ΠΎ Π·Π°Ρ‰ΠΈΡ‚Ρ‹, нСсмотря Π½Π° Π½Π°Π»ΠΈΡ‡ΠΈΠ΅ Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Ρ… Ρ‚Π΅Ρ…Π½ΠΎΠ»ΠΎΠ³ΠΈΠΉ, Ρ‚Π°ΠΊΠΈΡ… ΠΊΠ°ΠΊ DNSSEC/DANE, DNScrypt, DNS-over-TLS ΠΈ DNS-over-HTTPS, буксовал. И Ссли сСрвСрныС Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ, Π° Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΈΠ· Π½ΠΈΡ… ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‚ ΡƒΠΆΠ΅ довольно Π΄ΠΎΠ»Π³ΠΎΠ΅ врСмя, ΡˆΠΈΡ€ΠΎΠΊΠΎ извСстны ΠΈ доступны, Ρ‚ΠΎ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ° ΠΈΡ… со стороны клиСнтского ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½ΠΎΠ³ΠΎ обСспСчСния оставляСт ΠΆΠ΅Π»Π°Ρ‚ΡŒ ΠΌΠ½ΠΎΠ³ΠΎ Π»ΡƒΡ‡ΡˆΠ΅Π³ΠΎ.

К ΡΡ‡Π°ΡΡ‚ΡŒΡŽ, ситуация мСняСтся. Π’ частности, Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ популярного Π±Ρ€Π°ΡƒΠ·Π΅Ρ€Π° Firefox заявили ΠΎ ΠΏΠ»Π°Π½Π°Ρ… ΠΏΠΎ Π²ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡŽ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ Ρ€Π΅ΠΆΠΈΠΌΠ° ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠΈ Ρ€Π΅ΠΆΠΈΠΌΠ° DNS-over-HTTPS (DoH) Π² блиТайшСС врСмя. Π­Ρ‚ΠΎ Π΄ΠΎΠ»ΠΆΠ½ΠΎ ΠΏΠΎΠΌΠΎΡ‡ΡŒ Π·Π°Ρ‰ΠΈΡ‚ΠΈΡ‚ΡŒ DNS Ρ‚Ρ€Π°Ρ„ΠΈΠΊ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ WWW ΠΎΡ‚ Π²Ρ‹ΡˆΠ΅ΡƒΠΏΠΎΠΌΡΠ½ΡƒΡ‚Ρ‹Ρ… ΡƒΠ³Ρ€ΠΎΠ·, ΠΎΠ΄Π½Π°ΠΊΠΎ ΠΏΠΎΡ‚Π΅Π½Ρ†ΠΈΠ°Π»ΡŒΠ½ΠΎ способно Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ Π½ΠΎΠ²Ρ‹Π΅.

1. ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ DNS-over-HTTPS

На ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ взгляд, Π½Π°Ρ‡ΠΈΠ½Π°ΡŽΡ‰Π΅Π΅ΡΡ массовоС Π²Π½Π΅Π΄Ρ€Π΅Π½ΠΈΠ΅ DNS-over-HTTPS Π² ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½ΠΎΠ΅ обСспСчСниС Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‰Π΅Π΅ Π² Π˜Π½Ρ‚Π΅Ρ€Π½Π΅Ρ‚ Π²Ρ‹Π·Ρ‹Π²Π°Π΅Ρ‚ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΠΎΠ·ΠΈΡ‚ΠΈΠ²Π½ΡƒΡŽ Ρ€Π΅Π°ΠΊΡ†ΠΈΡŽ. Однако, Ρ‡Ρ‘Ρ€Ρ‚, ΠΊΠ°ΠΊ говорится, кроСтся Π² дСталях.

ΠŸΠ΅Ρ€Π²ΠΎΠΉ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠΎΠΉ, которая ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡ΠΈΠ²Π°Π΅Ρ‚ сфСру массового примСнСния DoH, являСтся Π΅Π³ΠΎ ориСнтация ΠΈΡΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ Π½Π° Π²Π΅Π±-Ρ‚Ρ€Π°Ρ„ΠΈΠΊ. Π”Π΅ΠΉΡΡ‚Π²ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ, ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» HTTP ΠΈ Π΅Π³ΠΎ Π°ΠΊΡ‚ΡƒΠ°Π»ΡŒΠ½Π°Ρ рСдакция HTTP/2, Π½Π° ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ базируСтся DoH, являСтся основой WWW. Но Π˜Π½Ρ‚Π΅Ρ€Π½Π΅Ρ‚ это Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π²Π΅Π±. БущСствуСт масса популярых сСрвисов, Ρ‚Π°ΠΊΠΈΠ΅, ΠΊΠ°ΠΊ элСктронная ΠΏΠΎΡ‡Ρ‚Π°, всСвозмоТныС мСссСндТСры, систСмы ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ Ρ„Π°ΠΉΠ»ΠΎΠ², стриминг ΠΌΡƒΠ»ΡŒΡ‚ΠΈΠΌΠ΅Π΄ΠΈΠ° ΠΈ ΠΏΡ€ΠΎΡ‡., ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π½Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ HTTP. Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, нСсмотря Π½Π° восприятиС ΠΌΠ½ΠΎΠ³ΠΈΠΌΠΈ DoH ΠΊΠ°ΠΊ ΠΏΠ°Π½Π°Ρ†Π΅ΠΈ, ΠΎΠ½ оказываСтся Π½Π΅ΠΏΡ€ΠΈΠΌΠ΅Π½ΠΈΠΌ Π±Π΅Π· Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Ρ… (Π΄Π° ΠΈ Π½Π΅ Π½ΡƒΠΆΠ½Ρ‹Ρ…) усилий, Π½ΠΈ для Ρ‡Π΅Π³ΠΎ ΠΈΠ½ΠΎΠ³ΠΎ, ΠΊΡ€ΠΎΠΌΠ΅ Π±Ρ€Π°ΡƒΠ·Π΅Ρ€Π½Ρ‹Ρ… Ρ‚Π΅Ρ…Π½ΠΎΠ»ΠΎΠ³ΠΈΠΉ. К слову, Π½Π° эту Ρ€ΠΎΠ»ΡŒ ΠΊΡƒΠ΄Π° ΠΊΠ°ΠΊ Π±ΠΎΠ»Π΅Π΅ достойным ΠΊΠ°Π½Π΄ΠΈΠ΄Π°Ρ‚ΠΎΠΌ выглядит DNS-over-TLS, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠ΅Ρ‚ ΠΈΠ½ΠΊΠ°ΠΏΡΡƒΠ»ΡΡ†ΠΈΡŽ стандартного DNS Ρ‚Ρ€Π°Ρ„ΠΈΠΊΠ° Π² Π·Π°Ρ‰ΠΈΡ‰Ρ‘Π½Π½Ρ‹ΠΉ стандартный ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» TLS.

Π’Ρ‚ΠΎΡ€ΠΎΠΉ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠΎΠΉ, которая ΠΏΠΎΡ‚Π΅Π½Ρ†ΠΈΠ°Π»ΡŒΠ½ΠΎ ΠΊΡƒΠ΄Π° ΠΊΠ°ΠΊ Π±ΠΎΠ»Π΅Π΅ Π·Π½Π°Ρ‡ΠΈΠΌΠ°, Ρ‡Π΅ΠΌ пСрвая, являСтся фактичСский ΠΎΡ‚ΠΊΠ°Π· ΠΎΡ‚ присущСй DNS by design Π΄Π΅Ρ†Π΅Π½Ρ‚Ρ€Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Π² ΡƒΠ³ΠΎΠ΄Ρƒ использования ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅ΠΌΠΎΠ³ΠΎ Π² настройках Π±Ρ€Π°ΡƒΠ·Π΅Ρ€Π° Π΅Π΄ΠΈΠ½ΠΎΠ³ΠΎ DoH сСрвСра. Π’ частности, Mozilla ΠΏΡ€Π΅Π΄Π»Π°Π³Π°Π΅Ρ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ сСрвис ΠΎΡ‚ Cloudflare. ΠŸΠΎΠ΄ΠΎΠ±Π½Ρ‹ΠΉ сСрвис запустили Ρ‚Π°ΠΊΠΆΠ΅ ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ Π·Π°ΠΌΠ΅Ρ‚Π½Ρ‹Π΅ Ρ„ΠΈΠ³ΡƒΡ€Ρ‹ Π˜Π½Ρ‚Π΅Ρ€Π½Π΅Ρ‚, Π² частности Google. ΠŸΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ΡΡ, Ρ‡Ρ‚ΠΎ Π²Π½Π΅Π΄Ρ€Π΅Π½ΠΈΠ΅ DNS-over-HTTPS Π² Ρ‚ΠΎΠΌ Π²ΠΈΠ΄Π΅, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ это прСдлагаСтся сСйчас, лишь ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΠ²Π°Π΅Ρ‚ Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡ‚ΡŒ ΠΊΠΎΠ½Π΅Ρ‡Π½Ρ‹Ρ… ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ ΠΎΡ‚ ΠΊΡ€ΡƒΠΏΠ½Π΅ΠΉΡˆΠΈΡ… сСрвисов. НС сСкрСт, Ρ‡Ρ‚ΠΎ информация, ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²ΠΈΡ‚ΡŒ Π°Π½Π°Π»ΠΈΠ· DNS запросов способСн ΡΠΎΠ±ΠΈΡ€Π°Ρ‚ΡŒ Π΅Ρ‰Ρ‘ большС Π΄Π°Π½Π½Ρ‹Ρ… ΠΎ Π½Ρ‘ΠΌ, Π° Ρ‚Π°ΠΊΠΆΠ΅ ΠΏΠΎΠ²Ρ‹ΡΠΈΡ‚ΡŒ ΠΈΡ… Ρ‚ΠΎΡ‡Π½ΠΎΡΡ‚ΡŒ ΠΈ Π°ΠΊΡ‚ΡƒΠ°Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ.

Π’ этой связи, Π°Π²Ρ‚ΠΎΡ€ Π±Ρ‹Π» ΠΈ остаётся сторонником массового внСдрСния Π½Π΅ DNS-over-HTTPS, Π° DNS-over-TLS совмСстно с DNSSEC/DANE ΠΊΠ°ΠΊ ΡƒΠ½ΠΈΠ²Π΅Ρ€ΡΠ°Π»ΡŒΠ½ΠΎΠ³ΠΎ, бСзопасного ΠΈ Π½Π΅ ΡΠΏΠΎΡΠΎΠ±ΡΡ‚Π²ΡƒΡŽΡ‰Π΅Π³ΠΎ дальнСйшСй Ρ†Π΅Π½Ρ‚Ρ€Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Π˜Π½Ρ‚Π΅Ρ€Π½Π΅Ρ‚ срСдства для обСспСчСния бСзопасности DNS Ρ‚Ρ€Π°Ρ„ΠΈΠΊΠ°. К соТалСнию, ΠΎΠΆΠΈΠ΄Π°Ρ‚ΡŒ быстроС Π²Π½Π΅Π΄Ρ€Π΅Π½ΠΈΠ΅ массовой ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠΈ Π°Π»ΡŒΡ‚Π΅Ρ€Π½Π°Ρ‚ΠΈΠ² DoH Π² клиСнтский софт Π² силу понятных ΠΏΡ€ΠΈΡ‡ΠΈΠ½, Π½Π΅ приходится ΠΈ Π΅Ρ‘ ΡƒΠ΄Π΅Π»ΠΎΠΌ ΠΏΠΎΠΊΠ° ΠΎΡΡ‚Π°ΡŽΡ‚ΡΡ энтузиасты бСзопасных Ρ‚Π΅Ρ…Π½ΠΎΠ»ΠΎΠ³ΠΈΠΉ.

Но, коль ΡƒΠΆ ΠΌΡ‹ Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ DoH, Ρ‚ΠΎ ΠΏΠΎΡ‡Π΅ΠΌΡƒ Π±Ρ‹ Π½Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π΅Π³ΠΎ, ΠΏΡ€Π΅Π΄Π²Π°Ρ€ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ уйдя ΠΎΡ‚ ΠΏΠΎΡ‚Π΅Π½Ρ†ΠΈΠ°Π»ΡŒΠ½ΠΎΠΉ слСТки ΠΏΠΎ стороны ΠΊΠΎΡ€ΠΏΠΎΡ€Π°Ρ†ΠΈΠΉ посрСдством ΠΈΡ… сСрвСров Π½Π° свой собствСнный DNS-over-HTTPS сСрвСр?

2. ΠŸΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» DNS-over-HTTPS

Если Π²Π·Π³Π»ΡΠ½ΡƒΡ‚ΡŒ Π² стандарт RFC8484 ΠΎΠΏΠΈΡΡ‹Π²Π°ΡŽΡ‰ΠΈΠΉ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» DNS-over-HTTPS, Ρ‚ΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΡƒΠ²ΠΈΠ΄Π΅Ρ‚ΡŒ, Ρ‡Ρ‚ΠΎ ΠΎΠ½, ΠΏΠΎ сути, прСдставляСт собой Π²Π΅Π± API ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‰ΠΈΠΉ ΠΈΠ½ΠΊΠ°ΠΏΡΡƒΠ»ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ стандартный ΠΏΠ°ΠΊΠ΅Ρ‚ DNS Π² ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» HTTP/2. Π­Ρ‚ΠΎ рСализуСтся посрСдством ΡΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½Ρ‹Ρ… HTTP-Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΎΠ², Π° Ρ‚Π°ΠΊΠΆΠ΅ конвСрсии Π±ΠΈΠ½Π°Ρ€Π½ΠΎΠ³ΠΎ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π° ΠΏΠ΅Ρ€Π΅Π΄Π°Π²Π°Π΅ΠΌΡ‹Ρ… DNS Π΄Π°Π½Π½Ρ‹Ρ… (см. RFC1035 ΠΈ ΠΏΠΎΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Ρ‹) Π² Ρ„ΠΎΡ€ΠΌΡƒ, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‰ΡƒΡŽ ΠΏΠ΅Ρ€Π΅Π΄Π°Π²Π°Ρ‚ΡŒ ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π°Ρ‚ΡŒ ΠΈΡ…, Π° Ρ‚Π°ΠΊΠΆΠ΅ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ с Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹ΠΌΠΈ ΠΌΠ΅Ρ‚Π°Π΄Π°Π½Π½Ρ‹ΠΌΠΈ.

По стандарту поддСрТиваСтся Ρ‚ΠΎΠ»ΡŒΠΊΠΎ HTTP/2 ΠΈ Π·Π°Ρ‰ΠΈΡ‰Ρ‘Π½Π½ΠΎΠ΅ соСдинСниС TLS.

ΠžΡ‚ΠΏΡ€Π°Π²ΠΊΠ° DNS-запроса ΠΌΠΎΠΆΠ΅Ρ‚ производится стандартными ΠΌΠ΅Ρ‚ΠΎΠ΄Π°ΠΌΠΈ GET ΠΈ POST. Π’ ΠΏΠ΅Ρ€Π²ΠΎΠΌ случаС запрос трансформируСтся base64URL-encoded строку, Π° Π²ΠΎ-Π²Ρ‚ΠΎΡ€ΠΎΠΌ β€” Ρ‡Π΅Ρ€Π΅Π· Ρ‚Π΅Π»ΠΎ POST-запроса Π² Π΄Π²ΠΎΠΈΡ‡Π½ΠΎΠΉ Ρ„ΠΎΡ€ΠΌΠ΅. ΠŸΡ€ΠΈ этом ΠΏΡ€ΠΈ запросС ΠΈ ΠΏΡ€ΠΈ ΠΎΡ‚Π²Π΅Ρ‚Π΅ DNS ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΡΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½Ρ‹ΠΉ MIME-Ρ‚ΠΈΠΏ Π΄Π°Π½Π½Ρ‹Ρ… application/dns-message.

root@eprove:~ # curl -H 'accept: application/dns-message' 'https://my.domaint/dns-query?dns=q80BAAABAAAAAAAAB2V4YW1wbGUDY29tAAABAAE' -v
*   Trying 2001:100:200:300::400:443...
* TCP_NODELAY set
* Connected to eprove.net (2001:100:200:300::400) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /usr/local/share/certs/ca-root-nss.crt
  CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=my.domain
*  start date: Jul 22 00:07:13 2019 GMT
*  expire date: Oct 20 00:07:13 2019 GMT
*  subjectAltName: host "my.domain" matched cert's "my.domain"
*  issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x801441000)
> GET /dns-query?dns=q80BAAABAAAAAAAAB2V4YW1wbGUDY29tAAABAAE HTTP/2
> Host: eprove.net
> User-Agent: curl/7.65.3
> accept: application/dns-message
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* Connection state changed (MAX_CONCURRENT_STREAMS == 100)!
< HTTP/2 200
< server: h2o/2.3.0-beta2
< content-type: application/dns-message
< cache-control: max-age=86274
< date: Thu, 12 Sep 2019 13:07:25 GMT
< strict-transport-security: max-age=15768000; includeSubDomains; preload
< content-length: 45
<
Warning: Binary output can mess up your terminal. Use "--output -" to tell
Warning: curl to output it to your terminal anyway, or consider "--output
Warning: <FILE>" to save to a file.
* Failed writing body (0 != 45)
* stopped the pause stream!
* Connection #0 to host eprove.net left intact

ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Ρ‚Π°ΠΊΠΆΠ΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π° Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ cache-control: Π² ΠΎΡ‚Π²Π΅Ρ‚Π΅ со стороны Π²Π΅Π±-сСрвСра. Π’ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π΅ max-age содСрТится Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ TTL для Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΠΎΠΉ записи DNS (ΠΈΠ»ΠΈ минимальноС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Ссли возвращаСтся ΠΈΡ… Π½Π°Π±ΠΎΡ€).

Π˜ΡΡ…ΠΎΠ΄Ρ ΠΈΠ· Π²Ρ‹ΡˆΠ΅ΠΈΠ·Π»ΠΎΠΆΠ΅Π½Π½ΠΎΠ³ΠΎ, Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ DoH сСрвСра состоит ΠΈΠ· Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… этапов.

  • ΠŸΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ HTTP запрос. Если это GET Ρ‚ΠΎ Π΄Π΅ΠΊΠΎΠ΄ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΠ°ΠΊΠ΅Ρ‚ ΠΈΠ· base64URL ΠΊΠΎΠ΄ΠΈΡ€ΠΎΠ²ΠΊΠΈ.
  • ΠžΡ‚ΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ этот ΠΏΠ°ΠΊΠ΅Ρ‚ DNS сСрвСру.
  • ΠŸΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ ΠΎΡ‚Π²Π΅Ρ‚ ΠΎΡ‚ DNS сСрвСра
  • Найти минимальноС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ TTL Π² ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½Ρ‹Ρ… записях.
  • Π’Π΅Ρ€Π½ΡƒΡ‚ΡŒ ΠΊΠ»ΠΈΠ΅Π½Ρ‚Ρƒ ΠΎΡ‚Π²Π΅Ρ‚ ΠΏΠΎ HTTP.

3. Π‘Π²ΠΎΠΉ DNS-over-HTTPS сСрвСр

НаиболСС простым, быстрым ΠΈ эффСктивным способом Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ свой собствСнный DNS-over-HTTPS сСрвСр прСдставляСтся использованиС HTTP/2 Π²Π΅Π±-сСрвСра H2O, ΠΎ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ Π°Π²Ρ‚ΠΎΡ€ ΡƒΠΆΠ΅ Π²ΠΊΡ€Π°Ρ‚Ρ†Π΅ писал (см. «Π’Ρ‹ΡΠΎΠΊΠΎΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ Π²Π΅Π±-сСрвСр H2O«).

Π’ ΠΏΠΎΠ»ΡŒΠ·Ρƒ этого Π²Ρ‹Π±ΠΎΡ€Π° ΠΈΠ³Ρ€Π°Π΅Ρ‚ Ρ‚ΠΎΡ‚ Ρ„Π°ΠΊΡ‚, Ρ‡Ρ‚ΠΎ вСсь ΠΊΠΎΠ΄ собствСнного DoH сСрвра ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½ срСдствами ΠΈΠ½Ρ‚Π΅Π³Ρ€ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ³ΠΎ Π² сам H2O ΠΈΠ½Ρ‚Π΅Ρ€ΠΏΡ€Π΅Ρ‚Π°Ρ‚ΠΎΡ€ΠΎΠΌ mruby. Помимо стандартных Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊ, для ΠΎΠ±ΠΌΠ΅Π½Π° Π΄Π°Π½Π½Ρ‹ΠΌΠΈ с DNS сСрвСром Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠ° Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° (mrbgem) Socket, которая, ΠΏΠΎ ΡΡ‡Π°ΡΡ‚ΡŒΡŽ, ΡƒΠΆΠ΅ Π²ΠΊΠ»ΡŽΡ‡Π΅Π½Π° Π² Ρ‚Π΅ΠΊΡƒΡ‰ΡƒΡŽ Π΄Π΅Π²Π΅Π»ΠΎΠΏΠ΅Ρ€ΡΠΊΡƒΡŽ Π²Π΅Ρ€ΡΠΈΡŽ H2O 2.3.0-beta2 ΠΏΡ€ΠΈΡΡƒΡ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΡƒΡŽ Π² ΠΏΠΎΡ€Ρ‚Π°Ρ… FreeBSD. Π’ΠΏΡ€ΠΎΡ‡Π΅ΠΌ, Π½Π΅ Ρ‚Ρ€ΡƒΠ΄Π½ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ Π΅Ρ‘ ΠΈ Π² Π»ΡŽΠ±ΡƒΡŽ ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΡƒΡŽ Π²Π΅Ρ€ΡΠΈΡŽ ΠΊΠ»ΠΎΠ½ΠΈΡ€ΠΎΠ²Π°Π² Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΉ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ Socket Π² ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³ /deps ΠΏΠ΅Ρ€Π΅Π΄ компиляциСй.

root@beta:~ # uname -v
FreeBSD 12.0-RELEASE-p10 GENERIC
root@beta:~ # cd /usr/ports/www/h2o
root@beta:/usr/ports/www/h2o # make extract
===>  License MIT BSD2CLAUSE accepted by the user
===>   h2o-2.2.6 depends on file: /usr/local/sbin/pkg - found
===> Fetching all distfiles required by h2o-2.2.6 for building
===>  Extracting for h2o-2.2.6.
=> SHA256 Checksum OK for h2o-h2o-v2.2.6_GH0.tar.gz.
===>   h2o-2.2.6 depends on file: /usr/local/bin/ruby26 - found
root@beta:/usr/ports/www/h2o # cd work/h2o-2.2.6/deps/
root@beta:/usr/ports/www/h2o/work/h2o-2.2.6/deps # git clone https://github.com/iij/mruby-socket.git
ΠšΠ»ΠΎΠ½ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Π² Β«mruby-socket»…
remote: Enumerating objects: 385, done.
remote: Total 385 (delta 0), reused 0 (delta 0), pack-reused 385
ΠŸΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ²: 100% (385/385), 98.02 KiB | 647.00 KiB/s, Π³ΠΎΡ‚ΠΎΠ²ΠΎ.
ΠžΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ: 100% (208/208), Π³ΠΎΡ‚ΠΎΠ²ΠΎ.
root@beta:/usr/ports/www/h2o/work/h2o-2.2.6/deps # ll
total 181
drwxr-xr-x   9 root  wheel  18 12 Π°Π²Π³.  16:09 brotli/
drwxr-xr-x   2 root  wheel   4 12 Π°Π²Π³.  16:09 cloexec/
drwxr-xr-x   2 root  wheel   5 12 Π°Π²Π³.  16:09 golombset/
drwxr-xr-x   4 root  wheel  35 12 Π°Π²Π³.  16:09 klib/
drwxr-xr-x   2 root  wheel   5 12 Π°Π²Π³.  16:09 libgkc/
drwxr-xr-x   4 root  wheel  26 12 Π°Π²Π³.  16:09 libyrmcds/
drwxr-xr-x  13 root  wheel  32 12 Π°Π²Π³.  16:09 mruby/
drwxr-xr-x   5 root  wheel  11 12 Π°Π²Π³.  16:09 mruby-digest/
drwxr-xr-x   5 root  wheel  10 12 Π°Π²Π³.  16:09 mruby-dir/
drwxr-xr-x   5 root  wheel  10 12 Π°Π²Π³.  16:09 mruby-env/
drwxr-xr-x   4 root  wheel   9 12 Π°Π²Π³.  16:09 mruby-errno/
drwxr-xr-x   5 root  wheel  14 12 Π°Π²Π³.  16:09 mruby-file-stat/
drwxr-xr-x   5 root  wheel  10 12 Π°Π²Π³.  16:09 mruby-iijson/
drwxr-xr-x   5 root  wheel  11 12 Π°Π²Π³.  16:09 mruby-input-stream/
drwxr-xr-x   6 root  wheel  11 12 Π°Π²Π³.  16:09 mruby-io/
drwxr-xr-x   5 root  wheel  10 12 Π°Π²Π³.  16:09 mruby-onig-regexp/
drwxr-xr-x   4 root  wheel  10 12 Π°Π²Π³.  16:09 mruby-pack/
drwxr-xr-x   5 root  wheel  10 12 Π°Π²Π³.  16:09 mruby-require/
drwxr-xr-x   6 root  wheel  10 12 сСнт. 16:10 mruby-socket/
drwxr-xr-x   2 root  wheel   9 12 Π°Π²Π³.  16:09 neverbleed/
drwxr-xr-x   2 root  wheel  13 12 Π°Π²Π³.  16:09 picohttpparser/
drwxr-xr-x   2 root  wheel   4 12 Π°Π²Π³.  16:09 picotest/
drwxr-xr-x   9 root  wheel  16 12 Π°Π²Π³.  16:09 picotls/
drwxr-xr-x   4 root  wheel   8 12 Π°Π²Π³.  16:09 ssl-conservatory/
drwxr-xr-x   8 root  wheel  18 12 Π°Π²Π³.  16:09 yaml/
drwxr-xr-x   2 root  wheel   8 12 Π°Π²Π³.  16:09 yoml/
root@beta:/usr/ports/www/h2o/work/h2o-2.2.6/deps # cd ../../..
root@beta:/usr/ports/www/h2o # make install clean
...

ΠšΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡ Π²Π΅Π±-сСрвСра, Π² Ρ†Π΅Π»ΠΎΠΌ, стандартная.

root@beta:/usr/ports/www/h2o #  cd /usr/local/etc/h2o/
root@beta:/usr/local/etc/h2o # cat h2o.conf
# this sample config gives you a feel for how h2o can be used
# and a high-security configuration for TLS and HTTP headers
# see https://h2o.examp1e.net/ for detailed documentation
# and h2o --help for command-line options and settings

# v.20180207 (c)2018 by Max Kostikov http://kostikov.co e-mail: [email protected]

user: www
pid-file: /var/run/h2o.pid
access-log:
    path: /var/log/h2o/h2o-access.log
    format: "%h %v %l %u %t "%r" %s %b "%{Referer}i" "%{User-agent}i""
error-log: /var/log/h2o/h2o-error.log

expires: off
compress: on
file.dirlisting: off
file.send-compressed: on

file.index: [ 'index.html', 'index.php' ]

listen:
    port: 80
listen:
    port: 443
    ssl:
        cipher-suite: ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS
        cipher-preference: server
        dh-file: /etc/ssl/dhparams.pem
        certificate-file: /usr/local/etc/letsencrypt/live/eprove.net/fullchain.pem
        key-file: /usr/local/etc/letsencrypt/live/my.domain/privkey.pem

hosts:
    "*.my.domain":
        paths: &go_tls
            "/":
                redirect:
                    status: 301
                    url: https://my.domain/
    "my.domain:80":
        paths: *go_tls
    "my.domain:443":
        header.add: "Strict-Transport-Security: max-age=15768000; includeSubDomains; preload"
        paths:
            "/dns-query":
               mruby.handler-file: /usr/local/etc/h2o/h2odoh.rb

Π˜ΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ составляСт лишь ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ URL /dns-query Π·Π° ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΎΡ‚Π²Π΅Ρ‡Π°Π΅Ρ‚, собствСнно, наш DNS-over-HTTPS сСрвСр, написанный Π½Π° mruby ΠΈ Π²Ρ‹Π·Ρ‹Π²Π°Π΅ΠΌΡ‹ΠΉ Ρ‡Π΅Ρ€Π΅Π· ΠΎΠΏΡ†ΠΈΡŽ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ° mruby.handler-file.

root@beta:/usr/local/etc/h2o # cat h2odoh.rb
# H2O HTTP/2 web server as DNS-over-HTTP service
# v.20190908 (c)2018-2019 Max Kostikov https://kostikov.co e-mail: [email protected]

proc {|env|
    if env['HTTP_ACCEPT'] == "application/dns-message"
        case env['REQUEST_METHOD']
            when "GET"
                req = env['QUERY_STRING'].gsub(/^dns=/,'')
                # base64URL decode
                req = req.tr("-_", "+/")
                if !req.end_with?("=") && req.length % 4 != 0
                    req = req.ljust((req.length + 3) & ~3, "=")
                end
                req = req.unpack1("m")
            when "POST"
                req = env['rack.input'].read
            else
                req = ""
        end
        if req.empty?
            [400, { 'content-type' => 'text/plain' }, [ "Bad Request" ]]
        else
            # --- ask DNS server
            sock = UDPSocket.new
            sock.connect("localhost", 53)
            sock.send(req, 0)
            str = sock.recv(4096)
            sock.close
            # --- find lowest TTL in response
            nans = str[6, 2].unpack1('n') # number of answers
            if nans > 0 # no DNS failure
                shift = 12
                ttl = 0
                while nans > 0
                    # process domain name compression
                    if str[shift].unpack1("C") < 192
                        shift = str.index("x00", shift) + 5
                        if ttl == 0 # skip question section
                            next
                        end
                    end
                    shift += 6
                    curttl = str[shift, 4].unpack1('N')
                    shift += str[shift + 4, 2].unpack1('n') + 6 # responce data size
                    if ttl == 0 or ttl > curttl
                        ttl = curttl
                    end
                    nans -= 1
                 end
                 cc = 'max-age=' + ttl.to_s
            else
                 cc = 'no-cache'
            end
            [200, { 'content-type' => 'application/dns-message', 'content-length' => str.size, 'cache-control' => cc }, [ str ] ]
        end
    else
        [415, { 'content-type' => 'text/plain' }, [ "Unsupported Media Type" ]]
    end
}

ΠžΠ±Ρ€Π°Ρ‚ΠΈΠ΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, Ρ‡Ρ‚ΠΎ Π·Π° ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² DNS ΠΎΡ‚Π²Π΅Ρ‡Π°Π΅Ρ‚ Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ ΠΊΡΡˆΠΈΡ€ΡƒΡŽΡ‰ΠΈΠΉ сСрвСр, Π² Π΄Π°Π½Π½ΠΎΠΌ случаС Unbound ΠΈΠ· стандратной поставки FreeBSD. Π‘ Ρ‚ΠΎΡ‡ΠΊΠΈ зрСния бСзопасности это ΠΎΠΏΡ‚ΠΈΠΌΠ°Π»ΡŒΠ½ΠΎΠ΅ Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅. Π’ΠΏΡ€ΠΎΡ‡Π΅ΠΌ, Π½ΠΈΡ‡Ρ‚ΠΎ Π½Π΅ ΠΌΠ΅ΡˆΠ°Π΅Ρ‚ Π·Π°ΠΌΠ΅Π½ΠΈΡ‚ΡŒ localhost Π½Π° адрСс Π΄Ρ€ΡƒΠ³ΠΎΠ³ΠΎ DNS, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π²Ρ‹ ΠΏΡ€Π΅Π΄ΠΏΠΎΠ»Π°Π³Π°Π΅Ρ‚Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ.

root@beta:/usr/local/etc/h2o # local-unbound verison
usage:  local-unbound [options]
        start unbound daemon DNS resolver.
-h      this help
-c file config file to read instead of /var/unbound/unbound.conf
        file format is described in unbound.conf(5).
-d      do not fork into the background.
-p      do not create a pidfile.
-v      verbose (more times to increase verbosity)
Version 1.8.1
linked libs: mini-event internal (it uses select), OpenSSL 1.1.1a-freebsd  20 Nov 2018
linked modules: dns64 respip validator iterator
BSD licensed, see LICENSE in source package for details.
Report bugs to [email protected]
root@eprove:/usr/local/etc/h2o # sockstat -46 | grep unbound
unbound  local-unbo 69749 3  udp6   ::1:53                *:*
unbound  local-unbo 69749 4  tcp6   ::1:53                *:*
unbound  local-unbo 69749 5  udp4   127.0.0.1:53          *:*
unbound  local-unbo 69749 6  tcp4   127.0.0.1:53          *:*

ΠžΡ‚ΡΡ‚Π°Ρ‘Ρ‚ΡΡ ΠΏΠ΅Ρ€Π΅Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ H2O ΠΈ ΠΏΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ‡Ρ‚ΠΎ ΠΆΠ΅ ΠΈΠ· этого ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ»ΠΎΡΡŒ.

root@beta:/usr/local/etc/h2o # service h2o restart
Stopping h2o.
Waiting for PIDS: 69871.
Starting h2o.
start_server (pid:70532) starting now...

4. ВСстированиС

Π˜Ρ‚Π°ΠΊ, ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΠΌ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΈΠ² вновь ΠΏΡ€ΠΎΠ±Π½Ρ‹ΠΉ запрос ΠΈ посмотрСв сСтСвой Ρ‚Ρ€Π°Ρ„ΠΈΠΊ ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ ΡƒΡ‚ΠΈΠ»ΠΈΡ‚Ρ‹ tcpdump.

root@beta/usr/local/etc/h2o # curl -H 'accept: application/dns-message' 'https://my.domain/dns-query?dns=q80BAAABAAAAAAAAB2V4YW1wbGUDY29tAAABAAE'
Warning: Binary output can mess up your terminal. Use "--output -" to tell
Warning: curl to output it to your terminal anyway, or consider "--output
Warning: <FILE>" to save to a file.
...
root@beta:~ # tcpdump -n -i lo0 udp port 53 -xx -XX -vv
tcpdump: listening on lo0, link-type NULL (BSD loopback), capture size 262144 bytes
16:32:40.420831 IP (tos 0x0, ttl 64, id 37575, offset 0, flags [none], proto UDP (17), length 57, bad cksum 0 (->e9ea)!)
    127.0.0.1.21070 > 127.0.0.1.53: [bad udp cksum 0xfe38 -> 0x33e3!] 43981+ A? example.com. (29)
        0x0000:  0200 0000 4500 0039 92c7 0000 4011 0000  ....E..9....@...
        0x0010:  7f00 0001 7f00 0001 524e 0035 0025 fe38  ........RN.5.%.8
        0x0020:  abcd 0100 0001 0000 0000 0000 0765 7861  .............exa
        0x0030:  6d70 6c65 0363 6f6d 0000 0100 01         mple.com.....
16:32:40.796507 IP (tos 0x0, ttl 64, id 37590, offset 0, flags [none], proto UDP (17), length 73, bad cksum 0 (->e9cb)!)
    127.0.0.1.53 > 127.0.0.1.21070: [bad udp cksum 0xfe48 -> 0x43fa!] 43981 q: A? example.com. 1/0/0 example.com. A 93.184.216.34 (45)
        0x0000:  0200 0000 4500 0049 92d6 0000 4011 0000  ....E..I....@...
        0x0010:  7f00 0001 7f00 0001 0035 524e 0035 fe48  .........5RN.5.H
        0x0020:  abcd 8180 0001 0001 0000 0000 0765 7861  .............exa
        0x0030:  6d70 6c65 0363 6f6d 0000 0100 01c0 0c00  mple.com........
        0x0040:  0100 0100 0151 8000 045d b8d8 22         .....Q...].."
^C
2 packets captured
23 packets received by filter
0 packets dropped by kernel

Π’ Π²Ρ‹Π²ΠΎΠ΄Π΅ Π²ΠΈΠ΄Π½ΠΎ, ΠΊΠ°ΠΊ запрос Π½Π° Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ адрСса example.com Π±Ρ‹Π» ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ ΠΈ ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π°Π½ DNS сСрвСром.

Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΎΡΡ‚Π°Π»ΠΎΡΡŒ Π°ΠΊΡ‚ΠΈΠ²ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ наш сСрвСр Π² Π±Ρ€Π°ΡƒΠ·Π΅Ρ€Π΅ Firefox. Для этого Π½Π° страницы ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ слСдуСт ΠΈΠ·ΠΌΠ΅Π½ΠΈΡ‚ΡŒ нСсколько настроСк about:config.

ПоднимаСм свой DNS-over-HTTPS сСрвСр

Π’ΠΎ-ΠΏΠ΅Ρ€Π²Ρ‹Ρ…, это адрСс нашСго API ΠΏΠΎ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌΡƒ Π±Ρ€Π°ΡƒΠ·Π΅Ρ€ Π±ΡƒΠ΄Π΅Ρ‚ Π·Π°ΠΏΡ€Π°ΡˆΠΈΠ²Π°Ρ‚ΡŒ Π² DNS ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ Π² network.trr.uri. РСкомСндуСтся Ρ‚Π°ΠΊΠΆΠ΅ ΡƒΠΊΠ°Π·Π°Ρ‚ΡŒ IP Π΄ΠΎΠΌΠ΅Π½Π° ΠΈΠ· этого URL для бСзопасного Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ Π² IP срСдствами самого Π±Ρ€Π°ΡƒΠ·Π΅Ρ€Π° Π±Π΅Π· обращСния ΠΊ DNS Π² network.trr.bootstrapAddress. И, Π½Π°ΠΊΠΎΠ½Π΅Ρ†, собствСнно сам ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ network.trr.mode Π²ΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‰ΠΈΠΉ использованиС DoH. Установка значСния Π² «3» заставит Π±Ρ€Π°ΡƒΠ·Π΅Ρ€ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ DNS-over-HTTPS для Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ ΠΈΠΌΡ‘Π½, Π° Π±ΠΎΠ»Π΅Π΅ Π½Π°Π΄Ρ‘ΠΆΠ½ΠΎΠ΅ ΠΈ бСзопасноС «2» отдаст ΠΏΡ€ΠΈΠΎΡ€ΠΈΡ‚Π΅Ρ‚ DoH отставив стандартноС ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠ΅ ΠΊ DNS Π² качСствС Ρ€Π΅Π·Π΅Ρ€Π²Π½ΠΎΠ³ΠΎ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚Π°.

5. PROFIT!

Π‘Ρ‚Π°Ρ‚ΡŒΡ Π±Ρ‹Π»Π° ΠΏΠΎΠ»Π΅Π·Π½ΠΎΠΉ? Π’ΠΎΠ³Π΄Π° ΠΏΡ€ΠΎΡˆΡƒ Π½Π΅ ΡΡ‚Π΅ΡΠ½ΡΡ‚ΡŒΡΡ ΠΈ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Ρ‚ΡŒ дСньгами Ρ‡Π΅Ρ€Π΅Π· Ρ„ΠΎΡ€ΠΌΡƒ Π΄ΠΎΠ½Π°Ρ‚Π° (Π½ΠΈΠΆΠ΅).

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com