Q. IPv4 by default protect internal host using RFC 1918 private IP address. But IPv6 offers direct global address which result into exposing all internal hosts as well. How do I create default IPv6 firewall to drop all incoming (except ping6 request) connection and only allow outgoing requests from Linux workstation?
A. You need to use Ip6tables command to create IPv6 firewall scripts. Ip6tables is used to set up, maintain, and inspect the tables of IPv6 packet filter rules in the Linux kernel.
A note about IPv6 private ips
IPv6 does not include private network features such as NAT. Because of the very large number of IPv6 addresses. However, FC00::/7 prefix used to identify Local IPv6 unicast addresses. All IPv6 users should be able to obtain IPv6 address space for use at their discretion and without artificial barriers between their network and the Internet.
Redhat / CentOS / Fedora Linux Specific Configuration
The /etc/sysconfig/ip6tables can be used to configure and open ports, the default config is as follows:
*filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] :RH-Firewall-1-INPUT - [0:0] -A INPUT -j RH-Firewall-1-INPUT -A FORWARD -j RH-Firewall-1-INPUT -A RH-Firewall-1-INPUT -i lo -j ACCEPT -A RH-Firewall-1-INPUT -i eth0 -j ACCEPT -A RH-Firewall-1-INPUT -i br0 -j ACCEPT -A RH-Firewall-1-INPUT -p icmpv6 -j ACCEPT -A RH-Firewall-1-INPUT -p 50 -j ACCEPT -A RH-Firewall-1-INPUT -p 51 -j ACCEPT -A RH-Firewall-1-INPUT -p udp --dport 5353 -d ff02::fb -j ACCEPT -A RH-Firewall-1-INPUT -p udp -m udp --dport 631 -j ACCEPT -A RH-Firewall-1-INPUT -p tcp -m tcp --dport 631 -j ACCEPT -A RH-Firewall-1-INPUT -p udp -m udp --dport 32768:61000 -j ACCEPT -A RH-Firewall-1-INPUT -p tcp -m tcp --dport 32768:61000 ! --syn -j ACCEPT -A RH-Firewall-1-INPUT -j REJECT --reject-with icmp6-adm-prohibited COMMIT
To open port tcp and udp port 53 add the following line before final --reject-with icmp6-adm-prohibited line:
# open port 22 -A RH-Firewall-1-INPUT -m tcp -p tcp --dport 22 -j ACCEPT
At the end it should look as follows to which will open IPv6 port numbers, 53, 22, 25, 80, 110, and 443:
*filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] :RH-Firewall-1-INPUT - [0:0] -A INPUT -j RH-Firewall-1-INPUT -A FORWARD -j RH-Firewall-1-INPUT -A RH-Firewall-1-INPUT -i lo -j ACCEPT -A RH-Firewall-1-INPUT -i eth0 -j ACCEPT -A RH-Firewall-1-INPUT -i br0 -j ACCEPT -A RH-Firewall-1-INPUT -p icmpv6 -j ACCEPT -A RH-Firewall-1-INPUT -p 50 -j ACCEPT -A RH-Firewall-1-INPUT -p 51 -j ACCEPT -A RH-Firewall-1-INPUT -p udp --dport 5353 -d ff02::fb -j ACCEPT -A RH-Firewall-1-INPUT -p udp -m udp --dport 631 -j ACCEPT -A RH-Firewall-1-INPUT -p tcp -m tcp --dport 631 -j ACCEPT -A RH-Firewall-1-INPUT -p udp -m udp --dport 32768:61000 -j ACCEPT -A RH-Firewall-1-INPUT -p tcp -m tcp --dport 32768:61000 ! --syn -j ACCEPT # open port 53 -A RH-Firewall-1-INPUT -m tcp -p tcp --dport 53 -j ACCEPT -A RH-Firewall-1-INPUT -m udp -p udp --dport 53 -j ACCEPT # open port 22 -A RH-Firewall-1-INPUT -m tcp -p tcp --dport 22 -j ACCEPT # open mail server ports smtp, pop3, and imap -A RH-Firewall-1-INPUT -m tcp -p tcp --dport 25 -j ACCEPT -A RH-Firewall-1-INPUT -m tcp -p tcp --dport 110 -j ACCEPT -A RH-Firewall-1-INPUT -m tcp -p tcp --dport 143 -j ACCEPT # open port 80 & 443 -A RH-Firewall-1-INPUT -m tcp -p tcp --dport 80 -j ACCEPT -A RH-Firewall-1-INPUT -m tcp -p tcp --dport 443 -j ACCEPT -A RH-Firewall-1-INPUT -j REJECT --reject-with icmp6-adm-prohibited COMMIT
Save and close the file. Now, you can restart firewall as follows:
# service ip6tables restart
# ip6tables -L -v -n
Sample Restricted IPv6 Linux Firewall Script
#!/bin/bash IPT6="/sbin/ip6tables" PUBIF="eth1" echo "Starting IPv6 firewall..." $IPT6 -F $IPT6 -X $IPT6 -t mangle -F $IPT6 -t mangle -X #unlimited access to loopback $IPT6 -A INPUT -i lo -j ACCEPT $IPT6 -A OUTPUT -o lo -j ACCEPT # DROP all incomming traffic $IPT6 -P INPUT DROP $IPT6 -P OUTPUT DROP $IPT6 -P FORWARD DROP # Allow full outgoing connection but no incomming stuff $IPT6 -A INPUT -i $PUBIF -m state --state ESTABLISHED,RELATED -j ACCEPT $IPT6 -A OUTPUT -o $PUBIF -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT # allow incoming ICMP ping pong stuff $IPT6 -A INPUT -i $PUBIF -p ipv6-icmp -j ACCEPT $IPT6 -A OUTPUT -o $PUBIF -p ipv6-icmp -j ACCEPT ############# add your custom rules below ############ ### open IPv6 port 80 #$IPT6 -A INPUT -i $PUBIF -p tcp --destination-port 80 -j ACCEPT ### open IPv6 port 22 #$IPT6 -A INPUT -i $PUBIF -p tcp --destination-port 22 -j ACCEPT ### open IPv6 port 25 #$IPT6 -A INPUT -i $PUBIF -p tcp --destination-port 25 -j ACCEPT ############ End custom rules ################ #### no need to edit below ### # log everything else $IPT6 -A INPUT -i $PUBIF -j LOG $IPT6 -A INPUT -i $PUBIF -j DROP
Further readings:
- man page ip6tables
- Private network in the Wikipedia.
Featured Articles:
- 20 Linux System Monitoring Tools Every SysAdmin Should Know
- 20 Linux Server Hardening Security Tips
- My 10 UNIX Command Line Mistakes
- Linux: 20 Iptables Examples For New SysAdmins

