вторник, 1 ноября 2016 г.

DNSCrypt: блокирование запросов AAAA

Как это ни дико звучит для некоторых, однако есть целый ряд стран (или сетей), где IPv6 отсутствует как класс - не сконфигурирован, не используется, или не планируется к использованию.

Соответственно, некоторые виды программного обеспечения, которые, в соответствие с RFC (чтоб его черти драли, это рекомендации, а не догма) имеют неотключаемую поддержку IPv6 (или не рекомендуемую к отключению, в соответствии со все теми же, не к ночи помянутыми, RFC). 

На практике это иногда ведет к ухудшению качественных показателей, задержкам или таймаутам при выполнении сетевых запросов, либо к отказам при выполнении сетевых запросов.

Для подобных случаев существует возможность (да, я говорю о вынесенном в заголовок ПО - DNSCrypt) не выполнять запросы AAAA, а немедленно, без выполнения запросов, ответить пустой строкой.

Хочу подчеркнуть, что этого в принципе можно было бы добиться, например, отключением выполнения запросов IPv6 в Unbound, но это частный случай, а далеко не всякое ПО позволяет это проделать, и, кроме того, в случае с комбинацией Unbound+DNSCrypt это, как правило, не помогает.

Итак, как ликвидировать в случае "IPv4 only" данную проблему (смотрим на заголовок - для DNSCrypt)  и добиться повышения латентности, исключения отказа некоторых запросов итп.?

В DNSCrypt существуют плагины, один из которых, в частности, позволяет добиться указанной цели в одно действие (не обращаем внимания на слово example в названии плагинов - они вполне себе продуктивные) - libdcplugin_example_ldns_aaaa_blocking.

Плагин работает в точности по описанному выше принципу - на запрос AAAA он немедленно возвращает пустую строку, что предотвращает выполнение IPv6 DNS-запросов в среде, не предназначенной для передачи IPv6.

Обратите внимание - чтобы плагин (и связанная с ldns группа плагинов DNSCrypt)  собрался, требуется наличие установленной библиотеки libdns( и libdns-dev, разумеется).

Допустим, что все хорошо и после установки DNSCrypt мы имеем весь набор плагинов в /usr/local/lib/dnscrypt-proxy:

 root @ khorne / # ls -al /usr/local/lib/dnscrypt-proxy  
 total 75  
 drwxr-xr-x 2 root root  14 Nov 1 01:53 .  
 drwxr-xr-x 6 root root  78 Oct 26 20:57 ..  
 -rwxr-xr-x 1 root root 1069 Nov 1 01:53 libdcplugin_example.la  
 -rwxr-xr-x 1 root root 7184 Nov 1 01:53 libdcplugin_example.so  
 -rwxr-xr-x 1 root root 1190 Nov 1 01:53 libdcplugin_example_ldns_aaaa_blocking.la  
 -rwxr-xr-x 1 root root 7448 Nov 1 01:53 libdcplugin_example_ldns_aaaa_blocking.so  
 -rwxr-xr-x 1 root root 1160 Nov 1 01:53 libdcplugin_example_ldns_blocking.la  
 -rwxr-xr-x 1 root root 12520 Nov 1 01:53 libdcplugin_example_ldns_blocking.so  
 -rwxr-xr-x 1 root root 1208 Nov 1 01:53 libdcplugin_example_ldns_opendns_deviceid.la  
 -rwxr-xr-x 1 root root 8984 Nov 1 01:53 libdcplugin_example_ldns_opendns_deviceid.so  
 -rwxr-xr-x 1 root root 1238 Nov 1 01:53 libdcplugin_example_ldns_opendns_set_client_ip.la  
 -rwxr-xr-x 1 root root 9416 Nov 1 01:53 libdcplugin_example_ldns_opendns_set_client_ip.so  
 -rwxr-xr-x 1 root root 1117 Nov 1 01:53 libdcplugin_example_logging.la  
 -rwxr-xr-x 1 root root 8880 Nov 1 01:53 libdcplugin_example_logging.so  
   

