Local caching resolver in FreeBSD 10

As of a few hours ago, all it takes to set up a local caching resolver in FreeBSD 10 is:

# echo local_unbound_enable=yes >>/etc/rc.conf
# service local_unbound start

Yes, it really is that simple—and it works fine with DHCP, too. Hold my beer and watch this:

# pgrep -lf dhclient
1316 dhclient: vtnet0
1265 dhclient: vtnet0 [priv]
# cat /etc/resolv.conf
# Generated by resolvconf
search example.com
nameserver 192.0.2.53
# time host www.freebsd.org
www.freebsd.org is an alias for wfe0.ysv.freebsd.org.
wfe0.ysv.freebsd.org has address 8.8.178.110
wfe0.ysv.freebsd.org has IPv6 address 2001:1900:2254:206a::50:0
wfe0.ysv.freebsd.org mail is handled by 0 .
        0.02 real         0.00 user         0.01 sys

As you can see, we’re running DHCP on a VirtIO network interface. Let’s work our magic:

# echo local_unbound_enable=yes >>/etc/rc.conf
# service local_unbound start
Performing initial setup.
Extracting forwarders from /etc/resolv.conf.
/var/unbound/forward.conf created
/var/unbound/unbound.conf created
/etc/resolvconf.conf created
original /etc/resolv.conf saved as /etc/resolv.conf.20130923.075319
Starting local_unbound.

And presto:

# pgrep -lf unbound
3799 /usr/sbin/unbound -c/var/unbound/unbound.conf
# cat /var/unbound/unbound.conf 
# Generated by local-unbound-setup
server:
        username: unbound
        directory: /var/unbound
        chroot: /var/unbound
        pidfile: /var/run/local_unbound.pid
        auto-trust-anchor-file: /var/unbound/root.key

include: /var/unbound/forward.conf
# cat /var/unbound/forward.conf
# Generated by local-unbound-setup
forward-zone:
        name: .
        forward-addr: 192.0.2.53
# cat /etc/resolv.conf
# Generated by resolvconf
search example.com
# nameserver 192.0.2.53

nameserver 127.0.0.1
options edns0

We can see the cache at work; the first request takes significantly longer than before, but the second is served from cache:

# time host www.freebsd.org
www.freebsd.org is an alias for wfe0.ysv.freebsd.org.
wfe0.ysv.freebsd.org has address 8.8.178.110
wfe0.ysv.freebsd.org has IPv6 address 2001:1900:2254:206a::50:0
wfe0.ysv.freebsd.org mail is handled by 0 .
        0.07 real         0.01 user         0.00 sys
# time host www.freebsd.org
www.freebsd.org is an alias for wfe0.ysv.freebsd.org.
wfe0.ysv.freebsd.org has address 8.8.178.110
wfe0.ysv.freebsd.org has IPv6 address 2001:1900:2254:206a::50:0
wfe0.ysv.freebsd.org mail is handled by 0 .
        0.01 real         0.00 user         0.00 sys

Finally, let’s see how this interacts with DHCP:

# resolvconf -u
# cat /etc/resolv.conf
# Generated by resolvconf
search example.com
nameserver 127.0.0.1
nameserver 192.0.2.53
options edns0

# cat /var/unbound/forward.conf 
# Generated by resolvconf

forward-zone:
        name: "example.com"
        forward-addr: 192.0.2.53

forward-zone:
        name: "."
        forward-addr: 192.0.2.53

Note that resolvconf(8) re-added the 192.0.2.53 entry. It doesn’t really matter, as long as 127.0.0.1 comes first.

[ETA: it does matter—see Jakob Schlyter’s comment below and my reply.]

[ETA: see my followup about the motivation for importing Unbound.]

