DNS Hardening on Manjaro: Ignore DHCP
A rabbit hole but who is to blame?
Introduction
This article aims to show how easy it is to configure DNS on a Manjaro host so that you do not rely on the configuration the DHCP server provides. Having a proper DNS configuration is not something you do just to brag, but it comes with serious security, privacy and performance considerations.
To help you understand: by blindly following your DHCP provider’s suggestions when it comes to DNS, you risk:
- security: If they have a misconfigured or insecure DNS server, DNS poisoning can occur at that level. You might think you’ve visited your bank’s website, but in actuality, you are just visiting a malicious clone.
- privacy: If a provider wants to track your internet activity, it is trivial to do so: they can see all websites that you visit (without the need for extensive infrastructure - for plain MitM attacks).
- performance: Inadequate DNS servers have the potential to slow all your requests down.
Make sure to avoid copying the exact same configuration if you (or your company) has a dedicated DNS server; otherwise, you might lose access to certain endpoints and severely impact your workflow.
Only read if you have absolutely no idea what DNS is
If you’re reading this, then in all probability your network (at least your home one) looks like this:
We have a device that we are quick to call a router but in actuality, it is much
more than that. It also functions as a:
- Wireless Access Point - Providing wireless access to our devices
- Ethernet (/ Layer 2) Switch - Providing LAN functionality
- Network Attached Storage (NAS) - Strangely, I’ve seen a lot of people attach a hard drive directly to the router when this functionality is supported
- and so much more, but crucially it also
- WORKS AS A
DHCPSERVER1
DHCP
This simplified model of the network focuses on IPv4. IPv6 introduced different ways of handling many of the underlying parts.
Now, what is a DHCP server you might ask… To understand that I’ll (grossly)
explain in a paragraph all of computer networking (-_-): I’m sure that you’ve
seen or heard many times that computers have IP addresses. If you’ve
ever thought about it, I’m pretty sure that you reached the following
conclusion: they can’t be born with them2 since an address must always
be able to reach you, no matter where you are (which network you are connected to). And
that is right! I’ll keep simplifying, but you can think of your
over-the-internet communications according to the following pattern:
- You somehow (that’s DNS) find the IP of the server/computer you want to talk to.
- You create the message with that
Destination IPand your address asSource IP. Not knowing where to send it, you pass it to your router. - Your router does its magic and forwards it to a path that will ultimately
reach
Destination IPand waits for its answer (the server will send their reply to yourSource IP). - Your
Source IPobviously needs to somehow be linked to your router (otherwise, how would the network know where to forward it to reach you?).
A lot of interesting stuff might happen when it comes to generating your IP, but
let us ignore them. We’ve proven that it is necessary, and that it is related to
your router in one way or another. When it comes to home networks, your IP is
leased by the DHCP server inside your router: when you connect, you ask for it,
and you receive one for a given time. That’s it… almost.
There are many significant technologies that are hidden in this simplistic model (such as NAT), but these are not needed in this context.
You see, DHCP servers are usually kinda nice and want to help you out. So,
instead of just handing out addresses, they also give you some extra information
such as those for:
- The
router - The
DNSservers
DNS
We took a long way to get here! DNS stands for Domain Name System and it is
effectively a protocol for us to go from a Name to an Address.
-> nslookup google.com Server: 127.0.0.53 Address: 127.0.0.53#53 Non-authoritative answer: Name: google.com Address: 192.178.24.46 Name: google.com Address: 2a00:1450:4017:812::200e
The default DNS stack on Manjaro
By default, Manjaro lets NetworkManager handle practically everything around
networking, which includes DHCP and DNS configuration. Thus, systemd-resolved
might be installed but is disabled: we trust that the DHCP server promotes the
name servers we want. Have a look at /etc/resolv.conf (for you non-believers):
# Use this to verify that systemd-resolved is in fact disabled systemctl status systemd-resolved
# My hallucinated /etc/resolv.conf # This often is not an actual file, but a link to somewhere else in the system. search home.arpa nameserver 192.168.1.1 nameserver 8.8.8.8
It works (but we’ll break it).
The Goal
The rest of this article covers how we’ll:
- force
NetworkManagerto ignoreDNSservers advertised by the network and instead rely onsystemd-resolved - enable
systemd-resolved - configure
systemd-resolved(and add a couple of security features)
Before moving on, make sure that you understand what you’re doing. If in doubt, read some more.
NetworkManager let go of DNS pleeeeeeease
Simply enough, you’ll see that NetworkManager, following the standard convention,
can be configured through: /etc/NetworkManager/conf.d/<files>
All we need, thus, is to edit (or create) dns.conf in that directory:
# /etc/NetworkManager/conf.d/dns.conf [main] # This tells NM to avoid passing information to systemd-resolved dns=none systemd-resolved=false
In this process we effectively redirect the /etc/resolv.conf file to
the stub created by systemd-resolved. The system then knows to look to
systemd-resolved, but without proper configuration, it receives information from NetworkManager.
Configure systemd-resolved
In the same way, either through man 5 resolved.conf or by visiting
/etc/systemd/resolved.conf, we’ll see that a standard configuration (minimal) is
suggested:
[Resolve] # Some examples of DNS servers which may be used for DNS= and FallbackDNS=: # Cloudflare: 1.1.1.1#cloudflare-dns.com 1.0.0.1#cloudflare-dns.com 2606:4700:4700::1111#cloudflare-dns.com 2606:4700:4700::1001#cloudflare-dns.com # Google: 8.8.8.8#dns.google 8.8.4.4#dns.google 2001:4860:4860::8888#dns.google 2001:4860:4860::8844#dns.google # Quad9: 9.9.9.9#dns.quad9.net 149.112.112.112#dns.quad9.net 2620:fe::fe#dns.quad9.net 2620:fe::9#dns.quad9.net # # Using DNS= configures global DNS servers and does not suppress link-specific # configuration. Parallel requests will be sent to per-link DNS servers # configured automatically by systemd-networkd.service(8), NetworkManager(8), or # similar management services, or configured manually via resolvectl(1). See # resolved.conf(5) and systemd-resolved(8) for more details.
Not only does it give us properly formatted entries to use for DNS, but it also
explains neatly that if misconfigured, other services such as NetworkManager
may affect our active DNS configuration.
Visiting the suggested manpage explains the syntax in each of the Cloudflare,
Google and Quad9 lines:
# From man 5 resolved.conf
DNS=
A space-separated list of IPv4 and IPv6 addresses to use as system DNS servers. Each address can optionally take a port number
separated with ":", a network interface name or index separated with "%", and a Server Name Indication (SNI) separated with "#".
When IPv6 address is specified with a port number, then the address must be in the square brackets. That is, the acceptable full
formats are "111.222.333.444:9953%ifname#example.com" for IPv4 and "[1111:2222::3333]:9953%ifname#example.com" for IPv6. DNS
requests are sent to one of the listed DNS servers in parallel to suitable per-link DNS servers acquired from systemd-
networkd.service(8) or set at runtime by external applications. For compatibility reasons, if this setting is not specified, the
DNS servers listed in /etc/resolv.conf are used instead, if that file exists and any servers are configured in it. This setting
defaults to the empty list.
At this point, one could just copy any of these as the DNS= and a different one
as the FallbackDNS= and skip over to the part where we enable systemd-resolved.
However, this article will not stop at that:
[Resolve] DNS=1.1.1.1#cloudflare-dns.com 1.0.0.1#cloudflare-dns.com 2606:4700:4700::1111#cloudflare-dns.com 2606:4700:4700::1001#cloudflare-dns.com FallbackDNS=9.9.9.9#dns.quad9.net 2620:fe::9#dns.quad9.net 1.1.1.1#cloudflare-dns.com 2606:4700:4700::1111#cloudflare-dns.com 8.8.8.8#dns.google 2001:4860:4860::8888#dns.google
Hardening
Why bother? Adding a couple of minutes to this configuration can make your browsing more secure and private by enabling the following features:
DNS over TLS: This encrypts yourDNS QueriesthroughTLSso that it is difficult for others to eavesdrop on your requests. In an ideal world, this setting would mean that only yourDNS Serverknows what you asked for: Privacy.DNSSEChandles security by providing integrity: its mechanisms make it difficult for anyone to give false information or tamper with the responses: the response must come from the legitimate owners of that domain.
These are both easily added to one’s configuration:
[Resolve] DNS=1.1.1.1#cloudflare-dns.com 1.0.0.1#cloudflare-dns.com 2606:4700:4700::1111#cloudflare-dns.com 2606:4700:4700::1001#cloudflare-dns.com FallbackDNS=9.9.9.9#dns.quad9.net 2620:fe::9#dns.quad9.net 1.1.1.1#cloudflare-dns.com 2606:4700:4700::1111#cloudflare-dns.com 8.8.8.8#dns.google 2001:4860:4860::8888#dns.google DNSSEC=yes DNSOverTLS=allow-downgrade ReadEtcHosts=yes Cache=yes
In this snippet I have DNSOverTLS=allow-downgrade, since it is notoriously easy
for DoT to fail. However, if you do not mind your connection breaking down, use DNSOverTLS=yes instead.
Enabling systemd-resolved
If you’ve followed so far, all you need to do is:
- enable the service
- make
NetworkManagerreload its configuration so that it does not handleDNS
sudo systemctl enable --now systemd-resolved sudo systemctl restart NetworkManager
Verifying the installation
This article would not be complete if it did not include the following tests to verify that we did in fact configure the system properly:
# These tests are within resolvectl resolvectl status # look for DNSOverTLS, DNSSEC
resolvectl statistics
You can also verify DNSSEC against this domain (it should fail):
resolvectl query sigfail.verteiltesysteme.net
Finally, you can have a look at NetworkManager DNS-related settings using:
nmcli connection show $yourconnection | grep dns
A couple of notes on resolvectl status
- If you see that
resolv.conf mode: foreign, it usually means that somehow that file is not a link to the usualsystemd-resolved stub. You might want to use:sudo ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf- Fixing that will show
resolv.conf mode: stub
If you see proper
Globaloptions, but your interface is still using theDHCPprovided configuration: According to this, theNetworkManagerconfiguration should suffice. For me, it required restarting: after restarting, this resulted in me seeing an empty configuration for my interface, thus falling back on myGlobaloptions.Link 2 (enp2s0) Current Scopes: LLMNR/IPv4 LLMNR/IPv6 mDNS/IPv4 mDNS/IPv6 Protocols: -DefaultRoute +LLMNR +mDNS +DNSOverTLS DNSSEC=yes/supported Default Route: no
You might see too many breadcrumbs in ArchWiki and in multiple random posts,
pointing to the modification of /etc/systemd/networkd.conf (or sub-configuration
files) to have UseDNS=false. Just make sure that systemd-networkd is enabled
first (not by default) because otherwise, all actions will be futile.