Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unbound does not allow access WireGuard interface despite told to #4142

Closed
pengshao opened this issue May 28, 2020 · 28 comments
Closed

Unbound does not allow access WireGuard interface despite told to #4142

pengshao opened this issue May 28, 2020 · 28 comments
Labels
help wanted Contributor missing / timeout support Community support

Comments

@pengshao
Copy link

pengshao commented May 28, 2020

Describe the bug

After setting up WireGuard VPN and specify the OPNsense unbound as the DNS server, I noticed that VPN clients cannot resolve DNS names. However if I restart the unbound after the system boots up manually, everything resumes working.

Here is a brief diagram of my interfaces set up.

WAN (ipv4, ipv6 address from ISP)
    |
LAN (10.0.1.1/24)
    |
IOT (vlan, 10.0.50.1/24)
    |
WG (tunnel address 10.252.0.1/24)

firefox_OP26kLWdP3
firefox_hWbwx12d3l

LAN clients are not affected by this bug.

Firewall log indicated the DNS request successfully made it to the unbound port. The WireGuard interface has already been assigned to interface "WG" (so I have a WG under "interface" and a "WireGuard" and "WG" under firewall rules).

Changing "Services->Unbound DNS->General->Network Interfaces" from "all" to manually picking "LAN WAN WG" does not resolve the bug. Checking access list conf file suggests that the WG interface (whose "address" is 10.252.0.1) is not allowed immediately after the system starts up, but somehow appears after a manual restart of unboud itself.

The Web GUI however successfully lists the WG address as being allowed in "Services->Unbound DNS->General->Allowed list" despite the address is not in the conf file.

firefox_Q0ImdnydR7

Could this be because unbound started "too early" than WG, that it cannot see the interface? I also noticed that my WAN for some reason often has ipv6 address bound very late, potentially 1 or 2 minutes after the system starts. And checking the access list of unbound suggests that the WAN ipv6 address is not in the list neither if it is not bound during the system start up, only appears after a manual unbound restart.

Steps to reproduce the behavior:

  1. Set up WireGuard following official doc with tunnel address "10.252.0.1/24"
  2. Add interface "WG" over "wg0"
  3. Configure unbound to listen on all interfaces
  4. Connect to VPN from a client, assign "10.252.0.1" as the dns address
  5. Client cannot resolve DNS names.
  6. Manually restart unbound from Web GUI.
  7. Client can resolve DNS names.

Relevant log files
/var/unbound/access_lists.conf
Immediate after boot:

access-control: 127.0.0.1/8 allow
access-control: ::1/64 allow
access-control: 10.0.50.1/24 allow
access-control: fe80::4262:31ff:fe08:8c1d/64 allow
access-control: 10.0.1.1/24 allow
access-control: 2604:4080:11ac:86e0:4262:31ff:fe08:8c1d/64 allow
access-control: 24.35.90.97/25 allow
access-control: fe80::4262:31ff:fe08:8c1c/64 allow

After a manual restart of unbound, notice the last line which is the WG interface. Also the second IPv6 address was on WAN port, which may suffer from the same issue as the WG interface.

access-control: 127.0.0.1/8 allow
access-control: ::1/64 allow
access-control: 10.0.50.1/24 allow
access-control: fe80::4262:31ff:fe08:8c1d/64 allow
access-control: 10.0.1.1/24 allow
access-control: 2604:4080:11ac:86e0:4262:31ff:fe08:8c1d/64 allow
access-control: 24.35.90.97/25 allow
access-control: 2604:4080:11ac:0:4262:31ff:fe08:8c1c/64 allow
access-control: fe80::4262:31ff:fe08:8c1c/64 allow
access-control: 10.252.0.1/24 allow

ifconfig:


