[libvirt-users] NWFilter and IPv6

Hi, Libvirt's nwfilter ships a number of useful filter scripts by default, but none to handle IPv6 traffic. Is there a particular reason for that, or is that just because nobody has got around to that yet? One interesting thing about dealing with IPv6 traffic is that hosts often have several auto-configured addresses, usually at least one auto-configured link- local address under fe80::/64 and one auto-configured one from router- advertisements. For writing filter rules, it would be nice to have some function/notation to calculate those auto-configured addresses for the user, so we can write something like this: <rule action='return' direction='out' priority='500'> <ipv6 srcipaddr='ipv6_autoconf($IPV6_PREFIX[@1], $IPV6_MASK[@1], $MAC)'/> </rule> <rule action='return' direction='out' priority='500'> <ipv6 srcipaddr='$IPV6'/> </rule> <rule action='drop' direction='out' priority='1000'/> or maybe more like this: <ipv6 mode='autoconf' field='srcipaddr' prefix='$IPV6_PREFIX[@1]' netmask='$IPV6_MASK[@1]' mac='$MAC)'/> Guido

On 11/07/2012 03:22 AM, Guido Winkelmann wrote:
Hi,
Libvirt's nwfilter ships a number of useful filter scripts by default, but none to handle IPv6 traffic. Is there a particular reason for that, or is that just because nobody has got around to that yet?
Hi Guido! I just saw this message you sent to the list a couple weeks ago. Stefan Berger can confirm, but I believe the answer is the latter - nobody has gotten around to it. I'm sure patches would be greatly appreciated :-)
One interesting thing about dealing with IPv6 traffic is that hosts often have several auto-configured addresses, usually at least one auto-configured link- local address under fe80::/64 and one auto-configured one from router- advertisements. For writing filter rules, it would be nice to have some function/notation to calculate those auto-configured addresses for the user, so we can write something like this:
<rule action='return' direction='out' priority='500'> <ipv6 srcipaddr='ipv6_autoconf($IPV6_PREFIX[@1], $IPV6_MASK[@1], $MAC)'/> </rule> <rule action='return' direction='out' priority='500'> <ipv6 srcipaddr='$IPV6'/> </rule> <rule action='drop' direction='out' priority='1000'/>
or maybe more like this:
<ipv6 mode='autoconf' field='srcipaddr' prefix='$IPV6_PREFIX[@1]' netmask='$IPV6_MASK[@1]' mac='$MAC)'/>
There is similar functionality for IPv4, and it would be nice to have IPv6 variables that parallel those for IPv4. Again - patches welcome!

On 11/26/2012 10:41 AM, Laine Stump wrote:
On 11/07/2012 03:22 AM, Guido Winkelmann wrote:
Hi,
Libvirt's nwfilter ships a number of useful filter scripts by default, but none to handle IPv6 traffic. Is there a particular reason for that, or is that just because nobody has got around to that yet? Hi Guido! I just saw this message you sent to the list a couple weeks ago.
Stefan Berger can confirm, but I believe the answer is the latter - nobody has gotten around to it. I'm sure patches would be greatly appreciated :-)
Yes, patches would be appreciated. The IP address detection methods may also need to be extended for IPv6 support. One problem I want to mention, though: A bigger problem would be if a machine wanted to use IPv4 and IPv6 (dual stack) and use DHCP for both , which in effect would result in two variables that need to have values detected which in turn would require partial instantiation of filters (since one variable may not have a value assigned while the other has), which does not currently work... Also as I recall for IPv4 the ARP-equivalent is NDP (Neighbor Discovery Protocol based on ICMPv6), which may need support in ebtables. At least a while ago there was no support for filtering that NDP subset of ICMPv6 in ebtables. Regards, Stefan