- 25 PHP Security Best Practices For Sys Admins
- The Novice Guide To Buying A Linux Laptop
- 10 Greatest Open Source Software Of 2009
- Top 5 Email Client For Linux, Mac OS X, and Windows Users
- Top 20 OpenSSH Server Best Security Practices
- Top 10 Open Source Web-Based Project Management Software
- Top 5 Linux Video Editor Software
Facebook it - Tweet it - Print it -


{ 12 comments… read them below or add one }
thanks for sharing a shell script.
Hi, interesting script. Thanks for sharing it.
However, it’s missing one thing that would make it a lot more useful:
The PUBIF variable is set but never used, so the rules now apply to all interfaces, instead of just the public interface. If you could modify the script to use the PUBIF variable, it will still be useful for pc’s but also for IPv6 routers.
Hope you’ll consider this. Thanks.
@ Martijn,
I’ve just updated the script. Hope this helps!
Yes, that is definitely useful! Thanks for the quick response Vivek. Implementing it now.
Hi :)
I’m just wondering if the last Input DROP is necessary as the default policy already is DROP ?
cheers!
this script is NOT secure, read on icmpv6 security problems….
Alex: Last drop is not necessary, but it should be put there to be secure, it’s easy to make mistakes, and this will hopefully catch some…
Becouse the script doesn’t warn about this: IPv6 ICMP is much more than just PING. If one filter that one, IPv6 will not work propperly.
Bibi: Any links with more information? I am interested in all stuff about IPv6.
Yes, I forgot.
NAT has nothing to do with security. Firewall is the tool for that. There is ways of pass a NAT without a propper firewall setting.
There is LOTS of people that don’t understand this, and some will argue about that. Please don’t do that, just read relevant RFC:s. And use a propper firewall setting on all your machines.
Hello
Private networks I guess still have their use. It is difficult to convince certain organizations (health, banks, etc) to use ipv6 in their internal networks, as if they somehow need to “use the internet” for anything, their whole internal network is just a part of the whole “ipv6″ internet. They still want their “private” addressing while using IP protocols. They don’t want external “anlytics” being performed on what each of their potential ipv6 addresses look on the internet.
What’s the option for doing something like that, that does not imply application level proxies?
># Allow full outgoing connection but no incomming stuff
>$IPT6 -A INPUT -i $PUBIF -m state –state ESTABLISHED,RELATED -j ACCEPT
>$IPT6 -A OUTPUT -o $PUBIF -m state –state NEW,ESTABLISHED,RELATED -j ACCEPT
These lines do not work in RHEL/CentOS 5.x because its kernel does not support stateful IPv6 firewalling. See https://bugzilla.redhat.com/show_bug.cgi?id=243739
But I use similar configuration in another distros with newer kernel.
There are ways of randomize/annonymize your IPv6 host address.
With that you can’t analyze trafick outside your corporate firewall to see what is inside just by checking IPv6 addresses.
NAT is just not a good solution to any problem I have seen. The problem is the mind set on people that has been forced to use NAT the last 15 years.
NAT is a hack, to get around the problem with IPv4 addresses running out. It don’t give you any security that you can’t get with IPv6 and firewalls, which you MUST have anyway, even if you use NAT.
Using this firewall I’m not able to use autoconfiguration. Am I right? ‘Cause it uses ICMPv6 messages that you are blocking here, allowing only “ping” messages.