igb0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=400b8<VLAN_MTU,VLAN_HWTAGGING,JUMBO_MTU,VLAN_HWCSUM,VLAN_HWTSO>
        ether 40:62:31:08:8c:1c
        hwaddr 40:62:31:08:8c:1c
        inet6 fe80::4262:31ff:fe08:8c1c%igb0 prefixlen 64 scopeid 0x1
        inet6 2604:4080:11ac:0:4262:31ff:fe08:8c1c prefixlen 64 autoconf
        inet 24.35.90.97 netmask 0xffffff80 broadcast 24.35.90.127
        nd6 options=23<PERFORMNUD,ACCEPT_RTADV,AUTO_LINKLOCAL>
        media: Ethernet autoselect (1000baseT <full-duplex>)
        status: active
igb1: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=400b8<VLAN_MTU,VLAN_HWTAGGING,JUMBO_MTU,VLAN_HWCSUM,VLAN_HWTSO>
        ether 40:62:31:08:8c:1d
        hwaddr 40:62:31:08:8c:1d
        inet6 fe80::4262:31ff:fe08:8c1d%igb1 prefixlen 64 scopeid 0x2
        inet6 2604:4080:11ac:86e0:4262:31ff:fe08:8c1d prefixlen 64
        inet 10.0.1.1 netmask 0xffffff00 broadcast 10.0.1.255
        nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>
        media: Ethernet autoselect (1000baseT <full-duplex>)
        status: active
igb2: flags=8c02<BROADCAST,OACTIVE,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=6403bb<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,JUMBO_MTU,VLAN_HWCSUM,TSO4,TSO6,VLAN_HWTSO,RXCSUM_IPV6,TXCSUM_IPV6>
        ether 40:62:31:08:8c:1e
        hwaddr 40:62:31:08:8c:1e
        nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>
        media: Ethernet autoselect
        status: no carrier
igb3: flags=8c02<BROADCAST,OACTIVE,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=6403bb<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,JUMBO_MTU,VLAN_HWCSUM,TSO4,TSO6,VLAN_HWTSO,RXCSUM_IPV6,TXCSUM_IPV6>
        ether 40:62:31:08:8c:1f
        hwaddr 40:62:31:08:8c:1f
        nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>
        media: Ethernet autoselect
        status: no carrier
igb4: flags=8c02<BROADCAST,OACTIVE,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=6403bb<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,JUMBO_MTU,VLAN_HWCSUM,TSO4,TSO6,VLAN_HWTSO,RXCSUM_IPV6,TXCSUM_IPV6>
        ether 40:62:31:08:8c:20
        hwaddr 40:62:31:08:8c:20
        nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>
        media: Ethernet autoselect
        status: no carrier
igb5: flags=8c02<BROADCAST,OACTIVE,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=6403bb<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,JUMBO_MTU,VLAN_HWCSUM,TSO4,TSO6,VLAN_HWTSO,RXCSUM_IPV6,TXCSUM_IPV6>
        ether 40:62:31:08:8c:21
        hwaddr 40:62:31:08:8c:21
        nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>
        media: Ethernet autoselect
        status: no carrier
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
        options=600003<RXCSUM,TXCSUM,RXCSUM_IPV6,TXCSUM_IPV6>
        inet6 ::1 prefixlen 128
        inet6 fe80::1%lo0 prefixlen 64 scopeid 0x7
        inet 127.0.0.1 netmask 0xff000000
        nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>
        groups: lo
enc0: flags=0<> metric 0 mtu 1536
        nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>
        groups: enc
pflog0: flags=100<PROMISC> metric 0 mtu 33160
        groups: pflog
pfsync0: flags=0<> metric 0 mtu 1500
        groups: pfsync
        syncpeer: 0.0.0.0 maxupd: 128 defer: off
igb1_vlan50: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        ether 40:62:31:08:8c:1d
        inet6 fe80::4262:31ff:fe08:8c1d%igb1_vlan50 prefixlen 64 scopeid 0xb
        inet 10.0.50.1 netmask 0xffffff00 broadcast 10.0.50.255
        nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>
        media: Ethernet autoselect (1000baseT <full-duplex>)
        status: active
        vlan: 50 vlanpcp: 0 parent interface: igb1
        groups: vlan