Am Montag, 26. November 2012, 12:24:11 schrieb Stefan Berger:
On 11/26/2012 10:41 AM, Laine Stump wrote:
On 11/07/2012 03:22 AM, Guido Winkelmann wrote:
Hi,
Libvirt's nwfilter ships a number of useful filter scripts by default, but none to handle IPv6 traffic. Is there a particular reason for that, or is that just because nobody has got around to that yet?
Hi Guido! I just saw this message you sent to the list a couple weeks ago.
Stefan Berger can confirm, but I believe the answer is the latter - nobody has gotten around to it. I'm sure patches would be greatly appreciated :-)
Yes, patches would be appreciated. The IP address detection methods may also need to be extended for IPv6 support. One problem I want to mention, though: A bigger problem would be if a machine wanted to use IPv4 and IPv6 (dual stack) and use DHCP for both , which in effect would result in two variables that need to have values detected which in turn would require partial instantiation of filters (since one variable may not have a value assigned while the other has), which does not currently work...
Hm, how do you even do it with one variable? Do you leave the firewall undefined until you could detect the dhcp-answer package and then pull it up?
Also as I recall for IPv4 the ARP-equivalent is NDP (Neighbor Discovery Protocol based on ICMPv6), which may need support in ebtables. At least a while ago there was no support for filtering that NDP subset of ICMPv6 in ebtables.
According to the ebtables man-page, you've got --ip6-icmp-type, which should be enough for this. Router advertisements have ICMPv6 type 134 and multicast router advertisements are 153. AFAICT, you can just filter by those... Guido

Am Montag, 26. November 2012, 12:24:11 schrieb Stefan Berger:
On 11/26/2012 10:41 AM, Laine Stump wrote:
On 11/07/2012 03:22 AM, Guido Winkelmann wrote:
Hi,
Libvirt's nwfilter ships a number of useful filter scripts by default, but none to handle IPv6 traffic. Is there a particular reason for that, or is that just because nobody has got around to that yet? Hi Guido! I just saw this message you sent to the list a couple weeks ago.
Stefan Berger can confirm, but I believe the answer is the latter - nobody has gotten around to it. I'm sure patches would be greatly appreciated :-) Yes, patches would be appreciated. The IP address detection methods may also need to be extended for IPv6 support. One problem I want to mention, though: A bigger problem would be if a machine wanted to use IPv4 and IPv6 (dual stack) and use DHCP for both , which in effect would result in two variables that need to have values detected which in turn would require partial instantiation of filters (since one variable may not have a value assigned while the other has), which does not currently work... Hm, how do you even do it with one variable? Do you leave the firewall undefined until you could detect the dhcp-answer package and then pull it up? We assume that DHCP is being used and for example put a filter in that only allows DHCP traffic to pass and once we grab the IP address we instantiate the user-provided filter. For that we use $IP. The variable is set once the IP address has been detected. For IPv6 we should
On 12/04/2012 09:39 AM, Guido Winkelmann wrote: probably use $IPV6 (reserved variable).
Also as I recall for IPv4 the ARP-equivalent is NDP (Neighbor Discovery Protocol based on ICMPv6), which may need support in ebtables. At least a while ago there was no support for filtering that NDP subset of ICMPv6 in ebtables. According to the ebtables man-page, you've got --ip6-icmp-type, which should be enough for this. Router advertisements have ICMPv6 type 134 and multicast router advertisements are 153. AFAICT, you can just filter by those...
I am not the expert on IPv6, but from reading on this page here http://www.tcpipguide.com/free/t_ICMPv6NeighborAdvertisementandNeighborSolic... I get the impression that for example the target address should be verified for possible 'abuse'. I don't think one can grab that field with ebtables and compare against allowed values. Stefan