68 thoughts on “Local caching resolver in FreeBSD 10”

  1. Beware! With DNSSEC validation turned on (which is the default above), you must not have your non-local DNS nameserver still in /etc/resolv.conf, or validation failures will not be handled correctly. This is because a validation failure results in SERVFAIL, and libresolv will happily continue to the next name server in resolv.conf (where validation might be turned off) and succeed.

    Hence, resolvconf(8) should really NOT re-add non-local name servers to resolv.conf.

  2. I just tried to set up unbound by
    1) stopping named
    2) adding local_unbound_enable=yes to /etc/rc.conf
    3) typing % service local_unbound start
    Now there is no dns-resolution anymore – even on my localhost.

    Did I miss anything?

    Greetings Peter

    1. I assume you typed “service local_unbound start” at a root prompt; “%” is the csh and zsh prompt character for unprivileged users.

      1. Is unbound running? (pgrep -lf unbound)
      2. What are the contents of your /etc/resolv.conf?
      3. What are the contents of your /var/unbound/forward.conf?
      4. Are you using DHCP?
  3. Hello. thanks for this. I have a question though:

    Does unbound have a method of using dhcpd like bind does? For example, let’s say i have a laptop that signs on to my network with the hostname “wonslung-lap” . On bind, with my setup, it dhcpd will insert an A record and a reverse DNS record into bind’s Zone files.

    Because of this, i can ssh in from any other client on the network.

    Does unbound have a similar option for local authoritative dns?

    1. If you’re talking about DDNS: the LDNS distribution includes a DDNS client, but we do not build it. There are several DDNS clients in the ports tree.

  4. Hi,
    I have installed FreeBSD 10 beta4 where unbound has replaced bind. I have installed unbound according to your instruction. Unfortunately unbound can’t forward requests from localhost to provider’s DNS servers. Can you help me fix this trouble?

    # pgrep -lf unbou
    2856 /usr/sbin/unbound -c/var/unbound/unbound.conf

    cat /etc/resolv.conf
    search beeline
    # nameserver 85.21.192.3
    # nameserver 213.234.192.8
    nameserver 127.0.0.1
    options edns0

    cat /var/unbound/forward.conf
    # Generated by local-unbound-setup
    forward-zone:
    name: .
    forward-addr: 85.21.192.3
    forward-addr: 213.234.192.8

    sockstat -4 | grep unbound
    unbound unbound 2856 3 udp4 127.0.0.1:53 *:*
    unbound unbound 2856 4 tcp4 127.0.0.1:53 *:*
    unbound unbound 2856 5 tcp4 127.0.0.1:953 *:*

    cat /etc/unbound/unbound.conf
    # Generated by local-unbound-setup
    server:
    username: unbound
    directory: /var/unbound
    chroot: /var/unbound
    pidfile: /var/run/local_unbound.pid
    auto-trust-anchor-file: /var/unbound/root.key
    access-control: 127.0.0.0/8 allow_snoop
    remote-control:
    control-enable: yes
    control-interface: 127.0.0.1
    control-port: 953
    include: /var/unbound/forward.conf

    ping tp.internet.beeline.ru
    ping: cannot resolve tp.internet.beeline.ru: Host name lookup failure

    And if
    cat /etc/resolv.conf
    search beeline
    nameserver 85.21.192.3
    # nameserver 213.234.192.8
    nameserver 127.0.0.1
    options edns0

    then
    ping tp.internet.beeline.ru
    PING tp.internet.beeline.ru (85.21.0.240): 56 data bytes
    64 bytes from 85.21.0.240: icmp_seq=0 ttl=251 time=0.796 ms
    64 bytes from 85.21.0.240: icmp_seq=1 ttl=251 time=0.772 ms

    1. I don’t know. Try running tcpdump on the loopback interface (sudo tcpdump -i lo0 udp port domain) to see DNS traffic between ping and unbound, and on the external interface to see DNS traffic between unbound and your forwarders.

      1. That would disable DNSSEC validation, which is the point of running Unbound locally.

  5. I had installed unbound on FreeBSD 10 beta RC 3 and then upgraded to RC5. Unbound still works for local requests but now longer serves requests by other machines.
    Do you have any idea what might be going wrong?

    1. What do you mean by “installed unbound”? Just enabled the local_unbound service?

      1. No I had it running really well then it logs a failed to prime trust anchor. I assumed it was answering for local host but I still had another name server in resolv.conf.

        1. A “failed to generate a trust anchor” error is harmless, as long as it has succeeded at least once. It just means that it was unable to retrieve a new copy of the DNS root public key, but that key should never change unless it’s been compromised, which would be all over the news.

  6. After upgrading to 10.0 I can’t get unbound to work. The “service local_unbound start” generates an error saying “su: unknown login: unbound”. I checked the passwd, master.passwd, and group files and they all have an ‘unbound’ entry. I can run “su -m bind -c whoami” however I get the same su error if I run “su -m unbound -c whoami”. Anyone know how to resolve this?

    1. Check the timestamp on /etc/*passwd and /etc/*pwd.db. If the former are more recent than the latter, you need to run pwd_mkdb(8).

      1. I found pwd_mkdb(8), but the man page was kind of intimidating so I ran adduser and set everything to the values already in passwd and that fixed the db. Now local_unbound is working. Thanks!

        1. Perhaps Someone™ should add an example section to the man page. The command you want is pwd_mkdb -p /etc/master.passwd. Either freebsd-update(8) or mergemaster(8) should have taken care of it for you.

  7. I had the same problem.
    I ran:
    pwd_mkdb -p /etc/master.passwd

    which fixed the problem. Thanks for pointing me the right direction.

  8. Nice explanation…

    What about local_unbound + dnscrypt-proxy?

    I was trying to run dnscrypt on 127.0.0.2 (lo0 alias) and then point local_unbound to it!

    But I’m having no luck…
    cat /etc/unbound/forward.conf
    forward-zone:
    name: "."
    forward-addr: 127.0.0.2

    % drill txt debug.opendns.com @127.0.0.2
    ;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 42930
    ;; flags: qr rd ra ; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 0
    ;; QUESTION SECTION:
    ;; debug.opendns.com. IN TXT

    ;; ANSWER SECTION:
    debug.opendns.com. 0 IN TXT "server 5.fra"
    debug.opendns.com. 0 IN TXT "flags 20 0 2f4 4000800000000000000"
    debug.opendns.com. 0 IN TXT "id 0"
    debug.opendns.com. 0 IN TXT "source 77.54.234.20:43972"
    debug.opendns.com. 0 IN TXT "dnscrypt enabled (################)"

    ;; AUTHORITY SECTION:

    ;; ADDITIONAL SECTION:

    ;; Query time: 54 msec
    ;; EDNS: version 0; flags: ; udp: 4096
    ;; SERVER: 127.0.0.2
    ;; WHEN: Fri Feb 28 00:42:45 2014
    ;; MSG SIZE rcvd: 221

    host debug.opendns.com 127.0.0.1
    Using domain server:
    Name: 127.0.0.1
    Address: 127.0.0.1#53
    Aliases:

    Host debug.opendns.com not found: 2(SERVFAIL)

    host -t txt debug.opendns.com 127.0.0.2
    Using domain server:
    Name: 127.0.0.2
    Address: 127.0.0.2#53
    Aliases:

    debug.opendns.com descriptive text "server 5.fra"
    debug.opendns.com descriptive text "flags 20 0 2f4 4000800000000000000"
    debug.opendns.com descriptive text "id 0"
    debug.opendns.com descriptive text "source 77.54.234.20:43972"
    debug.opendns.com descriptive text "dnscrypt enabled

    ....

    1. I don’t know anything about DNSCrypt. Does Unbound say anything interesting in the logs? Have you tried running it in debug mode?

      1. Well dnscrypt here would work only as a forwarder and it seems to work well now, the only problem is that it seems local-domain lookup is not working, but this is probably not related to dnscrypt, I’m probably doing something wrong in local-unbound config.

        this is my unbound.conf:
        server:
        username: unbound
        directory: /var/unbound
        chroot: /var/unbound
        pidfile: /var/run/local_unbound.pid
        auto-trust-anchor-file: /var/unbound/root.key
        private-domain: "geek.lan"

        include: /var/unbound/forward.conf

        and forward.conf
        forward-zone:
        name: "geek.lan"
        forward-addr: 10.10.50.254

        forward-zone:
        name: "."
        forward-addr: 127.0.0.2

        what would be wrong here?

        1. What do you mean when you say local domain lookup doesn’t work? You don’t get an answer when you try to look something up in geek.lan?

          Try adding something to your local zone file that resolved to a routable address, e.g.

          freebsd.geek.lan. IN CNAME www.freebsd.org.

          then look it up through local_unbound. If it works, there is a bug (or misfeature) in unbound relating to forwarding of zones with private addresses.

          1. I was trying to query with drill -D yoda.geek.lan now and I get this:
            drill -D yoda.geek.lan
            ;; ->>HEADER<<- opcode: QUERY, rcode: SERVFAIL, id: 59098
            ;; flags: qr rd ra ; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0
            ;; QUESTION SECTION:
            ;; yoda.geek.lan. IN A

            ;; ANSWER SECTION:

            ;; AUTHORITY SECTION:

            ;; ADDITIONAL SECTION:

            ;; Query time: 7 msec
            ;; EDNS: version 0; flags: do ; udp: 4096
            ;; SERVER: 127.0.0.1
            ;; WHEN: Sat Mar 1 18:20:26 2014
            ;; MSG SIZE rcvd: 42

            However in the debug output from unbound:
            [1393698026] unbound[10467:0] info: 0RDd mod1 rep yoda.geek.lan. A IN [32/4683]
            [1393698026] unbound[10467:0] debug: cache memory msg=66424 rrset=66846 infra=3091 val=66401
            [1393698026] unbound[10467:0] debug: answer cb
            [1393698026] unbound[10467:0] debug: Incoming reply id = 7d92
            [1393698026] unbound[10467:0] debug: Incoming reply addr = ip4 10.10.50.254 port 53 (len 16)
            [1393698026] unbound[10467:0] debug: lookup size is 1 entries
            [1393698026] unbound[10467:0] debug: received udp reply.
            [1393698026] unbound[10467:0] debug: udp message[47:0] 7D928590000100010000000004796F6461046765656B036C616E0000010001C00C000100010000000000040A0A3232
            [1393698026] unbound[10467:0] debug: outnet handle udp reply
            [1393698026] unbound[10467:0] debug: measured roundtrip at 2 msec
            [1393698026] unbound[10467:0] debug: svcd callbacks start
            [1393698026] unbound[10467:0] debug: worker svcd callback for qstate 0x8026b5080
            [1393698026] unbound[10467:0] debug: mesh_run: start
            [1393698026] unbound[10467:0] debug: iterator[module 1] operate: extstate:module_wait_reply event:module_event_reply
            [1393698026] unbound[10467:0] info: iterator operate: query yoda.geek.lan. A IN
            [1393698026] unbound[10467:0] debug: process_response: new external response event
            [1393698026] unbound[10467:0] info: scrub for geek.lan. NS IN
            [1393698026] unbound[10467:0] info: response for yoda.geek.lan. A IN
            [1393698026] unbound[10467:0] info: reply from 10.10.50.254#53
            [1393698026] unbound[10467:0] info: incoming scrubbed packet: ;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 0
            ;; flags: qr aa rd ra ; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
            ;; QUESTION SECTION:
            ;; yoda.geek.lan. IN A

            ;; ANSWER SECTION:
            yoda.geek.lan. 0 IN A 10.10.50.50

            ;; AUTHORITY SECTION:

            ;; ADDITIONAL SECTION:

            ;; Query time: 0 msec
            ;; WHEN: Thu Jan 1 01:00:00 1970
            ;; MSG SIZE rcvd: 47

            [1393698026] unbound[10467:0] debug: iter_handle processing q with state QUERY RESPONSE STATE
            [1393698026] unbound[10467:0] info: query response was ANSWER
            [1393698026] unbound[10467:0] debug: TTL 0: dropped msg from cache
            [1393698026] unbound[10467:0] debug: iter_handle processing q with state FINISHED RESPONSE STATE
            [1393698026] unbound[10467:0] info: finishing processing for yoda.geek.lan. A IN
            [1393698026] unbound[10467:0] debug: mesh_run: iterator module exit state is module_finished
            [1393698026] unbound[10467:0] debug: validator[module 0] operate: extstate:module_wait_module event:module_event_moddone
            [1393698026] unbound[10467:0] info: validator operate: query yoda.geek.lan. A IN
            [1393698026] unbound[10467:0] debug: validator: nextmodule returned
            [1393698026] unbound[10467:0] debug: val handle processing q with state VAL_INIT_STATE
            [1393698026] unbound[10467:0] debug: validator classification positive
            [1393698026] unbound[10467:0] info: no signer, using yoda.geek.lan. TYPE0 CLASS0
            [1393698026] unbound[10467:0] debug: val handle processing q with state VAL_FINISHED_STATE
            [1393698026] unbound[10467:0] debug: mesh_run: validator module exit state is module_finished
            [1393698026] unbound[10467:0] debug: query took 0.002532 sec
            [1393698026] unbound[10467:0] info: mesh_run: end 0 recursion states (0 with reply, 0 detached), 0 waiting replies, 2 recursion replies sent, 0 replies dropped, 0 states jostled out
            [1393698026] unbound[10467:0] info: average recursion processing time 0.170909 sec
            [1393698026] unbound[10467:0] info: histogram of recursion processing times
            [1393698026] unbound[10467:0] info: [25%]=0 median[50%]=0 [75%]=0
            [1393698026] unbound[10467:0] info: lower(secs) upper(secs) recursions
            [1393698026] unbound[10467:0] info: 0.002048 0.004096 1
            [1393698026] unbound[10467:0] info: 0.262144 0.524288 1
            [1393698026] unbound[10467:0] debug: cache memory msg=66424 rrset=66846 infra=3091 val=66401

            1. Yep, looks like it’s dropping the answer due to the RFC1918 address. Did you try the freebsd.geek.lan thing I suggested?

            2. Wait, I spoke too soon. I just noticed this bit:

              ;; QUESTION SECTION:
              ;; yoda.geek.lan. IN A

              ;; ANSWER SECTION:
              yoda.geek.lan. 0 IN A 10.10.50.50

              followed by

              [1393698026] unbound[10467:0] debug: TTL 0: dropped msg from cache

              so it looks like Unbound is dropping the answer it got from upstream because its TTL is 0. This raises a number of questions:

              • Did dnscrypt intentionally set the TTL to 0?
              • Does the DNS specification actually allow this?
              • Was it a conscious decision on the unbound developers’ part to ignore a response with a TTL of 0, or did they just not consider that scenario?

              Assuming that dnscrypt intentionally sets the TTL to 0 to prevent downstream resolvers from caching the response, it shouldn’t be too hard to make unbound accept that answer and pass it on without caching it. As a workaround, see if it is possible to configure dnscrypt to use a non-zero TTL.

            3. Grr, spoke too soon again. I didn’t notice that the TTL 0 issue is not related to dnscrypt, but to whatever you’re using for your local domain. What do you run on 10.10.50.254?

  9. Sorry for the late reply that’s my local router (running asus merlin firmware)

    I also just found a more weired thing... tcpdump (wireshark shows this):
    12 12.637094000 127.0.0.1 127.0.0.1 DNS 129 Standard query response 0x51d3 No such name
    13 21.769253000 127.0.0.1 127.0.0.1 DNS 65 Standard query 0xf10d A c3po.geek.local
    14 21.769856000 10.10.50.70 10.10.50.254 DNS 86 Standard query 0xc826 A c3po.geek.local
    15 21.771011000 10.10.50.254 10.10.50.70 DNS 91 Standard query response 0xc826 A 10.10.50.10

    So, it seems that the query DID retrun an ANWSER and its local_unbound that’s somehow …. not parsing it/Seeing it as ’empty’?

  10. Sorry for the late reply, was having problems posting from smartphone!

    The ‘10.10.50.254’ machine is my local router, running Asus Merlin firmware… An interesting thing is that according to wireshark/tcpdump the rely did came

    No. Time Source Destination Protocol Length Info
    11 12.637054000 127.0.0.1 127.0.0.1 DNS 54 Standard query 0x51d3 A c3po
    12 12.637094000 127.0.0.1 127.0.0.1 DNS 129 Standard query response 0x51d3 No such name
    13 21.769253000 127.0.0.1 127.0.0.1 DNS 65 Standard query 0xf10d A c3po.geek.local
    14 21.769856000 10.10.50.70 10.10.50.254 DNS 86 Standard query 0xc826 A c3po.geek.local
    15 21.771011000 10.10.50.254 10.10.50.70 DNS 91 Standard query response 0xc826 A 10.10.50.10

    But local unbound log shows nothing after AWNSER.

    1. Like I said, Unbound receives the answer but discards it because it has a TTL of 0; at least, that’s what the log says. Unfortunately, neither tcpdump nor wireshark seem to display the DNS TTL (as opposed to the IP TTL). I would suggest asking unbound-users@unbound.net for advice.

  11. What you suggest does seem to be pointing to the problem, I’ll ask in the list and post feedback later.

    Another thing I noticed is that each time I reboot I have to update forwarders.conf with the dnscrypt-proxy ip for “.”, its always re-updating the file using resolvconf… has if it was running “setup” before the start… wonder if this is the expected behavior with local_unbound

    1. Yes, it is the expected behavior. You should place that part of your configuration either directly in unbound.conf or in a separate .conf file which you include in unbound.conf.

      1. Just follow the steps in “Unbound DNS Tutorial” in calomel.org, specifically “Authoritative, validating, recursive DNS caching” for not skip auto-trust-anchor-file in unbound.conf

  12. interface: 127.0.0.1
    do-ip4: yes
    do-ip6: no
    do-udp: yes
    do-tcp: yes
    hide-version: yes

  13. $ sudo service local_unbound start
    Performing initial setup.
    Extracting forwarders from /etc/resolv.conf.
    /var/unbound/forward.conf created
    /var/unbound/lan-zones.conf created
    /var/unbound/unbound.conf created
    /etc/resolvconf.conf not modified
    original /etc/resolv.conf saved as /etc/resolv.conf.20150407.145724
    Starting local_unbound.

    $ host msn.com
    Host msn.com not found: 2(SERVFAIL)

    1. There are a number of reasons why this might happen, including an incorrect clock (causing unbound to reject the DNSSEC root anchor) which is a common issue with VMs. It’s hard to tell without additional information. You could try to run unbound manually in debug mode. Off the top of my head:


      $ sudo service local_unbound stop
      $ sudo /usr/sbin/unbound -c/var/unbound/unbound.conf -dd

      This generates a lot of output, so you may want to redirect to a log file and look at it after your test is complete.

  14. I just ran into the same issue as others, getting SERVFAIL on a fresh setup. The problem turned out to be the DHCP-provided resolver does not support DNSSEC. Removing the forward allowed it to work. This was on AWS EC2. Perhaps the setup script should sanity check the forwarder before using it.

    1. That’s a bit difficult in the DHCP case since the forwarder can change every time you renew your lease. However, I am very surprised to hear that Amazon’s resolvers are incapable of or unwilling to handle requests for DNSSEC record types (Unbound does its own checking, so it’s not so much a matter of “supporting DNSSEC” as one of passing on requests and responses involving DNSKEY, RRSIG, DS etc. records).

  15. I’m also getting SERVFAIL on my fresh setup, on FreeBSD 10-STABLE.

    My router is an Apple AirPort Time Capsule (current model), configured to use my ISP’s resolver (Comcast’s 75.75.75.75). The router’s DHCP server is telling the devices on my LAN to use the router’s own IP address as the resolver, so dhclient wrote that into /etc/resolv.conf, and that’s what was propagated into Unbound’s forward.conf on first run of Unbound. With that configuration, I only get SERVFAIL.

    I can get DNS resolution to work if I replace the forward.conf entries with 75.75.75.75. I would rather not have to do anything special like this; I don’t see why the router’s resolver won’t just work and pass everything through to my ISP. But if this is what I have to do, then how do I make the setting “stick”? Running resolvconf -u continues to result in the router’s IP address being pulled from somewhere (a DHCP lease renewal, I assume) and written into forward.conf, overwriting my 75.75.75.75.

    Unrelated issue: Some computers, like my BeagleBone Black, don’t have a clock battery, or the battery is just dying or dead; either way, the clock resets to a date well in the past with each power cycle. Naturally, I run ntpdate or ntpd at boot time and pray that networking works so that the correct time can be fetched from an NTP server pool on the Internet. The pools are all referenced by domain names, though, so unless replace the names with IP addresses (not advisable), DNS resolution must be working first. It seems like letting the system start Unbound at boot time is a bad idea, then; it needs to be delayed until the clock is accurately set. What’s the right way to deal with this?

    1. In theory, you could add local_unbound_forwarders=75.75.75.75 to rc.conf and re-run service local_unbound setup, but it will only work until the next time the lease is refreshed or renewed. You need to patch local-unbound-setup so that it generates a resolvconf.conf without the unbound_* lines if one or more forwarders were specified on the command line (then send me the patch, of course).

      As for the BeagleBone issue, the best advice I can give you is to point it at some other machine on your network that runs ntpd with the stock ntp.conf. You still have to hardcode an IP address, but at least it’s one you control.

        1. Hmm, well, I figured out that if I instead just add name_servers=”75.75.75.75″ to resolvconf.conf, this IP will be listed ahead of the DHCP-assigned resolver in forward.conf, which I think gives me the “sticky” behavior I want, as long as I don’t run the Unbound setup again. I could also use name_server_blacklist to prevent the DHCP-assigned resolver from being listed as a forwarder at all.

          So, would it be better to have your patch just add a name_servers line instead of blanking resolvconf.conf?

          I’m also wondering what’s the best way to specify exceptions. When running a mail server, to fight spam it’s common to use DNS-based RBL services. In your resolver config you need to be able to say that for certain RBL domains which refuse queries from the major ISPs’ DNS servers, you don’t want to use the normal forwarders; Unbound should directly query the RBL servers instead. In BIND’s named.conf, the procedure was to set empty forwarders for certain zones, as I documented at the bottom of https://wiki.apache.org/spamassassin/CachingNameserver … what’s the equivalent for Unbound?

          If there’s a better forum for these questions, please point me to it. :)

          1. So, would it be better to have your patch just add a name_servers line instead of blanking resolvconf.conf?

            Relying on resolvconf to apply a static nameserver configuration only works when resolvconf actually runs, i.e. in the DHCP case.

            In your resolver config you need to be able to say that for certain RBL domains which refuse queries from the major ISPs’ DNS servers, you don’t want to use the normal forwarders; Unbound should directly query the RBL servers instead.

            Create a file in /var/unbound/conf.d containing a forward-zone definition for the appropriate domain. Off the top of my head:

            # cat >/var/unbound/conf.d/surbl.conf <<EOF
            forward-zone:
                    name: multi.surbl.org
                    forward-host: a.surbl.org
                    forward-host: b.surbl.org
                    forward-host: c.surbl.org
            EOF
            # service local_unbound reload
            
            1. Thank you man, I did not understand why forward.conf is overwritten. Creating my custom forward in /var/unbound/conf.d/mycustom.conf fixed that.

              1. Assuming you just want to hardcode your forwarders, you should set local_unbound_forwarders in /etc/rc.conf or /etc/rc.conf.d/local_unbound instead.

  16. For some reason ‘service local_unbound reload’ is not picking up the includes; you can see this if you run ‘unbound-control list_forwards’. You must do ‘restart’ instead of ‘reload’. And then if you ‘reload’ you will lose the includes again. I assume it’s a bug.

    Perhaps related: local-unbound-setup.sh writes into resolvconf.conf: ‘unbound_conf=”/var/unbound/forward.conf”‘ … should that not be referring to unbound.conf, which includes forward.conf etc.?

    1. For some reason ‘service local_unbound reload’ is not picking up the includes; you can see this if you run ‘unbound-control list_forwards’. You must do ‘restart’ instead of ‘reload’. And then if you ‘reload’ you will lose the includes again.

      That’s weird. If you stop the service, then run ktrace -di /usr/sbin/unbound -c/var/unbound/unbound.conf -d and send a SIGHUP to the unbound process, then kill it; kdump -tns will show you the names of all files it tried to access, as well as where the signals occurred.

      Perhaps related: local-unbound-setup.sh writes into resolvconf.conf: ‘unbound_conf=”/var/unbound/forward.conf”‘ … should that not be referring to unbound.conf, which includes forward.conf etc.?

      No, that variable points to the file that resolvconf is supposed to edit.

      1. I haven’t yet replaced local-unbound-setup.sh with your patched version yet, but see http://pastebin.com/raw.php?i=j6tpHvit for kdump output as instructed, plus the current contents of various config files.

        Sorry for not really understanding. Most of this is magic to me.

        Depsite the fact that after restarting the service, ‘unbound-control list_forwards’ shows me that the DNSBL config file has been taken into consideration, command-line testing shows that the DNSBL lookups are still being forwarded through my ISP’s resolvers and are thus being refused. The only way to get the lookups to work is to disable forwarding entirely (‘unbound-control forward off’) or at least take my ISP’s server out of the mix, as demonstrated below:

        # cat /var/unbound/conf.d/uribl.conf
        forward-zone:
        name: multi.uribl.com
        forward-host: multi.uribl.com
        # unbound-control reload
        ok
        # unbound-control list_forwards
        . IN forward 75.75.75.75
        # unbound-control forward_add multi.uribl.com multi.uribl.com
        ok
        # unbound-control list_forwards
        unbound-control list_forwards
        . IN forward 75.75.75.75
        multi.uribl.com. IN forward multi.uribl.com.
        host -tTXT test.uribl.com.multi.uribl.com
        test.uribl.com.multi.uribl.com descriptive text "127.0.0.1 -> Query Refused. See http://uribl.com/refused.shtml for more information [Your DNS IP: 76.96.107.199]"
        # unbound-control forward_remove .
        ok
        # unbound-control list_forwards
        multi.uribl.com. IN forward multi.uribl.com.
        # unbound-control flush_zone multi.uribl.com
        ok removed 1 rrsets, 1 messages and 0 key entries
        # host -tTXT test.uribl.com.multi.uribl.com
        test.uribl.com.multi.uribl.com descriptive text "permanent testpoint"
        # unbound-control flush_zone multi.uribl.com
        ok removed 2 rrsets, 0 messages and 0 key entries
        # unbound-control forward 75.75.75.75
        ok
        # unbound-control list_forwards
        . IN forward 75.75.75.75
        multi.uribl.com. IN forward multi.uribl.com.
        # host -tTXT test.uribl.com.multi.uribl.com
        test.uribl.com.multi.uribl.com descriptive text "127.0.0.1 -> Query Refused. See http://uribl.com/refused.shtml for more information [Your DNS IP: 76.96.107.199]"

        I’m not sure what to make of this.

        Just to be clear, all I want is to ignore my DHCP-assigned resolver and instead just forward by default through my ISP’s nameserver, except lookups in certain zones which need to never be forwarded at all…and nothing should get clobbered by DHCP lease renewals.

        1. Start by applying both patches (r287880 and r287918), then define unbound_forwarders appropriately in rc.conf, run local-unbound-setup and restart the service. If it still doesn’t work, move the forward.conf line in unbound.conf to the bottom (after the conf.d line) and restart.

          1. Actually, I’m 99% sure that moving that line won’t work. Try running unbound in debug mode instead:

            # /usr/sbin/unbound -c/var/unbound/unbound.conf -ddv
            

            then perform the query in another terminal:

            # host -t txt test.uribl.com.multi.uribl.com
            

            and see what unbound does behind the scenes. It works fine here (i.e. it queried one of the uribl.com servers, not my local forwarder).

            1. (let’s increase the nesting limit…)

              You’re not supposed to build in contrib.

              # cd /usr/src/lib/libunbound
              # make obj && make depend all install
              # cd /usr/src/usr.sbin/unbound
              # make obj && make depend all install
              
              1. Ah, OK, user error, of course. Thanks for pointing me in the right direction. Unbound is rebuilt with the patches. To start fresh(-ish), I deleted resolvconf.conf, forward.conf, unbound.conf, and restored my original resolv.conf with DHCP-assigned nameserver. I made sure local_unbound_forwarders "75.75.75.75 75.75.76.76" was in rc.conf. Then I ran ‘service local_unbound setup’ and observed resolv.conf is fine (pointing to 127.0.0.1 now), forward.conf only refers to the specified forwarders, and resolvconf.conf doesn’t have the unbound_* lines. So I ran ‘service local_unbound start’ and then tried ‘unbound-control list_forwards’. This was the result:

                [1442662531] unbound-control[89027:0] error: Could not open /usr/local/etc/unbound/unbound.conf: No such file or directory
                [1442662531] unbound-control[89027:0] fatal error: could not read config file

                So the rebuilt unbound-control seems to have lost the knowledge of where the config file lives. I can get it to work if I specify the file, but I didn’t have to do that before:

                # unbound-control -c /var/unbound/unbound.conf list_forwards
                . IN forward 75.75.75.75 75.75.76.76
                multi.uribl.com. IN forward multi.uribl.com.

                Anyway, ‘host -tTXT test.uribl.com.multi.uribl.com’ is failing :

                Host test.uribl.com.multi.uribl.com not found: 3(NXDOMAIN)

                This is weird; I would expect a “descriptive text” result of some kind, as I demonstrated earlier. So I stopped the service and started the server in debug mode, with the command line you gave me above, and retried the ‘host’ comand. Same result, and the debug output was this: http://pastebin.com/raw.php?i=RdRRdWDD

                1. You seem to have the unbound port installed, and are trying to start that rather than the base system version.

                  Also, the error is pretty obvious if you actually look at the debugging output and at your configuration.

                  1. I never installed the unbound port. My rebuilt base system version was started with /usr/sbin/unbound -c/var/unbound/unbound.conf -ddv as you instructed.

                    I see in the debug output that the ‘search’ domain from /etc/resolv.conf is being appended. This was DHCP-assigned but was not commented out when resolv.conf was automatically edited during the ‘service local_unbound setup’ process. Commenting it out does not really help; it just changes the result from NXDOMAIN to SERVFAIL:

                    [1442782774] unbound[89074:0] info: resolving test.uribl.com.multi.uribl.com. TXT IN
                    [1442782774] unbound[89074:0] info: resolving multi.uribl.com. AAAA IN
                    [1442782774] unbound[89074:0] info: resolving multi.uribl.com. A IN

                    I guess I am blind. I’m not seeing the problem.

                    # cat /etc/resolv.conf
                    # Generated by resolvconf
                    # search hsd1.co.comcast.net.
                    # nameserver 10.0.1.1
                    nameserver 127.0.0.1
                    options edns0

                    # cat /etc/resolvconf.conf
                    # This file was generated by local-unbound-setup.
                    # Modifications will be overwritten.
                    resolv_conf="/dev/null" # prevent updating /etc/resolv.conf
                    # Static DNS configuration

                    # cat /var/unbound/unbound.conf
                    # This file was generated by local-unbound-setup.
                    # Modifications will be overwritten.
                    server:
                    username: unbound
                    directory: /var/unbound
                    chroot: /var/unbound
                    pidfile: /var/run/local_unbound.pid
                    auto-trust-anchor-file: /var/unbound/root.key

                    include: /var/unbound/forward.conf
                    include: /var/unbound/lan-zones.conf
                    include: /var/unbound/control.conf
                    include: /var/unbound/conf.d/*.conf

                    # cat /var/unbound/forward.conf
                    # This file was generated by local-unbound-setup.
                    # Modifications will be overwritten.
                    forward-zone:
                    name: .
                    forward-addr: 75.75.75.75
                    forward-addr: 75.75.76.76

                    # cat /var/unbound/conf.d/uribl.conf
                    forward-zone:
                    name: multi.uribl.com
                    forward-host: multi.uribl.com

                    1. I can only guess the problem with unbound-control looking in /usr/local/etc was due to my botched attempt to rebuild Unbound in contrib. I’m unable to reproduce that problem after starting with a completely clean 10.2-STABLE installation, applying the patches, and running the proper ‘make’ commands. So, starting fresh, I documented everything in my wiki.

                      1. In a nutshell: As you probably saw when I asked about the DNSBL zone config issue on the unbound-users list, it is apparently impossible to replicate BIND’s “forward by default, but for certain zones, recursively resolve” behavior in Unbound. But if you don’t mind maintaining your own list of authoritative servers for those zones, you can put them in stub-zone entries. This works well enough.
                      2. This may be helpful for others stumbling across this thread: debug output can be enabled via local_unbound_flags=”-vvv” (or whatever) in /etc/rc.conf, then ‘service local_unbound restart’. If you still have the standard ‘*.=debug /var/log/debug.log’ in /etc/syslog.conf, you can just ‘tail -f /var/log/debug.log’ to watch the fireworks. You may have seen on the FreeBSD forum that someone reported sig_stop=”QUIT” should be added to /etc/rc.d/local_unbound.
                      3. I encountered another problem (perhaps) in local-unbound-setup.sh. Run ‘service local_unbound setup’ after adding a non-empty unbound_forwarders line to /etc/rc.conf. All should be well in the config files; forwarding is set up as you asked for in rc.conf. Now remove that line from /etc/rc.conf, or just empty the list, and run ‘service local_unbound setup’ again. The idea is to disable the forwarding and go back to how it would be if your rc.conf had been this way all along. Because the now-invalid forward.conf still exists, though, local-unbound-setup leaves a reference to it in unbound.conf. I understand this might be normal in some situations, but I would expect that the lack of forwarders in rc.conf would override this. Anyway, I thought I could work around it by deleting/renaming forward.conf and re-running ‘service local_unbound setup’, but /etc/resolvconf.conf then contains unbound_conf=”/var/unbound/forward.conf” which of course does not exist. If this is not a problem and I’m just expecting the wrong things, please have patience with me. I am still learning. Thanks.
                      1. Fixed your formatting the way I think you intended it.

                        1. It should not be too hard to add a recursive-zone directive to Unbound which can be used to indicate that a specific zone should be resolved recursively rather than forwarded.
                        2. The SIGQUIT thing is purely imaginary, see #203580.
                        3. The behavior of using forward.conf if it exists is intentional. In the common case (you either use DHCP or had a statically configured resolv.conf, and did not specify any forwarders in rc.conf) the first time you run local-unbound-setup, it will create forward.conf and change resolv.conf to point at localhost. If you run it again, it will not be able to determine which forwarders to use. If local-unbound-setup deleted forward.conf like you expected it to, then running it twice would render your system unusable.
                        1. Thanks. Formatting is close enough (SIGQUIT thing was a separate item).

                          I understand the reason for setup not deleting forward.conf; your explanation helped.

                          After thinking about it some more, I also see I don’t need to be concerned about the forward.conf reference in resolvconf.conf after I run local-unbound-setup with forward.conf deleted and no forwarders mentioned in rc.conf. I was afraid resolvconf wasn’t going to like the fact that forward.conf is missing, but it doesn’t care.

                          C isn’t my forte, so I won’t be adding any features to Unbound anytime soon.

    2. I just upgraded Unbound to 1.5.4 in head, then found and fixed the reload bug in r287918. The patch should apply cleanly to stable/10.

  17. I know this post is a bit dated, but maybe you have some idea why unbound are placed in /var? This seems very non FreeBSD to me?

    1. We did the same for BIND, with symlinks in /etc. Besides, the local_unbound configuration is not intended to be user-serviceable.

    1. Yes. It will use the resolvers that were listed in /etc/resolv.conf when you first ran the setup script, or you can set the local_unbound_resolvers variable (either in /etc/rc.conf or /etc/rc.conf.d/local_unbound) to a space-separated list of IP addresses, or to none for a recursing configuration, and re-run service local_unbound setup.

Leave a Reply to Dag-Erling Smørgrav Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.