Чтобы использовать вышеуказанный плагин (и, кстати, любой другой; кроме того, можно использовать и несколько плагинов одновременно), достаточно указать при запуске демона DNSCrypt по имени в соответствующем аргументе dnscrypt-proxy его la-файл:

 dnscrypt-proxy 1.7.0  
   
 Options:  
   
  -R  --resolver-name=...  
  -a  --local-address=...  
  -d  --daemonize  
  -E  --ephemeral-keys  
  -K  --client-key=...  
  -L  --resolvers-list=...  
  -l  --logfile=...  
  -m  --loglevel=...  
  -p  --pidfile=...  
  -X  --plugin=...  
  -N  --provider-name=...  
  -k  --provider-key=...  
  -r  --resolver-address=...  
  -S  --syslog  
  -Z  --syslog-prefix=...  
  -n  --max-active-requests=...  
  -u  --user=...  
  -t  --test=...  
  -T  --tcp-only  
  -e  --edns-payload-size=...  
  -I  --ignore-timestamps  
  -V  --version  
  -h  --help  
   
 Please consult the dnscrypt-proxy(8) man page for details.  
   

То есть:

 --plugin=libdcplugin_example_ldns_aaaa_blocking.la    

После перезапуска сервиса DNSCrypt можно убедиться, что указанный плагин загружен при помощи команды pldd:

 root @ khorne / # ps -ef|grep [d]nscrypt  
   root 8083   1  0 02:29:24 ?      0:02 /usr/local/sbin/dnscrypt-proxy --daemonize --pidfile=/tmp/dnscrypt_ha_5555.pid   
   root 8071   1  0 02:29:24 ?      0:01 /usr/local/sbin/dnscrypt-proxy --daemonize --pidfile=/tmp/dnscrypt_ha_5553.pid   
   root 8065   1  0 02:29:24 ?      0:01 /usr/local/sbin/dnscrypt-proxy --daemonize --pidfile=/tmp/dnscrypt_ha_5552.pid   
   root 8077   1  0 02:29:24 ?      0:01 /usr/local/sbin/dnscrypt-proxy --daemonize --pidfile=/tmp/dnscrypt_ha_5554.pid   
   root 8059   1  0 02:29:24 ?      0:02 /usr/local/sbin/dnscrypt-proxy --daemonize --pidfile=/tmp/dnscrypt_ha_5551.pid   
 root @ khorne / # pldd 8083  
 8083:  /usr/local/sbin/dnscrypt-proxy --daemonize --pidfile=/tmp/dnscrypt_ha_  
 /lib/amd64/libsendfile.so.1  
 /opt/csw/lib/amd64/libltdl.so.7.3.1  
 /usr/local/lib/libsodium.so.18.1.1  
 /usr/lib/amd64/libkvm.so.1  
 /lib/amd64/libsocket.so.1  
 /lib/amd64/libnsl.so.1  
 /lib/amd64/librt.so.1  
 /lib/amd64/libm.so.2  
 /opt/csw/lib/amd64/libssp.so.0.0.0  
 /lib/amd64/libpthread.so.1  
 /lib/amd64/libc.so.1  
 /opt/csw/lib/amd64/libgcc_s.so.1  
 /lib/amd64/libelf.so.1  
 /lib/amd64/libaio.so.1  
 /lib/amd64/libmd.so.1  
 /lib/amd64/libmp.so.2  
 /lib/amd64/libscf.so.1  
 /lib/amd64/libdoor.so.1  
 /lib/amd64/libuutil.so.1  
 /lib/amd64/libgen.so.1  
 /usr/local/lib/dnscrypt-proxy/libdcplugin_example_ldns_aaaa_blocking.so  
 /opt/csw/lib/amd64/libldns.so.1.6.17  
 /opt/csw/lib/amd64/libcrypto.so.1.0.0  
   

Не забудьте внести изменения в запускные скрипты/сервисы DNSCrypt.

Вот и все, folks!