Am Dienstag, 4. Dezember 2012, 19:18:01 schrieb Stefan Berger:
Am Montag, 26. November 2012, 12:24:11 schrieb Stefan Berger:
On 11/26/2012 10:41 AM, Laine Stump wrote: [...] One problem I want to mention, though: A bigger problem would be if a machine wanted to use IPv4 and IPv6 (dual stack) and use DHCP for both , which in effect would result in two variables that need to have values detected which in turn would require partial instantiation of filters (since one variable may not have a value assigned while the other has), which does not currently work...
Hm, how do you even do it with one variable? Do you leave the firewall undefined until you could detect the dhcp-answer package and then pull it up? We assume that DHCP is being used and for example put a filter in that only allows DHCP traffic to pass and once we grab the IP address we instantiate the user-provided filter. For that we use $IP. The variable is set once the IP address has been detected. For IPv6 we should
On 12/04/2012 09:39 AM, Guido Winkelmann wrote: probably use $IPV6 (reserved variable).
How do you control this behavior? Can you just set the $IP to a value in the filterref instantiation to disable it? Like so: <filterref filter='clean-traffic-with-v6'>" <parameter name='MAC' value='11:11:11:11:11:11'/>"; <parameter name='IP' value='192.168.0.10'/>"; <parameter name='IP' value='192.168.0.11'/>"; </filterref>" Anyway, I think combining DHCP and DHCPv6 is going to be a minor problem in practice, because most people will probably use stateless autoconfiguration to set the IPv6 address on a device and use DHCPv6 only for additional information, like DNS servers or NTP servers. How about this approach instead for combining DHCP and DHCPv6: - Instead of putting up a special network filter for the detection phase, we put up the actual user-requested filter, but with $IP and $IPV6 unset. (except of course when these variables are specifically set by the user as above...) - The default-shipped filters like clean-traffic should let DHCP(v6) through in this configuration. If the user-requested filters don't, that's just a configuration error. - As soon as we detect an incoming DHCP or DHCPv6 packet for the guest, we add that address to the filter parameters, reinitialize the filter with the new parameters and stop detecting addresses for this particular L3 protocol.
Also as I recall for IPv4 the ARP-equivalent is NDP (Neighbor Discovery Protocol based on ICMPv6), which may need support in ebtables. At least a while ago there was no support for filtering that NDP subset of ICMPv6 in ebtables.
According to the ebtables man-page, you've got --ip6-icmp-type, which should be enough for this. Router advertisements have ICMPv6 type 134 and multicast router advertisements are 153. AFAICT, you can just filter by those... I am not the expert on IPv6, but from reading on this page here
http://www.tcpipguide.com/free/t_ICMPv6NeighborAdvertisementandNeighborSolic itation-2.htm
BTW, I wouldn't recommend this particular guide. Not only is it cluttered with advertisements to the point of a major annoyance, there's at least one part where it has simply plain wrong information: On http://www.tcpipguide.com/free/t_IPv6InterfaceIdentifiersandPhysicalAddressM... Bit 7 of the EUI-64 address needs to be flipped, not just set to 1. (It took me a while to figure out why my code would arrvive at different autoconfigured addresses than the linux kernel for virtualized machines...)
I get the impression that for example the target address should be verified for possible 'abuse'.
That's only for neighbor advertisements. Router advertisements can simply be blocked wholesale. Normal network nodes have no business sending those under any circumstances, and your actual routers are hopefully trusted enough to not need their router advertisements checked for sanity... Then again, for neighbor advertisements, you're right. I was under the impression that, for those, it was enough to check the source address in the ipv6 header. Apparently I was wrong.
I don't think one can grab that field with ebtables and compare against allowed values.
No, but ip6tables has --u32, which possibly could be abused for that... Guido

