Настройка DNS резорвера Unbound на Ubuntu 20.04

В предыдущей статье я описал как легко и быстро поднять свой собственный VPN. Но, в плане анонимности, VPN сам по себе не имеет смысла без связки с собственным DNS резолвером, либо использованием DNSCrypt.
В этой статье я покажу как поднять кеширующий DNS резолвер.

Подготовительные работы:

При устаноке Unbound на Ubuntu, возникает проблема вызванная конфликтом на 53 порту, т.к. этот порт по умолчанию уже занят сервисом systemd-resolved.
Для разрешения этой задачи прописываем DNSStubListener=no в файл /etc/systemd/resolved.conf:

Код:
~$ sudo sh -c 'echo DNSStubListener=no >> /etc/systemd/resolved.conf'

Перезагружаем сервис:
~$ sudo systemctl restart systemd-resolved.service

И убеждаемся, что порт 53 не занят сервисом systemd-resolved:
~$ sudo ss -tulpn | grep :53

Some housekeeping stuff:

Код:
~$ sudo systemctl stop systemd-resolved.service
~$ sudo rm -f /etc/resolv.conf
~$ sudo ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf
~$ sudo systemctl start systemd-resolved.service

Установка и настройка Unbound:

Устанавливаем Unbound и Curl

Код:
~$ sudo apt install unbound curl

По умолчанию, Unbound подтягивает конфигурацию из файлов с расширением .conf, которые лежат по пути /etc/unbound/unbound.conf.d/
Удаляем все стандартные файлы конфигурации и создаём свой:

Код:
~$ sudo rm /etc/unbound/unbound.conf.d/*
~$ sudo nano /etc/unbound/unbound.conf.d/main.conf

Под спойлером мой пример файла main.conf. Копируем и вставляем. Всё что выделено жирным, настраиваем под себя.

# Блок описания конфигурации DNS-сервера Unbound
server:

# Используемые для управления ресурсы
directory: «/etc/unbound»
pidfile: «/var/run/unbound.pid»

# Имя пользователя, от которого запускается сервис
username: unbound

# Запускаем в несколько потоков (по одному на ядро процессора)
num-threads: 1

# Данные параметры соотносятся с числом потоков*2
msg-cache-slabs: 2
rrset-cache-slabs: 2
infra-cache-slabs: 2
key-cache-slabs: 2

# Включаем оптимизацию быстрого перераспределения ресурсов
so-reuseport: yes

# Описываем параметры сетевого подключения, на котором сервис принимает запросы
port: 53
interface: 0.0.0.0

# Указываем, с какого из интерфейсов высылать рекурсивные запросы и получать ответы на запросы
outgoing-interface: <вписать сюда ipv4-адрес сервера>
# Важно! Нужно вписать ipv4-адрес интерфейса eth0, который можно посмотреть командой ip addr

# Уточняем перечень протоколов, с которыми работаем
do-ip4: yes
do-ip6: no
do-udp: yes
do-tcp: yes

# Перечисляем сети, рекурсивные запросы от которых обслуживаются (по умолчанию всё неразрешенное запрещено)
access-control: 127.0.0.0/8 allow
access-control: 192.168.0.0/8 allow
access-control: 10.0.0.0/8 allow

# Скрываем данные о программном обеспечении в ответах на запросы
hide-identity: yes
hide-version: yes
hide-trustanchor: yes
identity: «DNS»

# Уровень детализации журнала событий (0 — только ошибки; 1 — каждый запрос; 2 — включает еще и ответы; 3 — детальный разбор)
#verbosity: 2

# На период отладки полезно включить детальное журналирование запросов пользователей
#log-queries: yes

# Месторасположение файла журнала событий
#logfile: «/var/log/unbound.log»

# Использовать в журнале человекопонятный формат метки времени
#log-time-ascii: yes

# Предписываем не дублировать сообщения о событиях в системный журнал
#use-syslog: no

# Указвыаем актуальный перечень корневых DNS-серверов
root-hints: «/etc/unbound/root.hints»

# The following line will configure unbound to perform cryptographic
# DNSSEC validation using the root trust anchor.
auto-trust-anchor-file: «/var/lib/unbound/root.key»

# Module configuration, a list of module names separated by spaces,
# surround the string with quotes («»)
module-config: «validator iterator»

# Aggressive NSEC uses the DNSSEC NSEC chain to synthesize NXDOMAIN
# and other denials, using information from previous NXDOMAINs answers.
# Default is no. It helps to reduce the query rate towards targets
# that get a very high nonexistent name lookup rate.
aggressive-nsec: yes

# Time to live maximum for RRsets and messages in the cache.
cache-max-ttl: 21600

# Time to live minimum for RRsets and messages in the cache.
cache-min-ttl: 2600

# If yes, Unbound doesn’t insert authority/additional sections
# into response messages when those sections are not required.
minimal-responses: yes

# If yes, message cache elements are prefetched before they expire
# to keep the cache up to date. Default is no.
prefetch: yes

# If enabled, unbound attempts to serve old responses from cache
# with a TTL of 0 in the response without waiting for the actual
# resolution to finish.
serve-expired: no

# Detect source interface on UDP queries and copy them to replies.
interface-automatic: yes

# Send minimum amount of information to upstream servers to
# enhance privacy.
qname-minimisation: yes

# If yes, Unbound rotates RRSet order in response (the random num-
# ber is taken from the query ID, for speed and thread safety).
rrset-roundrobin: yes

# Use 0x20-encoded random bits in the query to foil spoof
# attempts. This perturbs the lowercase and uppercase of query
# names sent to authority servers and checks if the reply still
# has the correct casing.
use-caps-for-id: yes

# Number of bytes size of the RRset cache. Default is 4 megabytes.
# A plain number is in bytes, append ‘k’, ‘m’ or ‘g’ for kilo-
# bytes, megabytes or gigabytes (1024*1024 bytes in a megabyte).
rrset-cache-size: 256m
# Number of bytes size of the message cache. Default is 4
# megabytes.
msg-cache-size: 128m

# Set the SO_RCVBUF socket option to get more buf-
# fer space on UDP port 53 incoming queries.
so-rcvbuf: 4m

# Set the SO_SNDBUF socket option to get more buf-
# fer space on UDP port 53 outgoing queries.
so-sndbuf: 4m

# Enable ratelimiting of queries sent to nameserver for performing
# recursion.
ratelimit: 1000

# Enable or disable whether the unbound server forks into the
# background as a daemon. Set the value to no when unbound runs
# as systemd service. Default is yes.
do-daemonize: no

# Harden against algorithm downgrade when multiple algorithms are
# advertised in the DS record. If no, allows the weakest algo-
# rithm to validate the zone.
harden-algo-downgrade: yes

# Will trust glue only if it is within the servers authority.
harden-glue: yes

# Number of hosts for which information is cached.
infra-cache-numhosts: 10000

# Number of ports to open. This number of file descriptors can be
# opened per thread.
outgoing-range: 8192

# The number of queries that every thread will service simultane-
# ously.
num-queries-per-thread: 4096

# Instruct the validator to remove data from the additional sec-
# tion of secure messages that are not signed properly.
val-clean-additional: yes

# Number of incoming TCP buffers to allocate per thread. Default
# is 10. If set to 0, or if do-tcp is «no», no TCP queries from
# clients are accepted. For larger installations increasing this
# value is a good idea.
incoming-num-tcp: 100

# Number of outgoing TCP buffers to allocate per thread. Default
# is 10. If set to 0, or if do-tcp is «no», no TCP queries to
# authoritative servers are done. For larger installations
# increasing this value is a good idea.
outgoing-num-tcp: 100

# Number of bytes size to advertise as the EDNS reassembly buffer
# size. This is the value put into datagrams over UDP towards
# peers. The actual buffer size is determined by msg-buffer-size
# (both for TCP and UDP).
edns-buffer-size: 1232

# Set the target fetch policy used by unbound to determine if it
# should fetch nameserver target addresses opportunistically. The
# policy is described per dependency depth.
# The number of values determines the maximum dependency depth
# that unbound will pursue in answering a query. A value of -1
# means to fetch all targets opportunistically for that dependency
# depth. A value of 0 means to fetch on demand only. A positive
# value fetches that many targets opportunistically.
# Enclose the list between quotes («») and put spaces between num-
# bers. The default is «3 2 1 0 0». Setting all zeroes, «0 0 0 0
# 0» gives behaviour closer to that of BIND 9, while setting «-1
# -1 -1 -1 -1» gives behaviour rumoured to be closer to that of
# BIND 8.
target-fetch-policy: «0 0 0 0 0»

# Enabled or disable whether the upstream queries use TLS only for
# transport.
tls-upstream: no

# If null or «», no file is used. Set it to the certificate bun-
# dle file, for example «/etc/pki/tls/certs/ca-bundle.crt». These
# certificates are used for authenticating connections made to
# outside peers. For example auth-zone urls, and also DNS over
# TLS connections.
tls-cert-bundle: /etc/ssl/certs/ca-certificates.crt

Т.к. Unbound умеет обращаться к корневым серверам DNS, ему нужны их адреса:

Код:
sudo curl -o /etc/unbound/root.hints https://www.internic.net/domain/named.cache

Для поддержания этих адесов в актуальном состоянии проделываем следующее:

Код:
Здесь мы создаем файл root.hints по пути /etc/cron.daily/ , что позволит ежедневно проверять адреса корневых DNS, и в случае, если эти адреса обновятся - перезапишется файл /etc/unbound/root.hints
~$ sudo sh -c 'echo "#!/bin/sh\ncurl -z /etc/unbound/root.hints https://www.internic.net/domain/named.cache -o /etc/unbound/root.hints\nexit 0" >> /etc/cron.daily/root.hints'

Делаем файл /etc/cron.daily/root.hints исполняемым:
~$ sudo chmod +x /etc/cron.daily/root.hints

Для работы DNSSEC надо отдельно проделать следующее:

Код:
~$ sudo unbound-anchor -a /etc/unbound/root.key
~$ sudo chown unbound.unbound /etc/unbound/root.key

Запускаем Unbound:

Код:
~$ sudo systemctl start unbound.service
Проверяем на отсутствие ошибок:
~$ unbound-checkconf
Добавляем Unbound в автозагрузку:
~$ sudo systemctl enable unbound.service

PS:
Для проверки DNSSEC можете зайти на сайт и нажать кнопочку, если палец вверх, значит все ок.
Еще один сайт для проверки утечки DNS

Проверяем работу DNS вводим: dig @127.0.0.1 bbc.com и смотрим на [Query time]
Проверяем кеширующие функции DNS, второй раз вводим: dig @127.0.0.1 bbc.com и смотрим на [Query time] Должно быть [0 msec]

Не забываем добавить ipv4-адрес сервера, при настройке VPN, чтоб ваш DNS трафик шел внутри VPN туннеля.