SEI Insights

CERT/CC Blog

Vulnerability Insights

Managing IPv6 - Part 2

Posted on by in

Past entries have addressed both securing and disabling IPv6. This entry describes ways that administrators can secure their networks and generate test cases to test those settings.

Administrators and developers who work with IPv4 will notice that IPv6 has made some changes beyond offering many more addresses than IPv4. The following are some of the changes that have security impacts:

  • Many hosts that currently have private IPv4 addresses will have global, publicly reachable addresses.
  • ICMPv6 contains much of the functionality of DHCP in IPv4 and cannot easily be entirely filtered.
  • IPv6 addresses can be predictable or partially random. Modern operating systems allow both, and there is a tradeoff between system management ease of use and user privacy.

These changes can cause problems. For example, a host that accepts any ICMPv6 type can be fingerprinted easily from remote systems. That might not be a problem for some networks, but it could be critical for others.

There are ways for administrators to handle these challenges. The examples below aren't universally applicable, so use them as a general guide.

Managing networks using global IPv6 addresses

Globally reachable addresses are not "hidden" in the same way as NAT addresses. To filter traffic destined to these clients, administrators can use application-layer proxy servers, stateful network filtering, or host-based firewalls.

Below is an example of filtering traffic to a globally reachable IPv6 address. For the purpose of these rules, 2001:1::/64 is the local network, eth0 is the LAN interface on a firewall, eth1 is the WAN interface on the firewall, and 2001:3::1 is an IPv6 address on the internet.

ip6tables -A FORWARD -p tcp -i eth0 -s 2001:1::/64 -p tcp -j ACCEPT
ip6tables -A FORWARD -p tcp -m state --state ESTABLISHED,RELATED -j ACCEPT

ip6tables -A FORWARD -p tcp -i eth1 --dport 3389 -s 2001:3::1 -j ACCEPT
ip6tables -A FORWARD -p tcp -i eth1 -m state --state NEW,INVALID -j DROP

The following is an explanation of what's happening in these rules, based on the behavior of a typical router doing NAT.

ip6tables -A FORWARD -p tcp -i eth0 -s 2001:1::/64 -p tcp -j ACCEPT
Pass any traffic that has entered on our LAN's ethernet interface (-i eth0) and that has a source address in the range our LAN is using (2001:1::/64).

ip6tables -A FORWARD -p tcp -m state --state ESTABLISHED,RELATED -j ACCEPT
Pass any traffic that is part of an existing connection.

ip6tables -A FORWARD -p tcp -i eth1 --dport 3389 -s 2001:3::1 -j ACCEPT
Allow any traffic coming into our WAN interface (-i eth1) to pass through to our LAN if it matches the TCP port used for RDP (--dport 3389).

ip6tables -A FORWARD -p tcp -i eth1 -m state --state NEW,INVALID -j DROP
Drop all other traffic.

After configuring the firewall, administrators should test the ruleset to confirm it is working as expected. Two commonly used tools that can test IPv6 TCP and UDP policies are nmap and netcat6.

Building on the example above, let's imagine that a user logs into a host with IP address 2001:1::2/64 and starts a netcat listener on port 3389:

$ netcat6 -l -p 3389

A scan of that IP from any host on the internet other than 2001:3::1 should fail. This result can be verified with an nmap comand:

$ nmap -PN -sT 2001:1::2/64 -p 3389

