This article is a quick-start guide for ip6tables - the IPv6 version of iptables, covering the basics of installing, configuring, viewing, editing, and persistence. It’s primarily intended for those already familiar with iptables for IPv4.
For those unfamiliar with iptables, it is a command-line tool used for firewalling, NAT, and traffic accounting purposes. Policy chains are created to handle these various functions, acting on traffic coming into or going out of the host running it. It is most frequently used to firewall traffic coming into the host, such as permitting anyone on the internet to access a webpage but denying SSH or SQL access to all except for a set of trusted hosts.
To read the man page for ip6tables you can visit https://linux.die.net/man/8/ip6tables.
Summary of key concepts
This article covers the following areas, primarily using Ubuntu OS as a reference in our examples.
{{banner-13="/design/banners"}}
Installation
Debian/Ubuntu
Update the apt cache and install the iptables package, which includes v4 and v6 commands:
After reading this article, you might wish to refer to this community-authored Ubuntu iptables how-to guide at https://help.ubuntu.com/community/IptablesHowTo.
CentOS
Installing on CentOS/RPM based systems is a little different. Starting with CentOS 7, iptables is still used, but configuring rules is now performed with firewalld as a frontend/wrapper. To switch back to iptables, you must remove firewalld and install iptables:
From here, the article uses Ubuntu as the reference, but most of the commands are identical after installing and starting the services. One exception is persistence. Here instead you do this:
By default, on reboot, iptables will not be running, so you must enable the iptables service to ensure that it starts on boot (it will load any saved configuration):
Creating rules for a web server example
Let’s create some ip6tables rules for a hypothetical web server. Note that for IPv6 to work fully, we must ensure certain kinds of ICMPv6 messages are permitted. Here we will permit all ICMPv6 messages, but for further reading on ip6tables rules for specific ICMPv6 message types, please see: https://resources.sei.cmu.edu/tools/downloads/vulnerability-analysis/assets/IPv6/ip6tables_rules.txt.
Other requirements
We must not forget that the machine’s loopback interface is also affected by the ip6tables configuration. The machine must be able to communicate freely over the loopback interface because it is used for process-to-process communication. This is the first rule we will add.
We must also permit ESTABLISHED and RELATED traffic, which is traffic coming in related to any outbound session initiated from our server and any traffic related to an existing session initiated from the outside. A rule like this is usually entered near the very top of the list because the majority of traffic will usually be processed by it.
Finally, we will deny ALL other traffic as a security best practice. This is our catch-all term applied at the end.
5-tuple pseudocode: What are our objectives, in simple terms?
When familiarizing yourself with iptables syntax, it is very important to consider in simple terms what your objectives are before attempting to compose or enter any commands. This practice helps ensure that rule composition and ordering are correct before making your change; after all, firewall issues could cut off your SSH management session and/or disrupt user traffic in a way that is time-consuming to correct.
In our case, our objectives are:
- From SRC ANY to DST loopback then ACCEPT
- From ESTABLISHED or RELATED then ACCEPT
- From SRC ANY to DST ICMP then ACCEPT
- From SRC ANY to DST TCP 22 then ACCEPT
- From SRC ANY to DST TCP 80 then ACCEPT
- From SRC ANY to DST TCP 443 then ACCEPT
- From SRC ANY to DST ANY then DROP
Entering the configuration
Viewing the configuration
Here we have left out our ICMP rule because we will later show you how to insert this rule in a specific location.
Persistent configuration
We must ensure that ip6tables rules are saved every time after editing and then restored after rebooting. A common way to do this through editing /etc/network/interfaces is to add pre-up and post-down commands or scripts to run. These would call the ip6tables-save and ip6tables-restore commands. Refer to the Ubuntu community how-to linked above if you wish to explore this more advanced method.
The most elegant solution is to simply use the (Ubuntu) iptables-persistent package. Let’s install it and let it save our rules so that they persist on reboot:
Follow the prompts, which will ask you if you want to save your IPv4 and IPv6 rules. Generally, you will choose Yes here unless you wish NOT to save them, e.g., if you have misconfigured any rules.
If you selected Yes and saved both your IPv4 and IPv6 rules at the prompts, they will now persist across a reboot instead of being lost.
Additional changes
If you make further changes to your rules, consider whether and when to update the “on-boot” configuration. If your new in-memory rules are not yet fully tested, you may want to avoid updating the on-boot configuration, so that in the event of a major problem with iptables filtering, a reboot will ensure that a known-good state is restored.
Let’s say you have made a rule change in memory and are certain that you want to save it to the on-boot configuration. Let’s use iptables-persistent to update that configuration. For this, you need to actually become root: sudo alone is not sufficient with the default permissions set by the iptables-persistent package:
Let’s verify the on-boot configuration; here, only only v6 rules are shown:
Manually save to another location (e.g., backup, version control, creating files for exporting to another system, etc). As an example, we will save to the home directory:
{{banner-9="/design/banners"}}
Operations
View rules
Run ip6tables with option -L for list and -v for verbose. In this example, there are no rules specified; the default configuration is to ACCEPT.
Edit rules
Earlier in the article, we saw output that was missing our ICMP ACCEPT rule. Let’s see how we can insert this new rule in the correct location. First we get the rule line numbers, like this:
We want to insert our ICMP rule after our RELATED/ESTABLISHED rule on line number 2 (see the first column of output for line numbers).
To insert our new rule specifically at line number 3, we enter -I for insert into our INPUT chain at line number 3:
To verify, we use the same line-numbers command as before and here follow with grep to shorten the output to the ICMP rule plus the line before (-B 1) and the line after (-A 1). You can see that the previous line 3 is now line 4:
{{banner-10="/design/banners"}}
Delete Rules
As an example, let’s delete the line that permits HTTPS access on TCP port 443. After the previous example, this rule is unchanged, except it is line number 6 now. To delete line 6 we do -D for delete, INPUT chain, and in this case we want to target line number 6 - the command to delete looks like this:
Now let’s enter the full sequence of commands (see comments inline):
Flushing
You may misconfigure your IPv4 or IPv6 rules and need to quickly disable the ip6tables firewalling. For example, if you implement some complex connection tracking or logging, and this adversely impacts user traffic or system stability, you need to recover quickly. The simplest way to do this is to flush all the rules.
For example, consider this before state:
Next, we flush the rules:
And here’s how it looks after:
At this point, the server is wide open to all connections, so it’s imperative that you quickly restore a known-good configuration as soon as possible. See the section on persistence for how best to manage on-boot (known-good) configurations; restoring from here is likely the better option for both test and production environments.
Restoring configuration
You can restore the known-good configuration like this (assuming files saved in /etc/iptables/rules.v[4|6] - adjust your path to suit):
Recommendations
- Start in a Test Environment: Read the man page for ip6tables, try the examples given, and familiarize yourself in a test environment.
- Beware of Losing Access: When modifying iptables rules, whether in an IPv4 or IPv6 environment, you risk cutting off network connectivity if you make a mistake in configuration. It is best to ensure that you make rules persistent only after testing them, or you could disrupt your access to the server and be unable to fix the issue.
- Work on Each IP Address Family Independently at First: For example, if you first develop, test, and persist your IPv4 rules, then you know that no matter what changes you make to IPv6 rules, you can still access the server via IPv4.
- Test a Known-Good Configuration First: If you are transitioning to IPv6 only and want to remove IPv4 addressing from the server, it is recommended that you fully test and persist a known-good ip6tables configuration before doing so.
- Investigate Remote Access: Many VM hosting providers offer remote console access via a web control panel, so even if you cut off your IP access, you can still access the machine to fix any issues. It is still good practice to exercise extreme caution when making changes to your configuration: It’s a habit you should insist on because you may find yourself in a situation where the server does not have console access or the console is down for maintenance.
- Use Pseudocode and Intention Statements: Familiarize yourself with the concepts of crafting and composing individual rules and rule chains using pseudocode and “5-tuple’’ intention statements. Prepare iptables/ip6tables configurations in a text editor before applying them on the CLI.
{{banner-sre="/design/banners"}}
Conclusion
You should come away from this article with an understanding of the fundamentals of deploying and working with ip6tables. Hopefully you’re already familiar with iptables (IPv4) and find that not much differs other than the command name. Good luck securing your IPv6 perimeters!