(No extra content from me, but I'm setting Followup-To: libvir-list@redhat.com for this (and setting To: to the same), since this is talking about new development, so we want to make sure as many developers as possible see it...) On 12/05/2012 09:23 AM, Guido Winkelmann wrote:
Am Dienstag, 4. Dezember 2012, 19:18:01 schrieb Stefan Berger:
Am Montag, 26. November 2012, 12:24:11 schrieb Stefan Berger:
On 11/26/2012 10:41 AM, Laine Stump wrote: [...] One problem I want to mention, though: A bigger problem would be if a machine wanted to use IPv4 and IPv6 (dual stack) and use DHCP for both , which in effect would result in two variables that need to have values detected which in turn would require partial instantiation of filters (since one variable may not have a value assigned while the other has), which does not currently work... Hm, how do you even do it with one variable? Do you leave the firewall undefined until you could detect the dhcp-answer package and then pull it up? We assume that DHCP is being used and for example put a filter in that only allows DHCP traffic to pass and once we grab the IP address we instantiate the user-provided filter. For that we use $IP. The variable is set once the IP address has been detected. For IPv6 we should
On 12/04/2012 09:39 AM, Guido Winkelmann wrote: probably use $IPV6 (reserved variable). How do you control this behavior? Can you just set the $IP to a value in the filterref instantiation to disable it? Like so:
<filterref filter='clean-traffic-with-v6'>" <parameter name='MAC' value='11:11:11:11:11:11'/>"; <parameter name='IP' value='192.168.0.10'/>"; <parameter name='IP' value='192.168.0.11'/>"; </filterref>"
Anyway, I think combining DHCP and DHCPv6 is going to be a minor problem in practice, because most people will probably use stateless autoconfiguration to set the IPv6 address on a device and use DHCPv6 only for additional information, like DNS servers or NTP servers.
How about this approach instead for combining DHCP and DHCPv6:
- Instead of putting up a special network filter for the detection phase, we put up the actual user-requested filter, but with $IP and $IPV6 unset. (except of course when these variables are specifically set by the user as above...) - The default-shipped filters like clean-traffic should let DHCP(v6) through in this configuration. If the user-requested filters don't, that's just a configuration error. - As soon as we detect an incoming DHCP or DHCPv6 packet for the guest, we add that address to the filter parameters, reinitialize the filter with the new parameters and stop detecting addresses for this particular L3 protocol.
Also as I recall for IPv4 the ARP-equivalent is NDP (Neighbor Discovery Protocol based on ICMPv6), which may need support in ebtables. At least a while ago there was no support for filtering that NDP subset of ICMPv6 in ebtables. According to the ebtables man-page, you've got --ip6-icmp-type, which should be enough for this. Router advertisements have ICMPv6 type 134 and multicast router advertisements are 153. AFAICT, you can just filter by those... I am not the expert on IPv6, but from reading on this page here
http://www.tcpipguide.com/free/t_ICMPv6NeighborAdvertisementandNeighborSolic itation-2.htm BTW, I wouldn't recommend this particular guide. Not only is it cluttered with advertisements to the point of a major annoyance, there's at least one part where it has simply plain wrong information: On
http://www.tcpipguide.com/free/t_IPv6InterfaceIdentifiersandPhysicalAddressM...
Bit 7 of the EUI-64 address needs to be flipped, not just set to 1. (It took me a while to figure out why my code would arrvive at different autoconfigured addresses than the linux kernel for virtualized machines...)
I get the impression that for example the target address should be verified for possible 'abuse'. That's only for neighbor advertisements. Router advertisements can simply be blocked wholesale. Normal network nodes have no business sending those under any circumstances, and your actual routers are hopefully trusted enough to not need their router advertisements checked for sanity...
Then again, for neighbor advertisements, you're right. I was under the impression that, for those, it was enough to check the source address in the ipv6 header. Apparently I was wrong.
I don't think one can grab that field with ebtables and compare against allowed values. No, but ip6tables has --u32, which possibly could be abused for that...
Guido

Am Montag, 26. November 2012, 10:41:47 schrieb Laine Stump:
On 11/07/2012 03:22 AM, Guido Winkelmann wrote:
Hi,
Libvirt's nwfilter ships a number of useful filter scripts by default, but none to handle IPv6 traffic. Is there a particular reason for that, or is that just because nobody has got around to that yet?
Hi Guido! I just saw this message you sent to the list a couple weeks ago.
Stefan Berger can confirm, but I believe the answer is the latter - nobody has gotten around to it. I'm sure patches would be greatly appreciated :-)
Well, I have defined a few filters for my own use, mostly by copying the clean-traffic filter and making a few additions. They don't fully work yet, especially the part about filtering router advertisements. For some reason, nwfilter does not seem to actually do anything with the icmpv6 filter rules, at least ebtables -t nat -L does not show anything... The filters are optimized for hosts with statically configured addresses. I haven't tested this with DHCP at all. They look like this: <filter name='clean-traffic-with-v6' chain='root'> <filterref filter='no-mac-spoofing'/> <filterref filter='no-ip-spoofing'/> <filterref filter='no-dhcp-server'/> <rule action='accept' direction='out' priority='-650'> <mac protocolid='ipv4'/> </rule> <filterref filter='allow-incoming-ipv4'/> <filterref filter='no-ipv6-spoofing'/> <filterref filter='no-ipv6-router-advertisement'/> <filterref filter='no-dhcpv6-server'/> <rule action='accept' direction='out' priority='-600'> <mac protocolid='ipv6'/> </rule> <filterref filter='allow-incoming-ipv6'/> <filterref filter='no-arp-spoofing'/> <rule action='accept' direction='inout' priority='-500'> <mac protocolid='arp'/> </rule> <filterref filter='no-other-l2-traffic'/> <filterref filter='qemu-announce-self'/> </filter> <filter name='no-dhcp-server' chain='ipv4' priority='-701'> <rule action='drop' direction='out' priority='100'> <ip protocol='udp' dstportstart='68'/> </rule> </filter> <filter name='no-ipv6-spoofing' chain='ipv6' priority='-700'> <rule action='return' direction='out' priority='500'> <ipv6 srcipaddr='$IPV6'/> </rule> <rule action='drop' direction='out' priority='1000'/> </filter> <filter name='no-ipv6-router-advertisement' chain='root' priority='-690'> <rule action='drop' direction='out' priority='600'> <icmpv6 type='134'/> </rule> <rule action='drop' direction='out' priority='600'> <icmpv6 type='153'/> </rule> </filter> <filter name='no-dhcpv6-server' chain='ipv6' priority='-680'> <rule action='drop' direction='out' priority='100'> <ipv6 protocol='udp' dstportstart='546'/> </rule> </filter> <filter name='allow-incoming-ipv6' chain='ipv6' priority='-680'> <rule action='accept' direction='in' priority='500'/> </filter>
One interesting thing about dealing with IPv6 traffic is that hosts often have several auto-configured addresses, usually at least one auto-configured link- local address under fe80::/64 and one auto-configured one from router- advertisements. For writing filter rules, it would be nice to have some function/notation to calculate those auto-configured addresses for the user, so we can write something like this:
<rule action='return' direction='out' priority='500'>
<ipv6 srcipaddr='ipv6_autoconf($IPV6_PREFIX[@1], $IPV6_MASK[@1], $MAC)'/>
</rule> <rule action='return' direction='out' priority='500'>
<ipv6 srcipaddr='$IPV6'/>
</rule> <rule action='drop' direction='out' priority='1000'/>
or maybe more like this:
<ipv6 mode='autoconf' field='srcipaddr' prefix='$IPV6_PREFIX[@1]' netmask='$IPV6_MASK[@1]' mac='$MAC)'/>
There is similar functionality for IPv4, and it would be nice to have IPv6 variables that parallel those for IPv4. Again - patches welcome!
I don't quite understand, what similar functionality are you talking about? IPv4 does not have stateless autoconfiguration... Guido

On 12/04/2012 10:22 AM, Guido Winkelmann wrote:
Am Montag, 26. November 2012, 10:41:47 schrieb Laine Stump:
On 11/07/2012 03:22 AM, Guido Winkelmann wrote:
One interesting thing about dealing with IPv6 traffic is that hosts often have several auto-configured addresses, usually at least one auto-configured link- local address under fe80::/64 and one auto-configured one from router- advertisements. For writing filter rules, it would be nice to have some function/notation to calculate those auto-configured addresses for the user, so we can write something like this:
<rule action='return' direction='out' priority='500'>
<ipv6 srcipaddr='ipv6_autoconf($IPV6_PREFIX[@1], $IPV6_MASK[@1], $MAC)'/>
</rule> <rule action='return' direction='out' priority='500'>
<ipv6 srcipaddr='$IPV6'/>
</rule> <rule action='drop' direction='out' priority='1000'/>
or maybe more like this:
<ipv6 mode='autoconf' field='srcipaddr' prefix='$IPV6_PREFIX[@1]' netmask='$IPV6_MASK[@1]' mac='$MAC)'/> There is similar functionality for IPv4, and it would be nice to have IPv6 variables that parallel those for IPv4. Again - patches welcome! I don't quite understand, what similar functionality are you talking about? IPv4 does not have stateless autoconfiguration...
I mean just the idea of being able to specify the IP address as a variable in a rule, and have it be auto-discovered and filled in by nwfilter.
participants (3)
-
Guido Winkelmann
-
Laine Stump
-
Stefan Berger