Systemd-resolved block a domain name

dnsdnsmasqsystemdsystemd-networkdsystemd-resolved

Using systemd-resolved how do I block, route, or resolve, a domain name to a black hole, or a nowhere address. Bonus points for subdomains as well.

I tried a single domain in /etc/hosts:

127.0.0.1 google.com
::1 google.com

I also tried /etc/systemd/network/100-blocked.network:

[Match]
Name=wlp113s0

[Network]
Description="Just block the domain, and sub domains"
DNS=127.0.0.255
DNS=::1

[Resolve]
Domains=google.com

sudo systemd-resolve --status:

Link 3 (wlp113s0)
      Current Scopes: DNS
       LLMNR setting: yes
MulticastDNS setting: no
      DNSSEC setting: no
    DNSSEC supported: no
         DNS Servers: 127.0.0.255
                      ::1
                      2001:4888:3a:ff00:304:d::
                      2001:4888:39:ff00:308:d::

for example using dnsmasq i was able to do:

server=192.168.43.1
address=/google.com/0.0.0.0
# a very long list of "address=/domain/0"

related:

Best Answer

Adding an entry to /etc/hosts is supposed to work and in my tests it worked as expected. My tests are on Fedora Rawhide, with version systemd-239-9.git9f3aed1.fc30.x86_64, so that's a pretty recent snapshot of systemd, maybe older versions will not work the same as expected...


Before adding the entry to /etc/hosts:

1) resolvectl query:

$ resolvectl query google.com
google.com: 172.217.6.78

-- Information acquired via protocol DNS in 1.4ms.
-- Data is authenticated: no

2) ping:

$ ping -c1 google.com
PING google.com (172.217.6.78) 56(84) bytes of data.
64 bytes from sfo07s17-in-f78.1e100.net (172.217.6.78): icmp_seq=1 ttl=54 time=12.4 ms

--- google.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 12.435/12.435/12.435/0.000 ms

3) curl:

$ curl http://google.com
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="http://www.google.com/">here</A>.
</BODY></HTML>

After adding the entry, in which case /etc/hosts looks like this:

$ cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

127.0.0.1 google.com
::1 google.com

Tests showed the blocking is working:

1) resolvectl query:

$ resolvectl query google.com
google.com: 127.0.0.1
            ::1

-- Information acquired via protocol DNS in 1.8ms.
-- Data is authenticated: yes

2) ping:

$ ping -c1 google.com
PING google.com(localhost (::1)) 56 data bytes
64 bytes from localhost (::1): icmp_seq=1 ttl=64 time=0.613 ms

--- google.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.613/0.613/0.613/0.000 ms

3) curl:

$ curl http://google.com
curl: (7) Failed to connect to google.com port 80: Connection refused

So the block seems to be working.


I expected this would work, since this was brought up recently in an issue filed against systemd. Issue #9718 talked about adding millions of entries to /etc/hosts, which has one usecase and that's blacklisting domains, such as here.

Please note that there are quite a few moving parts here, so it's important to consider those while troubleshooting this.

My /etc/systemd/resolved.conf has no overridden configuration, all entries are commented out, network setup is using systemd-networkd with DHCP and no overrides either.

Output of resolvectl status includes:

Global
       LLMNR setting: yes
MulticastDNS setting: yes
  DNSOverTLS setting: no
      DNSSEC setting: allow-downgrade
    DNSSEC supported: no
Fallback DNS Servers: 8.8.8.8
                      8.8.4.4
                      2001:4860:4860::8888
                      2001:4860:4860::8844

Link 2 (ens33)
      Current Scopes: DNS LLMNR/IPv4 LLMNR/IPv6
       LLMNR setting: yes
MulticastDNS setting: no
  DNSOverTLS setting: no
      DNSSEC setting: allow-downgrade
    DNSSEC supported: no

Configuration of /etc/resolv.conf is using the stub resolver:

$ ls -l /etc/resolv.conf
lrwxrwxrwx. 1 root root 39 Nov  7 22:08 /etc/resolv.conf -> ../run/systemd/resolve/stub-resolv.conf
$ grep '^[^#]' /etc/resolv.conf
nameserver 127.0.0.53

And nsswitch.conf is configured to use nss-resolve(8) according to the recommendation from its man page:

$ grep ^hosts: /etc/nsswitch.conf
hosts:      files resolve [!UNAVAIL=return] dns myhostname

If you still can't make it work, you might want to check these settings in your system and confirm they are all configured correctly. Or, at least, post your current configuration here (together with Linux distro and systemd version) to help diagnose why it might not be working for you.

Related Question