Running unbound inside a jail

on 2021-09-15

In my quest for a safe safer browsing experience, I put my browser in a jail (a coming post about this). Then, I decided that it would also be great to do some AdBlocking based on DNS using unbound. Since my browser was already in a jail, I decided to put unbound into another one. The troubles were just starting... In what follows I am going to speak only about "classic" jails not VNET ones (I know nothing about them).

Jails and localhost

Simply put, a jail has no such a thing as a localhost. When you use localhost inside a jail, it is replaced by the actual IP address of the jail. You should keep that in mind if you think the service you run inside a jail is only listening to localhost... it is not. I was aware of that when I started my journey to setup my unbound jail. What I did not expect is that this localhost/IP dance could give some weird results when it came to resolving host names into IPs.

Unbound and access-control

If you setup unbound and start it the way you would do on a FreeBSD host, you will have a first suprise:

# drill -t _http._tcp.pkg.freebsd.org SRV
;; ->>HEADER<<- opcode: QUERY, rcode: REFUSED, id: 9679
;; flags: qr rd ; QUERY: 0, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;;
;; ANSWER SECTION:

;; AUTHORITY SECTION:

;; ADDITIONAL SECTION:

;; Query time: 0 msec
;; SERVER: 127.0.0.1
;; WHEN: Fri Feb  5 07:42:29 2021
;; MSG SIZE  rcvd: 12

As you can see, the connexion is refused. This due to the fact that, by default, only localhost has access to unbound, but your IP address is not localhost. You therefore have to explicitly allow the jail IP to access to unbound. For instance, you can create a /var/unbound/conf.d/controls.conf file with the following content:

server:
    access-control: 10.0.0.0/8 allow

Here I allow the entire network of the jail which has the following IP: 10.0.0.21. Now, drill works:

# drill -t _http._tcp.pkg.freebsd.org SRV
;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 11250
;; flags: qr rd ra ; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;; _http._tcp.pkg.freebsd.org.  IN      SRV

;; ANSWER SECTION:
_http._tcp.pkg.freebsd.org.     226     IN      SRV     10 10 80 pkgmir.geo.freebsd.org.
_http._tcp.pkg.freebsd.org.     226     IN      SRV     50 10 80 pkg0.nyi.freebsd.org.
_http._tcp.pkg.freebsd.org.     226     IN      SRV     50 10 80 pkg0.isc.freebsd.org.
_http._tcp.pkg.freebsd.org.     226     IN      SRV     50 10 80 pkg0.tuk.freebsd.org.
_http._tcp.pkg.freebsd.org.     226     IN      SRV     50 10 80 pkg0.bme.freebsd.org.
_http._tcp.pkg.freebsd.org.     226     IN      SRV     50 10 80 pkg0.pkt.freebsd.org.

;; AUTHORITY SECTION:

;; ADDITIONAL SECTION:

;; Query time: 0 msec
;; SERVER: 127.0.0.1
;; WHEN: Fri Feb  5 07:47:02 2021
;; MSG SIZE  rcvd: 286

When I stumbled accross this first error, it was easy to diagnose because the symptoms are pretty clear: REFUSED. So it took me few minutes to solve it. It took me two days to find the second issue.

Resolv.conf

When you start unbound, it will modify your /etc/resolv.conf file as follow:

# Generated by resolvconf
# nameserver 192.168.1.1
# nameserver 8.8.8.8

nameserver 127.0.0.1
options edns0

As you have seen previously it is enough for drill to resolve host names such a _http._tcp.pkg.freebsd.org. The host command confirms this:

# host pkg.freebsd.org
pkg.freebsd.org is an alias for pkgmir.geo.freebsd.org.
pkgmir.geo.freebsd.org has address 213.138.116.73
pkgmir.geo.freebsd.org has address 139.178.72.201
pkgmir.geo.freebsd.org has IPv6 address 2001:41c8:112:8300::50:1
pkgmir.geo.freebsd.org has IPv6 address 2604:1380:2000:9501::50:2

Having done all the checkings, I was suprised to see this:

# fetch http://pkg.freebsd.org/FreeBSD:12:amd64/latest/meta.conf
fetch: http://pkg.freebsd.org/FreeBSD:12:amd64/latest/meta.conf: No address record

I won't hold the suspens here. This strange behaviour when some tools manage to resolve but others do not can be solved by using the actual IP address of the jail in the /etc/resolv.conf file like this:

# Generated by resolvconf
# nameserver 192.168.1.1
# nameserver 8.8.8.8

nameserver 10.0.0.21
options edns0

It took me two days... (actually, two evenings). Of course, I skipped the part when I ran tcpdump trying to pin down the problem but I have a picture that sums up this moment:

Two days later

Two days after finding the above solution, I discovered that a Bastille template existed for unbound. I went to see the details and found this comment:

Conclusion

Network is complicated. Network in jail even more.