OPNsense Forum
Archive => 21.1 Legacy Series => Topic started by: allebone on May 20, 2021, 09:52:28 pm
-
Hello,
I have an outbound NAT rewrite rule that captures devices that ignore DNS and forces them to go via my internal pihole. For example if a client such as my Roku TV attempts to connect to 8.8.8.8 on port 53 this is captured and sent correctly internal to my pihole.
See figure 1: (https://i.imgur.com/hbUKaZm.png)
My issue is the logs do not tell me what ip this device attempted to access externally. I would like to know how to capture this information. Eg: I can see that 192.168.2.51 tried to access an IP on port 53 as the rewrite rule kicked in. But would like to know what that IP is (ie was it 8.8.8.8 or some other Ip etc).
How can I know this?
Here is the rewrite rule: (https://i.imgur.com/QrO1pvI.png)
Here is the LAN FW rule: (https://i.imgur.com/VeZSe3S.png)
Thanks in advance :)
Pete
-
Does nobody know the answer to this question? I can log a ticket on github if its an unknown question?
Kind regards
Pete
-
Sorry if this is obtuse (me not understanding fully) - would it not be easier to use a block policy for all DNS with logging enabled, and whitelist the correct servers (also logged)? Or if you must let the traffic pass log everything DNS with a inverted destination maybe of not your good DNS servers (via alias) or something similar. NAT seems to be complicating it a bit from what I can tell.
-
I must be honest. I also dont fully understand what you are telling me.
My desire (and why I set it up like this) is to silently capture devices on the network that try use other dns servers and reroute them to my internal dns server without them knowing (ie blocking them).
This is working as intended but I cant see what external dns servers they are trying to query.
Sorry if you explained how to do this. I didnt fully understand your comment.
Pete
-
I must be honest. I also dont fully understand what you are telling me.
My desire (and why I set it up like this) is to silently capture devices on the network that try use other dns servers and reroute them to my internal dns server without them knowing (ie blocking them).
This is working as intended but I cant see what external dns servers they are trying to query.
Sorry if you explained how to do this. I didnt fully understand your comment.
Pete
I'm doing the same NAT redirect to my DNS server. I can confirm as well even with logging enabled on that NAT rule I do not see logs for the rewrite either. At least not in the live view.
Also check this post out https://forum.opnsense.org/index.php?topic=20149.0
-
Sorry, can be deleted
Greeting Meditux
-
Hi guys,
I do the same, however the redirects show up in the livelog for me.
Greeting Meditux
I can see the resulting rewrite as well but I think what the OP looking for is an entry like
NAT - <Orig> Dest 8.8.8.8:53 > <New> Dest 192.168.1.1:53
to see the original destination.
-
Yes exactly there is no log showing the destination the client tried to access like to 8.8.8.8 as you say in your example.
-
I am still looking for a solution to this problem if anyone is aware of one :)
-
I suspect the code to log the original destination IP for the NAT rule is just not there.
A workaround perhaps is to have a specific firewall rule for the source IPs that are being rewritten on the DNS port and log that.
-
Do you mean the workaround is to log this on the DNS server and not the opnsense firewall?
-
No, I meant to create a firewall (filter) rule on the relevant OPNsense interface for the source IPs (eg LAN if they are in the LAN subnet), destination port 53, and then have logging on for that. Put that rule above any general pass rule (such as the default allow LAN to any rule). So the incoming DNS requests will hit that and be logged before they even reach the NAT rule
-
I dont know how to do this. How do I create a firewall rule that does not block or pass the packets, so that the rewrite rule can take effect after the logging? If I make a rule the only options are "pass" "block" or "reject" I do not wish to block the packet or reject it. I also dont want to pass it (Ie allow it out). I want it to be captured and rewritten.
-
?
You do want to pass the packets on the internal interface, otherwise they will be dropped by OPNsense and there will be no DNS resolution, with or without a NAT rule
-
The rule that is there allows only the packet to pass to the internal DNS server. The packet is already rewritten by the time it gets to that rule. There is not an allow rule that allows the LAN client out to anywhere on 53 as this would be undesirable. I dont know how to implement what you are suggesting.
-
Destination NAT happens after the filter rule. The packet has to get into OPNsense before it is NATed
-
I still dont understand how this can work.
The only DNS rule I have allowed is as such:
IPv4 TCP/UDP (Lan clients Alias) * 192.168.2.22 53 (DNS) * * lredirectrule DNS53Pihole
So for example a client would have 8.8.8.8 as its DNS server. in this case the packet is rewritten to go to 192.168.2.22.
Once its rewritten, the only DNS rule is the one above. Logging has no effect as its too late.
What rule are you proposing I add above this rule in order to log the client trying to access 8.8.8.8 on port 53, and is it pass, block, or reject?
-
You have a “allow LAN to any” filter rule on the LAN interface right?
-
Yes it is the last rule in the table.
-
Is logging turned on for the filter rule that you put in your post above? That filter rule is what is automatically created to work with the NAT rule, and is essentially what I was saying you should log (I forgot that an outbound NAT rule on an internal interface automatically creates a corresponding filter rule)
-
Ok I will try and report back.
-
Im afraid it does not work. I even tried making a rule and placing it as the very first rule in my firewall as such:
IPv4 TCP/UDP * * * 53 (DNS) * *
It had no effect and this makes me think that the nat rewrite rules are processed before the firewall rule on that interface. Otherwise it should have been allowed out to 8.8.8.8.
The only logs I see are as example:
lan Jun 24 16:04:02 192.168.2.2:61891 192.168.2.22:53 udp nat rule
lan Jun 24 16:04:02 192.168.2.16:54209 192.168.2.22:53 udp
lan Jun 24 16:04:02 192.168.2.2:25605 192.168.2.22:53 udp nat rule
lan Jun 24 16:04:02 192.168.2.16:54208 192.168.2.22:53 udp
-
I think outbound nat is done first if you check this post its first in the list:
https://forum.opnsense.org/index.php?topic=11233.0
-
I checked that debug file by ssh to my firewall and indeed outbound nat is processed first. The lan rules are listed afterwards in that file. So making firewall rules has no effect.
-
Hmm. Can you post the full content of your NAT rule, rather than just the summary? Wonder if it is written correctly
-
The screenshot is on page one. The debug log lists this:
(snipped)
# NAT Redirects
no nat proto carp all
no rdr proto carp all
# [prio: 100]
nat log on em1 inet from !$AllowQueryDNSServers to 192.168.2.22/32 port 53 -> (em1:0) port 1024:65535 # DNSOutRewrite
nat log on em1 inet from !$AllowQueryDNSServers to 192.168.2.22/32 port 853 -> (em1:0) port 1024:65535 # DNSOutRewrite853
nat on pppoe0 inet from (wireguard:network) to any -> (pppoe0:0) port 1024:65535 # Allow WG Clients to NAT
# [prio: 200]
-
I meant what is the full content when you edit the NAT rule in the GUI? And what does the source alias represent?
-
Here are the images:
-
I mean it does log when the rule runs, it just does not show the destination that was attempted to be accessed. im thinking the functionality is not exposed in opnsense and would need a change to allow it in the code (if even possible I dont know).
-
So here is where I am confused. That rule only operates where the original destination IP is .22. Is that your pihole? If so the destination should be inverted, and the translation/target address changed to the pihole address
So the logging is working as expected at the moment
-
Ah hang on. I am confusing myself. Don’t you need a port forward in this scenario (with an outbound NAT simply to deal with source address errors)?
I haven’t implemented this myself yet but have disabled rules set up ready for testing when I get the chance. Will post them later FYI
-
Yup give it a go. I believe what I am asking is impossible. You cannot know the destination ip (eg: 8.8.8.8) the client attempted to access that was then redirected. Its simply not logged.
-
Sorry about the confusion in my earlier posts - I shouldn't try to exercise and troubleshoot on the forum at the same time!
Attached are the draft rules I have set up (can't test until I don't have people on the network, in case DNS breaks!). Note that ALL_LOCAL is an interface group that includes all of my local networks/VLANs.
First is a port forward rule (destination NAT) that redirects to the pi-hole any DNS request from a local host that is not the pi-hole and that is not already destined for the pi-hole.
Second are outbound NAT rules (source NAT) to fix any source address errors as a result of the redirection.
Finally, my filter rules. The second rule in this screenshot is automatically created by the port forward. The first rule is to ensure that the pi-hole itself is able to access external DNS servers.
If logging is enabled on the port forward, does that not give the original destination IP in the logs? If not, then I agree that this functionality probably doesn't exist currently.
-
Yes these rules are almost identical to what I have setup. Logging is enabled on the first rule in your example for me as well. I dont believe its possible, and instead I think the information is lost at this point in time.
-
The other think that makes me think its impossible is that the very first thing processed in
cat /tmp/rules.debug
Ie the Nat rewrite rules listed first in that file. Since its done first, anything that happens after is happening after the rewrite and so logging later on is not going to help. There would need to be a logging mechanism that processes before the (current) very first rule processed which does not exist :(
-
I finally implemented my rules but in the end disabled the outbound NAT rules, because they basically meant that the Pi-hole saw every DNS request as coming from the router. There is no way AFAIK to distinguish for the outbound NAT rules between packets that have been port forwarded and packets that are going to the Pi-hole normally, because by the time the outbound NAT rules apply the packets have already been destination NATed.
On the processing order I actually don’t agree that the order in rules.debug is the order they are applied. My understanding is that destination NAT occurs first, then the filter rules, and then source NAT. The issue here is simply that OPNsense does not log the original destination IP in the port forward logs. Presumably it could with a code change, because OPNsense has the information when it applies the port forward.
-
Actually, just had a thought about distinguishing packets - by setting a local tag on the port forward and matching that on the outbound NAT. That could actually work…
-
Nope, the tag doesn’t seem to work. This behaviour is really hard to figure out lol
Edit: the tag does actually work. It just had a syntax error when I originally tried it (for some reason I can’t figure out)
-
I came across this thread attempting to achieve the same goal as OP: redirecting all DNS traffic to a specific address, but logging the original destination address before network translation took place. I've tried various combinations of enabling firewall/NAT logging and setting local tags, but have not been successful so far. Now that I've done some digging into the matter, I understand why it's not as straightforward as you might think it would be.
It's been established (https://forum.opnsense.org/index.php?topic=11233.msg50896#msg50896) (and confirmed by franco (https://forum.opnsense.org/index.php?topic=11233.msg50900#msg50900)) that OPNsense processes NAT and firewall rules in the same order as pfSense. I.e. the pfSense documentation (https://docs.netgate.com/pfsense/en/latest/nat/process-order.html) on this matter is relevant in OPNsense and, most importantly, NAT occurs before firewall rules. Meaning that address translation occurs first and any subsequent firewall rules (and associated logging) occurs on the translated address. So there is no opportunity to log any details about the pre-NAT'ed traffic, including the original destination address.
That's not to say obtaining this information is impossible. Searching for prior art on the subject, I came across these projects
- pfnattrack - Logging NAT Translations on PF firewalls (https://github.com/italovalcy/pfnattrack)
- pf_poc (https://github.com/monsterxx03/pf_poc)
- pf_nat_log_freebsd_10.2r.patch (https://gist.github.com/raitech/4150c8767d8f1f8642ccd9d44c4c57c6)
OPNsense's firewall logs (`/var/log/filter/filter_yyyymmdd.log`) are generated by `/usr/local/sbin/filterlog`. When `pf` processes a packet that matches a rule with the `log` flag set, it makes it available on the `pflog0` interface. `filterlog` then reads the packet, parses out various properties (https://github.com/opnsense/ports/blob/21.1.7/opnsense/filterlog/files/filterlog.c), then writes out logging information in a defined format (https://github.com/opnsense/ports/blob/21.1.7/opnsense/filterlog/files/description.txt). It's possible there's scope to extend parsing to extract pre-NAT destination address and port information. If it were possible, it's likely only one step of many required to expose the information through the web interface. I.e modifying views, updating the API, etc.
The above is based purely on my limited understanding of OPNsense and FreeBSD internals gained from poking around the source. I'd really appreciate if someone more knowledgeable could let me know if I'm on the right track. Better yet, if would be great if one of the developers could chime in on the feasibility of my speculative implementation.
-
Nice analysis, good work. Confirms my thinking that code changes could definitely address the logging.
The pfSense docs seem a little inconsistent on the rule processing order. The first section refers to outbound NAT being processed first, but then the examples given show it near the end. The latter makes more sense to me, and is also consistent with the fact that a local tag set on my port forward is picked up by my outbound NAT rule. If the outbound NAT rule was processed first, that presumably could not happen.
-
It seems this thread has a corresponding issue on GitHub (https://github.com/opnsense/core/issues/5005). If it's likely to get the devs' attention, I'm happy for for my write-up to be echoed over there.
-
Only issue is that the problem is misdescribed - it is not outbound NAT that is the issue, it is the port forward. Outbound NAT is source NAT, whereas the issue of concern is destination NAT (ie port forward)
-
Only issue is that the problem is misdescribed - it is not outbound NAT that is the issue, it is the port forward. Outbound NAT is source NAT, whereas the issue of concern is destination NAT (ie port forward)
I raised the issue to the best of my ability at the time on github. A lot more info has come through on this thread since then. Just trying my best man :)
-
Wasn’t a criticism, just pointing out that for it to get the right attention it should be updated. GH has an edit function
-
I think I have updated it to what you might consider adequate?
-
Hi,
Pete and me exchanged a few messages on GitHub. Basically, NAT logging is possible, but has some caveats...
Nevertheless, two patches can help with this in the future:
https://github.com/opnsense/core/commit/3eb235f25
We want to be able to search for "rdr" (port forward) or "nat" (outbound NAT) logs directly.
https://github.com/opnsense/src/commit/bdb244c37
The logging already works for builtin "pass" NAT rules, but with an associated firewall rule the logging is muted. Furthermore, while post-NAT logging makes sense for the associated firewall rule the NAT logging should probably be done pre-NAT as it would match the packet.
You can see the result in action here:
https://github.com/opnsense/core/issues/5005#issuecomment-871176383
I think that addresses all problems discussed here?
Cheers,
Franco
-
Many thanks. Yes it has resolved the issue.
I posted a screenshot anyone else in this thread can now view on:
https://github.com/opnsense/core/issues/5005
That shows how logging now looks with this patch. It is working for me and I will continue to monitor it for any undesirable effects but so far clients accessing port 53 are rerouted to my internal DNS and now logged correctly so it appears everything is working as desired and this provides logging as desired so it looks really good to me :)
Kind regards
Pete
-
I've been watching with interest. I thought being new to OPN I was not setting up things correctly. I was glad when I saw the thread. Also I was waiting for the OP to respond to avoid spoiling.
My question is I am on 21.1.6 . Can I use the patches on it or do I need to upgrade to 21.1.7 first if I want to try the patch?
-
Updating puts you on the release candidate version. Checking for updates normally would revert you back down to before the next version so you will lose the patch.
You would essentially be temporarily on a dev version and only able to update once the version catches up to where the patch is, or you will lose the patch.
A reboot is required when changing. Basically I will have to now wait until the community version catches up to the version I am using, or update and lose the patch and then have to wait until the patch makes it into the community version. It apparently wont make next version so I will have to decide to wait for 2 new versions to be released where the patch will likely make it in or instead update as normal and be without it for 2 versions until we catch up to when it will make it into the community version.
One thing I would say is being split between packages like this (because only one module is updated by running the command on github) means you are not on a snapshot of an official release, so obviously its going to be unsupported and not fit for business use etc. At home you can feel free to make the call. Depends how adventurous you are. I kind of feel its fine personally, so will probs just leave it and update only again in 2 versions time (2 months?).
P
-
understood. Thank you.
-
Hi,
It's not overly problematic. The kernel needs to be switched, but all other parts are untouched / allowed to be updated.
The snapshot kernel itself is basically 21.7-RC1 with the added fix on top. Deviation from 21.1x is minimal except for some driver updates.
# opnsense-update -zbkr 21.7.r_1
# opnsense-update -Lk
# opnsense-shell reboot
The above will install the newer kernel and lock it to prevent minor updates from overwriting it. You can always unlock the kernel from the GUI and reinstall the official release one or issue:
# opnsense-update -Uk
# opnsense-update -k
# opnsense-shell reboot
Cheers,
Franco
-
Most obliged franco.
I'll do that once I've settled a few kinks I have so I don't make changes whilst resolving.