wg0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> metric 0 mtu 1420
        options=80000<LINKSTATE>
        inet 10.252.0.1 --> 10.252.0.1 netmask 0xffffff00
        nd6 options=103<PERFORMNUD,ACCEPT_RTADV,NO_DAD>
        groups: tun wireguard
        Opened by PID 31549

Additional context
This appears to be similar to this issue: #3342, but the difference is that in my case the WG interface is not even showing up in the /var/unbound/access_lists.conf file until unbound being restarted.

Environment
OPNsense 20.1.7-amd64
Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz (4 cores)
Network Intel® I210-AT

@pengshao pengshao changed the title Unbound does not bind to WireGuard interface Unbound does not allow access WireGuard interface despite told to May 28, 2020
@mimugmail
Copy link
Member

You could set LAN IP as server address for the clients?

@pengshao
Copy link
Author

You could set LAN IP as server address for the clients?

You mean setting a LAN IP as DNS server for VPN clients? Yes, the VPN clients can ping hosts in LAN without issue, just of course the reverse DNS lookup does not work in LAN.

@AdSchellevis
Copy link
Member

An other option is to bind to a loopback interface and forward the traffic to the service at hand, which detaches the network layer from the service and ensures a more stable setup. I think most of the larger vendors advise this pattern with internal services, to avoid interface dependencies in services.

@pengshao
Copy link
Author

An other option is to bind to a loopback interface and forward the traffic to the service at hand, which detaches the network layer from the service and ensures a more stable setup. I think most of the larger vendors advise this pattern with internal services, to avoid interface dependencies in services.

Absolutely please do not make DNS depend on VPN :) I can live without VPN but not without DNS.

@AdSchellevis
Copy link
Member

not sure what you mean by that comment, but I'm not suggesting to add dependencies, just to remove them.

@pengshao
Copy link
Author

Ah sorry for sounded confusing. I am not a native English speaker and I was expressing agreement with your comment :) Would you please be more specific in the suggestion so I can follow it to help testing? Sorry I am not very good at networking :)

@AdSchellevis
Copy link
Member

No problem, small miscommunication, I'm not a native speaker either :)

The steps I suggest would look a bit like this (haven't tested this out for unbound, but works for other services so should function here too)

  • Add a new loopback interface (Interfaces -> Other types -> Loopback)
  • Assign the newly created interface (Interfaces Assignments)
  • Setup a private ip address or the loopback (can be anything, 127.0.0.2/32 or some unused address/network in the rfc1918 range)
  • Bind unbound to that new interface, since it's static and independent of hardware, it's assured to be available all the time.
  • Make sure within unbound there's an ACL to accept traffic from the networks you want to use (I'm not using this very often, but I assume unbound -> access lists will do the trick).
  • Add a portforward for port 53 (dns) from your source (wireguard for example) to 127.0.0.2 in Firewall -> Nat -> Port forward
  • Make sure to allow this traffic via a firewall rule (Firewall -> Rules).

Should do the trick, prevents all sorts of strange race conditions when the interface is not yet configured.

@pengshao
Copy link
Author

pengshao commented May 29, 2020

Thank you so much for your detailed instruction! However I must have missed something that I could not make it work. So here is what I have done

  1. Create a loopback interface as you suggested
  2. Assign this interface as "LO", and give it an ip '127.0.0.252/32'
  3. Since I chose to run unbound on "all interfaces", I was able to see this LO address in both web ui access lists and the file /var/unbound/access_lists.conf
  4. I have a default "to all" firewall rule on "WireGuard" interface, which is the one auto created by WireGuard. So hopefully this rule is enough for this testing.
  5. I am sure this is likely where I messed up: in the NAT step, I set a port fowrading rule
    • on interface WireGuard
    • from any source, any port
    • to any source, 53 port
    • forwarding to 127.0.0.252

I also tried to set the NAT rule on other interfaces including WG (the one I manually assigned for wireguard) but they didn't work either. Would you please help me check if I missed any steps? Thanks :)

Firewall rule:
firefox_Cf5UoZ9aS8

port fowarding:
firefox_B2hCZ9EPEO