Starting Nmap 4.76 ( http://nmap.org ) at 2009-09-02 14:32 EDT
Interesting ports on
2001:1::2:
PORT STATE SERVICE

Filtering selected ICMPv6 types

The ICMPv6 protocol includes some great functionality. IANA maintains a list of ICMPv6 types and codes.

It is hard to make general statements about which ICMPv6 types should be allowed or denied. The following chart provides some guidance about reasonable firewall policies applied to ICMPv6 types. The types are listed based on whether or not the ICMPv6 type can typically be allowed or denied.

ICMPv6 types typically safe to allow
Purpose/Comments
1, Destination Unreachable general connectivity testing
2, Packet Too Big

sent by routers to notify a node that it should fragment the packets

3, Time Exceeded protects against routing loops
4, Parameter Problem error messages and handling
128, Echo Request ping
129, Echo Reply ping reply
133, Router Solicitation sent by clients to the all-nodes multicast address to request an IP address assignment
134, Router Advertisement

sent by routers to the all-nodes multicast address; clients can use the information in this message to generate an address

135, Neighbor Solicitation queries nodes for IP and connectivity information
136, Neigbor Advertisement

sends IP and connectivity information to other nodes

ICMPv6 types that can typically be denied
Purpose/Comments
137, Redirect

alerts clients to send traffic to another router, presumably one with a more direct route to the destination; like other ICMPv6 types listed, these messages are unauthenticated and could be malicious

138, Router Renumbering automatic reconfiguration of routers
139, Node Information Query allows a host to be fingerprinted
140, Node Information Response allows a host to be fingerprinted
151-154 deny by default
others not yet used, deny by default


We've talked about filtering ICMPv6 types before, so there's no reason to discuss it again. Instead, let's focus on some test case generation options.

There don't seem to be many tools that can generate arbitrary ICMPv6 packets. One of the more commonly used tools is ping6 or ping -6. The ping command sends an echo request message to an individual IPv6 address. Creating arbitrary ICMPv6 types requires a different tool.

Newer versions of the scapy packet crafting tool can be used to generate most ICMPv6 types. Here's an example of typical scapy usage:

# scapy
Welcome to Scapy (2.0.1-dev)
>>> a=IPv6(dst="2001:1::2")/ICMPv6ND_Redirect()
>>> send(a)

To list the available ICMPv6 types (layers), use the ls() command:

>>> ls()
ARP : ARP
ASN1_Packet : None
BOOTP : BOOTP
CookedLinux : cooked linux
...
ICMPerror : ICMP in ICMP
ICMPv6DestUnreach : ICMPv6 Destination Unreachable
ICMPv6EchoReply : ICMPv6 Echo Reply
ICMPv6EchoRequest : ICMPv6 Echo Request
ICMPv6HAADReply : ICMPv6 Home Agent Address Discovery Reply
ICMPv6HAADRequest : ICMPv6 Home Agent Address Discovery Request
ICMPv6MLDone : MLD - Multicast Listener Done
ICMPv6MLQuery : MLD - Multicast Listener Query
ICMPv6MLReport : MLD - Multicast Listener Report
...

To view what parameters a layer will take, use the ls() command again:

>>> ls(ICMPv6ND_Redirect())
type : ByteEnumField = 137 (137)
code : ByteField = 0 (0)
cksum : XShortField = None (None)
res : XIntField = 0 (0)
tgt : IP6Field = '::' ('::')
dst : IP6Field = '::' ('::')

This information can be used when creating packets to allow greater control over specific packets:

a=IPv6(dst="2001:1::2")/ICMPv6ND_Redirect(tgt="2001:1::3")

Disabling/enabling privacy extensions

Currently, IPv6 addresses are typically assigned via stateless autoconfiguration, DHCPv6 or static assignment.

With stateless autoconfiguration, an operating system is expected to generate part (usually the lower 64-bits) of its address. If privacy extensions are enabled, the generated address will be pseudo-random. This is good for privacy but makes remote management difficult.

On Windows Server 2008, privacy extensions can be controlled with a netsh command:

C:\> netsh interface ipv6 privacy enabled|disabled

Linux users should check /proc/sys/net/ip6/conf (the exact location varies between distributions and kernel versions).

Testing the address status of other systems on the same Ethernet segment is possible, assuming that echo requests and replies are accepted on those machines. If the following commands run on a Linux system produce predictable addresses, privacy extensions are disabled:

$ ping6 -B -I eth0 -I [global IPv6 address attached to eth0] ff02::1
$ ip neighbor

Windows users can use these commands:

C:\> ping -S [global IPv6 address] -6 ff02::2
C:\> netsh interface ipv6 show neighbors

About the Author