Stubby is an application that acts as a local DNS Privacy stub resolver (using DNS-over-TLS). Stubby encrypts DNS queries sent from a client machine (desktop or laptop) to a DNS Privacy resolver increasing end user privacy. (https://github.com/getdnsapi/stubby)
The following steps will guide you through the installation and configuration of stubby on RHEL 9. These steps may be repeatable for other Linux distributions.
- Enable Extra Packages for Enterprise Linux (EPEL) for RHEL 9:
subscription-manager repos --enable codeready-builder-for-rhel-9-$(arch)-rpms
Repository 'codeready-builder-for-rhel-9-x86_64-rpms' is enabled for this system.
dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm
Updating Subscription Management repositories.
Red Hat CodeReady Linux Builder for RHEL 9 x86_64 (RPMs) 3.7 MB/s | 7.1 MB 00:01
epel-release-latest-9.noarch.rpm 13 kB/s | 19 kB 00:01
Dependencies resolved.
=================================================================================================================================================================
Package Architecture Version Repository Size
=================================================================================================================================================================
Installing:
epel-release noarch 9-7.el9 @commandline 19 k
Transaction Summary
=================================================================================================================================================================
Install 1 Package
Total size: 19 k
Installed size: 26 k
Is this ok [y/N]: y
Downloading Packages:
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Installing : epel-release-9-7.el9.noarch 1/1
Running scriptlet: epel-release-9-7.el9.noarch 1/1
Many EPEL packages require the CodeReady Builder (CRB) repository.
It is recommended that you run /usr/bin/crb enable to enable the CRB repository.
Verifying : epel-release-9-7.el9.noarch 1/1
Installed products updated.
Installed:
epel-release-9-7.el9.noarch
Complete!
- Install the
getdns
andstubby
packages:
dnf install getdns stubby
Updating Subscription Management repositories.
Last metadata expiration check: 0:04:55 ago on Wed 24 Apr 2024 23:27:39.
Dependencies resolved.
=================================================================================================================================================================
Package Architecture Version Repository Size
=================================================================================================================================================================
Installing:
getdns x86_64 1.7.3-1.el9 epel 219 k
stubby x86_64 0.4.3-1.el9 epel 41 k
Installing dependencies:
libev x86_64 4.33-5.el9 rhel-9-for-x86_64-baseos-rpms 56 k
unbound-libs x86_64 1.16.2-3.el9_3.5 rhel-9-for-x86_64-appstream-rpms 553 k
Transaction Summary
=================================================================================================================================================================
Install 4 Packages
Total download size: 869 k
Installed size: 2.2 M
Is this ok [y/N]: y
Downloading Packages:
(1/4): stubby-0.4.3-1.el9.x86_64.rpm 148 kB/s | 41 kB 00:00
(2/4): getdns-1.7.3-1.el9.x86_64.rpm 772 kB/s | 219 kB 00:00
(3/4): libev-4.33-5.el9.x86_64.rpm 102 kB/s | 56 kB 00:00
(4/4): unbound-libs-1.16.2-3.el9_3.5.x86_64.rpm 1.3 MB/s | 553 kB 00:00
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
Total 173 kB/s | 869 kB 00:05
Extra Packages for Enterprise Linux 9 - x86_64 67 kB/s | 1.6 kB 00:00
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Running scriptlet: unbound-libs-1.16.2-3.el9_3.5.x86_64 1/4 Installing : unbound-libs-1.16.2-3.el9_3.5.x86_64 1/4
Running scriptlet: unbound-libs-1.16.2-3.el9_3.5.x86_64 1/4
Created symlink /etc/systemd/system/timers.target.wants/unbound-anchor.timer → /usr/lib/systemd/system/unbound-anchor.timer.
Installing : libev-4.33-5.el9.x86_64 2/4
Installing : getdns-1.7.3-1.el9.x86_64 3/4
Running scriptlet: getdns-1.7.3-1.el9.x86_64 3/4
Installing : stubby-0.4.3-1.el9.x86_64 4/4
Running scriptlet: stubby-0.4.3-1.el9.x86_64 4/4
Verifying : getdns-1.7.3-1.el9.x86_64 1/4
Verifying : stubby-0.4.3-1.el9.x86_64 2/4
Verifying : libev-4.33-5.el9.x86_64 3/4
Verifying : unbound-libs-1.16.2-3.el9_3.5.x86_64 4/4
Installed products updated.
Installed:
getdns-1.7.3-1.el9.x86_64 libev-4.33-5.el9.x86_64 stubby-0.4.3-1.el9.x86_64 unbound-libs-1.16.2-3.el9_3.5.x86_64
Complete!
- Edit the stubby configuration file (
/etc/stubby/stubby.yml
). Ensure the files has the following configuration:
dns_transport_list:
- GETDNS_TRANSPORT_TLS
tls_authentication: GETDNS_AUTHENTICATION_REQUIRED
listen_addresses:
- 127.0.0.1@8053
- 0::1@8053
Comment out the out-of-the-box enabled DNS resolvers:
### Test servers ###
# The getdnsapi.net server
# - address_data: 185.49.141.37
# tls_auth_name: "getdnsapi.net"
# tls_pubkey_pinset:
# - digest: "sha256"
# value: foxZRnIh9gZpWnl+zEiKa0EJ2rdCGroMWm02gaxSc9Q=
####### IPv6 addresses ######
### Test servers ###
# The getdnsapi.net server
# - address_data: 2a04:b900:0:100::38
# tls_auth_name: "getdnsapi.net"
# tls_pubkey_pinset:
# - digest: "sha256"
# value: foxZRnIh9gZpWnl+zEiKa0EJ2rdCGroMWm02gaxSc9Q=
Uncomment the Quad9 DNS resolvers. These resolvers provide a private (an encrypted transport) and secured (safe*) DNS service:
## Quad 9 'secure' service - Filters, does DNSSEC, doesn't send ECS
- address_data: 9.9.9.9
tls_auth_name: "dns.quad9.net"
- address_data: 149.112.112.112
tls_auth_name: "dns.quad9.net"
- Edit the Bind server configuration file (
/var/named/chroot/etc/named.conf
) to use the stubby service as the upstream forwarder. The DNS flow can be visualised as Client > Bind > Stubby (TLS) > Quad9:
options {
...
forwarders { 127.0.0.1 port 8053; };
...
};
- Enable and/or start the stubby service:
systemctl enable --now stubby.service
Created symlink /etc/systemd/system/multi-user.target.wants/stubby.service → /usr/lib/systemd/system/stubby.service.
systemctl status stubby.service
● stubby.service - stubby DNS resolver
Loaded: loaded (/usr/lib/systemd/system/stubby.service; enabled; preset: disabled)
Active: active (running) since Thu 2024-04-25 20:18:59 AEST; 8s ago
Main PID: 2827 (stubby)
Tasks: 1 (limit: 10974)
Memory: 2.5M
CPU: 24ms
CGroup: /system.slice/stubby.service
└─2827 /usr/bin/stubby
Apr 25 20:18:59 rhel9 systemd[1]: Started stubby DNS resolver.
- Enable and/or start the Bind service:
systemctl enable --now named-chroot.service
Created symlink /etc/systemd/system/multi-user.target.wants/named-chroot.service → /usr/lib/systemd/system/named-chroot.service.
systemctl status named-chroot.service
● named-chroot.service - Berkeley Internet Name Domain (DNS)
Loaded: loaded (/usr/lib/systemd/system/named-chroot.service; enabled; preset: disabled)
Active: active (running) since Thu 2024-04-25 20:06:31 AEST; 16min ago
Main PID: 2711 (named)
Tasks: 6 (limit: 10974)
Memory: 20.8M
CPU: 60ms
CGroup: /system.slice/named-chroot.service
└─2711 /usr/sbin/named -u named -c /etc/named.conf -t /var/named/chroot
...
- Test name resolution:
nslookup google.com localhost
Server: localhost
Address: 127.0.0.1#53
Non-authoritative answer:
Name: google.com
Address: 142.250.204.14
Name: google.com
Address: 2404:6800:4006:814::200e
Verify that stubby is receiving requests through a simple packet capture:
tcpdump -nnqi lo -c 4
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on lo, link-type EN10MB (Ethernet), snapshot length 262144 bytes
21:14:35.320052 IP 127.0.0.1.54029 > 127.0.0.1.8053: UDP, length 48
21:14:35.422034 IP 127.0.0.1.8053 > 127.0.0.1.54029: UDP, length 52
21:14:35.426235 IP 127.0.0.1.49300 > 127.0.0.1.8053: UDP, length 48
21:14:35.540919 IP 127.0.0.1.8053 > 127.0.0.1.49300: UDP, length 92
4 packets captured
8 packets received by filter
0 packets dropped by kernel
With that, stubby receives DNS requests from bind and sends them upstream to Quad9 over TLS. In theory, no one should be able to easily intercept and interpret DNS transactions.