Creating rule for outgoing NAT on IPv6 packets not possible from GUI?
-
First of all, there IS a somewhat reasonable reason for this setup at the moment. I get one /64 network prefix from Comcast that the LAN interface is tracking. All is well in IPv6 land as long as I stay on the local network. For test purposes I'm now experimenting with OpenVPN and IPv6 - and because Comcast won't give me anything bigger than a /64 at this point I'm stuck with a local IPv6 address on my OpenVPN clients (in this case a fd00:4242::/48 network). So far so good, OpenVPN connected clients can connect to IPv6 services on the local LAN. As I did not have local IPv6 connectivity where I had my OpenVPN client connecting from today I thought I would easily be able to create an outgoing NAT rule in pfSense for this local network, masquerading it behind the WAN address (or any address from the LAN network really) and with a quick default IPv6 gateway add on the OpenVPN client I should be able to get IPv6 connectivity with very little effort.
I fired up my pfSense GUI, loading the firewall_nat_out page - only to find out that the netmask can only be set from /0 to /32, and an IPv6 address as input will not be recognized.. As I was in a bit of a hurry to get IPv6 connectivity I just make a quick addition to the /tmp/rules.debug file, adding this along with my normal IPv4 outgoing NAT rule:
nat on $WAN inet6 from fd00:4242::/48 to any -> xxxx:xxxx:xxxx:xxxx::f00f/128 port 1024:65535
and reloaded with pfctl -f /tmp/rules.debug - and it works like a charm!
Is this supposed to be possible to do from within the GUI? Most likely people will say that IPv6 shouldn't be NAT:ed this way, but I can definitely see some use-cases for this when the IPv6 address space allocated isn't large enough.
Turns out that the code in /etc/inc/filter.inc (specifically in the filter_nat_rules_generate_if function) has no way of tacking on "inet6" after the interface name, and I'm not sure if the nat part of filters.inc knows about the IPv6 address for the interface (for masquerading). In my test I just took a really low address from the routed network that cannot be used for SLAAC.
Are there other places in need of modification to support something like this, or should some relatively minor modifications to firewall_nat_out.php and filters.inc be enough?
/wj
-
I've used IPv6 "Hide-"NAT for half a year on an OpenBSD gateway using a SixXS tunnel. It worked fine with the exception of Facebook, which would sometimes have problems. I could never really debug this, so it could have also been due to general IPv6 problems Facebook was facing, routing, DNS etc.
I would really like the option to NAT v6 when there's no other way. But that function should come with a big red warning sign, as nobody running an IPv6 service will expect you to NAT or help you with any problems that might arise. -
I would really like the option to NAT v6 when there's no other way. But that function should come with a big red warning sign, as nobody running an IPv6 service will expect you to NAT or help you with any problems that might arise.
I completely agree, I also see some use-cases for this, but as you mention: there may very well be some things that just doesn't work, and I'm completely fine with that. As I was able to get the desired functionality out of a simple manual add to the pf rules this is not a limitation of the underlying platform which I was afraid it would be at first. I'll look deeper into the actual files when I have some spare time, just wanted a quick sanity-check that I wasn't completely off-base here.. :)
/wj
-
Sooo… Turns out that the major part of the issues were easily solved. I believe I stumbled upon a bug in /etc/inc/util.inc though, in the gen_subnet function. It will happily return 0.0.0.0/32 when given an IPv6 address where it should have returned an empty string. Easily solved by calling is_ipaddrv4 instead of the generic is_ipaddr. The attached patch performs the way I want it but it contains an ugly hack in filters.inc to determine whether the nat rule should be marked inet6 or not (by checking if $src or $dst contains a ":"). Maybe the rule from the GUI should be specified as IPv4 or IPv6 just as the firewall rules. That would also make input validation (where gen_subnet was called in firewall_out_nat_edit.php) easier. Now it just concatenates the results of the two gen_subnet / gen_subnetv6 calls (which is where I encountered the odd behavior of gen_subnet when handed an IPv6 address). But I assume that adding a new config file field to the nat rules requires a newer config version, so maybe it's not so simple?
Anyway, patch is attached if anyone else wishes to do the same thing as I tried to accomplish. Any possibility of having a cleaned up version of this pulled into the official code?
/wj
-
Did not have time to test the patch, but it would be really nice if this went into pfSense. As you seem to already have done the major part, why not make it a feature request over at http://redmine.pfsense.org referring to this post / your patch?
-
why not make it a feature request over at http://redmine.pfsense.org referring to this post / your patch?
That I can most definitely do, I just wasn't sure whether this would be considered a separate feature or not (IPv6 support already there, Hide-NAT already there, just the combination that didn't work). I'll go ahead and add a feature request for this, then it could be dealt with either way.
/wj
-
Submitting the change as a github pull request is also the best way to get the attention of the developers, since the changes are simple to review, test/apply, and commit.
-
Submitting the change as a github pull request is also the best way to get the attention of the developers, since the changes are simple to review, test/apply, and commit.
Great idea! I think I managed to get it right (first time dealing with pull requests on github). This should be the Pull Request: https://github.com/pfsense/pfsense/pull/427
/wj
-
Yeah for god's sake give as NAT66!
Just one line code! :-)