As the Cisco Labs measurements show, IPv6 is a protocol that cannot be ignored any more. In some countries, like Belgium, Greece, Germany, the US, etc. the percentage of the users employing IPv6 is about 30% or even to 50%, and, based on the estimations, the increase of IPv6 traffic will continue to grow exponentially. So, it’s time to ensure that our firewall supports IPv6 as well.
While there are several open-source based solutions regarding firewalls, Linux-based or FreeBSD-based ones, this is not also the case when we want IPv6 support as well. Since m0n0wall project has officially ended, the only two options actually left for open-source users seeking for an iPv6 firewall are OPNsense and pfSense (if someone has an additional suggestion, please let me know).
Whilst pfSense supports IPv6 for quite a long time, as a firewall from a security perspective has a significant disadvantage: As of version 2.3.3 Community Edition it does not allow the filtering of IPv6 datagrams based on the used IPv6 Extension Headers. Therefore, if its administrator wants to filter e.g. IPv6 traffic carrying a Hop-by-Hop header, a Destination Options header, etc. (see [RFC 2460] for more details on IPv6 Extension headers), he simply cannot do it. And I do consider the capability of filtering IPv6 Extension headers really important for the reasons demonstrated here and here. In my opinion, this capability should be configurable.Therefore, I decided to give OPNsense a try since it seems to be the only open-source solutions that currently offers IPv6 Extension headers filtering capabilities.
At the time of this writing, the latest available version of OPNsense is 17.1.4, based on FreeBSD 11.0.
As far as IPv6 is concerned, OPNsense provides all the options typically required to configure the interfaces of a device for IPv6 usage (e.g. static, using DHCPv6, SLAAC, etc.).
The user has also the capability to configure the IPv6 addresses of the LAN hosts by various means, e.g. by sending Router Advertisements (RAs), by operating a DHCPv6 server, etc. Furthermore, the configuration options provided per case seem to be more than enough. For instance, regarding RAs, it can be configured whether the Managed bit should be set or not, the router priority, the minimum and maximum intervals between RAs, etc. (see figure at the right).
However, given that I was mainly interested in the IPv6 filtering capabilities that OPNSense provides, let’s jump directly to them.
OPNsense at the “Protocol” field provides the options to select for filtering various IPv6 headers, including an IPv6 (encapsulated) header, ICMPv6, as well as some Extension headers like IPv6 Routing header, Fragment Extension header, IPv6 Options header (without clarifying here if it for Destination Options header, Hob-by-hop header, or for both), etc. (see figure at he right).
Of course, all the above configuration capabilities would be of a low significance if they were not tested. For this reason, some basic testing was performed by using my tool, Chiron. As a target IPv6 address, the LAN IPv6 address of the firewall itself was used (so as to check at the same time, when possible, both the filtering capabilities as well as the OPNsense/FreeBSD compliance regarding IPv6 Extension headers). To this end, a rule was added to allow http traffic over IPv6 to the LAN IPv6 address.
After the above configuration, it was found out that by default the following traffic is allowed:
Unfragmented HTTP over IPv6 (as obviously was expected).
Hop-by-hop header, Destination Options header, or their combination (only in the correct order).
Up to 14(!) Destination Options headers in one unfragmented datagram (certainly this is not a compliant behaviour from FreeBSD).
Fragmented HTTP over IPv6.
Fragmented packets of the aforementioned use cases (e.g. multiple Extension headers in fragmented datagrams).
On the contrary, by default no responses are received at the following use-cases, probably not because of firewall filtering but due to compliance of the host to the corresponding RFCs:
Now let’s repeat the same tests by configuring OPNsense to reject IPv6-OPTS (I prefer to use "reject" instead of "block" during my tests to have a clear indication of the firewall capability due to the received ICMPv6 information packet).
To my disappointment, I found out that packets with a Hop-by-hop header, a Destination options header, or both, can still reach the target and trigger a response.
For instance, traffic generated using the Chiron command depicted at the figure at the right "works" perfectly (i.e. the packet is not blocked, as it should, and a SYN-ACK is received back).
For those not familiar with Chiron, the depicted command constructs an unfragmented datagram consisting of a Hop-by-hop header, 14(!) Destination Options header and TCP/HTTP, and it still passes through the firewall and triggers a response!
Then, I configured OPNsense to also drop Fragment Extension header. A snapshot of the rules is presented at the figure at the right:
The results showed that:
Simple fragments still pass through the firewall.
Atomic fragments also pass through the firewall and reach the target.
A combination of the above and some of the previously use-cases of the IPv6 Extension headers (e.g. a combination of Hop-by-hop and Destination Options header) still pas through.
An example of the tests performed against this configuration are presented at the figure at the right. As before, the depicted Chiron command constructs a datagram consisting of a Hop-by-hop header, 14(!) Destination Options header and TCP/HTTP, but this time it fragments it in two fragments. These fragments still pass through the firewall and trigger a response from the target.
This means that none of the IPv6 Extension headers blocking rules is actually applied.
Despite the fact that OPNsense seems to offer capabilities of filtering IPv6 headers, this does not actually seem to be the case. Testing showed that even if OPNsense is configured to reject some IPv6 Extension headers, IPv6 packets incorporating these Extension headers still pass through the firewall and reach the target.
While this behaviour on its own is not enough to allow the evasion of the firewall (i.e. to reach a blocked port), in my humble opinion it provides a false sense of
security because it shows that it provides the capability to filter IPv6 Extension headers while this does not seem to be really the case. Therefore, I reached the developers two days ago, and I
also requested a CVE (CVE-2017-7880). Despite that I haven't received any feedback from the developers yet and it has been just two days since I tried to reach them, I decided to disclosure it
now since the aforementioned behaviour does not allow the evasion of the firewall on its own, whilst users should be informed as soon as possible so as not to be misled from filtering
capabilities that are not actually applied.
More testing results will be soon published, so, stay tuned ;-)