@AdSchellevis
Copy link
Member

at a first glance it looks good, you can try to capture some traffic on your new interface and the wireguard one to see if it actually matches anything.

@pengshao
Copy link
Author

pengshao commented May 29, 2020

So I used my very limited knowledge to try the following debug. I noticed that if I configure unbound not to run either LO or WG, all DNS request on wg0 53 port went unanswered (without surprise):

root@OPNsense:~ # tcpdump port 53 -n -i wg0 -vvvv
tcpdump: listening on wg0, link-type NULL (BSD loopback), capture size 262144 bytes
09:07:57.630391 IP (tos 0x0, ttl 255, id 61742, offset 0, flags [none], proto UDP (17), length 59)
    10.252.0.12.61377 > 10.252.0.1.53: [udp sum ok] 28507+ A? www.apple.com. (31)
09:07:57.630412 IP (tos 0x0, ttl 255, id 46049, offset 0, flags [none], proto UDP (17), length 60)
    10.252.0.12.50045 > 10.252.0.1.53: [udp sum ok] 33667+ A? www.icloud.com. (32)
09:07:57.630419 IP (tos 0x0, ttl 255, id 25817, offset 0, flags [none], proto UDP (17), length 61)
    10.252.0.12.49312 > 10.252.0.1.53: [udp sum ok] 37768+ A? eas.outlook.com. (33)
09:07:58.749826 IP (tos 0x0, ttl 255, id 56731, offset 0, flags [none], proto UDP (17), length 69)
    10.252.0.12.63731 > 10.252.0.1.53: [udp sum ok] 42543+ A? reports.crashlytics.com. (41)
09:07:58.943557 IP (tos 0x0, ttl 255, id 60131, offset 0, flags [none], proto UDP (17), length 70)
    10.252.0.12.59112 > 10.252.0.1.53: [udp sum ok] 4005+ A? settings.crashlytics.com. (42)

But if I enable unbound on LO only, not on WG, the client's request actually got "Refused"

root@OPNsense:~ # tcpdump port 53 -n -i wg0 -vvvv
tcpdump: listening on wg0, link-type NULL (BSD loopback), capture size 262144 bytes
09:05:53.132307 IP (tos 0x0, ttl 255, id 1832, offset 0, flags [none], proto UDP (17), length 60)
    10.252.0.12.50045 > 10.252.0.1.53: [udp sum ok] 33667+ A? www.icloud.com. (32)
09:05:53.132349 IP (tos 0x0, ttl 64, id 5507, offset 0, flags [none], proto UDP (17), length 40)
    10.252.0.1.53 > 10.252.0.12.50045: [udp sum ok] 33667 Refused- [0q] 0/0/0 (12) 

Howver, listening on LO (lo1) has no traffic at all it appears:

root@OPNsense:~ # tcpdump -n -i lo1 -vvvv
tcpdump: listening on lo1, link-type NULL (BSD loopback), capture size 262144 bytes

(silence for like 5 min)

I am confused what to do next... it seems the NAT is working as now the DNS request can reach LO but for some reason I could not capture the traffic in tcpdump. But still, unbound refused the request despite it allowed LO in both the web UI and check on access_lists.conf

@AdSchellevis
Copy link
Member

the refused suggests a missing policy in unbound. can you try to use another address? if I'm using 127.0.0.0/8 it seems to be captured on lo0 on my end (same netblock).

@pengshao
Copy link
Author

Thanks for your suggestion. I tried another loopback with 127.0.1.1/8 (does mask matter?) and still refused and no traffic captured.

Actually, I wonder why I cannot forward the port to my LAN address, since my LAN is always up before unbound anyway? I tried this and still got refused, plus, capturing on LAN (igb1) does not yield dns request from my vpn client.

I came upon a post that seems to suggest that redirected traffic, if on same machine, is handled directly by OS therefore not actually reaching the target interface. If this is true it might explain why I could not capture the traffic on LO.

Sorry if I was too stupid on testing this :)

@AdSchellevis
Copy link
Member

