-
-
Notifications
You must be signed in to change notification settings - Fork 358
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
big hammer to get ip-transparent working with pf divert-to rules on OpenBSD #921
base: master
Are you sure you want to change the base?
Conversation
…bsd. if you divert all dns requests to an unbound server, this sets things up so replies to diverted udp requests come from what looks like the right IP. set_recvpktinfo() needs to be called on listening sockets so the kernel will wire up the control messages that include the original destination ip address of the packet. comm_point_create_udp_ancil() needs to be used instead of comm_point_create_udp() so it will use recvmsg with a control message buffer and process the CMSGs inside it. for IP_SENDSRCMSG to work when sending the replies to the diverted client, the listening socket also has to be set up with the SO_BINDANY sockopt.
Diverting DNS traffic, like this, is not really good, and I think perhaps only useful as a debug aid, it looks like tampering to me, for the end clients. If the inspection of the traffic is wanted, something like wireshark can do that. It can also be set to filter out particular messages and display them. The ip transparent option sets the socket option. But in addition you want to enable cmsg stuff, and this particular cmsg stuff is enabled by If the code change still needs to be made, it would be nice to allow this as an additional option that can be enabled by the user for the specific use case, instead of an always active bypass. Some devices ignore the DHCP provided DNS server, instead relying on others, and cloud providers are popular. There are encrypted connections that can be set up, using for example the dns over TLS and HTTPS options. Unbound can provide this kind of connectivity, and this is precisely to avoid the firewall here. It is possible to configure the certificate that unbound provides, but also wants to admit, to verify the server identity. |
I probably shouldn't have wasted time explaining all the logging background. I agree that capturing or duplicating packets also lets me log requests, but if I ever enable DoT or DoH on my local networks then the best point to observe DNS requests will be from inside unbound. If my goal is to intercept or tamper with DNS in the clear, then I can do that already with an IP rewrite. The question is more whether
Sounds to me like the cmsg bits could also be enabled when
There's an interesting philosophical discussion we could have here about ownership and authority over the equipment we purchase and are responsible for operating, and whether than ends at the network port on an individual device or on port on my router facing the public internet. It's one thing for a malicious network operator to intercept or modify my DNS requests, it's another thing for a device that we've bought and put on my network to think it always knows better than me about where it should do DNS lookups. Am I allowed to intercept DNS in the clear that's trying to leave my network and upgrade it to DoT to a more trusted provider on the public internet? What if I'm doing RPZ? |
Yes that is a complicated space of concerns about device ownership and traffic patterns. But I wanted to make you aware, if you weren't, about DoT and so on. The Perhaps the existing |
I'll try When to cmsg or not to cmsg is an annoyingly complicated decision tree. Technically you can use the Without the cmsgs the traditional approach is iterate over all addresses in the system and bind to them on startup. The more advanced approach is listen on the routing socket for new addresses and bind to them as they appear. This needs privs if you're trying to bind to a low port though, which sucks a bit. The way The only real gap is the (ab)use case I have, which is that I'm binding to a non-wildcard address and redirecting/diverting packets to it. To divert packets with pf it needs to be bound with So, is that 4 possible configurations?
Am I missing anything? |
It may also be possible to enable both the There is an option in Unbound to list the addresses of an interface, with I am not sure what the different configurations are you want; but in terms of the code change I was looking for, I thought of adding code that enables a new config option, that can be toggled together with other options, or on its own. The option enables the cmsg handling, the srcaddr handling, and it could be called |
I've been tinkering with trying to get logging of DNS requests out of unbound so I can see what terrible things are happening on my network(s). That's been ok, except I noticed some devices ignore the DNS server I provide via DHCP, and I would like to log those requests too.
In this setup I am using an OpenBSD box as a router, and it's running unbound too. Assume i have the following interface:
And this up the top of my pf.conf:
I can then use a rule like this to catch the misbehaving hosts:
This is fine, DNS works, and unbound replies to the redirected DNS requests fine. However, in the logs this
looks like the misbehaving clients are doing the same thing as the well behaved ones. I would like to be able to tell the types of devices apart so I can identify/classify them and maybe fix them. An evolution of this is to have
unbound listen somehwere weird and redirect to that so there's something different in the logs.
So I put this in unbound.conf:
... and this in pf.conf:
Now I can look for client requests to port 35 in the logs and I have my answer.
However, the ultimate would be being able to see address of the nameserver the misbehaving clients were trying to connect to in the logs. Reading the unbound.conf man page (and a bit of the code), it sounds like
ip-transparent
is what i want. It's supposed to enableSO_BINDANY
on listening sockets and usegetsockname()
/IP_RECVDSTADDR
to figure outwhat the original IP was, and then use
IP_SENDSRCADDR
for replies.So with this in unbound.conf:
... and this in pf.conf:
... it should work. For most things it does.
DNS clients using TCP and UDP to talk to 10.0.127.1 port 53 (like they're supposed to) work. DHS clients trying to talk to another NS like 8.8.8.8 port 53 work too. However, DNS clients using UDP to talk to 8.8.8.8 port 53 do not. They look
like this:
Turns out that unbound isn't using the
cmsg
stuff to get the original IP addresses. This means when unbound replies, the addresses on the listening socket are used and they are not the right ones for the client. Turns out that's because unbound only enables "ancillary" data collection in specific situations, and at the moment enablingip-transparent
isn't one of them.
This diff forces unbound to set all UDP sockets up to do the cmsg stuff. I know this is not the right solution, but I thought I'd ask for direction rather than make a guess and have to do the work again.