IPv6 Tables

Creating Firewall Rules with ip6tables

Preparing the Ruleset

ip6tables is usually configured with a firewall script. This step can occur at system startup, for example, from the /etc/rc.local directory, or a separate init script can be called. For flexibility, it has proved useful to create variables for the interfaces first and then reference them in the lines of the ruleset. Also, networks or prefixes can be defined in this way. To make changes to an interface or a subnet prefix, you just need to adjust the variables.

# Interface definitions

Next, completely reset the firewall rules to delete any previously existing rules. You can use the -F option for this. You also need to define a policy that applies if no other rule applies. The following applies as a general rule for firewalls: Everything that is not expressly permitted is forbidden. Accordingly, you would set the policy like this for all three chains:

# Delete the Ruleset
ip6tables -F
# Define a policy
ip6tables -P INPUT DROP
ip6tables -P FORWARD DROP
ip6tables -P OUTPUT DROP

At this point, no communication to, from, or through the system is possible, not even loopback traffic (Figure 3). But, because loopback should always be allowed, you add a loopback rule:

Figure 3: Nailed down: In the current state, the firewall does not allow any traffic to localhost.
# Allow loopback communication
ip6tables -A INPUT -i lo -j ACCEPT
ip6tables -A OUTPUT -o lo -j ACCEPT

Another important step is to enable stateful inspection by allowing everything that belongs to an existing communication:

# Enable stateful inspection
ip6tables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
ip6tables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
ip6tables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

For all other forms of communication, sections with matching rules now follow.


To prevent an attacker from using an internal address for access to specific systems, you need to introduce some anti-spoofing measures. An approach that is supported by iptables and ip6tables is to restrict the rules to incoming and outgoing interfaces so an internal sender address cannot arrive on any interface other than the LAN interface. Another possibility is the explicit rejection of incoming traffic from certain address ranges on the Internet interface. The two approaches are not mutually exclusive but complementary.

At this point, you can define some address ranges that should be discarded if they arrive on the external interface as the sender address. These include in particular the loopback address 1:: and the Unique Local Addresses FC00::/7. As a result, you can define the following anti-spoofing rules:

# Anti-spoofing
ip6tables -A INPUT ! -i lo -s ::1/128 -j DROP
ip6tables -A INPUT -i $WAN_IF -s FC00::/7 -j DROP
ip6tables -A FORWARD -s ::1/128 -j DROP
ip6tables -A FORWARD -i $WAN_IF -s FC00::/7 -j DROP

The loopback rule was negated with an exclamation mark. The condition that follows must not be satisfied for the rule to apply. In this case, all packets with a sender address of ::1/128 that did not arrive via the loopback interface are blocked. Unique Local Addresses could theoretically occur on the internal network; you would thus restrict the filter for them to packets that arrive through the WAN interface. Strictly speaking, you would typically want to filter the outgoing packets in the OUTPUT chain, but this is a secondary precaution, as long as the firewall itself has not been compromised.

You will want to save your firewall script in the meantime, then execute it and check the results. You can check the rules with ip6tables -v -L (Figure 4).

Figure 4: Allowing local traffic but blocking everything else.

Tunnel Traffic

Internal systems do not require a communication tunnel with native IPv6 connectivity. In this case, you can block the known tunnel prefixes for 6to4 and Teredo: 2002::/16 and 2001:0::/32. The following rules are the result:

# Block tunnel prefixes
ip6tables -A INPUT -s 2002::/16 -j DROP
ip6tables -A INPUT -s 2001:0::/32 -j DROP
ip6tables -A FORWARD -s 2002::/16 -jDROP
ip6tables -A FORWARD -s 2001:0::/32 -j DROP

You still have one important point to consider: IPv6 packets tunneled in IPv4 in part are not directly visible from the outside because they are prefixed with an IPv4 header. However, the protocol field in the IPv4 header contains a value of 41 to indicate IPv6 tunnel traffic. Thus, you can intercept this traffic on the IPv4 firewall; that is, using iptables, not ip6tables. The corresponding rule for tunneled traffic on the IPv4 firewall is:

# Block IPv6 in IPv4
iptables -A INPUT -p 41 -j DROP
iptables -A FORWARD -p 41 -j DROP

Thus far, the firewall has been set up to block everything. Now you need to extend the firewall policy for the allowed traffic, and you should begin with the communication necessary for managing the firewall itself (i.e., incoming traffic).

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy ADMIN Magazine

Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

comments powered by Disqus
Subscribe to our ADMIN Newsletters
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs

Support Our Work

ADMIN content is made possible with support from readers like you. Please consider contributing when you've found an article to be beneficial.