127.0.1.1/8 is also in the same range, try something like 10.123.0.1/32 to avoid confusion

@pengshao
Copy link
Author

Ah sorry I didn't realize you were suggesting an IP out of the range.

  1. Change LO IP to 10.123.0.1/32
  2. Change NAT rule to point to the new address
  3. Make sure unbound is running and allowing LO with the new address
  4. Same result, Refused on WG, and no traffic on LO.

@AdSchellevis
Copy link
Member

not totally what I expected, haven't captured traffic on these lo interfaces lately, but the refused response still points to unbound. I can't help you further at the moment, sorry.

@pengshao
Copy link
Author

You already helped me so much, thank you all the same :)

@fichtner
Copy link
Member

Unbound binds to addresses, not interfaces. Dynamic interfaces pose an issue then, because you would need to stop and start unbound dynamically, which causes cache loss and general dns resolution disruption. The bind interface feature is a popular request but people often forget that this has side effects that have these annoying operational effects / implementation quirks.

In this particular case I assume Unbound simply forgets to load the correct address or is not notified of it. Best to use a manual ACL with listen on any IMO.

@fichtner fichtner added the support Community support label May 29, 2020
@pengshao
Copy link
Author

pengshao commented May 29, 2020

Thanks fichtner, yes adding ACL works perfectly. Before this issue is resolved eventually (if it ever be), could we maybe add some suggestions on the documentation regarding WireGuard over this issue so maybe it can help other users to avoid some hassle :)

Thanks!

@Brainfrazzle
Copy link

Any chance we could get the variables of the ACL you added, like internal/external, action (allow I assume) and especially "network" was it 127.0.0.252, what did you put in there, the tunnel address?

@QNimbus
Copy link

QNimbus commented Oct 20, 2020

Just to chime in since I ran into this exact same issue. The 'best' work around for me was to manually add the WireGuard network (i.e. 10.0.0.0/24 which is used by the configured WireGuard 'peers') to the UnBound ACL.

@Brainfrazzle This is the UnBound ACL config that I used:

image

@zanechua
Copy link

@QNimbus suggestion worked for me. Was not getting dns responds for all my wireguard clients. The moment I added the range to the access list, it worked.

@AdSchellevis
Copy link
Member

This issue has been automatically timed-out (after 180 days of inactivity).

For more information about the policies for this repository,
please read https://github.com/opnsense/core/blob/master/CONTRIBUTING.md for further details.

If someone wants to step up and work on this issue,
just let us know, so we can reopen the issue and assign an owner to it.

@AdSchellevis AdSchellevis added the help wanted Contributor missing / timeout label Dec 16, 2020
@TheHellSite
Copy link

TheHellSite commented Apr 21, 2021

Just to chime in since I ran into this exact same issue. The 'best' work around for me was to manually add the WireGuard network (i.e. 10.0.0.0/24 which is used by the configured WireGuard 'peers') to the UnBound ACL.

Thank you very much @QNimbus! This solved my issue.
I was starting to think I misconfigured something until I found your post.

@oli-h
Copy link

oli-h commented Aug 1, 2021

Thx, guys - also encountered this problem. Solution with the ACL in Unbound solved the problem also for me.

@TheHellSite
Copy link

Any news on this? I just tried it without the manual ACL and the issue is still present.

@eljeffeg
Copy link
Contributor

eljeffeg commented Mar 2, 2022

Agree that WireGuard net should be automatically added to the Unbound ACL. Took me a bit to figure this out.

@TheHellSite
Copy link

@AdSchellevis

Is this manual ACL still necessary in order to get the DNS working in a RoadWarrior configuration?

I just disabled the old ACL in Unbound and DNS seems to keep working for wireguard clients.

@fichtner
Copy link
Member

ACL defaults have been switched to 0.0.0.0/0 a while back. If you need fine grained ACL you’d have to manage those according to your networks attached manually and delete the wildcard, but for most purposes that is overkill.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Contributor missing / timeout support Community support
Development

No branches or pull requests

10 participants