<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="http://72.14.177.54/skins/common/feed.css?207"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
	<channel>
		<title>Sfvlug - User contributions [en]</title>
		<link>http://72.14.177.54/SFVLUG/Special:Contributions/Jeff</link>
		<description>From Sfvlug</description>
		<language>en</language>
		<generator>MediaWiki 1.15.1</generator>
		<lastBuildDate>Tue, 23 Jun 2026 01:06:30 GMT</lastBuildDate>
		<item>
			<title>User:Jeff</title>
			<link>http://72.14.177.54/SFVLUG/User:Jeff</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* About Me */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==About Me==&lt;br /&gt;
&lt;br /&gt;
I am Jeff Carlson. I am a Systems Administrator by profession, geek by nature, and Linux advocate by choice. But I must be frank, Linux is only part of my technical passion. I am also very big on other open source operating systems (like the BSDs and OpenSolaris), and just Unix (like Irix and HP-UX) and its kin in general.&lt;br /&gt;
&lt;br /&gt;
I speak Bourne shell and Perl pretty fluently. I've also been known to whip up some pretty useful sed and awk from time to time. My understanding of C is rudimentary but accountable. Quite honestly, I have no love of Java and a reputation of the same.&lt;br /&gt;
&lt;br /&gt;
My weapons of choice are as follows. Fedora is my distro. Mate is my desktop. Emacs is my editor. Firefox is my browser. Thunderbird is my email client. I choose hexchat for IRC but Pidgin for everything else. I love Apache HTTPD. I know sendmail like the back of my hand. I'm also quite handy with Cyrus IMAP. I have done an awful lot of work with OpenLDAP and MySQL. I also use the ISC's BIND and DHCPD quite often. My favorite virtualization technology is still Xen, but qemu and kvm are pretty cool as well.&lt;br /&gt;
&lt;br /&gt;
Additionally I'm proficient with these. I've done a lot with Linux Netfilter, iptables, and its related projects. I have worked a lot with OpenSSH. I'm pretty good with OpenSSL. I've also set up OpenS/WAN and (back when there was one) FreeS/WAN, and also OpenVPN. I'm a big fan of SELinux. A couple of my favorite sysadmin tools are cfengine and Nagios.&lt;br /&gt;
&lt;br /&gt;
Lately I have been interested in embedded Linux. I have been playing with uClibc, busybox, dnsmasq, and dropbear a bit.&lt;br /&gt;
&lt;br /&gt;
I would be happy to answer any questions about any of these. I have given a number of presentations on some of them, and I plan to do more as well as include some notes on many of these topics here on this wiki.&lt;br /&gt;
&lt;br /&gt;
As well as being a member of SFVLUG, I am also a contributor to the Fedora Project, and a staff member of SCALE.&lt;br /&gt;
&lt;br /&gt;
==Notes On==&lt;br /&gt;
&lt;br /&gt;
* [[DD-WRT on Airlink 101 AR430W]]&lt;br /&gt;
* [[NotesOnQuotas|Filesystem Quotas]]&lt;br /&gt;
* [[NFS and the Automounter]]&lt;br /&gt;
* [[NotesOnOpenLDAP|OpenLDAP]]&lt;br /&gt;
* [[OpenSSH Power Tutorial]]&lt;br /&gt;
* [[OpenSSL Certificate Authority]]&lt;br /&gt;
* [[NetBSD as a Xen domU]]&lt;br /&gt;
* [[Mini-How-To Turn My Laptop Into A Wifi Access Point]]&lt;br /&gt;
* [[Get On IPv6 Right Now]]&lt;br /&gt;
* [[Securing SSH with tcp_wrappers]]&lt;br /&gt;
* [[OpenSolaris as a Xen domU]]&lt;br /&gt;
* [[OpenBSD as a Xen domU]]&lt;br /&gt;
* [[Build a VPN using only OpenSSH]]&lt;br /&gt;
* [[Make Your Own Bootable Thumbdrive with Buildroot]]&lt;br /&gt;
* [[Things You Should Know About Netfilter]]&lt;br /&gt;
* [[How To Configure OpenVPN]]&lt;/div&gt;</description>
			<pubDate>Sat, 10 Dec 2022 12:15:34 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/User_talk:Jeff</comments>		</item>
		<item>
			<title>Get On IPv6 Right Now</title>
			<link>http://72.14.177.54/SFVLUG/Get_On_IPv6_Right_Now</link>
			<description>&lt;p&gt;Jeff:&amp;#32;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;There are currently three ways to get on the IPv6 Internet today.  They are either sign up with an ISP that provides native IPv6 connectivity, register with a tunnel broker, or use 6 to 4 relay.  I don't believe any ISPs in the United States currently offer IPv6.  Using a tunnel broker requires additional software and although the software and the account are usually free, this is kind of a hassle.  But using a 6 to 4 relay tunnel is easy to configure and you already have the software necessary to make the connection.&lt;br /&gt;
&lt;br /&gt;
You must configure the 6 to 4 relay tunnel on an Internet-facing interface.  Doing this on a computer behind a NAT will not work.&lt;br /&gt;
&lt;br /&gt;
A 6 to 4 tunnel derives your IPv6 address from your IPv4 address.  To figure out what it is, just convert your IPv4 address to hexadecimal and prefix it with 2002 (8194 in decimal).  This produces a 48-bit prefix.  In IPv6, networks are 64 bits wide, and the other 64 bits of the 128-bit address is the host portion.  You are free to assign the next 16 bits for up to 65,535 networks.  Well, the first network, zero, will be used as an external gateway to your IPv6 internal network.  If you don't know which IP to use, it is the one associated with your default route.  If you don't know that, try this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
IPV4ADDR=`curl icanhazip.com`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Identify your IPv6 prefix.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
IPV6PRE=`echo $IPV4ADDR | awk -F. '{ printf(&amp;quot;2002:%x%02x:%x%02x&amp;quot;, $1, $2, $3, $4) }'`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Configure your IPv6-to-IPv4 tunnel device.  Here, we're going to use zero for the network number, and one for the host number.  Remember, in IPv6 addresses, you can substitute a string of zeros with just a blank between colons.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
iptables -I INPUT -p 41 -i eth0 -j ACCEPT&lt;br /&gt;
ip tunnel add tun6to4 mode sit ttl 64 remote any local $IPV4ADDR&lt;br /&gt;
ip link set dev tun6to4 up&lt;br /&gt;
ip -6 addr add $IPV6PRE::1 dev tun6to4&lt;br /&gt;
ip -6 route add 2000::/3 via ::192.88.99.1 dev tun6to4 metric 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this is the only computer you want on IPv6, then you're done.  You have set up a 6 to 4 tunnel.&lt;br /&gt;
&lt;br /&gt;
If you want to act as an IPv6 gateway, enable forwarding and add an IPv6 subnet to your internal interface.  Here, I'm arbitrarily picking one as the network number.  It can be anything from 1 to 0xffff (65,536 in decimal).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv6/conf/all/forwarding&lt;br /&gt;
ip -6 addr add $IPV6PRE:1::1/64 dev eth1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to enable automatic address configuration, create a radvd.conf file like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
interface eth1 {&lt;br /&gt;
    AdvSendAdvert on;&lt;br /&gt;
    prefix $IPV6PRE:1::0/64 {&lt;br /&gt;
        AdvOnLink on;&lt;br /&gt;
        AdvAutonomous on;&lt;br /&gt;
    };&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And start radvd (use -C /path/to/radvd.conf if necessary).&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[User:Jeff|Jeff]]&lt;/div&gt;</description>
			<pubDate>Mon, 04 Jun 2018 22:54:13 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Get_On_IPv6_Right_Now</comments>		</item>
		<item>
			<title>How To Configure OpenVPN</title>
			<link>http://72.14.177.54/SFVLUG/How_To_Configure_OpenVPN</link>
			<description>&lt;p&gt;Jeff:&amp;#32;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Setting up and running OpenVPN is pretty easy.  You just have to&lt;br /&gt;
understand a couple principles and set up the certificates.  So let's&lt;br /&gt;
start with the basics.&lt;br /&gt;
&lt;br /&gt;
== TUN And TAP Networking ==&lt;br /&gt;
&lt;br /&gt;
Running OpenVPN requires you to either set up a TUN or TAP network&lt;br /&gt;
interface.  These are both fairly similar but there is a critical&lt;br /&gt;
difference and I'll try to explain it as best as I can.&lt;br /&gt;
&lt;br /&gt;
You can think of both of these as network interfaces that are attached&lt;br /&gt;
to a program in userspace.  With them, the program is able to interact&lt;br /&gt;
with the rest of the network as if it were its own node on the&lt;br /&gt;
network.  In the case of OpenVPN, this is very useful because it&lt;br /&gt;
allows OpenVPN to send encrypted packets over your real network&lt;br /&gt;
interface, but it encrypts and decrypts packets entering or leaving&lt;br /&gt;
the tun or tap interface.  So OpenVPN gets to manipulate the&lt;br /&gt;
cryptography around the packets on its tun or tap interface and use&lt;br /&gt;
the machine's real interface for sending the packets just like any&lt;br /&gt;
other client or server program.&lt;br /&gt;
&lt;br /&gt;
;TUN&lt;br /&gt;
: A tun interface operates at layer 3.  This means it can encapsulate packets at the IP address layer.  Use a tun interface if you want to route packets between VPN endpoints.  That means both sides of the VPN will use different IP address spaces and use the VPN to route between the two networks.  This tutorial will be using the tun interface.  It is also worth mentioning that OpenBSD only supports tun interfaces.&lt;br /&gt;
;TAP&lt;br /&gt;
: A tap interface operates at layer 2.  This means it can encapsulate entire ethernet frames.  Use a tap interface when you want to bridge packets between VPN endpoints.  That means packets on either side of the VPN will be from the same address space.  Hopefully that will mean you can avoid NAT, if both sides of the VPN have all unique addresses.&lt;br /&gt;
&lt;br /&gt;
== X.509 Certificates ==&lt;br /&gt;
&lt;br /&gt;
We have all heard of SSL certificates.  They are the implementation of&lt;br /&gt;
the X.509 protocol.  Let's look at what we need.&lt;br /&gt;
&lt;br /&gt;
When seting up OpenVPN, I create my own Certificate Authority (CA).&lt;br /&gt;
This is just a self-signed certificate with a very long expiration&lt;br /&gt;
period.  In general, generating any X.509 results in three files.&lt;br /&gt;
First, there is the private key.  This is a secret file which contains&lt;br /&gt;
some important random numbers.  Second, from this file I generate what&lt;br /&gt;
is called a Certificate Signing Request (sometimes a CSR or req file).&lt;br /&gt;
The CSR is an unsigned public key, it contains no secrets.  However,&lt;br /&gt;
it contains the Subject which will identify the user of the&lt;br /&gt;
certificate.  Third, I use the CA to sign the CSR.  This results in a&lt;br /&gt;
Certificate, which is a signed public key.  Certificates also contain&lt;br /&gt;
no secrets.  They are just the CSR which contains the Subject and a&lt;br /&gt;
cryptographic signature generated using the CA's key to make a special&lt;br /&gt;
checksum.  The idea is, instead of sharing your public key with&lt;br /&gt;
everyone you want to communicate, every participant only needs a copy&lt;br /&gt;
of the CA's public key or Certificate.  Each participant can validate&lt;br /&gt;
the signature of any certificate any other participant tries to share.&lt;br /&gt;
&lt;br /&gt;
;Key&lt;br /&gt;
: Private key&lt;br /&gt;
;CSR&lt;br /&gt;
: Unsigned public key&lt;br /&gt;
;Cert&lt;br /&gt;
: Signed public key&lt;br /&gt;
&lt;br /&gt;
== Installing OpenVPN ==&lt;br /&gt;
&lt;br /&gt;
I am going to assume that you will be using the precompiled package of&lt;br /&gt;
OpenVPN which every distro provides.  I see no good reason to compile&lt;br /&gt;
it from source.&lt;br /&gt;
&lt;br /&gt;
We are going to configure OpenVPN with one server and multiple&lt;br /&gt;
road-warrior style clients.  This just means that the server will&lt;br /&gt;
always have the same IP address, or at least DNS name, and will always&lt;br /&gt;
be on, and that the clients will come and go as they please and won't&lt;br /&gt;
have the same IP addresses or DNS names.&lt;br /&gt;
&lt;br /&gt;
The server is going to provide routing to its entire network.  Let's&lt;br /&gt;
assume the server is the gateway to a LAN, and that LAN's IP space is&lt;br /&gt;
192.168.1.0/24, and the router which runs OpenVPN has the address&lt;br /&gt;
192.168.1.1.  Since we are using TUN networking, we need to use an&lt;br /&gt;
interim network to route over.  Let's use 172.16.1.0/24 for this&lt;br /&gt;
space.  OpenVPN is actually going to break this space down into&lt;br /&gt;
multiple slash-30 networks, each containing four addresses -- two&lt;br /&gt;
usable, one network address and one broadcast address -- and it will&lt;br /&gt;
use up the first of these so in reality we will have room for only 63&lt;br /&gt;
clients in this scenario.  The first client to connect gets a network&lt;br /&gt;
that looks like this:&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|| 172.16.1.4 || network&lt;br /&gt;
|-&lt;br /&gt;
|| 172.16.1.5 || server&lt;br /&gt;
|-&lt;br /&gt;
|| 172.16.1.6 || client&lt;br /&gt;
|-&lt;br /&gt;
|| 172.16.1.7 || broadcast&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The clients won't necessarily provide routing to their networks so&lt;br /&gt;
this means they are participating in a one-to-many VPN.  Therefore we&lt;br /&gt;
don't care what the network space our clients are in is, so long as it&lt;br /&gt;
is possible to cleanly route to the server's network.  That means no&lt;br /&gt;
IP conflicts in the two networks.  It is possible to create a&lt;br /&gt;
many-to-many VPN with OpenVPN, but we just won't be doing that in this&lt;br /&gt;
example.&lt;br /&gt;
&lt;br /&gt;
== Configure The Server ==&lt;br /&gt;
&lt;br /&gt;
Every installation of OpenVPN I have installed (on Linux) has always&lt;br /&gt;
used /etc/openvpn to store the configuration.  On Windows or MacOS it&lt;br /&gt;
is wherever you installed it, and on FreeBSD and OpenBSD it's &lt;br /&gt;
/usr/local/etc/openvpn.  We'll start with the server configuration&lt;br /&gt;
file.  For the server I left all the comments in the file.  There are&lt;br /&gt;
example configuration files in /usr/share/doc.  Create the following&lt;br /&gt;
as /etc/openvpn/server.conf:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Which local IP address should OpenVPN&lt;br /&gt;
# listen on? (optional)&lt;br /&gt;
;local a.b.c.d&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is probably not necessary to specify a particular address to listen&lt;br /&gt;
on.  Only use this if you definitely don't want OpenVPN to listen on&lt;br /&gt;
every address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Which TCP/UDP port should OpenVPN listen on?&lt;br /&gt;
# If you want to run multiple OpenVPN instances&lt;br /&gt;
# on the same machine, use a different port&lt;br /&gt;
# number for each one.  You will need to&lt;br /&gt;
# open up this port on your firewall.&lt;br /&gt;
port 1194&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Port 1194 is the registered port for OpenVPN.  In actual practice, I&lt;br /&gt;
have never noticed any significant attempts to crack or otherwise&lt;br /&gt;
abuse the default port out on the wild Internet.  There are probably&lt;br /&gt;
two reasons for this.  First, since UDP is a connectionless protocol,&lt;br /&gt;
it's impossible to tell if the port is open or filtered using normal&lt;br /&gt;
port-scanning like nmap.  And second, since authentication is via&lt;br /&gt;
X.509 certificates which are typically thousands of bits, the&lt;br /&gt;
likelihood of successfully guessing the correct signature to gain&lt;br /&gt;
access is astronomically near impossible.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# TCP or UDP server?&lt;br /&gt;
;proto tcp&lt;br /&gt;
proto udp&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Use UDP for your VPN.  Tunneling TCP over TCP can be less reliable.&lt;br /&gt;
As previously stated, it's impossible to differentiate an open and a&lt;br /&gt;
filtered UDP port.  And the connection-oriented nature of TCP doesn't&lt;br /&gt;
actually buy you anything in this situation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# &amp;quot;dev tun&amp;quot; will create a routed IP tunnel,&lt;br /&gt;
# &amp;quot;dev tap&amp;quot; will create an ethernet tunnel.&lt;br /&gt;
# Use &amp;quot;dev tap0&amp;quot; if you are ethernet bridging&lt;br /&gt;
# and have precreated a tap0 virtual interface&lt;br /&gt;
# and bridged it with your ethernet interface.&lt;br /&gt;
# If you want to control access policies&lt;br /&gt;
# over the VPN, you must create firewall&lt;br /&gt;
# rules for the the TUN/TAP interface.&lt;br /&gt;
# On non-Windows systems, you can give&lt;br /&gt;
# an explicit unit number, such as tun0.&lt;br /&gt;
# On Windows, use &amp;quot;dev-node&amp;quot; for this.&lt;br /&gt;
# On most systems, the VPN will not function&lt;br /&gt;
# unless you partially or fully disable&lt;br /&gt;
# the firewall for the TUN/TAP interface.&lt;br /&gt;
;dev tap&lt;br /&gt;
dev tun&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As stated previously, we're using TUN networking for this example.&lt;br /&gt;
The comment mentions firewalls, and we'll cover iptables a little&lt;br /&gt;
later.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Windows needs the TAP-Win32 adapter name&lt;br /&gt;
# from the Network Connections panel if you&lt;br /&gt;
# have more than one.  On XP SP2 or higher,&lt;br /&gt;
# you may need to selectively disable the&lt;br /&gt;
# Windows firewall for the TAP adapter.&lt;br /&gt;
# Non-Windows systems usually don't need this.&lt;br /&gt;
;dev-node MyTap&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The preceding section should be irrelevant unless you're using&lt;br /&gt;
Windows.  Running Windows as a server is just stupid; using it as a&lt;br /&gt;
gateway just makes no sense at all.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# SSL/TLS root certificate (ca), certificate&lt;br /&gt;
# (cert), and private key (key).  Each client&lt;br /&gt;
# and the server must have their own cert and&lt;br /&gt;
# key file.  The server and all clients will&lt;br /&gt;
# use the same ca file.&lt;br /&gt;
#&lt;br /&gt;
# See the &amp;quot;easy-rsa&amp;quot; directory for a series&lt;br /&gt;
# of scripts for generating RSA certificates&lt;br /&gt;
# and private keys.  Remember to use&lt;br /&gt;
# a unique Common Name for the server&lt;br /&gt;
# and each of the client certificates.&lt;br /&gt;
#&lt;br /&gt;
# Any X509 key management system can be used.&lt;br /&gt;
# OpenVPN can also use a PKCS #12 formatted key file&lt;br /&gt;
# (see &amp;quot;pkcs12&amp;quot; directive in man page).&lt;br /&gt;
ca ca.crt&lt;br /&gt;
cert server.crt&lt;br /&gt;
key server.key  # This file should be kept secret&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All files are going to be relative to the configuration file&lt;br /&gt;
unless otherwise qualified.  Generating each of these will be covered&lt;br /&gt;
below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Diffie hellman parameters.&lt;br /&gt;
# Generate your own with:&lt;br /&gt;
#   openssl dhparam -out dh2048.pem 2048&lt;br /&gt;
dh dh2048.pem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The server should include a Diffie-Hellman parameter.  Use the command&lt;br /&gt;
shown above to generate it.  This file improves security and makes the&lt;br /&gt;
tunnel harder to decrypt.  Generating a Diffie-Hellman parameter is&lt;br /&gt;
very time consuming; it can take several minutes to generate a&lt;br /&gt;
two-thousand bit parameter.  Be patient, it is not worth generating a&lt;br /&gt;
weak parameter file just to save a little time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Network topology&lt;br /&gt;
# Should be subnet (addressing via IP)&lt;br /&gt;
# unless Windows clients v2.0.9 and lower have to&lt;br /&gt;
# be supported (then net30, i.e. a /30 per client)&lt;br /&gt;
# Defaults to net30 (not recommended)&lt;br /&gt;
;topology subnet&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As stated, this parameter shouldn't be necessary unless you have to&lt;br /&gt;
support outdated Windows software.  OpenVPN is open source, just&lt;br /&gt;
download a more recent copy why don'tcha?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Configure server mode and supply a VPN subnet&lt;br /&gt;
# for OpenVPN to draw client addresses from.&lt;br /&gt;
# The server will take 10.8.0.1 for itself,&lt;br /&gt;
# the rest will be made available to clients.&lt;br /&gt;
# Each client will be able to reach the server&lt;br /&gt;
# on 10.8.0.1. Comment this line out if you are&lt;br /&gt;
# ethernet bridging. See the man page for more info.&lt;br /&gt;
;;server 10.8.0.0 255.255.255.0&lt;br /&gt;
server 172.16.1.0 255.255.255.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is where we configure the pool of addresses which will be used by&lt;br /&gt;
the client-to-server connections as illustrated above.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Maintain a record of client &amp;lt;-&amp;gt; virtual IP address&lt;br /&gt;
# associations in this file.  If OpenVPN goes down or&lt;br /&gt;
# is restarted, reconnecting clients can be assigned&lt;br /&gt;
# the same virtual IP address from the pool that was&lt;br /&gt;
# previously assigned.&lt;br /&gt;
ifconfig-pool-persist ipp.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you include the above parameter, then each client will get the same&lt;br /&gt;
IP address from the server pool above each time it reconnects.  You&lt;br /&gt;
can take advantage of this to implement client-specific firewall&lt;br /&gt;
rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Configure server mode for ethernet bridging.&lt;br /&gt;
# You must first use your OS's bridging capability&lt;br /&gt;
# to bridge the TAP interface with the ethernet&lt;br /&gt;
# NIC interface.  Then you must manually set the&lt;br /&gt;
# IP/netmask on the bridge interface, here we&lt;br /&gt;
# assume 10.8.0.4/255.255.255.0.  Finally we&lt;br /&gt;
# must set aside an IP range in this subnet&lt;br /&gt;
# (start=10.8.0.50 end=10.8.0.100) to allocate&lt;br /&gt;
# to connecting clients.  Leave this line commented&lt;br /&gt;
# out unless you are ethernet bridging.&lt;br /&gt;
;server-bridge 10.8.0.4 255.255.255.0 10.8.0.50 10.8.0.100&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You would only need to use this parameter if you are using a TAP&lt;br /&gt;
interface and bridging your networks.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Configure server mode for ethernet bridging&lt;br /&gt;
# using a DHCP-proxy, where clients talk&lt;br /&gt;
# to the OpenVPN server-side DHCP server&lt;br /&gt;
# to receive their IP address allocation&lt;br /&gt;
# and DNS server addresses.  You must first use&lt;br /&gt;
# your OS's bridging capability to bridge the TAP&lt;br /&gt;
# interface with the ethernet NIC interface.&lt;br /&gt;
# Note: this mode only works on clients (such as&lt;br /&gt;
# Windows), where the client-side TAP adapter is&lt;br /&gt;
# bound to a DHCP client.&lt;br /&gt;
;server-bridge&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, this parameter is TAP networking and bridge specific.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Push routes to the client to allow it&lt;br /&gt;
# to reach other private subnets behind&lt;br /&gt;
# the server.  Remember that these&lt;br /&gt;
# private subnets will also need&lt;br /&gt;
# to know to route the OpenVPN client&lt;br /&gt;
# address pool (10.8.0.0/255.255.255.0)&lt;br /&gt;
# back to the OpenVPN server.&lt;br /&gt;
;push &amp;quot;route 192.168.10.0 255.255.255.0&amp;quot;&lt;br /&gt;
;push &amp;quot;route 192.168.20.0 255.255.255.0&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If your OpenVPN server is a gateway to multiple subnets, you can push&lt;br /&gt;
additional routes to the clients.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# To assign specific IP addresses to specific&lt;br /&gt;
# clients or if a connecting client has a private&lt;br /&gt;
# subnet behind it that should also have VPN access,&lt;br /&gt;
# use the subdirectory &amp;quot;ccd&amp;quot; for client-specific&lt;br /&gt;
# configuration files (see man page for more info).&lt;br /&gt;
&lt;br /&gt;
# EXAMPLE: Suppose the client&lt;br /&gt;
# having the certificate common name &amp;quot;Thelonious&amp;quot;&lt;br /&gt;
# also has a small subnet behind his connecting&lt;br /&gt;
# machine, such as 192.168.40.128/255.255.255.248.&lt;br /&gt;
# First, uncomment out these lines:&lt;br /&gt;
;client-config-dir ccd&lt;br /&gt;
;route 192.168.40.128 255.255.255.248&lt;br /&gt;
# Then create a file ccd/Thelonious with this line:&lt;br /&gt;
#   iroute 192.168.40.128 255.255.255.248&lt;br /&gt;
# This will allow Thelonious' private subnet to&lt;br /&gt;
# access the VPN.  This example will only work&lt;br /&gt;
# if you are routing, not bridging, i.e. you are&lt;br /&gt;
# using &amp;quot;dev tun&amp;quot; and &amp;quot;server&amp;quot; directives.&lt;br /&gt;
&lt;br /&gt;
# EXAMPLE: Suppose you want to give&lt;br /&gt;
# Thelonious a fixed VPN IP address of 10.9.0.1.&lt;br /&gt;
# First uncomment out these lines:&lt;br /&gt;
;client-config-dir ccd&lt;br /&gt;
;route 10.9.0.0 255.255.255.252&lt;br /&gt;
# Then add this line to ccd/Thelonious:&lt;br /&gt;
#   ifconfig-push 10.9.0.1 10.9.0.2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All of the above examples are to give a particular host specific&lt;br /&gt;
configurations.  In a simple scenario such as ours, it is not&lt;br /&gt;
necessary.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Suppose that you want to enable different&lt;br /&gt;
# firewall access policies for different groups&lt;br /&gt;
# of clients.  There are two methods:&lt;br /&gt;
# (1) Run multiple OpenVPN daemons, one for each&lt;br /&gt;
#     group, and firewall the TUN/TAP interface&lt;br /&gt;
#     for each group/daemon appropriately.&lt;br /&gt;
# (2) (Advanced) Create a script to dynamically&lt;br /&gt;
#     modify the firewall in response to access&lt;br /&gt;
#     from different clients.  See man&lt;br /&gt;
#     page for more info on learn-address script.&lt;br /&gt;
;learn-address ./script&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As the comments state, if you want to modify your firewall each time a&lt;br /&gt;
particular client connects, in some particular way, then you could use&lt;br /&gt;
a script to do it.  Personally, I think you should have your firewall&lt;br /&gt;
rules pre-set and use the above ipp.txt file to assign the client the&lt;br /&gt;
expected address.  If you have more clients than your IP pool allows&lt;br /&gt;
to assign each of them a separate address, then use this script to add&lt;br /&gt;
their address to an IPSet, which will be matched by rules you already&lt;br /&gt;
have established.  Modifying your firewall rules dynamically by a&lt;br /&gt;
script can be a recipe for disaster and it's very difficult to&lt;br /&gt;
thoroughly test all the possible outcomes with a large number of&lt;br /&gt;
modifications.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# If enabled, this directive will configure&lt;br /&gt;
# all clients to redirect their default&lt;br /&gt;
# network gateway through the VPN, causing&lt;br /&gt;
# all IP traffic such as web browsing and&lt;br /&gt;
# and DNS lookups to go through the VPN&lt;br /&gt;
# (The OpenVPN server machine may need to NAT&lt;br /&gt;
# or bridge the TUN/TAP interface to the internet&lt;br /&gt;
# in order for this to work properly).&lt;br /&gt;
;push &amp;quot;redirect-gateway def1 bypass-dhcp&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Some people want to configure OpenVPN as a proxy for their web&lt;br /&gt;
browsing.  This means all their web browsing traffic will pass out of&lt;br /&gt;
their local network encrypted and be kept out of the prying eyes of&lt;br /&gt;
whoever is watching at their gateway (either their ISP, employer, or&lt;br /&gt;
government).  If you want to configure this, follow the above example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Certain Windows-specific network settings&lt;br /&gt;
# can be pushed to clients, such as DNS&lt;br /&gt;
# or WINS server addresses.  CAVEAT:&lt;br /&gt;
# http://openvpn.net/faq.html#dhcpcaveats&lt;br /&gt;
# The addresses below refer to the public&lt;br /&gt;
# DNS servers provided by opendns.com.&lt;br /&gt;
;push &amp;quot;dhcp-option DNS 208.67.222.222&amp;quot;&lt;br /&gt;
;push &amp;quot;dhcp-option DNS 208.67.220.220&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can push any options normally available to any DHCP server.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Uncomment this directive to allow different&lt;br /&gt;
# clients to be able to &amp;quot;see&amp;quot; each other.&lt;br /&gt;
# By default, clients will only see the server.&lt;br /&gt;
# To force clients to only see the server, you&lt;br /&gt;
# will also need to appropriately firewall the&lt;br /&gt;
# server's TUN/TAP interface.&lt;br /&gt;
;client-to-client&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Most often, you don't need your clients to talk to each other over&lt;br /&gt;
your tunnel.  Usually they are only laptops or possibly desktop&lt;br /&gt;
computers and are not providing any services of their own to other&lt;br /&gt;
machines.  So you won't forward traffic from one client to another.&lt;br /&gt;
But if you do want to do this, then you need to turn on this&lt;br /&gt;
parameter.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Uncomment this directive if multiple clients&lt;br /&gt;
# might connect with the same certificate/key&lt;br /&gt;
# files or common names.  This is recommended&lt;br /&gt;
# only for testing purposes.  For production use,&lt;br /&gt;
# each client should have its own certificate/key&lt;br /&gt;
# pair.&lt;br /&gt;
#&lt;br /&gt;
# IF YOU HAVE NOT GENERATED INDIVIDUAL&lt;br /&gt;
# CERTIFICATE/KEY PAIRS FOR EACH CLIENT,&lt;br /&gt;
# EACH HAVING ITS OWN UNIQUE &amp;quot;COMMON NAME&amp;quot;,&lt;br /&gt;
# UNCOMMENT THIS LINE OUT.&lt;br /&gt;
;duplicate-cn&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Most of the time you should make sure each client has a unique common&lt;br /&gt;
name.  Quite often, the common name of a certificate will just be the&lt;br /&gt;
name of the person using it.  If that person happens to use multiple&lt;br /&gt;
computers, they might use the same name in multiple certificates (or&lt;br /&gt;
worse, use the same certificate across multiple machines -- discourage&lt;br /&gt;
this).  If this happens, then you must turn on this parameter.  Also,&lt;br /&gt;
you will probably not be able to use ipp.txt above.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# The keepalive directive causes ping-like&lt;br /&gt;
# messages to be sent back and forth over&lt;br /&gt;
# the link so that each side knows when&lt;br /&gt;
# the other side has gone down.&lt;br /&gt;
# Ping every 10 seconds, assume that remote&lt;br /&gt;
# peer is down if no ping received during&lt;br /&gt;
# a 120 second time period.&lt;br /&gt;
keepalive 10 120&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The comments here are pretty self-explanatory.  I think the defaults&lt;br /&gt;
are reasonable.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# For extra security beyond that provided&lt;br /&gt;
# by SSL/TLS, create an &amp;quot;HMAC firewall&amp;quot;&lt;br /&gt;
# to help block DoS attacks and UDP port flooding.&lt;br /&gt;
#&lt;br /&gt;
# Generate with:&lt;br /&gt;
#   openvpn --genkey --secret ta.key&lt;br /&gt;
#&lt;br /&gt;
# The server and each client must have&lt;br /&gt;
# a copy of this key.&lt;br /&gt;
# The second parameter should be '0'&lt;br /&gt;
# on the server and '1' on the clients.&lt;br /&gt;
;tls-auth ta.key 0 # This file is secret&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I'm not really sure how this is supposed to prevent flooding.  After&lt;br /&gt;
all, you can't control what someone else sends you.  Suffice it to&lt;br /&gt;
say, I haven't used this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Select a cryptographic cipher.&lt;br /&gt;
# This config item must be copied to&lt;br /&gt;
# the client config file as well.&lt;br /&gt;
;cipher BF-CBC        # Blowfish (default)&lt;br /&gt;
;cipher AES-128-CBC   # AES&lt;br /&gt;
;cipher DES-EDE3-CBC  # Triple-DES&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There have been a lot of issues concerning OpenSSL recently.  Some&lt;br /&gt;
were specific to the OpenSSL code, but some were just discoveries that&lt;br /&gt;
certain ciphers had weaknesses that weren't discovered previously.  If&lt;br /&gt;
this concerns you, you can discover what ciphers are available using&lt;br /&gt;
the command `openssl ciphers` and picking through the list until you&lt;br /&gt;
find a combination you like.  Make sure all clients are capable of&lt;br /&gt;
using the same one.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Enable compression on the VPN link.&lt;br /&gt;
# If you enable it here, you must also&lt;br /&gt;
# enable it in the client config file.&lt;br /&gt;
comp-lzo&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Adding encryption to any traffic means that traffic gets heavier.  You&lt;br /&gt;
have to encode additional data about what you are sending so that the&lt;br /&gt;
other end can properly identify and decode the packets.  This means&lt;br /&gt;
using more bandwidth than a plain text transmission.  To help with&lt;br /&gt;
this, use compression.  This trades CPU time for network time.  In&lt;br /&gt;
this day and age, your CPU is probably much faster than your network,&lt;br /&gt;
so the trade-off advantage should be obvious.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# The maximum number of concurrently connected&lt;br /&gt;
# clients we want to allow.&lt;br /&gt;
;max-clients 100&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As stated above, in this example we are already limited to 63 clients&lt;br /&gt;
due to the address space we chose.  Honestly, I'm not sure why you&lt;br /&gt;
would want to impose any other form of artificial limitation on your&lt;br /&gt;
clients.  Maybe if your gateway's CPU was just so taxed that 101&lt;br /&gt;
connections was just too much?  Still, the option is there if you want&lt;br /&gt;
it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# It's a good idea to reduce the OpenVPN&lt;br /&gt;
# daemon's privileges after initialization.&lt;br /&gt;
#&lt;br /&gt;
# You can uncomment this out on&lt;br /&gt;
# non-Windows systems.&lt;br /&gt;
;user nobody&lt;br /&gt;
;group nobody&lt;br /&gt;
user nobody&lt;br /&gt;
group nogroup&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Your distro may have a dedicated openvpn user and group.  I copied&lt;br /&gt;
this example from an installation which did not.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# The persist options will try to avoid&lt;br /&gt;
# accessing certain resources on restart&lt;br /&gt;
# that may no longer be accessible because&lt;br /&gt;
# of the privilege downgrade.&lt;br /&gt;
persist-key&lt;br /&gt;
persist-tun&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As the comment says, ephemeral keys and tunnel devices might tear down&lt;br /&gt;
across restarts.  In my own experience, these parameters don't make a&lt;br /&gt;
huge difference, but they make restarts a little quicker.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Output a short status file showing&lt;br /&gt;
# current connections, truncated&lt;br /&gt;
# and rewritten every minute.&lt;br /&gt;
status /tmp/openvpn-status.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This file is just a quick glance at the current state of affairs for&lt;br /&gt;
the VPN server.  I moved it to /tmp so that it would not continuously&lt;br /&gt;
write to flash memory, wearing it out quicker.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# By default, log messages will go to the syslog (or&lt;br /&gt;
# on Windows, if running as a service, they will go to&lt;br /&gt;
# the &amp;quot;\Program Files\OpenVPN\log&amp;quot; directory).&lt;br /&gt;
# Use log or log-append to override this default.&lt;br /&gt;
# &amp;quot;log&amp;quot; will truncate the log file on OpenVPN startup,&lt;br /&gt;
# while &amp;quot;log-append&amp;quot; will append to it.  Use one&lt;br /&gt;
# or the other (but not both).&lt;br /&gt;
;log         openvpn.log&lt;br /&gt;
;log-append  openvpn.log&lt;br /&gt;
log-append /tmp/openvpn.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
My own OpenVPN server is running on a small router.  I chose to write&lt;br /&gt;
to a local log rather than syslog.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Set the appropriate level of log&lt;br /&gt;
# file verbosity.&lt;br /&gt;
#&lt;br /&gt;
# 0 is silent, except for fatal errors&lt;br /&gt;
# 4 is reasonable for general usage&lt;br /&gt;
# 5 and 6 can help to debug connection problems&lt;br /&gt;
# 9 is extremely verbose&lt;br /&gt;
verb 3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the default.  I haven't seen a need to change it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Silence repeating messages.  At most 20&lt;br /&gt;
# sequential messages of the same message&lt;br /&gt;
# category will be output to the log.&lt;br /&gt;
;mute 20&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I have never had a reason to change this one.&lt;br /&gt;
&lt;br /&gt;
== Configure Clients ==&lt;br /&gt;
&lt;br /&gt;
Each of the clients can have multiple servers which they connect to.&lt;br /&gt;
For example you might have both an office LAN and a data center you&lt;br /&gt;
regularly log in to.  Or you might be a consultant with multiple&lt;br /&gt;
clients you regularly have to do maintenance for.  For this reason, I&lt;br /&gt;
usually name the client configurations after the servers they connect&lt;br /&gt;
to.  So name this appropriately, home.conf, office.conf, or whatever.&lt;br /&gt;
This time around I have stripped the comments aout of the&lt;br /&gt;
configuration file.  Examples should be available in /usr/share/doc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
client&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tells openvpn that it will be initiating an outbound connection.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
remote gateway.example.com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When configured as a client, OpenVPN needs to know where to connect.&lt;br /&gt;
Try to use a fully qualified domain name here.  Also, this fully&lt;br /&gt;
qualified domain name needs to be the common name or a subject&lt;br /&gt;
alternative name for the server's certificate.  If the clients must&lt;br /&gt;
use the server's IP address, it must be part of the subject of the&lt;br /&gt;
certificate.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ca ca.crt&lt;br /&gt;
cert client.example-com.crt&lt;br /&gt;
key client.example-com.key&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A separate CA can be used to sign the certificates of both the server&lt;br /&gt;
and the clients.  If you do this, the clients need the CA certificate&lt;br /&gt;
which matches the key that signed the server's certificate, and the&lt;br /&gt;
server needs the CA certificate that matches the key which signs all&lt;br /&gt;
the clients' certificates.&lt;br /&gt;
&lt;br /&gt;
Since a client can connect to multiple servers, I name the local key&lt;br /&gt;
and certificate files after the organization with which they will be&lt;br /&gt;
used.  It is possible to configure multiple servers to authenticate&lt;br /&gt;
certificates signed by the same CA, so clients connecting to multiple&lt;br /&gt;
servers like this will only need one certificate for the whole&lt;br /&gt;
organization.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dev tun&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, specify to use TUN networking.  This must match the server.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
proto udp&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, specify to use UDP.  This must also match the server.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
nobind&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This says not to specify the source port of the outgoing connection.&lt;br /&gt;
It should not be necessary to do so unless the server is expecting&lt;br /&gt;
only certain source ports.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
persist-key&lt;br /&gt;
persist-tun&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As with the server, this should reduce the amount of time it takes to&lt;br /&gt;
restart the software.  I don't think it will make a huge difference&lt;br /&gt;
for clients, but it doesn't hurt and the example encourages it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
user openvpn&lt;br /&gt;
group openvpn&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specify to run as an unprivileged user.&lt;/div&gt;</description>
			<pubDate>Sun, 21 Feb 2016 23:23:50 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:How_To_Configure_OpenVPN</comments>		</item>
		<item>
			<title>How To Configure OpenVPN</title>
			<link>http://72.14.177.54/SFVLUG/How_To_Configure_OpenVPN</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Configure The Server */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Setting up and running OpenVPN is pretty easy.  You just have to&lt;br /&gt;
understand a couple principles and set up the certificates.  So let's&lt;br /&gt;
start with the basics.&lt;br /&gt;
&lt;br /&gt;
== TUN And TAP Networking ==&lt;br /&gt;
&lt;br /&gt;
Running OpenVPN requires you to either set up a TUN or TAP network&lt;br /&gt;
interface.  These are both fairly similar but there is a critical&lt;br /&gt;
difference and I'll try to explain it as best as I can.&lt;br /&gt;
&lt;br /&gt;
You can think of both of these as network interfaces that are attached&lt;br /&gt;
to a program in userspace.  With them, the program is able to interact&lt;br /&gt;
with the rest of the network as if it were its own node on the&lt;br /&gt;
network.  In the case of OpenVPN, this is very useful because it&lt;br /&gt;
allows OpenVPN to send encrypted packets over your real network&lt;br /&gt;
interface, but it encrypts and decrypts packets entering or leaving&lt;br /&gt;
the tun or tap interface.  So OpenVPN gets to manipulate the&lt;br /&gt;
cryptography around the packets on its tun or tap interface and use&lt;br /&gt;
the machine's real interface for sending the packets just like any&lt;br /&gt;
other client or server program.&lt;br /&gt;
&lt;br /&gt;
;TUN&lt;br /&gt;
: A tun interface operates at layer 3.  This means it can encapsulate packets at the IP address layer.  Use a tun interface if you want to route packets between VPN endpoints.  That means both sides of the VPN will use different IP address spaces and use the VPN to route between the two networks.  This tutorial will be using the tun interface.  It is also worth mentioning that OpenBSD only supports tun interfaces.&lt;br /&gt;
;TAP&lt;br /&gt;
: A tap interface operates at layer 2.  This means it can encapsulate entire ethernet frames.  Use a tap interface when you want to bridge packets between VPN endpoints.  That means packets on either side of the VPN will be from the same address space.  Hopefully that will mean you can avoid NAT, if both sides of the VPN have all unique addresses.&lt;br /&gt;
&lt;br /&gt;
== X.509 Certificates ==&lt;br /&gt;
&lt;br /&gt;
We have all heard of SSL certificates.  They are the implementation of&lt;br /&gt;
the X.509 protocol.  Let's look at what we need.&lt;br /&gt;
&lt;br /&gt;
When seting up OpenVPN, I create my own Certificate Authority (CA).&lt;br /&gt;
This is just a self-signed certificate with a very long expiration&lt;br /&gt;
period.  In general, generating any X.509 results in three files.&lt;br /&gt;
First, there is the private key.  This is a secret file which contains&lt;br /&gt;
some important random numbers.  Second, from this file I generate what&lt;br /&gt;
is called a Certificate Signing Request (sometimes a CSR or req file).&lt;br /&gt;
The CSR is an unsigned public key, it contains no secrets.  However,&lt;br /&gt;
it contains the Subject which will identify the user of the&lt;br /&gt;
certificate.  Third, I use the CA to sign the CSR.  This results in a&lt;br /&gt;
Certificate, which is a signed public key.  Certificates also contain&lt;br /&gt;
no secrets.  They are just the CSR which contains the Subject and a&lt;br /&gt;
cryptographic signature generated using the CA's key to make a special&lt;br /&gt;
checksum.  The idea is, instead of sharing your public key with&lt;br /&gt;
everyone you want to communicate, every participant only needs a copy&lt;br /&gt;
of the CA's public key or Certificate.  Each participant can validate&lt;br /&gt;
the signature of any certificate any other participant tries to share.&lt;br /&gt;
&lt;br /&gt;
;Key&lt;br /&gt;
: Private key&lt;br /&gt;
;CSR&lt;br /&gt;
: Unsigned public key&lt;br /&gt;
;Cert&lt;br /&gt;
: Signed public key&lt;br /&gt;
&lt;br /&gt;
== Installing OpenVPN ==&lt;br /&gt;
&lt;br /&gt;
I am going to assume that you will be using the precompiled package of&lt;br /&gt;
OpenVPN which every distro provides.  I see no good reason to compile&lt;br /&gt;
it from source.&lt;br /&gt;
&lt;br /&gt;
We are going to configure OpenVPN with one server and multiple&lt;br /&gt;
road-warrior style clients.  This just means that the server will&lt;br /&gt;
always have the same IP address, or at least DNS name, and will always&lt;br /&gt;
be on, and that the clients will come and go as they please and won't&lt;br /&gt;
have the same IP addresses or DNS names.&lt;br /&gt;
&lt;br /&gt;
The server is going to provide routing to its entire network.  Let's&lt;br /&gt;
assume the server is the gateway to a LAN, and that LAN's IP space is&lt;br /&gt;
192.168.1.0/24, and the router which runs OpenVPN has the address&lt;br /&gt;
192.168.1.1.  Since we are using TUN networking, we need to use an&lt;br /&gt;
interim network to route over.  Let's use 172.16.1.0/24 for this&lt;br /&gt;
space.  OpenVPN is actually going to break this space down into&lt;br /&gt;
multiple slash-30 networks, each containing four addresses -- two&lt;br /&gt;
usable, one network address and one broadcast address -- and it will&lt;br /&gt;
use up the first of these so in reality we will have room for only 63&lt;br /&gt;
clients in this scenario.  The first client to connect gets a network&lt;br /&gt;
that looks like this:&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|| 172.16.1.4 || network&lt;br /&gt;
|-&lt;br /&gt;
|| 172.16.1.5 || server&lt;br /&gt;
|-&lt;br /&gt;
|| 172.16.1.6 || client&lt;br /&gt;
|-&lt;br /&gt;
|| 172.16.1.7 || broadcast&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The clients won't necessarily provide routing to their networks so&lt;br /&gt;
this means they are participating in a one-to-many VPN.  Therefore we&lt;br /&gt;
don't care what the network space our clients are in is, so long as it&lt;br /&gt;
is possible to cleanly route to the server's network.  That means no&lt;br /&gt;
IP conflicts in the two networks.  It is possible to create a&lt;br /&gt;
many-to-many VPN with OpenVPN, but we just won't be doing that in this&lt;br /&gt;
example.&lt;br /&gt;
&lt;br /&gt;
== Configure The Server ==&lt;br /&gt;
&lt;br /&gt;
Every installation of OpenVPN I have installed (on Linux) has always&lt;br /&gt;
used /etc/openvpn to store the configuration.  On Windows or MacOS it&lt;br /&gt;
is wherever you installed it, and on FreeBSD and OpenBSD it's &lt;br /&gt;
/usr/local/etc/openvpn.  We'll start with the server configuration&lt;br /&gt;
file.  For the server I left all the comments in the file.  There are&lt;br /&gt;
example configuration files in /usr/share/doc.  Create the following&lt;br /&gt;
as /etc/openvpn/server.conf:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
# Which local IP address should OpenVPN&lt;br /&gt;
# listen on? (optional)&lt;br /&gt;
;local a.b.c.d&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is probably not necessary to specify a particular address to listen&lt;br /&gt;
on.  Only use this if you definitely don't want OpenVPN to listen on&lt;br /&gt;
every address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
# Which TCP/UDP port should OpenVPN listen on?&lt;br /&gt;
# If you want to run multiple OpenVPN instances&lt;br /&gt;
# on the same machine, use a different port&lt;br /&gt;
# number for each one.  You will need to&lt;br /&gt;
# open up this port on your firewall.&lt;br /&gt;
port 1194&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Port 1194 is the registered port for OpenVPN.  In actual practice, I&lt;br /&gt;
have never noticed any significant attempts to crack or otherwise&lt;br /&gt;
abuse the default port out on the wild Internet.  There are probably&lt;br /&gt;
two reasons for this.  First, since UDP is a connectionless protocol,&lt;br /&gt;
it's impossible to tell if the port is open or filtered using normal&lt;br /&gt;
port-scanning like nmap.  And second, since authentication is via&lt;br /&gt;
X.509 certificates which are typically thousands of bits, the&lt;br /&gt;
likelihood of successfully guessing the correct signature to gain&lt;br /&gt;
access is astronomically near impossible.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
# TCP or UDP server?&lt;br /&gt;
;proto tcp&lt;br /&gt;
proto udp&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Use UDP for your VPN.  Tunneling TCP over TCP can be less reliable.&lt;br /&gt;
As previously stated, it's impossible to differentiate an open and a&lt;br /&gt;
filtered UDP port.  And the connection-oriented nature of TCP doesn't&lt;br /&gt;
actually buy you anything in this situation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
# &amp;quot;dev tun&amp;quot; will create a routed IP tunnel,&lt;br /&gt;
# &amp;quot;dev tap&amp;quot; will create an ethernet tunnel.&lt;br /&gt;
# Use &amp;quot;dev tap0&amp;quot; if you are ethernet bridging&lt;br /&gt;
# and have precreated a tap0 virtual interface&lt;br /&gt;
# and bridged it with your ethernet interface.&lt;br /&gt;
# If you want to control access policies&lt;br /&gt;
# over the VPN, you must create firewall&lt;br /&gt;
# rules for the the TUN/TAP interface.&lt;br /&gt;
# On non-Windows systems, you can give&lt;br /&gt;
# an explicit unit number, such as tun0.&lt;br /&gt;
# On Windows, use &amp;quot;dev-node&amp;quot; for this.&lt;br /&gt;
# On most systems, the VPN will not function&lt;br /&gt;
# unless you partially or fully disable&lt;br /&gt;
# the firewall for the TUN/TAP interface.&lt;br /&gt;
;dev tap&lt;br /&gt;
dev tun&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As stated previously, we're using TUN networking for this example.&lt;br /&gt;
The comment mentions firewalls, and we'll cover iptables a little&lt;br /&gt;
later.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
# Windows needs the TAP-Win32 adapter name&lt;br /&gt;
# from the Network Connections panel if you&lt;br /&gt;
# have more than one.  On XP SP2 or higher,&lt;br /&gt;
# you may need to selectively disable the&lt;br /&gt;
# Windows firewall for the TAP adapter.&lt;br /&gt;
# Non-Windows systems usually don't need this.&lt;br /&gt;
;dev-node MyTap&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The preceding section should be irrelevant unless you're using&lt;br /&gt;
Windows.  Running Windows as a server is just stupid; using it as a&lt;br /&gt;
gateway just makes no sense at all.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
# SSL/TLS root certificate (ca), certificate&lt;br /&gt;
# (cert), and private key (key).  Each client&lt;br /&gt;
# and the server must have their own cert and&lt;br /&gt;
# key file.  The server and all clients will&lt;br /&gt;
# use the same ca file.&lt;br /&gt;
#&lt;br /&gt;
# See the &amp;quot;easy-rsa&amp;quot; directory for a series&lt;br /&gt;
# of scripts for generating RSA certificates&lt;br /&gt;
# and private keys.  Remember to use&lt;br /&gt;
# a unique Common Name for the server&lt;br /&gt;
# and each of the client certificates.&lt;br /&gt;
#&lt;br /&gt;
# Any X509 key management system can be used.&lt;br /&gt;
# OpenVPN can also use a PKCS #12 formatted key file&lt;br /&gt;
# (see &amp;quot;pkcs12&amp;quot; directive in man page).&lt;br /&gt;
ca ca.crt&lt;br /&gt;
cert server.crt&lt;br /&gt;
key server.key  # This file should be kept secret&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All files are going to be relative to the configuration file&lt;br /&gt;
unless otherwise qualified.  Generating each of these will be covered&lt;br /&gt;
below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
# Diffie hellman parameters.&lt;br /&gt;
# Generate your own with:&lt;br /&gt;
#   openssl dhparam -out dh2048.pem 2048&lt;br /&gt;
dh dh2048.pem&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The server should include a Diffie-Hellman parameter.  Use the command&lt;br /&gt;
shown above to generate it.  This file improves security and makes the&lt;br /&gt;
tunnel harder to decrypt.  Generating a Diffie-Hellman parameter is&lt;br /&gt;
very time consuming; it can take several minutes to generate a&lt;br /&gt;
two-thousand bit parameter.  Be patient, it is not worth generating a&lt;br /&gt;
weak parameter file just to save a little time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
# Network topology&lt;br /&gt;
# Should be subnet (addressing via IP)&lt;br /&gt;
# unless Windows clients v2.0.9 and lower have to&lt;br /&gt;
# be supported (then net30, i.e. a /30 per client)&lt;br /&gt;
# Defaults to net30 (not recommended)&lt;br /&gt;
;topology subnet&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As stated, this parameter shouldn't be necessary unless you have to&lt;br /&gt;
support outdated Windows software.  OpenVPN is open source, just&lt;br /&gt;
download a more recent copy why don'tcha?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
# Configure server mode and supply a VPN subnet&lt;br /&gt;
# for OpenVPN to draw client addresses from.&lt;br /&gt;
# The server will take 10.8.0.1 for itself,&lt;br /&gt;
# the rest will be made available to clients.&lt;br /&gt;
# Each client will be able to reach the server&lt;br /&gt;
# on 10.8.0.1. Comment this line out if you are&lt;br /&gt;
# ethernet bridging. See the man page for more info.&lt;br /&gt;
;;server 10.8.0.0 255.255.255.0&lt;br /&gt;
server 172.16.1.0 255.255.255.0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is where we configure the pool of addresses which will be used by&lt;br /&gt;
the client-to-server connections as illustrated above.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
# Maintain a record of client &amp;lt;-&amp;gt; virtual IP address&lt;br /&gt;
# associations in this file.  If OpenVPN goes down or&lt;br /&gt;
# is restarted, reconnecting clients can be assigned&lt;br /&gt;
# the same virtual IP address from the pool that was&lt;br /&gt;
# previously assigned.&lt;br /&gt;
ifconfig-pool-persist ipp.txt&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you include the above parameter, then each client will get the same&lt;br /&gt;
IP address from the server pool above each time it reconnects.  You&lt;br /&gt;
can take advantage of this to implement client-specific firewall&lt;br /&gt;
rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
# Configure server mode for ethernet bridging.&lt;br /&gt;
# You must first use your OS's bridging capability&lt;br /&gt;
# to bridge the TAP interface with the ethernet&lt;br /&gt;
# NIC interface.  Then you must manually set the&lt;br /&gt;
# IP/netmask on the bridge interface, here we&lt;br /&gt;
# assume 10.8.0.4/255.255.255.0.  Finally we&lt;br /&gt;
# must set aside an IP range in this subnet&lt;br /&gt;
# (start=10.8.0.50 end=10.8.0.100) to allocate&lt;br /&gt;
# to connecting clients.  Leave this line commented&lt;br /&gt;
# out unless you are ethernet bridging.&lt;br /&gt;
;server-bridge 10.8.0.4 255.255.255.0 10.8.0.50 10.8.0.100&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You would only need to use this parameter if you are using a TAP&lt;br /&gt;
interface and bridging your networks.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
# Configure server mode for ethernet bridging&lt;br /&gt;
# using a DHCP-proxy, where clients talk&lt;br /&gt;
# to the OpenVPN server-side DHCP server&lt;br /&gt;
# to receive their IP address allocation&lt;br /&gt;
# and DNS server addresses.  You must first use&lt;br /&gt;
# your OS's bridging capability to bridge the TAP&lt;br /&gt;
# interface with the ethernet NIC interface.&lt;br /&gt;
# Note: this mode only works on clients (such as&lt;br /&gt;
# Windows), where the client-side TAP adapter is&lt;br /&gt;
# bound to a DHCP client.&lt;br /&gt;
;server-bridge&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, this parameter is TAP networking and bridge specific.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
# Push routes to the client to allow it&lt;br /&gt;
# to reach other private subnets behind&lt;br /&gt;
# the server.  Remember that these&lt;br /&gt;
# private subnets will also need&lt;br /&gt;
# to know to route the OpenVPN client&lt;br /&gt;
# address pool (10.8.0.0/255.255.255.0)&lt;br /&gt;
# back to the OpenVPN server.&lt;br /&gt;
;push &amp;quot;route 192.168.10.0 255.255.255.0&amp;quot;&lt;br /&gt;
;push &amp;quot;route 192.168.20.0 255.255.255.0&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If your OpenVPN server is a gateway to multiple subnets, you can push&lt;br /&gt;
additional routes to the clients.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
# To assign specific IP addresses to specific&lt;br /&gt;
# clients or if a connecting client has a private&lt;br /&gt;
# subnet behind it that should also have VPN access,&lt;br /&gt;
# use the subdirectory &amp;quot;ccd&amp;quot; for client-specific&lt;br /&gt;
# configuration files (see man page for more info).&lt;br /&gt;
&lt;br /&gt;
# EXAMPLE: Suppose the client&lt;br /&gt;
# having the certificate common name &amp;quot;Thelonious&amp;quot;&lt;br /&gt;
# also has a small subnet behind his connecting&lt;br /&gt;
# machine, such as 192.168.40.128/255.255.255.248.&lt;br /&gt;
# First, uncomment out these lines:&lt;br /&gt;
;client-config-dir ccd&lt;br /&gt;
;route 192.168.40.128 255.255.255.248&lt;br /&gt;
# Then create a file ccd/Thelonious with this line:&lt;br /&gt;
#   iroute 192.168.40.128 255.255.255.248&lt;br /&gt;
# This will allow Thelonious' private subnet to&lt;br /&gt;
# access the VPN.  This example will only work&lt;br /&gt;
# if you are routing, not bridging, i.e. you are&lt;br /&gt;
# using &amp;quot;dev tun&amp;quot; and &amp;quot;server&amp;quot; directives.&lt;br /&gt;
&lt;br /&gt;
# EXAMPLE: Suppose you want to give&lt;br /&gt;
# Thelonious a fixed VPN IP address of 10.9.0.1.&lt;br /&gt;
# First uncomment out these lines:&lt;br /&gt;
;client-config-dir ccd&lt;br /&gt;
;route 10.9.0.0 255.255.255.252&lt;br /&gt;
# Then add this line to ccd/Thelonious:&lt;br /&gt;
#   ifconfig-push 10.9.0.1 10.9.0.2&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All of the above examples are to give a particular host specific&lt;br /&gt;
configurations.  In a simple scenario such as ours, it is not&lt;br /&gt;
necessary.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
# Suppose that you want to enable different&lt;br /&gt;
# firewall access policies for different groups&lt;br /&gt;
# of clients.  There are two methods:&lt;br /&gt;
# (1) Run multiple OpenVPN daemons, one for each&lt;br /&gt;
#     group, and firewall the TUN/TAP interface&lt;br /&gt;
#     for each group/daemon appropriately.&lt;br /&gt;
# (2) (Advanced) Create a script to dynamically&lt;br /&gt;
#     modify the firewall in response to access&lt;br /&gt;
#     from different clients.  See man&lt;br /&gt;
#     page for more info on learn-address script.&lt;br /&gt;
;learn-address ./script&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As the comments state, if you want to modify your firewall each time a&lt;br /&gt;
particular client connects, in some particular way, then you could use&lt;br /&gt;
a script to do it.  Personally, I think you should have your firewall&lt;br /&gt;
rules pre-set and use the above ipp.txt file to assign the client the&lt;br /&gt;
expected address.  If you have more clients than your IP pool allows&lt;br /&gt;
to assign each of them a separate address, then use this script to add&lt;br /&gt;
their address to an IPSet, which will be matched by rules you already&lt;br /&gt;
have established.  Modifying your firewall rules dynamically by a&lt;br /&gt;
script can be a recipe for disaster and it's very difficult to&lt;br /&gt;
thoroughly test all the possible outcomes with a large number of&lt;br /&gt;
modifications.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
# If enabled, this directive will configure&lt;br /&gt;
# all clients to redirect their default&lt;br /&gt;
# network gateway through the VPN, causing&lt;br /&gt;
# all IP traffic such as web browsing and&lt;br /&gt;
# and DNS lookups to go through the VPN&lt;br /&gt;
# (The OpenVPN server machine may need to NAT&lt;br /&gt;
# or bridge the TUN/TAP interface to the internet&lt;br /&gt;
# in order for this to work properly).&lt;br /&gt;
;push &amp;quot;redirect-gateway def1 bypass-dhcp&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Some people want to configure OpenVPN as a proxy for their web&lt;br /&gt;
browsing.  This means all their web browsing traffic will pass out of&lt;br /&gt;
their local network encrypted and be kept out of the prying eyes of&lt;br /&gt;
whoever is watching at their gateway (either their ISP, employer, or&lt;br /&gt;
government).  If you want to configure this, follow the above example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
# Certain Windows-specific network settings&lt;br /&gt;
# can be pushed to clients, such as DNS&lt;br /&gt;
# or WINS server addresses.  CAVEAT:&lt;br /&gt;
# http://openvpn.net/faq.html#dhcpcaveats&lt;br /&gt;
# The addresses below refer to the public&lt;br /&gt;
# DNS servers provided by opendns.com.&lt;br /&gt;
;push &amp;quot;dhcp-option DNS 208.67.222.222&amp;quot;&lt;br /&gt;
;push &amp;quot;dhcp-option DNS 208.67.220.220&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can push any options normally available to any DHCP server.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
# Uncomment this directive to allow different&lt;br /&gt;
# clients to be able to &amp;quot;see&amp;quot; each other.&lt;br /&gt;
# By default, clients will only see the server.&lt;br /&gt;
# To force clients to only see the server, you&lt;br /&gt;
# will also need to appropriately firewall the&lt;br /&gt;
# server's TUN/TAP interface.&lt;br /&gt;
;client-to-client&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Most often, you don't need your clients to talk to each other over&lt;br /&gt;
your tunnel.  Usually they are only laptops or possibly desktop&lt;br /&gt;
computers and are not providing any services of their own to other&lt;br /&gt;
machines.  So you won't forward traffic from one client to another.&lt;br /&gt;
But if you do want to do this, then you need to turn on this&lt;br /&gt;
parameter.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
# Uncomment this directive if multiple clients&lt;br /&gt;
# might connect with the same certificate/key&lt;br /&gt;
# files or common names.  This is recommended&lt;br /&gt;
# only for testing purposes.  For production use,&lt;br /&gt;
# each client should have its own certificate/key&lt;br /&gt;
# pair.&lt;br /&gt;
#&lt;br /&gt;
# IF YOU HAVE NOT GENERATED INDIVIDUAL&lt;br /&gt;
# CERTIFICATE/KEY PAIRS FOR EACH CLIENT,&lt;br /&gt;
# EACH HAVING ITS OWN UNIQUE &amp;quot;COMMON NAME&amp;quot;,&lt;br /&gt;
# UNCOMMENT THIS LINE OUT.&lt;br /&gt;
;duplicate-cn&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Most of the time you should make sure each client has a unique common&lt;br /&gt;
name.  Quite often, the common name of a certificate will just be the&lt;br /&gt;
name of the person using it.  If that person happens to use multiple&lt;br /&gt;
computers, they might use the same name in multiple certificates (or&lt;br /&gt;
worse, use the same certificate across multiple machines -- discourage&lt;br /&gt;
this).  If this happens, then you must turn on this parameter.  Also,&lt;br /&gt;
you will probably not be able to use ipp.txt above.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
# The keepalive directive causes ping-like&lt;br /&gt;
# messages to be sent back and forth over&lt;br /&gt;
# the link so that each side knows when&lt;br /&gt;
# the other side has gone down.&lt;br /&gt;
# Ping every 10 seconds, assume that remote&lt;br /&gt;
# peer is down if no ping received during&lt;br /&gt;
# a 120 second time period.&lt;br /&gt;
keepalive 10 120&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The comments here are pretty self-explanatory.  I think the defaults&lt;br /&gt;
are reasonable.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
# For extra security beyond that provided&lt;br /&gt;
# by SSL/TLS, create an &amp;quot;HMAC firewall&amp;quot;&lt;br /&gt;
# to help block DoS attacks and UDP port flooding.&lt;br /&gt;
#&lt;br /&gt;
# Generate with:&lt;br /&gt;
#   openvpn --genkey --secret ta.key&lt;br /&gt;
#&lt;br /&gt;
# The server and each client must have&lt;br /&gt;
# a copy of this key.&lt;br /&gt;
# The second parameter should be '0'&lt;br /&gt;
# on the server and '1' on the clients.&lt;br /&gt;
;tls-auth ta.key 0 # This file is secret&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I'm not really sure how this is supposed to prevent flooding.  After&lt;br /&gt;
all, you can't control what someone else sends you.  Suffice it to&lt;br /&gt;
say, I haven't used this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
# Select a cryptographic cipher.&lt;br /&gt;
# This config item must be copied to&lt;br /&gt;
# the client config file as well.&lt;br /&gt;
;cipher BF-CBC        # Blowfish (default)&lt;br /&gt;
;cipher AES-128-CBC   # AES&lt;br /&gt;
;cipher DES-EDE3-CBC  # Triple-DES&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There have been a lot of issues concerning OpenSSL recently.  Some&lt;br /&gt;
were specific to the OpenSSL code, but some were just discoveries that&lt;br /&gt;
certain ciphers had weaknesses that weren't discovered previously.  If&lt;br /&gt;
this concerns you, you can discover what ciphers are available using&lt;br /&gt;
the command `openssl ciphers` and picking through the list until you&lt;br /&gt;
find a combination you like.  Make sure all clients are capable of&lt;br /&gt;
using the same one.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
# Enable compression on the VPN link.&lt;br /&gt;
# If you enable it here, you must also&lt;br /&gt;
# enable it in the client config file.&lt;br /&gt;
comp-lzo&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Adding encryption to any traffic means that traffic gets heavier.  You&lt;br /&gt;
have to encode additional data about what you are sending so that the&lt;br /&gt;
other end can properly identify and decode the packets.  This means&lt;br /&gt;
using more bandwidth than a plain text transmission.  To help with&lt;br /&gt;
this, use compression.  This trades CPU time for network time.  In&lt;br /&gt;
this day and age, your CPU is probably much faster than your network,&lt;br /&gt;
so the trade-off advantage should be obvious.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
# The maximum number of concurrently connected&lt;br /&gt;
# clients we want to allow.&lt;br /&gt;
;max-clients 100&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As stated above, in this example we are already limited to 63 clients&lt;br /&gt;
due to the address space we chose.  Honestly, I'm not sure why you&lt;br /&gt;
would want to impose any other form of artificial limitation on your&lt;br /&gt;
clients.  Maybe if your gateway's CPU was just so taxed that 101&lt;br /&gt;
connections was just too much?  Still, the option is there if you want&lt;br /&gt;
it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
# It's a good idea to reduce the OpenVPN&lt;br /&gt;
# daemon's privileges after initialization.&lt;br /&gt;
#&lt;br /&gt;
# You can uncomment this out on&lt;br /&gt;
# non-Windows systems.&lt;br /&gt;
;user nobody&lt;br /&gt;
;group nobody&lt;br /&gt;
user nobody&lt;br /&gt;
group nogroup&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Your distro may have a dedicated openvpn user and group.  I copied&lt;br /&gt;
this example from an installation which did not.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
# The persist options will try to avoid&lt;br /&gt;
# accessing certain resources on restart&lt;br /&gt;
# that may no longer be accessible because&lt;br /&gt;
# of the privilege downgrade.&lt;br /&gt;
persist-key&lt;br /&gt;
persist-tun&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As the comment says, ephemeral keys and tunnel devices might tear down&lt;br /&gt;
across restarts.  In my own experience, these parameters don't make a&lt;br /&gt;
huge difference, but they make restarts a little quicker.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
# Output a short status file showing&lt;br /&gt;
# current connections, truncated&lt;br /&gt;
# and rewritten every minute.&lt;br /&gt;
status /tmp/openvpn-status.log&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This file is just a quick glance at the current state of affairs for&lt;br /&gt;
the VPN server.  I moved it to /tmp so that it would not continuously&lt;br /&gt;
write to flash memory, wearing it out quicker.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
# By default, log messages will go to the syslog (or&lt;br /&gt;
# on Windows, if running as a service, they will go to&lt;br /&gt;
# the &amp;quot;\Program Files\OpenVPN\log&amp;quot; directory).&lt;br /&gt;
# Use log or log-append to override this default.&lt;br /&gt;
# &amp;quot;log&amp;quot; will truncate the log file on OpenVPN startup,&lt;br /&gt;
# while &amp;quot;log-append&amp;quot; will append to it.  Use one&lt;br /&gt;
# or the other (but not both).&lt;br /&gt;
;log         openvpn.log&lt;br /&gt;
;log-append  openvpn.log&lt;br /&gt;
log-append /tmp/openvpn.log&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
My own OpenVPN server is running on a small router.  I chose to write&lt;br /&gt;
to a local log rather than syslog.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
# Set the appropriate level of log&lt;br /&gt;
# file verbosity.&lt;br /&gt;
#&lt;br /&gt;
# 0 is silent, except for fatal errors&lt;br /&gt;
# 4 is reasonable for general usage&lt;br /&gt;
# 5 and 6 can help to debug connection problems&lt;br /&gt;
# 9 is extremely verbose&lt;br /&gt;
verb 3&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the default.  I haven't seen a need to change it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
# Silence repeating messages.  At most 20&lt;br /&gt;
# sequential messages of the same message&lt;br /&gt;
# category will be output to the log.&lt;br /&gt;
;mute 20&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I have never had a reason to change this one.&lt;br /&gt;
&lt;br /&gt;
== Configure Clients ==&lt;br /&gt;
&lt;br /&gt;
Each of the clients can have multiple servers which they connect to.&lt;br /&gt;
For example you might have both an office LAN and a data center you&lt;br /&gt;
regularly log in to.  Or you might be a consultant with multiple&lt;br /&gt;
clients you regularly have to do maintenance for.  For this reason, I&lt;br /&gt;
usually name the client configurations after the servers they connect&lt;br /&gt;
to.  So name this appropriately, home.conf, office.conf, or whatever.&lt;br /&gt;
This time around I have stripped the comments aout of the&lt;br /&gt;
configuration file.  Examples should be available in /usr/share/doc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
client&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tells openvpn that it will be initiating an outbound connection.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
remote gateway.example.com&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When configured as a client, OpenVPN needs to know where to connect.&lt;br /&gt;
Try to use a fully qualified domain name here.  Also, this fully&lt;br /&gt;
qualified domain name needs to be the common name or a subject&lt;br /&gt;
alternative name for the server's certificate.  If the clients must&lt;br /&gt;
use the server's IP address, it must be part of the subject of the&lt;br /&gt;
certificate.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ca ca.crt&lt;br /&gt;
cert client.example-com.crt&lt;br /&gt;
key client.example-com.key&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A separate CA can be used to sign the certificates of both the server&lt;br /&gt;
and the clients.  If you do this, the clients need the CA certificate&lt;br /&gt;
which matches the key that signed the server's certificate, and the&lt;br /&gt;
server needs the CA certificate that matches the key which signs all&lt;br /&gt;
the clients' certificates.&lt;br /&gt;
&lt;br /&gt;
Since a client can connect to multiple servers, I name the local key&lt;br /&gt;
and certificate files after the organization with which they will be&lt;br /&gt;
used.  It is possible to configure multiple servers to authenticate&lt;br /&gt;
certificates signed by the same CA, so clients connecting to multiple&lt;br /&gt;
servers like this will only need one certificate for the whole&lt;br /&gt;
organization.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
dev tun&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, specify to use TUN networking.  This must match the server.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
proto udp&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, specify to use UDP.  This must also match the server.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
nobind&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This says not to specify the source port of the outgoing connection.&lt;br /&gt;
It should not be necessary to do so unless the server is expecting&lt;br /&gt;
only certain source ports.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
persist-key&lt;br /&gt;
persist-tun&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As with the server, this should reduce the amount of time it takes to&lt;br /&gt;
restart the software.  I don't think it will make a huge difference&lt;br /&gt;
for clients, but it doesn't hurt and the example encourages it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
user openvpn&lt;br /&gt;
group openvpn&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specify to run as an unprivileged user.&lt;/div&gt;</description>
			<pubDate>Sun, 21 Feb 2016 22:56:30 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:How_To_Configure_OpenVPN</comments>		</item>
		<item>
			<title>How To Configure OpenVPN</title>
			<link>http://72.14.177.54/SFVLUG/How_To_Configure_OpenVPN</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* TUN And TAP Networking */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Setting up and running OpenVPN is pretty easy.  You just have to&lt;br /&gt;
understand a couple principles and set up the certificates.  So let's&lt;br /&gt;
start with the basics.&lt;br /&gt;
&lt;br /&gt;
== TUN And TAP Networking ==&lt;br /&gt;
&lt;br /&gt;
Running OpenVPN requires you to either set up a TUN or TAP network&lt;br /&gt;
interface.  These are both fairly similar but there is a critical&lt;br /&gt;
difference and I'll try to explain it as best as I can.&lt;br /&gt;
&lt;br /&gt;
You can think of both of these as network interfaces that are attached&lt;br /&gt;
to a program in userspace.  With them, the program is able to interact&lt;br /&gt;
with the rest of the network as if it were its own node on the&lt;br /&gt;
network.  In the case of OpenVPN, this is very useful because it&lt;br /&gt;
allows OpenVPN to send encrypted packets over your real network&lt;br /&gt;
interface, but it encrypts and decrypts packets entering or leaving&lt;br /&gt;
the tun or tap interface.  So OpenVPN gets to manipulate the&lt;br /&gt;
cryptography around the packets on its tun or tap interface and use&lt;br /&gt;
the machine's real interface for sending the packets just like any&lt;br /&gt;
other client or server program.&lt;br /&gt;
&lt;br /&gt;
;TUN&lt;br /&gt;
: A tun interface operates at layer 3.  This means it can encapsulate packets at the IP address layer.  Use a tun interface if you want to route packets between VPN endpoints.  That means both sides of the VPN will use different IP address spaces and use the VPN to route between the two networks.  This tutorial will be using the tun interface.  It is also worth mentioning that OpenBSD only supports tun interfaces.&lt;br /&gt;
;TAP&lt;br /&gt;
: A tap interface operates at layer 2.  This means it can encapsulate entire ethernet frames.  Use a tap interface when you want to bridge packets between VPN endpoints.  That means packets on either side of the VPN will be from the same address space.  Hopefully that will mean you can avoid NAT, if both sides of the VPN have all unique addresses.&lt;br /&gt;
&lt;br /&gt;
== X.509 Certificates ==&lt;br /&gt;
&lt;br /&gt;
We have all heard of SSL certificates.  They are the implementation of&lt;br /&gt;
the X.509 protocol.  Let's look at what we need.&lt;br /&gt;
&lt;br /&gt;
When seting up OpenVPN, I create my own Certificate Authority (CA).&lt;br /&gt;
This is just a self-signed certificate with a very long expiration&lt;br /&gt;
period.  In general, generating any X.509 results in three files.&lt;br /&gt;
First, there is the private key.  This is a secret file which contains&lt;br /&gt;
some important random numbers.  Second, from this file I generate what&lt;br /&gt;
is called a Certificate Signing Request (sometimes a CSR or req file).&lt;br /&gt;
The CSR is an unsigned public key, it contains no secrets.  However,&lt;br /&gt;
it contains the Subject which will identify the user of the&lt;br /&gt;
certificate.  Third, I use the CA to sign the CSR.  This results in a&lt;br /&gt;
Certificate, which is a signed public key.  Certificates also contain&lt;br /&gt;
no secrets.  They are just the CSR which contains the Subject and a&lt;br /&gt;
cryptographic signature generated using the CA's key to make a special&lt;br /&gt;
checksum.  The idea is, instead of sharing your public key with&lt;br /&gt;
everyone you want to communicate, every participant only needs a copy&lt;br /&gt;
of the CA's public key or Certificate.  Each participant can validate&lt;br /&gt;
the signature of any certificate any other participant tries to share.&lt;br /&gt;
&lt;br /&gt;
;Key&lt;br /&gt;
: Private key&lt;br /&gt;
;CSR&lt;br /&gt;
: Unsigned public key&lt;br /&gt;
;Cert&lt;br /&gt;
: Signed public key&lt;br /&gt;
&lt;br /&gt;
== Installing OpenVPN ==&lt;br /&gt;
&lt;br /&gt;
I am going to assume that you will be using the precompiled package of&lt;br /&gt;
OpenVPN which every distro provides.  I see no good reason to compile&lt;br /&gt;
it from source.&lt;br /&gt;
&lt;br /&gt;
We are going to configure OpenVPN with one server and multiple&lt;br /&gt;
road-warrior style clients.  This just means that the server will&lt;br /&gt;
always have the same IP address, or at least DNS name, and will always&lt;br /&gt;
be on, and that the clients will come and go as they please and won't&lt;br /&gt;
have the same IP addresses or DNS names.&lt;br /&gt;
&lt;br /&gt;
The server is going to provide routing to its entire network.  Let's&lt;br /&gt;
assume the server is the gateway to a LAN, and that LAN's IP space is&lt;br /&gt;
192.168.1.0/24, and the router which runs OpenVPN has the address&lt;br /&gt;
192.168.1.1.  Since we are using TUN networking, we need to use an&lt;br /&gt;
interim network to route over.  Let's use 172.16.1.0/24 for this&lt;br /&gt;
space.  OpenVPN is actually going to break this space down into&lt;br /&gt;
multiple slash-30 networks, each containing four addresses -- two&lt;br /&gt;
usable, one network address and one broadcast address -- and it will&lt;br /&gt;
use up the first of these so in reality we will have room for only 63&lt;br /&gt;
clients in this scenario.  The first client to connect gets a network&lt;br /&gt;
that looks like this:&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|| 172.16.1.4 || network&lt;br /&gt;
|-&lt;br /&gt;
|| 172.16.1.5 || server&lt;br /&gt;
|-&lt;br /&gt;
|| 172.16.1.6 || client&lt;br /&gt;
|-&lt;br /&gt;
|| 172.16.1.7 || broadcast&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The clients won't necessarily provide routing to their networks so&lt;br /&gt;
this means they are participating in a one-to-many VPN.  Therefore we&lt;br /&gt;
don't care what the network space our clients are in is, so long as it&lt;br /&gt;
is possible to cleanly route to the server's network.  That means no&lt;br /&gt;
IP conflicts in the two networks.  It is possible to create a&lt;br /&gt;
many-to-many VPN with OpenVPN, but we just won't be doing that in this&lt;br /&gt;
example.&lt;br /&gt;
&lt;br /&gt;
== Configure The Server ==&lt;br /&gt;
&lt;br /&gt;
Every installation of OpenVPN I have installed (on Linux) has always&lt;br /&gt;
used /etc/openvpn to store the configuration.  On Windows or MacOS it&lt;br /&gt;
is wherever you installed it, and on FreeBSD and OpenBSD it's &lt;br /&gt;
/usr/local/etc/openvpn.  We'll start with the server configuration&lt;br /&gt;
file.  For the server I left all the comments in the file.  There are&lt;br /&gt;
example configuration files in /usr/share/doc.  Create the following&lt;br /&gt;
as /etc/openvpn/server.conf:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
# Which local IP address should OpenVPN&lt;br /&gt;
# listen on? (optional)&lt;br /&gt;
;local a.b.c.d&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is probably not necessary to specify a particular address to listen&lt;br /&gt;
on.  Only use this if you definitely don't want OpenVPN to listen on&lt;br /&gt;
every address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# Which TCP/UDP port should OpenVPN listen on?&lt;br /&gt;
# If you want to run multiple OpenVPN instances&lt;br /&gt;
# on the same machine, use a different port&lt;br /&gt;
# number for each one.  You will need to&lt;br /&gt;
# open up this port on your firewall.&lt;br /&gt;
port 1194&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Port 1194 is the registered port for OpenVPN.  In actual practice, I&lt;br /&gt;
have never noticed any significant attempts to crack or otherwise&lt;br /&gt;
abuse the default port out on the wild Internet.  There are probably&lt;br /&gt;
two reasons for this.  First, since UDP is a connectionless protocol,&lt;br /&gt;
it's impossible to tell if the port is open or filtered using normal&lt;br /&gt;
port-scanning like nmap.  And second, since authentication is via&lt;br /&gt;
X.509 certificates which are typically thousands of bits, the&lt;br /&gt;
likelihood of successfully guessing the correct signature to gain&lt;br /&gt;
access is astronomically near impossible.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# TCP or UDP server?&lt;br /&gt;
;proto tcp&lt;br /&gt;
proto udp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Use UDP for your VPN.  Tunneling TCP over TCP can be less reliable.&lt;br /&gt;
As previously stated, it's impossible to differentiate an open and a&lt;br /&gt;
filtered UDP port.  And the connection-oriented nature of TCP doesn't&lt;br /&gt;
actually buy you anything in this situation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;quot;dev tun&amp;quot; will create a routed IP tunnel,&lt;br /&gt;
# &amp;quot;dev tap&amp;quot; will create an ethernet tunnel.&lt;br /&gt;
# Use &amp;quot;dev tap0&amp;quot; if you are ethernet bridging&lt;br /&gt;
# and have precreated a tap0 virtual interface&lt;br /&gt;
# and bridged it with your ethernet interface.&lt;br /&gt;
# If you want to control access policies&lt;br /&gt;
# over the VPN, you must create firewall&lt;br /&gt;
# rules for the the TUN/TAP interface.&lt;br /&gt;
# On non-Windows systems, you can give&lt;br /&gt;
# an explicit unit number, such as tun0.&lt;br /&gt;
# On Windows, use &amp;quot;dev-node&amp;quot; for this.&lt;br /&gt;
# On most systems, the VPN will not function&lt;br /&gt;
# unless you partially or fully disable&lt;br /&gt;
# the firewall for the TUN/TAP interface.&lt;br /&gt;
;dev tap&lt;br /&gt;
dev tun&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As stated previously, we're using TUN networking for this example.&lt;br /&gt;
The comment mentions firewalls, and we'll cover iptables a little&lt;br /&gt;
later.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# Windows needs the TAP-Win32 adapter name&lt;br /&gt;
# from the Network Connections panel if you&lt;br /&gt;
# have more than one.  On XP SP2 or higher,&lt;br /&gt;
# you may need to selectively disable the&lt;br /&gt;
# Windows firewall for the TAP adapter.&lt;br /&gt;
# Non-Windows systems usually don't need this.&lt;br /&gt;
;dev-node MyTap&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The preceding section should be irrelevant unless you're using&lt;br /&gt;
Windows.  Running Windows as a server is just stupid; using it as a&lt;br /&gt;
gateway just makes no sense at all.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# SSL/TLS root certificate (ca), certificate&lt;br /&gt;
# (cert), and private key (key).  Each client&lt;br /&gt;
# and the server must have their own cert and&lt;br /&gt;
# key file.  The server and all clients will&lt;br /&gt;
# use the same ca file.&lt;br /&gt;
#&lt;br /&gt;
# See the &amp;quot;easy-rsa&amp;quot; directory for a series&lt;br /&gt;
# of scripts for generating RSA certificates&lt;br /&gt;
# and private keys.  Remember to use&lt;br /&gt;
# a unique Common Name for the server&lt;br /&gt;
# and each of the client certificates.&lt;br /&gt;
#&lt;br /&gt;
# Any X509 key management system can be used.&lt;br /&gt;
# OpenVPN can also use a PKCS #12 formatted key file&lt;br /&gt;
# (see &amp;quot;pkcs12&amp;quot; directive in man page).&lt;br /&gt;
ca ca.crt&lt;br /&gt;
cert server.crt&lt;br /&gt;
key server.key  # This file should be kept secret&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All files are going to be relative to the configuration file&lt;br /&gt;
unless otherwise qualified.  Generating each of these will be covered&lt;br /&gt;
below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# Diffie hellman parameters.&lt;br /&gt;
# Generate your own with:&lt;br /&gt;
#   openssl dhparam -out dh2048.pem 2048&lt;br /&gt;
dh dh2048.pem&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The server should include a Diffie-Hellman parameter.  Use the command&lt;br /&gt;
shown above to generate it.  This file improves security and makes the&lt;br /&gt;
tunnel harder to decrypt.  Generating a Diffie-Hellman parameter is&lt;br /&gt;
very time consuming; it can take several minutes to generate a&lt;br /&gt;
two-thousand bit parameter.  Be patient, it is not worth generating a&lt;br /&gt;
weak parameter file just to save a little time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# Network topology&lt;br /&gt;
# Should be subnet (addressing via IP)&lt;br /&gt;
# unless Windows clients v2.0.9 and lower have to&lt;br /&gt;
# be supported (then net30, i.e. a /30 per client)&lt;br /&gt;
# Defaults to net30 (not recommended)&lt;br /&gt;
;topology subnet&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As stated, this parameter shouldn't be necessary unless you have to&lt;br /&gt;
support outdated Windows software.  OpenVPN is open source, just&lt;br /&gt;
download a more recent copy why don'tcha?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# Configure server mode and supply a VPN subnet&lt;br /&gt;
# for OpenVPN to draw client addresses from.&lt;br /&gt;
# The server will take 10.8.0.1 for itself,&lt;br /&gt;
# the rest will be made available to clients.&lt;br /&gt;
# Each client will be able to reach the server&lt;br /&gt;
# on 10.8.0.1. Comment this line out if you are&lt;br /&gt;
# ethernet bridging. See the man page for more info.&lt;br /&gt;
;;server 10.8.0.0 255.255.255.0&lt;br /&gt;
server 172.16.1.0 255.255.255.0&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is where we configure the pool of addresses which will be used by&lt;br /&gt;
the client-to-server connections as illustrated above.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# Maintain a record of client &amp;lt;-&amp;gt; virtual IP address&lt;br /&gt;
# associations in this file.  If OpenVPN goes down or&lt;br /&gt;
# is restarted, reconnecting clients can be assigned&lt;br /&gt;
# the same virtual IP address from the pool that was&lt;br /&gt;
# previously assigned.&lt;br /&gt;
ifconfig-pool-persist ipp.txt&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you include the above parameter, then each client will get the same&lt;br /&gt;
IP address from the server pool above each time it reconnects.  You&lt;br /&gt;
can take advantage of this to implement client-specific firewall&lt;br /&gt;
rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# Configure server mode for ethernet bridging.&lt;br /&gt;
# You must first use your OS's bridging capability&lt;br /&gt;
# to bridge the TAP interface with the ethernet&lt;br /&gt;
# NIC interface.  Then you must manually set the&lt;br /&gt;
# IP/netmask on the bridge interface, here we&lt;br /&gt;
# assume 10.8.0.4/255.255.255.0.  Finally we&lt;br /&gt;
# must set aside an IP range in this subnet&lt;br /&gt;
# (start=10.8.0.50 end=10.8.0.100) to allocate&lt;br /&gt;
# to connecting clients.  Leave this line commented&lt;br /&gt;
# out unless you are ethernet bridging.&lt;br /&gt;
;server-bridge 10.8.0.4 255.255.255.0 10.8.0.50 10.8.0.100&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You would only need to use this parameter if you are using a TAP&lt;br /&gt;
interface and bridging your networks.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# Configure server mode for ethernet bridging&lt;br /&gt;
# using a DHCP-proxy, where clients talk&lt;br /&gt;
# to the OpenVPN server-side DHCP server&lt;br /&gt;
# to receive their IP address allocation&lt;br /&gt;
# and DNS server addresses.  You must first use&lt;br /&gt;
# your OS's bridging capability to bridge the TAP&lt;br /&gt;
# interface with the ethernet NIC interface.&lt;br /&gt;
# Note: this mode only works on clients (such as&lt;br /&gt;
# Windows), where the client-side TAP adapter is&lt;br /&gt;
# bound to a DHCP client.&lt;br /&gt;
;server-bridge&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, this parameter is TAP networking and bridge specific.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# Push routes to the client to allow it&lt;br /&gt;
# to reach other private subnets behind&lt;br /&gt;
# the server.  Remember that these&lt;br /&gt;
# private subnets will also need&lt;br /&gt;
# to know to route the OpenVPN client&lt;br /&gt;
# address pool (10.8.0.0/255.255.255.0)&lt;br /&gt;
# back to the OpenVPN server.&lt;br /&gt;
;push &amp;quot;route 192.168.10.0 255.255.255.0&amp;quot;&lt;br /&gt;
;push &amp;quot;route 192.168.20.0 255.255.255.0&amp;quot;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If your OpenVPN server is a gateway to multiple subnets, you can push&lt;br /&gt;
additional routes to the clients.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# To assign specific IP addresses to specific&lt;br /&gt;
# clients or if a connecting client has a private&lt;br /&gt;
# subnet behind it that should also have VPN access,&lt;br /&gt;
# use the subdirectory &amp;quot;ccd&amp;quot; for client-specific&lt;br /&gt;
# configuration files (see man page for more info).&lt;br /&gt;
&lt;br /&gt;
# EXAMPLE: Suppose the client&lt;br /&gt;
# having the certificate common name &amp;quot;Thelonious&amp;quot;&lt;br /&gt;
# also has a small subnet behind his connecting&lt;br /&gt;
# machine, such as 192.168.40.128/255.255.255.248.&lt;br /&gt;
# First, uncomment out these lines:&lt;br /&gt;
;client-config-dir ccd&lt;br /&gt;
;route 192.168.40.128 255.255.255.248&lt;br /&gt;
# Then create a file ccd/Thelonious with this line:&lt;br /&gt;
#   iroute 192.168.40.128 255.255.255.248&lt;br /&gt;
# This will allow Thelonious' private subnet to&lt;br /&gt;
# access the VPN.  This example will only work&lt;br /&gt;
# if you are routing, not bridging, i.e. you are&lt;br /&gt;
# using &amp;quot;dev tun&amp;quot; and &amp;quot;server&amp;quot; directives.&lt;br /&gt;
&lt;br /&gt;
# EXAMPLE: Suppose you want to give&lt;br /&gt;
# Thelonious a fixed VPN IP address of 10.9.0.1.&lt;br /&gt;
# First uncomment out these lines:&lt;br /&gt;
;client-config-dir ccd&lt;br /&gt;
;route 10.9.0.0 255.255.255.252&lt;br /&gt;
# Then add this line to ccd/Thelonious:&lt;br /&gt;
#   ifconfig-push 10.9.0.1 10.9.0.2&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All of the above examples are to give a particular host specific&lt;br /&gt;
configurations.  In a simple scenario such as ours, it is not&lt;br /&gt;
necessary.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# Suppose that you want to enable different&lt;br /&gt;
# firewall access policies for different groups&lt;br /&gt;
# of clients.  There are two methods:&lt;br /&gt;
# (1) Run multiple OpenVPN daemons, one for each&lt;br /&gt;
#     group, and firewall the TUN/TAP interface&lt;br /&gt;
#     for each group/daemon appropriately.&lt;br /&gt;
# (2) (Advanced) Create a script to dynamically&lt;br /&gt;
#     modify the firewall in response to access&lt;br /&gt;
#     from different clients.  See man&lt;br /&gt;
#     page for more info on learn-address script.&lt;br /&gt;
;learn-address ./script&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As the comments state, if you want to modify your firewall each time a&lt;br /&gt;
particular client connects, in some particular way, then you could use&lt;br /&gt;
a script to do it.  Personally, I think you should have your firewall&lt;br /&gt;
rules pre-set and use the above ipp.txt file to assign the client the&lt;br /&gt;
expected address.  If you have more clients than your IP pool allows&lt;br /&gt;
to assign each of them a separate address, then use this script to add&lt;br /&gt;
their address to an IPSet, which will be matched by rules you already&lt;br /&gt;
have established.  Modifying your firewall rules dynamically by a&lt;br /&gt;
script can be a recipe for disaster and it's very difficult to&lt;br /&gt;
thoroughly test all the possible outcomes with a large number of&lt;br /&gt;
modifications.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# If enabled, this directive will configure&lt;br /&gt;
# all clients to redirect their default&lt;br /&gt;
# network gateway through the VPN, causing&lt;br /&gt;
# all IP traffic such as web browsing and&lt;br /&gt;
# and DNS lookups to go through the VPN&lt;br /&gt;
# (The OpenVPN server machine may need to NAT&lt;br /&gt;
# or bridge the TUN/TAP interface to the internet&lt;br /&gt;
# in order for this to work properly).&lt;br /&gt;
;push &amp;quot;redirect-gateway def1 bypass-dhcp&amp;quot;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Some people want to configure OpenVPN as a proxy for their web&lt;br /&gt;
browsing.  This means all their web browsing traffic will pass out of&lt;br /&gt;
their local network encrypted and be kept out of the prying eyes of&lt;br /&gt;
whoever is watching at their gateway (either their ISP, employer, or&lt;br /&gt;
government).  If you want to configure this, follow the above example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# Certain Windows-specific network settings&lt;br /&gt;
# can be pushed to clients, such as DNS&lt;br /&gt;
# or WINS server addresses.  CAVEAT:&lt;br /&gt;
# http://openvpn.net/faq.html#dhcpcaveats&lt;br /&gt;
# The addresses below refer to the public&lt;br /&gt;
# DNS servers provided by opendns.com.&lt;br /&gt;
;push &amp;quot;dhcp-option DNS 208.67.222.222&amp;quot;&lt;br /&gt;
;push &amp;quot;dhcp-option DNS 208.67.220.220&amp;quot;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can push any options normally available to any DHCP server.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# Uncomment this directive to allow different&lt;br /&gt;
# clients to be able to &amp;quot;see&amp;quot; each other.&lt;br /&gt;
# By default, clients will only see the server.&lt;br /&gt;
# To force clients to only see the server, you&lt;br /&gt;
# will also need to appropriately firewall the&lt;br /&gt;
# server's TUN/TAP interface.&lt;br /&gt;
;client-to-client&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Most often, you don't need your clients to talk to each other over&lt;br /&gt;
your tunnel.  Usually they are only laptops or possibly desktop&lt;br /&gt;
computers and are not providing any services of their own to other&lt;br /&gt;
machines.  So you won't forward traffic from one client to another.&lt;br /&gt;
But if you do want to do this, then you need to turn on this&lt;br /&gt;
parameter.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# Uncomment this directive if multiple clients&lt;br /&gt;
# might connect with the same certificate/key&lt;br /&gt;
# files or common names.  This is recommended&lt;br /&gt;
# only for testing purposes.  For production use,&lt;br /&gt;
# each client should have its own certificate/key&lt;br /&gt;
# pair.&lt;br /&gt;
#&lt;br /&gt;
# IF YOU HAVE NOT GENERATED INDIVIDUAL&lt;br /&gt;
# CERTIFICATE/KEY PAIRS FOR EACH CLIENT,&lt;br /&gt;
# EACH HAVING ITS OWN UNIQUE &amp;quot;COMMON NAME&amp;quot;,&lt;br /&gt;
# UNCOMMENT THIS LINE OUT.&lt;br /&gt;
;duplicate-cn&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Most of the time you should make sure each client has a unique common&lt;br /&gt;
name.  Quite often, the common name of a certificate will just be the&lt;br /&gt;
name of the person using it.  If that person happens to use multiple&lt;br /&gt;
computers, they might use the same name in multiple certificates (or&lt;br /&gt;
worse, use the same certificate across multiple machines -- discourage&lt;br /&gt;
this).  If this happens, then you must turn on this parameter.  Also,&lt;br /&gt;
you will probably not be able to use ipp.txt above.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# The keepalive directive causes ping-like&lt;br /&gt;
# messages to be sent back and forth over&lt;br /&gt;
# the link so that each side knows when&lt;br /&gt;
# the other side has gone down.&lt;br /&gt;
# Ping every 10 seconds, assume that remote&lt;br /&gt;
# peer is down if no ping received during&lt;br /&gt;
# a 120 second time period.&lt;br /&gt;
keepalive 10 120&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The comments here are pretty self-explanatory.  I think the defaults&lt;br /&gt;
are reasonable.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# For extra security beyond that provided&lt;br /&gt;
# by SSL/TLS, create an &amp;quot;HMAC firewall&amp;quot;&lt;br /&gt;
# to help block DoS attacks and UDP port flooding.&lt;br /&gt;
#&lt;br /&gt;
# Generate with:&lt;br /&gt;
#   openvpn --genkey --secret ta.key&lt;br /&gt;
#&lt;br /&gt;
# The server and each client must have&lt;br /&gt;
# a copy of this key.&lt;br /&gt;
# The second parameter should be '0'&lt;br /&gt;
# on the server and '1' on the clients.&lt;br /&gt;
;tls-auth ta.key 0 # This file is secret&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I'm not really sure how this is supposed to prevent flooding.  After&lt;br /&gt;
all, you can't control what someone else sends you.  Suffice it to&lt;br /&gt;
say, I haven't used this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# Select a cryptographic cipher.&lt;br /&gt;
# This config item must be copied to&lt;br /&gt;
# the client config file as well.&lt;br /&gt;
;cipher BF-CBC        # Blowfish (default)&lt;br /&gt;
;cipher AES-128-CBC   # AES&lt;br /&gt;
;cipher DES-EDE3-CBC  # Triple-DES&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There have been a lot of issues concerning OpenSSL recently.  Some&lt;br /&gt;
were specific to the OpenSSL code, but some were just discoveries that&lt;br /&gt;
certain ciphers had weaknesses that weren't discovered previously.  If&lt;br /&gt;
this concerns you, you can discover what ciphers are available using&lt;br /&gt;
the command `openssl ciphers` and picking through the list until you&lt;br /&gt;
find a combination you like.  Make sure all clients are capable of&lt;br /&gt;
using the same one.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# Enable compression on the VPN link.&lt;br /&gt;
# If you enable it here, you must also&lt;br /&gt;
# enable it in the client config file.&lt;br /&gt;
comp-lzo&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Adding encryption to any traffic means that traffic gets heavier.  You&lt;br /&gt;
have to encode additional data about what you are sending so that the&lt;br /&gt;
other end can properly identify and decode the packets.  This means&lt;br /&gt;
using more bandwidth than a plain text transmission.  To help with&lt;br /&gt;
this, use compression.  This trades CPU time for network time.  In&lt;br /&gt;
this day and age, your CPU is probably much faster than your network,&lt;br /&gt;
so the trade-off advantage should be obvious.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# The maximum number of concurrently connected&lt;br /&gt;
# clients we want to allow.&lt;br /&gt;
;max-clients 100&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As stated above, in this example we are already limited to 63 clients&lt;br /&gt;
due to the address space we chose.  Honestly, I'm not sure why you&lt;br /&gt;
would want to impose any other form of artificial limitation on your&lt;br /&gt;
clients.  Maybe if your gateway's CPU was just so taxed that 101&lt;br /&gt;
connections was just too much?  Still, the option is there if you want&lt;br /&gt;
it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# It's a good idea to reduce the OpenVPN&lt;br /&gt;
# daemon's privileges after initialization.&lt;br /&gt;
#&lt;br /&gt;
# You can uncomment this out on&lt;br /&gt;
# non-Windows systems.&lt;br /&gt;
;user nobody&lt;br /&gt;
;group nobody&lt;br /&gt;
user nobody&lt;br /&gt;
group nogroup&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Your distro may have a dedicated openvpn user and group.  I copied&lt;br /&gt;
this example from an installation which did not.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# The persist options will try to avoid&lt;br /&gt;
# accessing certain resources on restart&lt;br /&gt;
# that may no longer be accessible because&lt;br /&gt;
# of the privilege downgrade.&lt;br /&gt;
persist-key&lt;br /&gt;
persist-tun&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As the comment says, ephemeral keys and tunnel devices might tear down&lt;br /&gt;
across restarts.  In my own experience, these parameters don't make a&lt;br /&gt;
huge difference, but they make restarts a little quicker.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# Output a short status file showing&lt;br /&gt;
# current connections, truncated&lt;br /&gt;
# and rewritten every minute.&lt;br /&gt;
status /tmp/openvpn-status.log&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This file is just a quick glance at the current state of affairs for&lt;br /&gt;
the VPN server.  I moved it to /tmp so that it would not continuously&lt;br /&gt;
write to flash memory, wearing it out quicker.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# By default, log messages will go to the syslog (or&lt;br /&gt;
# on Windows, if running as a service, they will go to&lt;br /&gt;
# the &amp;quot;\Program Files\OpenVPN\log&amp;quot; directory).&lt;br /&gt;
# Use log or log-append to override this default.&lt;br /&gt;
# &amp;quot;log&amp;quot; will truncate the log file on OpenVPN startup,&lt;br /&gt;
# while &amp;quot;log-append&amp;quot; will append to it.  Use one&lt;br /&gt;
# or the other (but not both).&lt;br /&gt;
;log         openvpn.log&lt;br /&gt;
;log-append  openvpn.log&lt;br /&gt;
log-append /tmp/openvpn.log&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
My own OpenVPN server is running on a small router.  I chose to write&lt;br /&gt;
to a local log rather than syslog.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# Set the appropriate level of log&lt;br /&gt;
# file verbosity.&lt;br /&gt;
#&lt;br /&gt;
# 0 is silent, except for fatal errors&lt;br /&gt;
# 4 is reasonable for general usage&lt;br /&gt;
# 5 and 6 can help to debug connection problems&lt;br /&gt;
# 9 is extremely verbose&lt;br /&gt;
verb 3&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the default.  I haven't seen a need to change it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# Silence repeating messages.  At most 20&lt;br /&gt;
# sequential messages of the same message&lt;br /&gt;
# category will be output to the log.&lt;br /&gt;
;mute 20&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I have never had a reason to change this one.&lt;br /&gt;
&lt;br /&gt;
== Configure Clients ==&lt;br /&gt;
&lt;br /&gt;
Each of the clients can have multiple servers which they connect to.&lt;br /&gt;
For example you might have both an office LAN and a data center you&lt;br /&gt;
regularly log in to.  Or you might be a consultant with multiple&lt;br /&gt;
clients you regularly have to do maintenance for.  For this reason, I&lt;br /&gt;
usually name the client configurations after the servers they connect&lt;br /&gt;
to.  So name this appropriately, home.conf, office.conf, or whatever.&lt;br /&gt;
This time around I have stripped the comments aout of the&lt;br /&gt;
configuration file.  Examples should be available in /usr/share/doc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
client&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tells openvpn that it will be initiating an outbound connection.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
remote gateway.example.com&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When configured as a client, OpenVPN needs to know where to connect.&lt;br /&gt;
Try to use a fully qualified domain name here.  Also, this fully&lt;br /&gt;
qualified domain name needs to be the common name or a subject&lt;br /&gt;
alternative name for the server's certificate.  If the clients must&lt;br /&gt;
use the server's IP address, it must be part of the subject of the&lt;br /&gt;
certificate.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ca ca.crt&lt;br /&gt;
cert client.example-com.crt&lt;br /&gt;
key client.example-com.key&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A separate CA can be used to sign the certificates of both the server&lt;br /&gt;
and the clients.  If you do this, the clients need the CA certificate&lt;br /&gt;
which matches the key that signed the server's certificate, and the&lt;br /&gt;
server needs the CA certificate that matches the key which signs all&lt;br /&gt;
the clients' certificates.&lt;br /&gt;
&lt;br /&gt;
Since a client can connect to multiple servers, I name the local key&lt;br /&gt;
and certificate files after the organization with which they will be&lt;br /&gt;
used.  It is possible to configure multiple servers to authenticate&lt;br /&gt;
certificates signed by the same CA, so clients connecting to multiple&lt;br /&gt;
servers like this will only need one certificate for the whole&lt;br /&gt;
organization.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
dev tun&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, specify to use TUN networking.  This must match the server.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
proto udp&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, specify to use UDP.  This must also match the server.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
nobind&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This says not to specify the source port of the outgoing connection.&lt;br /&gt;
It should not be necessary to do so unless the server is expecting&lt;br /&gt;
only certain source ports.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
persist-key&lt;br /&gt;
persist-tun&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As with the server, this should reduce the amount of time it takes to&lt;br /&gt;
restart the software.  I don't think it will make a huge difference&lt;br /&gt;
for clients, but it doesn't hurt and the example encourages it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
user openvpn&lt;br /&gt;
group openvpn&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specify to run as an unprivileged user.&lt;/div&gt;</description>
			<pubDate>Sun, 21 Feb 2016 21:38:26 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:How_To_Configure_OpenVPN</comments>		</item>
		<item>
			<title>How To Configure OpenVPN</title>
			<link>http://72.14.177.54/SFVLUG/How_To_Configure_OpenVPN</link>
			<description>&lt;p&gt;Jeff:&amp;#32;Created page with 'Setting up and running OpenVPN is pretty easy.  You just have to understand a couple principles and set up the certificates.  So let's start with the basics.  == TUN And TAP Netw…'&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Setting up and running OpenVPN is pretty easy.  You just have to&lt;br /&gt;
understand a couple principles and set up the certificates.  So let's&lt;br /&gt;
start with the basics.&lt;br /&gt;
&lt;br /&gt;
== TUN And TAP Networking ==&lt;br /&gt;
&lt;br /&gt;
Running OpenVPN requires you to either set up a TUN or TAP network&lt;br /&gt;
interface.  These are both fairly similar but there is a critical&lt;br /&gt;
difference and I'll try to explain it as best as I can.&lt;br /&gt;
&lt;br /&gt;
You can think of both of these as network interfaces that are attached&lt;br /&gt;
to a program in userspace.  With them, the program is able to interact&lt;br /&gt;
with the rest of the network as if it were its own node on the&lt;br /&gt;
network.  In the case of OpenVPN, this is very useful because it&lt;br /&gt;
allows OpenVPN to send encrypted packets over your real network&lt;br /&gt;
interface, but it encrypts and decrypts packets entering or leaving&lt;br /&gt;
the tun or tap interface.  So OpenVPN gets to manipulate the&lt;br /&gt;
cryptography around the packets on its tun or tap interface and use&lt;br /&gt;
the machine's real interface for sending the packets just like any&lt;br /&gt;
other client or server program.&lt;br /&gt;
&lt;br /&gt;
;TUN&lt;br /&gt;
: A tun interface operates at layer 3.  This means it can encapsulate packets at the IP address layer.  Use a tun inter\&lt;br /&gt;
face if you want to route packets between VPN endpoints.  That means both sides of the VPN will use different IP addres\&lt;br /&gt;
s spaces and use the VPN to route between the two networks.  This tutorial will be using the tun interface.  It is also\&lt;br /&gt;
 worth mentioning that OpenBSD only supports tun interfaces.&lt;br /&gt;
;TAP&lt;br /&gt;
: A tap interface operates at layer 2.  This means it can encapsulate entire ethernet frames.  Use a tap interface when\&lt;br /&gt;
 you want to bridge packets between VPN endpoints.  That means packets on either side of the VPN will be from the same \&lt;br /&gt;
address space.  Hopefully that will mean you can avoid NAT, if both sides of the VPN have all unique addresses.&lt;br /&gt;
&lt;br /&gt;
== X.509 Certificates ==&lt;br /&gt;
&lt;br /&gt;
We have all heard of SSL certificates.  They are the implementation of&lt;br /&gt;
the X.509 protocol.  Let's look at what we need.&lt;br /&gt;
&lt;br /&gt;
When seting up OpenVPN, I create my own Certificate Authority (CA).&lt;br /&gt;
This is just a self-signed certificate with a very long expiration&lt;br /&gt;
period.  In general, generating any X.509 results in three files.&lt;br /&gt;
First, there is the private key.  This is a secret file which contains&lt;br /&gt;
some important random numbers.  Second, from this file I generate what&lt;br /&gt;
is called a Certificate Signing Request (sometimes a CSR or req file).&lt;br /&gt;
The CSR is an unsigned public key, it contains no secrets.  However,&lt;br /&gt;
it contains the Subject which will identify the user of the&lt;br /&gt;
certificate.  Third, I use the CA to sign the CSR.  This results in a&lt;br /&gt;
Certificate, which is a signed public key.  Certificates also contain&lt;br /&gt;
no secrets.  They are just the CSR which contains the Subject and a&lt;br /&gt;
cryptographic signature generated using the CA's key to make a special&lt;br /&gt;
checksum.  The idea is, instead of sharing your public key with&lt;br /&gt;
everyone you want to communicate, every participant only needs a copy&lt;br /&gt;
of the CA's public key or Certificate.  Each participant can validate&lt;br /&gt;
the signature of any certificate any other participant tries to share.&lt;br /&gt;
&lt;br /&gt;
;Key&lt;br /&gt;
: Private key&lt;br /&gt;
;CSR&lt;br /&gt;
: Unsigned public key&lt;br /&gt;
;Cert&lt;br /&gt;
: Signed public key&lt;br /&gt;
&lt;br /&gt;
== Installing OpenVPN ==&lt;br /&gt;
&lt;br /&gt;
I am going to assume that you will be using the precompiled package of&lt;br /&gt;
OpenVPN which every distro provides.  I see no good reason to compile&lt;br /&gt;
it from source.&lt;br /&gt;
&lt;br /&gt;
We are going to configure OpenVPN with one server and multiple&lt;br /&gt;
road-warrior style clients.  This just means that the server will&lt;br /&gt;
always have the same IP address, or at least DNS name, and will always&lt;br /&gt;
be on, and that the clients will come and go as they please and won't&lt;br /&gt;
have the same IP addresses or DNS names.&lt;br /&gt;
&lt;br /&gt;
The server is going to provide routing to its entire network.  Let's&lt;br /&gt;
assume the server is the gateway to a LAN, and that LAN's IP space is&lt;br /&gt;
192.168.1.0/24, and the router which runs OpenVPN has the address&lt;br /&gt;
192.168.1.1.  Since we are using TUN networking, we need to use an&lt;br /&gt;
interim network to route over.  Let's use 172.16.1.0/24 for this&lt;br /&gt;
space.  OpenVPN is actually going to break this space down into&lt;br /&gt;
multiple slash-30 networks, each containing four addresses -- two&lt;br /&gt;
usable, one network address and one broadcast address -- and it will&lt;br /&gt;
use up the first of these so in reality we will have room for only 63&lt;br /&gt;
clients in this scenario.  The first client to connect gets a network&lt;br /&gt;
that looks like this:&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|| 172.16.1.4 || network&lt;br /&gt;
|-&lt;br /&gt;
|| 172.16.1.5 || server&lt;br /&gt;
|-&lt;br /&gt;
|| 172.16.1.6 || client&lt;br /&gt;
|-&lt;br /&gt;
|| 172.16.1.7 || broadcast&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The clients won't necessarily provide routing to their networks so&lt;br /&gt;
this means they are participating in a one-to-many VPN.  Therefore we&lt;br /&gt;
don't care what the network space our clients are in is, so long as it&lt;br /&gt;
is possible to cleanly route to the server's network.  That means no&lt;br /&gt;
IP conflicts in the two networks.  It is possible to create a&lt;br /&gt;
many-to-many VPN with OpenVPN, but we just won't be doing that in this&lt;br /&gt;
example.&lt;br /&gt;
&lt;br /&gt;
== Configure The Server ==&lt;br /&gt;
&lt;br /&gt;
Every installation of OpenVPN I have installed (on Linux) has always&lt;br /&gt;
used /etc/openvpn to store the configuration.  On Windows or MacOS it&lt;br /&gt;
is wherever you installed it, and on FreeBSD and OpenBSD it's &lt;br /&gt;
/usr/local/etc/openvpn.  We'll start with the server configuration&lt;br /&gt;
file.  For the server I left all the comments in the file.  There are&lt;br /&gt;
example configuration files in /usr/share/doc.  Create the following&lt;br /&gt;
as /etc/openvpn/server.conf:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
# Which local IP address should OpenVPN&lt;br /&gt;
# listen on? (optional)&lt;br /&gt;
;local a.b.c.d&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is probably not necessary to specify a particular address to listen&lt;br /&gt;
on.  Only use this if you definitely don't want OpenVPN to listen on&lt;br /&gt;
every address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# Which TCP/UDP port should OpenVPN listen on?&lt;br /&gt;
# If you want to run multiple OpenVPN instances&lt;br /&gt;
# on the same machine, use a different port&lt;br /&gt;
# number for each one.  You will need to&lt;br /&gt;
# open up this port on your firewall.&lt;br /&gt;
port 1194&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Port 1194 is the registered port for OpenVPN.  In actual practice, I&lt;br /&gt;
have never noticed any significant attempts to crack or otherwise&lt;br /&gt;
abuse the default port out on the wild Internet.  There are probably&lt;br /&gt;
two reasons for this.  First, since UDP is a connectionless protocol,&lt;br /&gt;
it's impossible to tell if the port is open or filtered using normal&lt;br /&gt;
port-scanning like nmap.  And second, since authentication is via&lt;br /&gt;
X.509 certificates which are typically thousands of bits, the&lt;br /&gt;
likelihood of successfully guessing the correct signature to gain&lt;br /&gt;
access is astronomically near impossible.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# TCP or UDP server?&lt;br /&gt;
;proto tcp&lt;br /&gt;
proto udp&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Use UDP for your VPN.  Tunneling TCP over TCP can be less reliable.&lt;br /&gt;
As previously stated, it's impossible to differentiate an open and a&lt;br /&gt;
filtered UDP port.  And the connection-oriented nature of TCP doesn't&lt;br /&gt;
actually buy you anything in this situation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;quot;dev tun&amp;quot; will create a routed IP tunnel,&lt;br /&gt;
# &amp;quot;dev tap&amp;quot; will create an ethernet tunnel.&lt;br /&gt;
# Use &amp;quot;dev tap0&amp;quot; if you are ethernet bridging&lt;br /&gt;
# and have precreated a tap0 virtual interface&lt;br /&gt;
# and bridged it with your ethernet interface.&lt;br /&gt;
# If you want to control access policies&lt;br /&gt;
# over the VPN, you must create firewall&lt;br /&gt;
# rules for the the TUN/TAP interface.&lt;br /&gt;
# On non-Windows systems, you can give&lt;br /&gt;
# an explicit unit number, such as tun0.&lt;br /&gt;
# On Windows, use &amp;quot;dev-node&amp;quot; for this.&lt;br /&gt;
# On most systems, the VPN will not function&lt;br /&gt;
# unless you partially or fully disable&lt;br /&gt;
# the firewall for the TUN/TAP interface.&lt;br /&gt;
;dev tap&lt;br /&gt;
dev tun&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As stated previously, we're using TUN networking for this example.&lt;br /&gt;
The comment mentions firewalls, and we'll cover iptables a little&lt;br /&gt;
later.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# Windows needs the TAP-Win32 adapter name&lt;br /&gt;
# from the Network Connections panel if you&lt;br /&gt;
# have more than one.  On XP SP2 or higher,&lt;br /&gt;
# you may need to selectively disable the&lt;br /&gt;
# Windows firewall for the TAP adapter.&lt;br /&gt;
# Non-Windows systems usually don't need this.&lt;br /&gt;
;dev-node MyTap&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The preceding section should be irrelevant unless you're using&lt;br /&gt;
Windows.  Running Windows as a server is just stupid; using it as a&lt;br /&gt;
gateway just makes no sense at all.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# SSL/TLS root certificate (ca), certificate&lt;br /&gt;
# (cert), and private key (key).  Each client&lt;br /&gt;
# and the server must have their own cert and&lt;br /&gt;
# key file.  The server and all clients will&lt;br /&gt;
# use the same ca file.&lt;br /&gt;
#&lt;br /&gt;
# See the &amp;quot;easy-rsa&amp;quot; directory for a series&lt;br /&gt;
# of scripts for generating RSA certificates&lt;br /&gt;
# and private keys.  Remember to use&lt;br /&gt;
# a unique Common Name for the server&lt;br /&gt;
# and each of the client certificates.&lt;br /&gt;
#&lt;br /&gt;
# Any X509 key management system can be used.&lt;br /&gt;
# OpenVPN can also use a PKCS #12 formatted key file&lt;br /&gt;
# (see &amp;quot;pkcs12&amp;quot; directive in man page).&lt;br /&gt;
ca ca.crt&lt;br /&gt;
cert server.crt&lt;br /&gt;
key server.key  # This file should be kept secret&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All files are going to be relative to the configuration file&lt;br /&gt;
unless otherwise qualified.  Generating each of these will be covered&lt;br /&gt;
below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# Diffie hellman parameters.&lt;br /&gt;
# Generate your own with:&lt;br /&gt;
#   openssl dhparam -out dh2048.pem 2048&lt;br /&gt;
dh dh2048.pem&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The server should include a Diffie-Hellman parameter.  Use the command&lt;br /&gt;
shown above to generate it.  This file improves security and makes the&lt;br /&gt;
tunnel harder to decrypt.  Generating a Diffie-Hellman parameter is&lt;br /&gt;
very time consuming; it can take several minutes to generate a&lt;br /&gt;
two-thousand bit parameter.  Be patient, it is not worth generating a&lt;br /&gt;
weak parameter file just to save a little time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# Network topology&lt;br /&gt;
# Should be subnet (addressing via IP)&lt;br /&gt;
# unless Windows clients v2.0.9 and lower have to&lt;br /&gt;
# be supported (then net30, i.e. a /30 per client)&lt;br /&gt;
# Defaults to net30 (not recommended)&lt;br /&gt;
;topology subnet&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As stated, this parameter shouldn't be necessary unless you have to&lt;br /&gt;
support outdated Windows software.  OpenVPN is open source, just&lt;br /&gt;
download a more recent copy why don'tcha?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# Configure server mode and supply a VPN subnet&lt;br /&gt;
# for OpenVPN to draw client addresses from.&lt;br /&gt;
# The server will take 10.8.0.1 for itself,&lt;br /&gt;
# the rest will be made available to clients.&lt;br /&gt;
# Each client will be able to reach the server&lt;br /&gt;
# on 10.8.0.1. Comment this line out if you are&lt;br /&gt;
# ethernet bridging. See the man page for more info.&lt;br /&gt;
;;server 10.8.0.0 255.255.255.0&lt;br /&gt;
server 172.16.1.0 255.255.255.0&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is where we configure the pool of addresses which will be used by&lt;br /&gt;
the client-to-server connections as illustrated above.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# Maintain a record of client &amp;lt;-&amp;gt; virtual IP address&lt;br /&gt;
# associations in this file.  If OpenVPN goes down or&lt;br /&gt;
# is restarted, reconnecting clients can be assigned&lt;br /&gt;
# the same virtual IP address from the pool that was&lt;br /&gt;
# previously assigned.&lt;br /&gt;
ifconfig-pool-persist ipp.txt&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you include the above parameter, then each client will get the same&lt;br /&gt;
IP address from the server pool above each time it reconnects.  You&lt;br /&gt;
can take advantage of this to implement client-specific firewall&lt;br /&gt;
rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# Configure server mode for ethernet bridging.&lt;br /&gt;
# You must first use your OS's bridging capability&lt;br /&gt;
# to bridge the TAP interface with the ethernet&lt;br /&gt;
# NIC interface.  Then you must manually set the&lt;br /&gt;
# IP/netmask on the bridge interface, here we&lt;br /&gt;
# assume 10.8.0.4/255.255.255.0.  Finally we&lt;br /&gt;
# must set aside an IP range in this subnet&lt;br /&gt;
# (start=10.8.0.50 end=10.8.0.100) to allocate&lt;br /&gt;
# to connecting clients.  Leave this line commented&lt;br /&gt;
# out unless you are ethernet bridging.&lt;br /&gt;
;server-bridge 10.8.0.4 255.255.255.0 10.8.0.50 10.8.0.100&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You would only need to use this parameter if you are using a TAP&lt;br /&gt;
interface and bridging your networks.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# Configure server mode for ethernet bridging&lt;br /&gt;
# using a DHCP-proxy, where clients talk&lt;br /&gt;
# to the OpenVPN server-side DHCP server&lt;br /&gt;
# to receive their IP address allocation&lt;br /&gt;
# and DNS server addresses.  You must first use&lt;br /&gt;
# your OS's bridging capability to bridge the TAP&lt;br /&gt;
# interface with the ethernet NIC interface.&lt;br /&gt;
# Note: this mode only works on clients (such as&lt;br /&gt;
# Windows), where the client-side TAP adapter is&lt;br /&gt;
# bound to a DHCP client.&lt;br /&gt;
;server-bridge&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, this parameter is TAP networking and bridge specific.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# Push routes to the client to allow it&lt;br /&gt;
# to reach other private subnets behind&lt;br /&gt;
# the server.  Remember that these&lt;br /&gt;
# private subnets will also need&lt;br /&gt;
# to know to route the OpenVPN client&lt;br /&gt;
# address pool (10.8.0.0/255.255.255.0)&lt;br /&gt;
# back to the OpenVPN server.&lt;br /&gt;
;push &amp;quot;route 192.168.10.0 255.255.255.0&amp;quot;&lt;br /&gt;
;push &amp;quot;route 192.168.20.0 255.255.255.0&amp;quot;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If your OpenVPN server is a gateway to multiple subnets, you can push&lt;br /&gt;
additional routes to the clients.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# To assign specific IP addresses to specific&lt;br /&gt;
# clients or if a connecting client has a private&lt;br /&gt;
# subnet behind it that should also have VPN access,&lt;br /&gt;
# use the subdirectory &amp;quot;ccd&amp;quot; for client-specific&lt;br /&gt;
# configuration files (see man page for more info).&lt;br /&gt;
&lt;br /&gt;
# EXAMPLE: Suppose the client&lt;br /&gt;
# having the certificate common name &amp;quot;Thelonious&amp;quot;&lt;br /&gt;
# also has a small subnet behind his connecting&lt;br /&gt;
# machine, such as 192.168.40.128/255.255.255.248.&lt;br /&gt;
# First, uncomment out these lines:&lt;br /&gt;
;client-config-dir ccd&lt;br /&gt;
;route 192.168.40.128 255.255.255.248&lt;br /&gt;
# Then create a file ccd/Thelonious with this line:&lt;br /&gt;
#   iroute 192.168.40.128 255.255.255.248&lt;br /&gt;
# This will allow Thelonious' private subnet to&lt;br /&gt;
# access the VPN.  This example will only work&lt;br /&gt;
# if you are routing, not bridging, i.e. you are&lt;br /&gt;
# using &amp;quot;dev tun&amp;quot; and &amp;quot;server&amp;quot; directives.&lt;br /&gt;
&lt;br /&gt;
# EXAMPLE: Suppose you want to give&lt;br /&gt;
# Thelonious a fixed VPN IP address of 10.9.0.1.&lt;br /&gt;
# First uncomment out these lines:&lt;br /&gt;
;client-config-dir ccd&lt;br /&gt;
;route 10.9.0.0 255.255.255.252&lt;br /&gt;
# Then add this line to ccd/Thelonious:&lt;br /&gt;
#   ifconfig-push 10.9.0.1 10.9.0.2&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All of the above examples are to give a particular host specific&lt;br /&gt;
configurations.  In a simple scenario such as ours, it is not&lt;br /&gt;
necessary.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# Suppose that you want to enable different&lt;br /&gt;
# firewall access policies for different groups&lt;br /&gt;
# of clients.  There are two methods:&lt;br /&gt;
# (1) Run multiple OpenVPN daemons, one for each&lt;br /&gt;
#     group, and firewall the TUN/TAP interface&lt;br /&gt;
#     for each group/daemon appropriately.&lt;br /&gt;
# (2) (Advanced) Create a script to dynamically&lt;br /&gt;
#     modify the firewall in response to access&lt;br /&gt;
#     from different clients.  See man&lt;br /&gt;
#     page for more info on learn-address script.&lt;br /&gt;
;learn-address ./script&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As the comments state, if you want to modify your firewall each time a&lt;br /&gt;
particular client connects, in some particular way, then you could use&lt;br /&gt;
a script to do it.  Personally, I think you should have your firewall&lt;br /&gt;
rules pre-set and use the above ipp.txt file to assign the client the&lt;br /&gt;
expected address.  If you have more clients than your IP pool allows&lt;br /&gt;
to assign each of them a separate address, then use this script to add&lt;br /&gt;
their address to an IPSet, which will be matched by rules you already&lt;br /&gt;
have established.  Modifying your firewall rules dynamically by a&lt;br /&gt;
script can be a recipe for disaster and it's very difficult to&lt;br /&gt;
thoroughly test all the possible outcomes with a large number of&lt;br /&gt;
modifications.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# If enabled, this directive will configure&lt;br /&gt;
# all clients to redirect their default&lt;br /&gt;
# network gateway through the VPN, causing&lt;br /&gt;
# all IP traffic such as web browsing and&lt;br /&gt;
# and DNS lookups to go through the VPN&lt;br /&gt;
# (The OpenVPN server machine may need to NAT&lt;br /&gt;
# or bridge the TUN/TAP interface to the internet&lt;br /&gt;
# in order for this to work properly).&lt;br /&gt;
;push &amp;quot;redirect-gateway def1 bypass-dhcp&amp;quot;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Some people want to configure OpenVPN as a proxy for their web&lt;br /&gt;
browsing.  This means all their web browsing traffic will pass out of&lt;br /&gt;
their local network encrypted and be kept out of the prying eyes of&lt;br /&gt;
whoever is watching at their gateway (either their ISP, employer, or&lt;br /&gt;
government).  If you want to configure this, follow the above example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# Certain Windows-specific network settings&lt;br /&gt;
# can be pushed to clients, such as DNS&lt;br /&gt;
# or WINS server addresses.  CAVEAT:&lt;br /&gt;
# http://openvpn.net/faq.html#dhcpcaveats&lt;br /&gt;
# The addresses below refer to the public&lt;br /&gt;
# DNS servers provided by opendns.com.&lt;br /&gt;
;push &amp;quot;dhcp-option DNS 208.67.222.222&amp;quot;&lt;br /&gt;
;push &amp;quot;dhcp-option DNS 208.67.220.220&amp;quot;&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can push any options normally available to any DHCP server.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# Uncomment this directive to allow different&lt;br /&gt;
# clients to be able to &amp;quot;see&amp;quot; each other.&lt;br /&gt;
# By default, clients will only see the server.&lt;br /&gt;
# To force clients to only see the server, you&lt;br /&gt;
# will also need to appropriately firewall the&lt;br /&gt;
# server's TUN/TAP interface.&lt;br /&gt;
;client-to-client&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Most often, you don't need your clients to talk to each other over&lt;br /&gt;
your tunnel.  Usually they are only laptops or possibly desktop&lt;br /&gt;
computers and are not providing any services of their own to other&lt;br /&gt;
machines.  So you won't forward traffic from one client to another.&lt;br /&gt;
But if you do want to do this, then you need to turn on this&lt;br /&gt;
parameter.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# Uncomment this directive if multiple clients&lt;br /&gt;
# might connect with the same certificate/key&lt;br /&gt;
# files or common names.  This is recommended&lt;br /&gt;
# only for testing purposes.  For production use,&lt;br /&gt;
# each client should have its own certificate/key&lt;br /&gt;
# pair.&lt;br /&gt;
#&lt;br /&gt;
# IF YOU HAVE NOT GENERATED INDIVIDUAL&lt;br /&gt;
# CERTIFICATE/KEY PAIRS FOR EACH CLIENT,&lt;br /&gt;
# EACH HAVING ITS OWN UNIQUE &amp;quot;COMMON NAME&amp;quot;,&lt;br /&gt;
# UNCOMMENT THIS LINE OUT.&lt;br /&gt;
;duplicate-cn&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Most of the time you should make sure each client has a unique common&lt;br /&gt;
name.  Quite often, the common name of a certificate will just be the&lt;br /&gt;
name of the person using it.  If that person happens to use multiple&lt;br /&gt;
computers, they might use the same name in multiple certificates (or&lt;br /&gt;
worse, use the same certificate across multiple machines -- discourage&lt;br /&gt;
this).  If this happens, then you must turn on this parameter.  Also,&lt;br /&gt;
you will probably not be able to use ipp.txt above.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# The keepalive directive causes ping-like&lt;br /&gt;
# messages to be sent back and forth over&lt;br /&gt;
# the link so that each side knows when&lt;br /&gt;
# the other side has gone down.&lt;br /&gt;
# Ping every 10 seconds, assume that remote&lt;br /&gt;
# peer is down if no ping received during&lt;br /&gt;
# a 120 second time period.&lt;br /&gt;
keepalive 10 120&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The comments here are pretty self-explanatory.  I think the defaults&lt;br /&gt;
are reasonable.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# For extra security beyond that provided&lt;br /&gt;
# by SSL/TLS, create an &amp;quot;HMAC firewall&amp;quot;&lt;br /&gt;
# to help block DoS attacks and UDP port flooding.&lt;br /&gt;
#&lt;br /&gt;
# Generate with:&lt;br /&gt;
#   openvpn --genkey --secret ta.key&lt;br /&gt;
#&lt;br /&gt;
# The server and each client must have&lt;br /&gt;
# a copy of this key.&lt;br /&gt;
# The second parameter should be '0'&lt;br /&gt;
# on the server and '1' on the clients.&lt;br /&gt;
;tls-auth ta.key 0 # This file is secret&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I'm not really sure how this is supposed to prevent flooding.  After&lt;br /&gt;
all, you can't control what someone else sends you.  Suffice it to&lt;br /&gt;
say, I haven't used this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# Select a cryptographic cipher.&lt;br /&gt;
# This config item must be copied to&lt;br /&gt;
# the client config file as well.&lt;br /&gt;
;cipher BF-CBC        # Blowfish (default)&lt;br /&gt;
;cipher AES-128-CBC   # AES&lt;br /&gt;
;cipher DES-EDE3-CBC  # Triple-DES&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There have been a lot of issues concerning OpenSSL recently.  Some&lt;br /&gt;
were specific to the OpenSSL code, but some were just discoveries that&lt;br /&gt;
certain ciphers had weaknesses that weren't discovered previously.  If&lt;br /&gt;
this concerns you, you can discover what ciphers are available using&lt;br /&gt;
the command `openssl ciphers` and picking through the list until you&lt;br /&gt;
find a combination you like.  Make sure all clients are capable of&lt;br /&gt;
using the same one.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# Enable compression on the VPN link.&lt;br /&gt;
# If you enable it here, you must also&lt;br /&gt;
# enable it in the client config file.&lt;br /&gt;
comp-lzo&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Adding encryption to any traffic means that traffic gets heavier.  You&lt;br /&gt;
have to encode additional data about what you are sending so that the&lt;br /&gt;
other end can properly identify and decode the packets.  This means&lt;br /&gt;
using more bandwidth than a plain text transmission.  To help with&lt;br /&gt;
this, use compression.  This trades CPU time for network time.  In&lt;br /&gt;
this day and age, your CPU is probably much faster than your network,&lt;br /&gt;
so the trade-off advantage should be obvious.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# The maximum number of concurrently connected&lt;br /&gt;
# clients we want to allow.&lt;br /&gt;
;max-clients 100&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As stated above, in this example we are already limited to 63 clients&lt;br /&gt;
due to the address space we chose.  Honestly, I'm not sure why you&lt;br /&gt;
would want to impose any other form of artificial limitation on your&lt;br /&gt;
clients.  Maybe if your gateway's CPU was just so taxed that 101&lt;br /&gt;
connections was just too much?  Still, the option is there if you want&lt;br /&gt;
it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# It's a good idea to reduce the OpenVPN&lt;br /&gt;
# daemon's privileges after initialization.&lt;br /&gt;
#&lt;br /&gt;
# You can uncomment this out on&lt;br /&gt;
# non-Windows systems.&lt;br /&gt;
;user nobody&lt;br /&gt;
;group nobody&lt;br /&gt;
user nobody&lt;br /&gt;
group nogroup&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Your distro may have a dedicated openvpn user and group.  I copied&lt;br /&gt;
this example from an installation which did not.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# The persist options will try to avoid&lt;br /&gt;
# accessing certain resources on restart&lt;br /&gt;
# that may no longer be accessible because&lt;br /&gt;
# of the privilege downgrade.&lt;br /&gt;
persist-key&lt;br /&gt;
persist-tun&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As the comment says, ephemeral keys and tunnel devices might tear down&lt;br /&gt;
across restarts.  In my own experience, these parameters don't make a&lt;br /&gt;
huge difference, but they make restarts a little quicker.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# Output a short status file showing&lt;br /&gt;
# current connections, truncated&lt;br /&gt;
# and rewritten every minute.&lt;br /&gt;
status /tmp/openvpn-status.log&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This file is just a quick glance at the current state of affairs for&lt;br /&gt;
the VPN server.  I moved it to /tmp so that it would not continuously&lt;br /&gt;
write to flash memory, wearing it out quicker.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# By default, log messages will go to the syslog (or&lt;br /&gt;
# on Windows, if running as a service, they will go to&lt;br /&gt;
# the &amp;quot;\Program Files\OpenVPN\log&amp;quot; directory).&lt;br /&gt;
# Use log or log-append to override this default.&lt;br /&gt;
# &amp;quot;log&amp;quot; will truncate the log file on OpenVPN startup,&lt;br /&gt;
# while &amp;quot;log-append&amp;quot; will append to it.  Use one&lt;br /&gt;
# or the other (but not both).&lt;br /&gt;
;log         openvpn.log&lt;br /&gt;
;log-append  openvpn.log&lt;br /&gt;
log-append /tmp/openvpn.log&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
My own OpenVPN server is running on a small router.  I chose to write&lt;br /&gt;
to a local log rather than syslog.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# Set the appropriate level of log&lt;br /&gt;
# file verbosity.&lt;br /&gt;
#&lt;br /&gt;
# 0 is silent, except for fatal errors&lt;br /&gt;
# 4 is reasonable for general usage&lt;br /&gt;
# 5 and 6 can help to debug connection problems&lt;br /&gt;
# 9 is extremely verbose&lt;br /&gt;
verb 3&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the default.  I haven't seen a need to change it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
# Silence repeating messages.  At most 20&lt;br /&gt;
# sequential messages of the same message&lt;br /&gt;
# category will be output to the log.&lt;br /&gt;
;mute 20&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I have never had a reason to change this one.&lt;br /&gt;
&lt;br /&gt;
== Configure Clients ==&lt;br /&gt;
&lt;br /&gt;
Each of the clients can have multiple servers which they connect to.&lt;br /&gt;
For example you might have both an office LAN and a data center you&lt;br /&gt;
regularly log in to.  Or you might be a consultant with multiple&lt;br /&gt;
clients you regularly have to do maintenance for.  For this reason, I&lt;br /&gt;
usually name the client configurations after the servers they connect&lt;br /&gt;
to.  So name this appropriately, home.conf, office.conf, or whatever.&lt;br /&gt;
This time around I have stripped the comments aout of the&lt;br /&gt;
configuration file.  Examples should be available in /usr/share/doc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
client&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This tells openvpn that it will be initiating an outbound connection.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
remote gateway.example.com&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When configured as a client, OpenVPN needs to know where to connect.&lt;br /&gt;
Try to use a fully qualified domain name here.  Also, this fully&lt;br /&gt;
qualified domain name needs to be the common name or a subject&lt;br /&gt;
alternative name for the server's certificate.  If the clients must&lt;br /&gt;
use the server's IP address, it must be part of the subject of the&lt;br /&gt;
certificate.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ca ca.crt&lt;br /&gt;
cert client.example-com.crt&lt;br /&gt;
key client.example-com.key&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A separate CA can be used to sign the certificates of both the server&lt;br /&gt;
and the clients.  If you do this, the clients need the CA certificate&lt;br /&gt;
which matches the key that signed the server's certificate, and the&lt;br /&gt;
server needs the CA certificate that matches the key which signs all&lt;br /&gt;
the clients' certificates.&lt;br /&gt;
&lt;br /&gt;
Since a client can connect to multiple servers, I name the local key&lt;br /&gt;
and certificate files after the organization with which they will be&lt;br /&gt;
used.  It is possible to configure multiple servers to authenticate&lt;br /&gt;
certificates signed by the same CA, so clients connecting to multiple&lt;br /&gt;
servers like this will only need one certificate for the whole&lt;br /&gt;
organization.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
dev tun&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, specify to use TUN networking.  This must match the server.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
proto udp&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, specify to use UDP.  This must also match the server.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
nobind&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This says not to specify the source port of the outgoing connection.&lt;br /&gt;
It should not be necessary to do so unless the server is expecting&lt;br /&gt;
only certain source ports.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
persist-key&lt;br /&gt;
persist-tun&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As with the server, this should reduce the amount of time it takes to&lt;br /&gt;
restart the software.  I don't think it will make a huge difference&lt;br /&gt;
for clients, but it doesn't hurt and the example encourages it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
user openvpn&lt;br /&gt;
group openvpn&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specify to run as an unprivileged user.&lt;/div&gt;</description>
			<pubDate>Sun, 21 Feb 2016 21:36:07 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:How_To_Configure_OpenVPN</comments>		</item>
		<item>
			<title>User:Jeff</title>
			<link>http://72.14.177.54/SFVLUG/User:Jeff</link>
			<description>&lt;p&gt;Jeff:&amp;#32;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==About Me==&lt;br /&gt;
&lt;br /&gt;
I am Jeff Carlson. I am a Systems Administrator by profession, geek by nature, and Linux advocate by choice. But I must be frank, Linux is only part of my technical passion. I am also very big on other open source operating systems (like the BSDs and OpenSolaris), and just Unix (like Irix and HP-UX) and its kin in general.&lt;br /&gt;
&lt;br /&gt;
I speak Bourne shell and Perl pretty fluently. I've also been known to whip up some pretty useful sed and awk from time to time. My understanding of C is rudimentary but accountable. Quite honestly, I have no love of Java and a reputation of the same.&lt;br /&gt;
&lt;br /&gt;
My weapons of choice are as follows. Fedora is my distro. Gnome (2.x or Mate) is my desktop. Emacs is my editor. Firefox is my browser. Thunderbird is my email client. I choose xchat for IRC but Pidgin for everything else. I love Apache HTTPD. I know sendmail like the back of my hand. I'm also quite handy with Cyrus IMAP. I have done an awful lot of work with OpenLDAP and MySQL. I also use the ISC's BIND and DHCPD quite often. My favorite virtualization technology is still Xen, but qemu and kvm are pretty cool as well.&lt;br /&gt;
&lt;br /&gt;
Additionally I'm proficient with these. I've done a lot with Linux Netfilter, iptables, and its related projects. I have worked a lot with OpenSSH. I'm pretty good with OpenSSL. I've also set up OpenS/WAN and (back when there was one) FreeS/WAN, and also OpenVPN. Since this is covering security tools, I'll mention nmap as well as Snort and ACID. I'm a big fan of SELinux. A couple of my favorite sysadmin tools are cfengine and Nagios.&lt;br /&gt;
&lt;br /&gt;
Lately I have been interested in embedded Linux. I have been playing with uClibc, busybox, dnsmasq, and dropbear a bit.&lt;br /&gt;
&lt;br /&gt;
I would be happy to answer any questions about any of these. I have given a number of presentations on some of them, and I plan to do more as well as include some notes on many of these topics here on this wiki.&lt;br /&gt;
&lt;br /&gt;
As well as being a member of SFVLUG, I am also a contributor to the Fedora Project, and a staff member of SCALE.&lt;br /&gt;
&lt;br /&gt;
==Notes On==&lt;br /&gt;
&lt;br /&gt;
* [[DD-WRT on Airlink 101 AR430W]]&lt;br /&gt;
* [[NotesOnQuotas|Filesystem Quotas]]&lt;br /&gt;
* [[NFS and the Automounter]]&lt;br /&gt;
* [[NotesOnOpenLDAP|OpenLDAP]]&lt;br /&gt;
* [[OpenSSH Power Tutorial]]&lt;br /&gt;
* [[OpenSSL Certificate Authority]]&lt;br /&gt;
* [[NetBSD as a Xen domU]]&lt;br /&gt;
* [[Mini-How-To Turn My Laptop Into A Wifi Access Point]]&lt;br /&gt;
* [[Get On IPv6 Right Now]]&lt;br /&gt;
* [[Securing SSH with tcp_wrappers]]&lt;br /&gt;
* [[OpenSolaris as a Xen domU]]&lt;br /&gt;
* [[OpenBSD as a Xen domU]]&lt;br /&gt;
* [[Build a VPN using only OpenSSH]]&lt;br /&gt;
* [[Make Your Own Bootable Thumbdrive with Buildroot]]&lt;br /&gt;
* [[Things You Should Know About Netfilter]]&lt;br /&gt;
* [[How To Configure OpenVPN]]&lt;/div&gt;</description>
			<pubDate>Sun, 21 Feb 2016 21:21:55 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/User_talk:Jeff</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Using ipsets */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Loopback is more than just 127.0.0.1 ==&lt;br /&gt;
&lt;br /&gt;
It seems that a lot of people believe that when a packet is sent to the address assigned to a node's own interface, that packet really goes to that interface.  This is not true, and how could it be?  An interface's job is to put that packet on the wire.  If the packet is addressed to the same machine that sent it, where would it go?  That's the exact job of the loopback interface.&lt;br /&gt;
&lt;br /&gt;
Observe based on the following example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# ip -4 addr ls eth0&lt;br /&gt;
2: eth0: &amp;amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;amp;gt; mtu 1500 qdisc pfifo_fast state UP qlen 1000&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; inet 192.168.1.21/24 brd 192.168.1.255 scope global eth0&lt;br /&gt;
# ip route get 192.168.1.21&lt;br /&gt;
local 192.168.1.21 dev lo  src 192.168.1.21 &lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; cache &amp;amp;lt;local&amp;amp;gt;  mtu 16436 advmss 16396 hoplimit 64&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can see here that packets sent to this machine's own address will be routed on the lo device, or the loopback interface, even though the destination address was not 127.0.0.1.&lt;br /&gt;
&lt;br /&gt;
On the other hand, 127.0.0.1 is always the loopback interface.  In fact, all of 127.0.0.0/8 will always route to the loopback interface.  It is quite difficult to assign an address in this range to any other interface.  Likewise, you should encounter quite a bit of difficulty trying to send a packet to 127.0.0.0/8 on any interface other than lo.&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || 1     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || 2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
: 1 - Older versions of the kernel and iptables did not provide the &amp;lt;tt&amp;gt;nat/INPUT&amp;lt;/tt&amp;gt; hook.  Check your documentation.&lt;br /&gt;
: 2 - &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; will only be available if you installed the [http://xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is simply not tested, which is the same as if it were tested and resulted in a TRUE match.  For example, if you don't specify a protocol, then the rule matches packets of any protocol.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tcp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.  You could also specify a netmask of 255.255.255.1 and match all the even or odd addresses in a group of 256.  If you pass a comma-separated list of addresses to &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; will expand the line into multiple rules.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT -s 10.0.0.3,10.0.0.7,10.0.0.19 -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
results in:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT -s 10.0.0.3 -j DROP&lt;br /&gt;
-A INPUT -s 10.0.0.7 -j DROP&lt;br /&gt;
-A INPUT -s 10.0.0.19 -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, notice that we started this ruleset by allowing unlimited traffic on the loopback interface.  But of particular interest is that these rules do not mention the 127.0.0.1 address.  Why not?  Because the loopback interface is used by more than just the 127.0.0.1 address.  In fact, any time you send traffic from the machine to itself, on any IP, it is handled on the loopback interface.  Think about it, how would the computer send packets up to the ethernet adapter, but not actually onto the ethernet cable?  It can't, but it can use the loopback interface instead.&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for default chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Just what is a good scenario in which to use a custom chain?  Whenever you are segregating some portion of your traffic with a common criterion which doesn't apply to the vast majority of unrelated packets.  For example, here is my custom chain for staving off the onslaught of SSH brute force attackers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:SSH-Throttle -&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --set&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --update --seconds 5 --hitcount 2 -j DROP&lt;br /&gt;
-A SSH-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 22 -m conntrack --ctstate NEW -j SSH-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There you have it.  Three rules which don't need to test the protocol, port, or connection tracking state, because this is already done for them by the rule that sent the packets there.&lt;br /&gt;
&lt;br /&gt;
Additionally, here is my custom chain for blocking FTP abusers.  It limits login attempts to ten per minute and sessions to one per source IP.  It also throws some unexpected errors, so programs like hydra get confused and give up after a very short time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:FTP-Throttle -&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --set&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --update --seconds 60 --hitcount 10 -j DROP&lt;br /&gt;
-A FTP-Throttle -m connlimit --connlimit-above 1 -j REJECT --reject-with icmp-admin-prohibited&lt;br /&gt;
-A FTP-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 21 -m conntrack --ctstate NEW -j FTP-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== The Importance Of Organization ==&lt;br /&gt;
&lt;br /&gt;
From all zeros, to all ones, across 32 bits, there are 33 netmasks usable in IPv4 networking.  The ones are always on the left, and the zeros are always on the right.  That's it, 33.  When we line up the bits in a host address with the bits in the netmask, the bits that line up with the ones are the network portion of the address, and the bits that line up with the zeros are the host portion.  The address within the network where all the host bits are zeros (the first address in the network) is the network address.  The address within the network where all the host bits are ones (the last address in the network) is the broadcast address.  When we write a netmask as slash-some-number, like /24, we mean twenty-four ones on the left, and eight zeros on the right.  For every bit you add to the netmask, the size of the network is divided in half.&lt;br /&gt;
&lt;br /&gt;
Now that you understand how to do the math involved in calculating netmasks, network addresses, and broadcast addresses, let's examine how to plan your network.  Let's say you have been given 192.0.2.0/24 as your network allocation.  How are you going to assign addresses to web servers, mail servers, DNS servers, and the like?&lt;br /&gt;
&lt;br /&gt;
The fewer &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules you have, the faster packets will traverse your firewall.  Granted, a single rule takes only microseconds to process, but also your rules will be easier to read if the set is shorter.  So it is beneficial to reduce your rules as much as possible.  And a well planned network will make it easier to reduce your overall rules.&lt;br /&gt;
&lt;br /&gt;
We can divide our network into two /25 networks:  The network addresses will be 192.0.2.0/25 and 192.0.2.128/25.  We can subdivide again into four /26 networks, the last octet will then be 0, 64, 128, and 192.  Keep in mind, we have been allocated all of 192.0.2.0/24, so that's the space that will be routed to us, so we don't need to reserve multiple network and broadcast addresses, we can just use those points as borders between segments.&lt;br /&gt;
&lt;br /&gt;
If we host a lot of commercial web sites, we probably want to provide a lot of our IPs for web hosting.  If we divide up our allocation into four /26 segments, we can cover the two middle allocations with two rules, allowing us 128 web sites.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.64/26  -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.128/26 -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's much better than 128 individual rules allowing web traffic to individual addresses.  Below, we'll also examine how to reduce our rules even further, permitting disparate service allocations in only one rule.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,mark&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:mac&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; and hardly a handful of &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3260,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3260,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3260,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Sat, 01 Aug 2015 07:18:17 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Using ipsets */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Loopback is more than just 127.0.0.1 ==&lt;br /&gt;
&lt;br /&gt;
It seems that a lot of people believe that when a packet is sent to the address assigned to a node's own interface, that packet really goes to that interface.  This is not true, and how could it be?  An interface's job is to put that packet on the wire.  If the packet is addressed to the same machine that sent it, where would it go?  That's the exact job of the loopback interface.&lt;br /&gt;
&lt;br /&gt;
Observe based on the following example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# ip -4 addr ls eth0&lt;br /&gt;
2: eth0: &amp;amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;amp;gt; mtu 1500 qdisc pfifo_fast state UP qlen 1000&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; inet 192.168.1.21/24 brd 192.168.1.255 scope global eth0&lt;br /&gt;
# ip route get 192.168.1.21&lt;br /&gt;
local 192.168.1.21 dev lo  src 192.168.1.21 &lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; cache &amp;amp;lt;local&amp;amp;gt;  mtu 16436 advmss 16396 hoplimit 64&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can see here that packets sent to this machine's own address will be routed on the lo device, or the loopback interface, even though the destination address was not 127.0.0.1.&lt;br /&gt;
&lt;br /&gt;
On the other hand, 127.0.0.1 is always the loopback interface.  In fact, all of 127.0.0.0/8 will always route to the loopback interface.  It is quite difficult to assign an address in this range to any other interface.  Likewise, you should encounter quite a bit of difficulty trying to send a packet to 127.0.0.0/8 on any interface other than lo.&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || 1     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || 2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
: 1 - Older versions of the kernel and iptables did not provide the &amp;lt;tt&amp;gt;nat/INPUT&amp;lt;/tt&amp;gt; hook.  Check your documentation.&lt;br /&gt;
: 2 - &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; will only be available if you installed the [http://xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is simply not tested, which is the same as if it were tested and resulted in a TRUE match.  For example, if you don't specify a protocol, then the rule matches packets of any protocol.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tcp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.  You could also specify a netmask of 255.255.255.1 and match all the even or odd addresses in a group of 256.  If you pass a comma-separated list of addresses to &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; will expand the line into multiple rules.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT -s 10.0.0.3,10.0.0.7,10.0.0.19 -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
results in:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT -s 10.0.0.3 -j DROP&lt;br /&gt;
-A INPUT -s 10.0.0.7 -j DROP&lt;br /&gt;
-A INPUT -s 10.0.0.19 -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, notice that we started this ruleset by allowing unlimited traffic on the loopback interface.  But of particular interest is that these rules do not mention the 127.0.0.1 address.  Why not?  Because the loopback interface is used by more than just the 127.0.0.1 address.  In fact, any time you send traffic from the machine to itself, on any IP, it is handled on the loopback interface.  Think about it, how would the computer send packets up to the ethernet adapter, but not actually onto the ethernet cable?  It can't, but it can use the loopback interface instead.&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for default chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Just what is a good scenario in which to use a custom chain?  Whenever you are segregating some portion of your traffic with a common criterion which doesn't apply to the vast majority of unrelated packets.  For example, here is my custom chain for staving off the onslaught of SSH brute force attackers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:SSH-Throttle -&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --set&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --update --seconds 5 --hitcount 2 -j DROP&lt;br /&gt;
-A SSH-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 22 -m conntrack --ctstate NEW -j SSH-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There you have it.  Three rules which don't need to test the protocol, port, or connection tracking state, because this is already done for them by the rule that sent the packets there.&lt;br /&gt;
&lt;br /&gt;
Additionally, here is my custom chain for blocking FTP abusers.  It limits login attempts to ten per minute and sessions to one per source IP.  It also throws some unexpected errors, so programs like hydra get confused and give up after a very short time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:FTP-Throttle -&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --set&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --update --seconds 60 --hitcount 10 -j DROP&lt;br /&gt;
-A FTP-Throttle -m connlimit --connlimit-above 1 -j REJECT --reject-with icmp-admin-prohibited&lt;br /&gt;
-A FTP-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 21 -m conntrack --ctstate NEW -j FTP-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== The Importance Of Organization ==&lt;br /&gt;
&lt;br /&gt;
From all zeros, to all ones, across 32 bits, there are 33 netmasks usable in IPv4 networking.  The ones are always on the left, and the zeros are always on the right.  That's it, 33.  When we line up the bits in a host address with the bits in the netmask, the bits that line up with the ones are the network portion of the address, and the bits that line up with the zeros are the host portion.  The address within the network where all the host bits are zeros (the first address in the network) is the network address.  The address within the network where all the host bits are ones (the last address in the network) is the broadcast address.  When we write a netmask as slash-some-number, like /24, we mean twenty-four ones on the left, and eight zeros on the right.  For every bit you add to the netmask, the size of the network is divided in half.&lt;br /&gt;
&lt;br /&gt;
Now that you understand how to do the math involved in calculating netmasks, network addresses, and broadcast addresses, let's examine how to plan your network.  Let's say you have been given 192.0.2.0/24 as your network allocation.  How are you going to assign addresses to web servers, mail servers, DNS servers, and the like?&lt;br /&gt;
&lt;br /&gt;
The fewer &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules you have, the faster packets will traverse your firewall.  Granted, a single rule takes only microseconds to process, but also your rules will be easier to read if the set is shorter.  So it is beneficial to reduce your rules as much as possible.  And a well planned network will make it easier to reduce your overall rules.&lt;br /&gt;
&lt;br /&gt;
We can divide our network into two /25 networks:  The network addresses will be 192.0.2.0/25 and 192.0.2.128/25.  We can subdivide again into four /26 networks, the last octet will then be 0, 64, 128, and 192.  Keep in mind, we have been allocated all of 192.0.2.0/24, so that's the space that will be routed to us, so we don't need to reserve multiple network and broadcast addresses, we can just use those points as borders between segments.&lt;br /&gt;
&lt;br /&gt;
If we host a lot of commercial web sites, we probably want to provide a lot of our IPs for web hosting.  If we divide up our allocation into four /26 segments, we can cover the two middle allocations with two rules, allowing us 128 web sites.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.64/26  -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.128/26 -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's much better than 128 individual rules allowing web traffic to individual addresses.  Below, we'll also examine how to reduce our rules even further, permitting disparate service allocations in only one rule.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,mark&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:mac&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; and hardly a handful of &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3260,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3260,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Sat, 01 Aug 2015 07:17:29 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Using ipsets */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Loopback is more than just 127.0.0.1 ==&lt;br /&gt;
&lt;br /&gt;
It seems that a lot of people believe that when a packet is sent to the address assigned to a node's own interface, that packet really goes to that interface.  This is not true, and how could it be?  An interface's job is to put that packet on the wire.  If the packet is addressed to the same machine that sent it, where would it go?  That's the exact job of the loopback interface.&lt;br /&gt;
&lt;br /&gt;
Observe based on the following example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# ip -4 addr ls eth0&lt;br /&gt;
2: eth0: &amp;amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;amp;gt; mtu 1500 qdisc pfifo_fast state UP qlen 1000&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; inet 192.168.1.21/24 brd 192.168.1.255 scope global eth0&lt;br /&gt;
# ip route get 192.168.1.21&lt;br /&gt;
local 192.168.1.21 dev lo  src 192.168.1.21 &lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; cache &amp;amp;lt;local&amp;amp;gt;  mtu 16436 advmss 16396 hoplimit 64&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can see here that packets sent to this machine's own address will be routed on the lo device, or the loopback interface, even though the destination address was not 127.0.0.1.&lt;br /&gt;
&lt;br /&gt;
On the other hand, 127.0.0.1 is always the loopback interface.  In fact, all of 127.0.0.0/8 will always route to the loopback interface.  It is quite difficult to assign an address in this range to any other interface.  Likewise, you should encounter quite a bit of difficulty trying to send a packet to 127.0.0.0/8 on any interface other than lo.&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || 1     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || 2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
: 1 - Older versions of the kernel and iptables did not provide the &amp;lt;tt&amp;gt;nat/INPUT&amp;lt;/tt&amp;gt; hook.  Check your documentation.&lt;br /&gt;
: 2 - &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; will only be available if you installed the [http://xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is simply not tested, which is the same as if it were tested and resulted in a TRUE match.  For example, if you don't specify a protocol, then the rule matches packets of any protocol.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tcp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.  You could also specify a netmask of 255.255.255.1 and match all the even or odd addresses in a group of 256.  If you pass a comma-separated list of addresses to &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; will expand the line into multiple rules.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT -s 10.0.0.3,10.0.0.7,10.0.0.19 -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
results in:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT -s 10.0.0.3 -j DROP&lt;br /&gt;
-A INPUT -s 10.0.0.7 -j DROP&lt;br /&gt;
-A INPUT -s 10.0.0.19 -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, notice that we started this ruleset by allowing unlimited traffic on the loopback interface.  But of particular interest is that these rules do not mention the 127.0.0.1 address.  Why not?  Because the loopback interface is used by more than just the 127.0.0.1 address.  In fact, any time you send traffic from the machine to itself, on any IP, it is handled on the loopback interface.  Think about it, how would the computer send packets up to the ethernet adapter, but not actually onto the ethernet cable?  It can't, but it can use the loopback interface instead.&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for default chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Just what is a good scenario in which to use a custom chain?  Whenever you are segregating some portion of your traffic with a common criterion which doesn't apply to the vast majority of unrelated packets.  For example, here is my custom chain for staving off the onslaught of SSH brute force attackers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:SSH-Throttle -&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --set&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --update --seconds 5 --hitcount 2 -j DROP&lt;br /&gt;
-A SSH-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 22 -m conntrack --ctstate NEW -j SSH-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There you have it.  Three rules which don't need to test the protocol, port, or connection tracking state, because this is already done for them by the rule that sent the packets there.&lt;br /&gt;
&lt;br /&gt;
Additionally, here is my custom chain for blocking FTP abusers.  It limits login attempts to ten per minute and sessions to one per source IP.  It also throws some unexpected errors, so programs like hydra get confused and give up after a very short time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:FTP-Throttle -&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --set&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --update --seconds 60 --hitcount 10 -j DROP&lt;br /&gt;
-A FTP-Throttle -m connlimit --connlimit-above 1 -j REJECT --reject-with icmp-admin-prohibited&lt;br /&gt;
-A FTP-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 21 -m conntrack --ctstate NEW -j FTP-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== The Importance Of Organization ==&lt;br /&gt;
&lt;br /&gt;
From all zeros, to all ones, across 32 bits, there are 33 netmasks usable in IPv4 networking.  The ones are always on the left, and the zeros are always on the right.  That's it, 33.  When we line up the bits in a host address with the bits in the netmask, the bits that line up with the ones are the network portion of the address, and the bits that line up with the zeros are the host portion.  The address within the network where all the host bits are zeros (the first address in the network) is the network address.  The address within the network where all the host bits are ones (the last address in the network) is the broadcast address.  When we write a netmask as slash-some-number, like /24, we mean twenty-four ones on the left, and eight zeros on the right.  For every bit you add to the netmask, the size of the network is divided in half.&lt;br /&gt;
&lt;br /&gt;
Now that you understand how to do the math involved in calculating netmasks, network addresses, and broadcast addresses, let's examine how to plan your network.  Let's say you have been given 192.0.2.0/24 as your network allocation.  How are you going to assign addresses to web servers, mail servers, DNS servers, and the like?&lt;br /&gt;
&lt;br /&gt;
The fewer &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules you have, the faster packets will traverse your firewall.  Granted, a single rule takes only microseconds to process, but also your rules will be easier to read if the set is shorter.  So it is beneficial to reduce your rules as much as possible.  And a well planned network will make it easier to reduce your overall rules.&lt;br /&gt;
&lt;br /&gt;
We can divide our network into two /25 networks:  The network addresses will be 192.0.2.0/25 and 192.0.2.128/25.  We can subdivide again into four /26 networks, the last octet will then be 0, 64, 128, and 192.  Keep in mind, we have been allocated all of 192.0.2.0/24, so that's the space that will be routed to us, so we don't need to reserve multiple network and broadcast addresses, we can just use those points as borders between segments.&lt;br /&gt;
&lt;br /&gt;
If we host a lot of commercial web sites, we probably want to provide a lot of our IPs for web hosting.  If we divide up our allocation into four /26 segments, we can cover the two middle allocations with two rules, allowing us 128 web sites.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.64/26  -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.128/26 -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's much better than 128 individual rules allowing web traffic to individual addresses.  Below, we'll also examine how to reduce our rules even further, permitting disparate service allocations in only one rule.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,mark&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:mac&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; and hardly a handful of &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Sat, 01 Aug 2015 07:12:44 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Build a VPN using only OpenSSH</title>
			<link>http://72.14.177.54/SFVLUG/Build_a_VPN_using_only_OpenSSH</link>
			<description>&lt;p&gt;Jeff:&amp;#32;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
I have written about OpenSSH a few times in the past.  It is an amazing tool that can do lots of things.  Recently, some of us discovered it can completely replace dedicated VPN programs like OpenVPN.  Don't get me wrong, OpenVPN is a great program, but under certain circumstances using OpenSSH can be a lot less effort.&lt;br /&gt;
&lt;br /&gt;
To start with, you need root access on both ends of the VPN.  If you don't have root access on one or both ends, then whoever does needs to set this up for you.&lt;br /&gt;
&lt;br /&gt;
In this example, we will show a connection from a home computer to an office network.  This example shows a one-to-many VPN relationship.  It is possible to extend this configuration to a many-to-many VPN by repeating some of the steps from the office side on the home side.&lt;br /&gt;
&lt;br /&gt;
===Home Network===&lt;br /&gt;
&lt;br /&gt;
The home network will be 192.168.1.0/24.  Although it isn't important, for the sake of completeness, the client computer will have an address of 192.168.1.100.&lt;br /&gt;
&lt;br /&gt;
===Office Network===&lt;br /&gt;
&lt;br /&gt;
The office network will be 10.0.0.0/24.  In our example, we will be making a connection to a computer which has an internal address of 10.0.0.200.&lt;br /&gt;
&lt;br /&gt;
===VPN Network===&lt;br /&gt;
&lt;br /&gt;
In order to create our VPN, we need to set up tuntap networking on both sides before establishing the tunnel.  We will use the 172.16.2.0/24 network for this.  On the home side, we will assign 172.16.2.100 and on the office side it will be 172.16.2.200.&lt;br /&gt;
&lt;br /&gt;
==Preparation: Office==&lt;br /&gt;
&lt;br /&gt;
Before we can set up a VPN tunnel, we need to create a tunnel network interface.  So either prepare this via SSH, then log out and log back in with the tunnel, or do this all in advance before you leave for home.  Simply run the following commands as root.&lt;br /&gt;
&lt;br /&gt;
OpenSSH will not allow a tunnel to be created on the server side unless it is configured to do so.  First edit /etc/ssh/sshd_config, and allow tunneling.&lt;br /&gt;
&lt;br /&gt;
'''PermitTunnel yes'''&lt;br /&gt;
&lt;br /&gt;
Restart sshd and enter these commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
ip tuntap add tun0 mode tun user ''your username''&lt;br /&gt;
ip addr add 172.16.2.200/24 dev tun0&lt;br /&gt;
ip link set peer 172.16.2.100 dev tun0&lt;br /&gt;
iptables -t nat -A POSTROUTING -o eth0 -s 172.16.2.0/24 -j MASQUERADE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Connecting==&lt;br /&gt;
&lt;br /&gt;
Now that we have a tunnel interface waiting for us on the remote end back at the office, let's configure the local tunnel interface and connect it to the remote.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ip tuntap add tun0 mode tun user ''your username''&lt;br /&gt;
ip addr add 172.16.2.100/24 dev tun0&lt;br /&gt;
ip link set peer 172.16.2.200 dev tun0&lt;br /&gt;
ip route add network 10.0.0.0/24 via 172.16.2.100&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Return to your unprivileged user account and log in.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ssh -w 0:0 office.example.com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 03:42, 21 August 2011 (UTC)&lt;/div&gt;</description>
			<pubDate>Sat, 13 Sep 2014 21:12:43 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Build_a_VPN_using_only_OpenSSH</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Anatomy of an iptables rule */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Loopback is more than just 127.0.0.1 ==&lt;br /&gt;
&lt;br /&gt;
It seems that a lot of people believe that when a packet is sent to the address assigned to a node's own interface, that packet really goes to that interface.  This is not true, and how could it be?  An interface's job is to put that packet on the wire.  If the packet is addressed to the same machine that sent it, where would it go?  That's the exact job of the loopback interface.&lt;br /&gt;
&lt;br /&gt;
Observe based on the following example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# ip -4 addr ls eth0&lt;br /&gt;
2: eth0: &amp;amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;amp;gt; mtu 1500 qdisc pfifo_fast state UP qlen 1000&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; inet 192.168.1.21/24 brd 192.168.1.255 scope global eth0&lt;br /&gt;
# ip route get 192.168.1.21&lt;br /&gt;
local 192.168.1.21 dev lo  src 192.168.1.21 &lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; cache &amp;amp;lt;local&amp;amp;gt;  mtu 16436 advmss 16396 hoplimit 64&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can see here that packets sent to this machine's own address will be routed on the lo device, or the loopback interface, even though the destination address was not 127.0.0.1.&lt;br /&gt;
&lt;br /&gt;
On the other hand, 127.0.0.1 is always the loopback interface.  In fact, all of 127.0.0.0/8 will always route to the loopback interface.  It is quite difficult to assign an address in this range to any other interface.  Likewise, you should encounter quite a bit of difficulty trying to send a packet to 127.0.0.0/8 on any interface other than lo.&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || 1     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || 2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
: 1 - Older versions of the kernel and iptables did not provide the &amp;lt;tt&amp;gt;nat/INPUT&amp;lt;/tt&amp;gt; hook.  Check your documentation.&lt;br /&gt;
: 2 - &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; will only be available if you installed the [http://xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is simply not tested, which is the same as if it were tested and resulted in a TRUE match.  For example, if you don't specify a protocol, then the rule matches packets of any protocol.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tcp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.  You could also specify a netmask of 255.255.255.1 and match all the even or odd addresses in a group of 256.  If you pass a comma-separated list of addresses to &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; will expand the line into multiple rules.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT -s 10.0.0.3,10.0.0.7,10.0.0.19 -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
results in:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT -s 10.0.0.3 -j DROP&lt;br /&gt;
-A INPUT -s 10.0.0.7 -j DROP&lt;br /&gt;
-A INPUT -s 10.0.0.19 -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, notice that we started this ruleset by allowing unlimited traffic on the loopback interface.  But of particular interest is that these rules do not mention the 127.0.0.1 address.  Why not?  Because the loopback interface is used by more than just the 127.0.0.1 address.  In fact, any time you send traffic from the machine to itself, on any IP, it is handled on the loopback interface.  Think about it, how would the computer send packets up to the ethernet adapter, but not actually onto the ethernet cable?  It can't, but it can use the loopback interface instead.&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for default chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Just what is a good scenario in which to use a custom chain?  Whenever you are segregating some portion of your traffic with a common criterion which doesn't apply to the vast majority of unrelated packets.  For example, here is my custom chain for staving off the onslaught of SSH brute force attackers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:SSH-Throttle -&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --set&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --update --seconds 5 --hitcount 2 -j DROP&lt;br /&gt;
-A SSH-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 22 -m conntrack --ctstate NEW -j SSH-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There you have it.  Three rules which don't need to test the protocol, port, or connection tracking state, because this is already done for them by the rule that sent the packets there.&lt;br /&gt;
&lt;br /&gt;
Additionally, here is my custom chain for blocking FTP abusers.  It limits login attempts to ten per minute and sessions to one per source IP.  It also throws some unexpected errors, so programs like hydra get confused and give up after a very short time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:FTP-Throttle -&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --set&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --update --seconds 60 --hitcount 10 -j DROP&lt;br /&gt;
-A FTP-Throttle -m connlimit --connlimit-above 1 -j REJECT --reject-with icmp-admin-prohibited&lt;br /&gt;
-A FTP-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 21 -m conntrack --ctstate NEW -j FTP-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== The Importance Of Organization ==&lt;br /&gt;
&lt;br /&gt;
From all zeros, to all ones, across 32 bits, there are 33 netmasks usable in IPv4 networking.  The ones are always on the left, and the zeros are always on the right.  That's it, 33.  When we line up the bits in a host address with the bits in the netmask, the bits that line up with the ones are the network portion of the address, and the bits that line up with the zeros are the host portion.  The address within the network where all the host bits are zeros (the first address in the network) is the network address.  The address within the network where all the host bits are ones (the last address in the network) is the broadcast address.  When we write a netmask as slash-some-number, like /24, we mean twenty-four ones on the left, and eight zeros on the right.  For every bit you add to the netmask, the size of the network is divided in half.&lt;br /&gt;
&lt;br /&gt;
Now that you understand how to do the math involved in calculating netmasks, network addresses, and broadcast addresses, let's examine how to plan your network.  Let's say you have been given 192.0.2.0/24 as your network allocation.  How are you going to assign addresses to web servers, mail servers, DNS servers, and the like?&lt;br /&gt;
&lt;br /&gt;
The fewer &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules you have, the faster packets will traverse your firewall.  Granted, a single rule takes only microseconds to process, but also your rules will be easier to read if the set is shorter.  So it is beneficial to reduce your rules as much as possible.  And a well planned network will make it easier to reduce your overall rules.&lt;br /&gt;
&lt;br /&gt;
We can divide our network into two /25 networks:  The network addresses will be 192.0.2.0/25 and 192.0.2.128/25.  We can subdivide again into four /26 networks, the last octet will then be 0, 64, 128, and 192.  Keep in mind, we have been allocated all of 192.0.2.0/24, so that's the space that will be routed to us, so we don't need to reserve multiple network and broadcast addresses, we can just use those points as borders between segments.&lt;br /&gt;
&lt;br /&gt;
If we host a lot of commercial web sites, we probably want to provide a lot of our IPs for web hosting.  If we divide up our allocation into four /26 segments, we can cover the two middle allocations with two rules, allowing us 128 web sites.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.64/26  -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.128/26 -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's much better than 128 individual rules allowing web traffic to individual addresses.  Below, we'll also examine how to reduce our rules even further, permitting disparate service allocations in only one rule.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; and hardly a handful of &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Sun, 29 Jun 2014 22:28:06 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Anatomy of an iptables rule */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Loopback is more than just 127.0.0.1 ==&lt;br /&gt;
&lt;br /&gt;
It seems that a lot of people believe that when a packet is sent to the address assigned to a node's own interface, that packet really goes to that interface.  This is not true, and how could it be?  An interface's job is to put that packet on the wire.  If the packet is addressed to the same machine that sent it, where would it go?  That's the exact job of the loopback interface.&lt;br /&gt;
&lt;br /&gt;
Observe based on the following example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# ip -4 addr ls eth0&lt;br /&gt;
2: eth0: &amp;amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;amp;gt; mtu 1500 qdisc pfifo_fast state UP qlen 1000&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; inet 192.168.1.21/24 brd 192.168.1.255 scope global eth0&lt;br /&gt;
# ip route get 192.168.1.21&lt;br /&gt;
local 192.168.1.21 dev lo  src 192.168.1.21 &lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; cache &amp;amp;lt;local&amp;amp;gt;  mtu 16436 advmss 16396 hoplimit 64&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can see here that packets sent to this machine's own address will be routed on the lo device, or the loopback interface, even though the destination address was not 127.0.0.1.&lt;br /&gt;
&lt;br /&gt;
On the other hand, 127.0.0.1 is always the loopback interface.  In fact, all of 127.0.0.0/8 will always route to the loopback interface.  It is quite difficult to assign an address in this range to any other interface.  Likewise, you should encounter quite a bit of difficulty trying to send a packet to 127.0.0.0/8 on any interface other than lo.&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || 1     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || 2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
: 1 - Older versions of the kernel and iptables did not provide the &amp;lt;tt&amp;gt;nat/INPUT&amp;lt;/tt&amp;gt; hook.  Check your documentation.&lt;br /&gt;
: 2 - &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; will only be available if you installed the [http://xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is simply not tested, which is the same as if it were tested and resulted in a TRUE match.  For example, if you don't specify a protocol, then the rule matches packets of any protocol.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.  You could also specify a netmask of 255.255.255.1 and match all the even or odd addresses in a group of 256.  If you pass a comma-separated list of addresses to &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; will expand the line into multiple rules.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT -s 10.0.0.3,10.0.0.7,10.0.0.19 -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
results in:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT -s 10.0.0.3 -j DROP&lt;br /&gt;
-A INPUT -s 10.0.0.7 -j DROP&lt;br /&gt;
-A INPUT -s 10.0.0.19 -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, notice that we started this ruleset by allowing unlimited traffic on the loopback interface.  But of particular interest is that these rules do not mention the 127.0.0.1 address.  Why not?  Because the loopback interface is used by more than just the 127.0.0.1 address.  In fact, any time you send traffic from the machine to itself, on any IP, it is handled on the loopback interface.  Think about it, how would the computer send packets up to the ethernet adapter, but not actually onto the ethernet cable?  It can't, but it can use the loopback interface instead.&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for default chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Just what is a good scenario in which to use a custom chain?  Whenever you are segregating some portion of your traffic with a common criterion which doesn't apply to the vast majority of unrelated packets.  For example, here is my custom chain for staving off the onslaught of SSH brute force attackers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:SSH-Throttle -&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --set&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --update --seconds 5 --hitcount 2 -j DROP&lt;br /&gt;
-A SSH-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 22 -m conntrack --ctstate NEW -j SSH-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There you have it.  Three rules which don't need to test the protocol, port, or connection tracking state, because this is already done for them by the rule that sent the packets there.&lt;br /&gt;
&lt;br /&gt;
Additionally, here is my custom chain for blocking FTP abusers.  It limits login attempts to ten per minute and sessions to one per source IP.  It also throws some unexpected errors, so programs like hydra get confused and give up after a very short time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:FTP-Throttle -&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --set&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --update --seconds 60 --hitcount 10 -j DROP&lt;br /&gt;
-A FTP-Throttle -m connlimit --connlimit-above 1 -j REJECT --reject-with icmp-admin-prohibited&lt;br /&gt;
-A FTP-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 21 -m conntrack --ctstate NEW -j FTP-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== The Importance Of Organization ==&lt;br /&gt;
&lt;br /&gt;
From all zeros, to all ones, across 32 bits, there are 33 netmasks usable in IPv4 networking.  The ones are always on the left, and the zeros are always on the right.  That's it, 33.  When we line up the bits in a host address with the bits in the netmask, the bits that line up with the ones are the network portion of the address, and the bits that line up with the zeros are the host portion.  The address within the network where all the host bits are zeros (the first address in the network) is the network address.  The address within the network where all the host bits are ones (the last address in the network) is the broadcast address.  When we write a netmask as slash-some-number, like /24, we mean twenty-four ones on the left, and eight zeros on the right.  For every bit you add to the netmask, the size of the network is divided in half.&lt;br /&gt;
&lt;br /&gt;
Now that you understand how to do the math involved in calculating netmasks, network addresses, and broadcast addresses, let's examine how to plan your network.  Let's say you have been given 192.0.2.0/24 as your network allocation.  How are you going to assign addresses to web servers, mail servers, DNS servers, and the like?&lt;br /&gt;
&lt;br /&gt;
The fewer &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules you have, the faster packets will traverse your firewall.  Granted, a single rule takes only microseconds to process, but also your rules will be easier to read if the set is shorter.  So it is beneficial to reduce your rules as much as possible.  And a well planned network will make it easier to reduce your overall rules.&lt;br /&gt;
&lt;br /&gt;
We can divide our network into two /25 networks:  The network addresses will be 192.0.2.0/25 and 192.0.2.128/25.  We can subdivide again into four /26 networks, the last octet will then be 0, 64, 128, and 192.  Keep in mind, we have been allocated all of 192.0.2.0/24, so that's the space that will be routed to us, so we don't need to reserve multiple network and broadcast addresses, we can just use those points as borders between segments.&lt;br /&gt;
&lt;br /&gt;
If we host a lot of commercial web sites, we probably want to provide a lot of our IPs for web hosting.  If we divide up our allocation into four /26 segments, we can cover the two middle allocations with two rules, allowing us 128 web sites.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.64/26  -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.128/26 -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's much better than 128 individual rules allowing web traffic to individual addresses.  Below, we'll also examine how to reduce our rules even further, permitting disparate service allocations in only one rule.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; and hardly a handful of &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Sun, 18 May 2014 21:15:25 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Anatomy of an iptables rule */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Loopback is more than just 127.0.0.1 ==&lt;br /&gt;
&lt;br /&gt;
It seems that a lot of people believe that when a packet is sent to the address assigned to a node's own interface, that packet really goes to that interface.  This is not true, and how could it be?  An interface's job is to put that packet on the wire.  If the packet is addressed to the same machine that sent it, where would it go?  That's the exact job of the loopback interface.&lt;br /&gt;
&lt;br /&gt;
Observe based on the following example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# ip -4 addr ls eth0&lt;br /&gt;
2: eth0: &amp;amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;amp;gt; mtu 1500 qdisc pfifo_fast state UP qlen 1000&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; inet 192.168.1.21/24 brd 192.168.1.255 scope global eth0&lt;br /&gt;
# ip route get 192.168.1.21&lt;br /&gt;
local 192.168.1.21 dev lo  src 192.168.1.21 &lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; cache &amp;amp;lt;local&amp;amp;gt;  mtu 16436 advmss 16396 hoplimit 64&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can see here that packets sent to this machine's own address will be routed on the lo device, or the loopback interface, even though the destination address was not 127.0.0.1.&lt;br /&gt;
&lt;br /&gt;
On the other hand, 127.0.0.1 is always the loopback interface.  In fact, all of 127.0.0.0/8 will always route to the loopback interface.  It is quite difficult to assign an address in this range to any other interface.  Likewise, you should encounter quite a bit of difficulty trying to send a packet to 127.0.0.0/8 on any interface other than lo.&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || 1     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || 2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
: 1 - Older versions of the kernel and iptables did not provide the &amp;lt;tt&amp;gt;nat/INPUT&amp;lt;/tt&amp;gt; hook.  Check your documentation.&lt;br /&gt;
: 2 - &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; will only be available if you installed the  http //xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is simply not tested, which is the same as if it were tested and resulted in a TRUE match.  For example, if you don't specify a protocol, then the rule matches packets of any protocol.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.  You could also specify a netmask of 255.255.255.1 and match all the even or odd addresses in a group of 256.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, notice that we started this ruleset by allowing unlimited traffic on the loopback interface.  But of particular interest is that these rules do not mention the 127.0.0.1 address.  Why not?  Because the loopback interface is used by more than just the 127.0.0.1 address.  In fact, any time you send traffic from the machine to itself, on any IP, it is handled on the loopback interface.  Think about it, how would the computer send packets up to the ethernet adapter, but not actually onto the ethernet cable?  It can't, but it can use the loopback interface instead.&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for default chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Just what is a good scenario in which to use a custom chain?  Whenever you are segregating some portion of your traffic with a common criterion which doesn't apply to the vast majority of unrelated packets.  For example, here is my custom chain for staving off the onslaught of SSH brute force attackers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:SSH-Throttle -&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --set&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --update --seconds 5 --hitcount 2 -j DROP&lt;br /&gt;
-A SSH-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 22 -m conntrack --ctstate NEW -j SSH-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There you have it.  Three rules which don't need to test the protocol, port, or connection tracking state, because this is already done for them by the rule that sent the packets there.&lt;br /&gt;
&lt;br /&gt;
Additionally, here is my custom chain for blocking FTP abusers.  It limits login attempts to ten per minute and sessions to one per source IP.  It also throws some unexpected errors, so programs like hydra get confused and give up after a very short time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:FTP-Throttle -&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --set&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --update --seconds 60 --hitcount 10 -j DROP&lt;br /&gt;
-A FTP-Throttle -m connlimit --connlimit-above 1 -j REJECT --reject-with icmp-admin-prohibited&lt;br /&gt;
-A FTP-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 21 -m conntrack --ctstate NEW -j FTP-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== The Importance Of Organization ==&lt;br /&gt;
&lt;br /&gt;
From all zeros, to all ones, across 32 bits, there are 33 netmasks usable in IPv4 networking.  The ones are always on the left, and the zeros are always on the right.  That's it, 33.  When we line up the bits in a host address with the bits in the netmask, the bits that line up with the ones are the network portion of the address, and the bits that line up with the zeros are the host portion.  The address within the network where all the host bits are zeros (the first address in the network) is the network address.  The address within the network where all the host bits are ones (the last address in the network) is the broadcast address.  When we write a netmask as slash-some-number, like /24, we mean twenty-four ones on the left, and eight zeros on the right.  For every bit you add to the netmask, the size of the network is divided in half.&lt;br /&gt;
&lt;br /&gt;
Now that you understand how to do the math involved in calculating netmasks, network addresses, and broadcast addresses, let's examine how to plan your network.  Let's say you have been given 192.0.2.0/24 as your network allocation.  How are you going to assign addresses to web servers, mail servers, DNS servers, and the like?&lt;br /&gt;
&lt;br /&gt;
The fewer &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules you have, the faster packets will traverse your firewall.  Granted, a single rule takes only microseconds to process, but also your rules will be easier to read if the set is shorter.  So it is beneficial to reduce your rules as much as possible.  And a well planned network will make it easier to reduce your overall rules.&lt;br /&gt;
&lt;br /&gt;
We can divide our network into two /25 networks:  The network addresses will be 192.0.2.0/25 and 192.0.2.128/25.  We can subdivide again into four /26 networks, the last octet will then be 0, 64, 128, and 192.  Keep in mind, we have been allocated all of 192.0.2.0/24, so that's the space that will be routed to us, so we don't need to reserve multiple network and broadcast addresses, we can just use those points as borders between segments.&lt;br /&gt;
&lt;br /&gt;
If we host a lot of commercial web sites, we probably want to provide a lot of our IPs for web hosting.  If we divide up our allocation into four /26 segments, we can cover the two middle allocations with two rules, allowing us 128 web sites.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.64/26  -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.128/26 -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's much better than 128 individual rules allowing web traffic to individual addresses.  Below, we'll also examine how to reduce our rules even further, permitting disparate service allocations in only one rule.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; and hardly a handful of &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Sun, 18 May 2014 21:05:00 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Anatomy of an iptables rule */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Loopback is more than just 127.0.0.1 ==&lt;br /&gt;
&lt;br /&gt;
It seems that a lot of people believe that when a packet is sent to the address assigned to a node's own interface, that packet really goes to that interface.  This is not true, and how could it be?  An interface's job is to put that packet on the wire.  If the packet is addressed to the same machine that sent it, where would it go?  That's the exact job of the loopback interface.&lt;br /&gt;
&lt;br /&gt;
Observe based on the following example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# ip -4 addr ls eth0&lt;br /&gt;
2: eth0: &amp;amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;amp;gt; mtu 1500 qdisc pfifo_fast state UP qlen 1000&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; inet 192.168.1.21/24 brd 192.168.1.255 scope global eth0&lt;br /&gt;
# ip route get 192.168.1.21&lt;br /&gt;
local 192.168.1.21 dev lo  src 192.168.1.21 &lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; cache &amp;amp;lt;local&amp;amp;gt;  mtu 16436 advmss 16396 hoplimit 64&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can see here that packets sent to this machine's own address will be routed on the lo device, or the loopback interface, even though the destination address was not 127.0.0.1.&lt;br /&gt;
&lt;br /&gt;
On the other hand, 127.0.0.1 is always the loopback interface.  In fact, all of 127.0.0.0/8 will always route to the loopback interface.  It is quite difficult to assign an address in this range to any other interface.  Likewise, you should encounter quite a bit of difficulty trying to send a packet to 127.0.0.0/8 on any interface other than lo.&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || 1     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || 2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
: 1 - Older versions of the kernel and iptables did not provide the &amp;lt;tt&amp;gt;nat/INPUT&amp;lt;/tt&amp;gt; hook.  Check your documentation.\\&lt;br /&gt;
: 2 - &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; will only be available if you installed the  http //xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is simply not tested, which is the same as if it were tested and resulted in a TRUE match.  For example, if you don't specify a protocol, then the rule matches packets of any protocol.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.  You could also specify a netmask of 255.255.255.1 and match all the even or odd addresses in a group of 256.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, notice that we started this ruleset by allowing unlimited traffic on the loopback interface.  But of particular interest is that these rules do not mention the 127.0.0.1 address.  Why not?  Because the loopback interface is used by more than just the 127.0.0.1 address.  In fact, any time you send traffic from the machine to itself, on any IP, it is handled on the loopback interface.  Think about it, how would the computer send packets up to the ethernet adapter, but not actually onto the ethernet cable?  It can't, but it can use the loopback interface instead.&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for default chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Just what is a good scenario in which to use a custom chain?  Whenever you are segregating some portion of your traffic with a common criterion which doesn't apply to the vast majority of unrelated packets.  For example, here is my custom chain for staving off the onslaught of SSH brute force attackers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:SSH-Throttle -&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --set&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --update --seconds 5 --hitcount 2 -j DROP&lt;br /&gt;
-A SSH-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 22 -m conntrack --ctstate NEW -j SSH-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There you have it.  Three rules which don't need to test the protocol, port, or connection tracking state, because this is already done for them by the rule that sent the packets there.&lt;br /&gt;
&lt;br /&gt;
Additionally, here is my custom chain for blocking FTP abusers.  It limits login attempts to ten per minute and sessions to one per source IP.  It also throws some unexpected errors, so programs like hydra get confused and give up after a very short time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:FTP-Throttle -&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --set&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --update --seconds 60 --hitcount 10 -j DROP&lt;br /&gt;
-A FTP-Throttle -m connlimit --connlimit-above 1 -j REJECT --reject-with icmp-admin-prohibited&lt;br /&gt;
-A FTP-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 21 -m conntrack --ctstate NEW -j FTP-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== The Importance Of Organization ==&lt;br /&gt;
&lt;br /&gt;
From all zeros, to all ones, across 32 bits, there are 33 netmasks usable in IPv4 networking.  The ones are always on the left, and the zeros are always on the right.  That's it, 33.  When we line up the bits in a host address with the bits in the netmask, the bits that line up with the ones are the network portion of the address, and the bits that line up with the zeros are the host portion.  The address within the network where all the host bits are zeros (the first address in the network) is the network address.  The address within the network where all the host bits are ones (the last address in the network) is the broadcast address.  When we write a netmask as slash-some-number, like /24, we mean twenty-four ones on the left, and eight zeros on the right.  For every bit you add to the netmask, the size of the network is divided in half.&lt;br /&gt;
&lt;br /&gt;
Now that you understand how to do the math involved in calculating netmasks, network addresses, and broadcast addresses, let's examine how to plan your network.  Let's say you have been given 192.0.2.0/24 as your network allocation.  How are you going to assign addresses to web servers, mail servers, DNS servers, and the like?&lt;br /&gt;
&lt;br /&gt;
The fewer &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules you have, the faster packets will traverse your firewall.  Granted, a single rule takes only microseconds to process, but also your rules will be easier to read if the set is shorter.  So it is beneficial to reduce your rules as much as possible.  And a well planned network will make it easier to reduce your overall rules.&lt;br /&gt;
&lt;br /&gt;
We can divide our network into two /25 networks:  The network addresses will be 192.0.2.0/25 and 192.0.2.128/25.  We can subdivide again into four /26 networks, the last octet will then be 0, 64, 128, and 192.  Keep in mind, we have been allocated all of 192.0.2.0/24, so that's the space that will be routed to us, so we don't need to reserve multiple network and broadcast addresses, we can just use those points as borders between segments.&lt;br /&gt;
&lt;br /&gt;
If we host a lot of commercial web sites, we probably want to provide a lot of our IPs for web hosting.  If we divide up our allocation into four /26 segments, we can cover the two middle allocations with two rules, allowing us 128 web sites.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.64/26  -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.128/26 -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's much better than 128 individual rules allowing web traffic to individual addresses.  Below, we'll also examine how to reduce our rules even further, permitting disparate service allocations in only one rule.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; and hardly a handful of &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Sun, 18 May 2014 21:04:29 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Anatomy of an iptables rule */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Loopback is more than just 127.0.0.1 ==&lt;br /&gt;
&lt;br /&gt;
It seems that a lot of people believe that when a packet is sent to the address assigned to a node's own interface, that packet really goes to that interface.  This is not true, and how could it be?  An interface's job is to put that packet on the wire.  If the packet is addressed to the same machine that sent it, where would it go?  That's the exact job of the loopback interface.&lt;br /&gt;
&lt;br /&gt;
Observe based on the following example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# ip -4 addr ls eth0&lt;br /&gt;
2: eth0: &amp;amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;amp;gt; mtu 1500 qdisc pfifo_fast state UP qlen 1000&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; inet 192.168.1.21/24 brd 192.168.1.255 scope global eth0&lt;br /&gt;
# ip route get 192.168.1.21&lt;br /&gt;
local 192.168.1.21 dev lo  src 192.168.1.21 &lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; cache &amp;amp;lt;local&amp;amp;gt;  mtu 16436 advmss 16396 hoplimit 64&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can see here that packets sent to this machine's own address will be routed on the lo device, or the loopback interface, even though the destination address was not 127.0.0.1.&lt;br /&gt;
&lt;br /&gt;
On the other hand, 127.0.0.1 is always the loopback interface.  In fact, all of 127.0.0.0/8 will always route to the loopback interface.  It is quite difficult to assign an address in this range to any other interface.  Likewise, you should encounter quite a bit of difficulty trying to send a packet to 127.0.0.0/8 on any interface other than lo.&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || 1     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || 2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
(1) - Older versions of the kernel and iptables did not provide the &amp;lt;tt&amp;gt;nat/INPUT&amp;lt;/tt&amp;gt; hook.  Check your documentation.\\&lt;br /&gt;
(2) - &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; will only be available if you installed the  http //xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is simply not tested, which is the same as if it were tested and resulted in a TRUE match.  For example, if you don't specify a protocol, then the rule matches packets of any protocol.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.  You could also specify a netmask of 255.255.255.1 and match all the even or odd addresses in a group of 256.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, notice that we started this ruleset by allowing unlimited traffic on the loopback interface.  But of particular interest is that these rules do not mention the 127.0.0.1 address.  Why not?  Because the loopback interface is used by more than just the 127.0.0.1 address.  In fact, any time you send traffic from the machine to itself, on any IP, it is handled on the loopback interface.  Think about it, how would the computer send packets up to the ethernet adapter, but not actually onto the ethernet cable?  It can't, but it can use the loopback interface instead.&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for default chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Just what is a good scenario in which to use a custom chain?  Whenever you are segregating some portion of your traffic with a common criterion which doesn't apply to the vast majority of unrelated packets.  For example, here is my custom chain for staving off the onslaught of SSH brute force attackers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:SSH-Throttle -&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --set&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --update --seconds 5 --hitcount 2 -j DROP&lt;br /&gt;
-A SSH-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 22 -m conntrack --ctstate NEW -j SSH-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There you have it.  Three rules which don't need to test the protocol, port, or connection tracking state, because this is already done for them by the rule that sent the packets there.&lt;br /&gt;
&lt;br /&gt;
Additionally, here is my custom chain for blocking FTP abusers.  It limits login attempts to ten per minute and sessions to one per source IP.  It also throws some unexpected errors, so programs like hydra get confused and give up after a very short time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:FTP-Throttle -&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --set&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --update --seconds 60 --hitcount 10 -j DROP&lt;br /&gt;
-A FTP-Throttle -m connlimit --connlimit-above 1 -j REJECT --reject-with icmp-admin-prohibited&lt;br /&gt;
-A FTP-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 21 -m conntrack --ctstate NEW -j FTP-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== The Importance Of Organization ==&lt;br /&gt;
&lt;br /&gt;
From all zeros, to all ones, across 32 bits, there are 33 netmasks usable in IPv4 networking.  The ones are always on the left, and the zeros are always on the right.  That's it, 33.  When we line up the bits in a host address with the bits in the netmask, the bits that line up with the ones are the network portion of the address, and the bits that line up with the zeros are the host portion.  The address within the network where all the host bits are zeros (the first address in the network) is the network address.  The address within the network where all the host bits are ones (the last address in the network) is the broadcast address.  When we write a netmask as slash-some-number, like /24, we mean twenty-four ones on the left, and eight zeros on the right.  For every bit you add to the netmask, the size of the network is divided in half.&lt;br /&gt;
&lt;br /&gt;
Now that you understand how to do the math involved in calculating netmasks, network addresses, and broadcast addresses, let's examine how to plan your network.  Let's say you have been given 192.0.2.0/24 as your network allocation.  How are you going to assign addresses to web servers, mail servers, DNS servers, and the like?&lt;br /&gt;
&lt;br /&gt;
The fewer &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules you have, the faster packets will traverse your firewall.  Granted, a single rule takes only microseconds to process, but also your rules will be easier to read if the set is shorter.  So it is beneficial to reduce your rules as much as possible.  And a well planned network will make it easier to reduce your overall rules.&lt;br /&gt;
&lt;br /&gt;
We can divide our network into two /25 networks:  The network addresses will be 192.0.2.0/25 and 192.0.2.128/25.  We can subdivide again into four /26 networks, the last octet will then be 0, 64, 128, and 192.  Keep in mind, we have been allocated all of 192.0.2.0/24, so that's the space that will be routed to us, so we don't need to reserve multiple network and broadcast addresses, we can just use those points as borders between segments.&lt;br /&gt;
&lt;br /&gt;
If we host a lot of commercial web sites, we probably want to provide a lot of our IPs for web hosting.  If we divide up our allocation into four /26 segments, we can cover the two middle allocations with two rules, allowing us 128 web sites.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.64/26  -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.128/26 -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's much better than 128 individual rules allowing web traffic to individual addresses.  Below, we'll also examine how to reduce our rules even further, permitting disparate service allocations in only one rule.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; and hardly a handful of &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Sun, 18 May 2014 20:51:39 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Anatomy of an iptables rule */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Loopback is more than just 127.0.0.1 ==&lt;br /&gt;
&lt;br /&gt;
It seems that a lot of people believe that when a packet is sent to the address assigned to a node's own interface, that packet really goes to that interface.  This is not true, and how could it be?  An interface's job is to put that packet on the wire.  If the packet is addressed to the same machine that sent it, where would it go?  That's the exact job of the loopback interface.&lt;br /&gt;
&lt;br /&gt;
Observe based on the following example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# ip -4 addr ls eth0&lt;br /&gt;
2: eth0: &amp;amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;amp;gt; mtu 1500 qdisc pfifo_fast state UP qlen 1000&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; inet 192.168.1.21/24 brd 192.168.1.255 scope global eth0&lt;br /&gt;
# ip route get 192.168.1.21&lt;br /&gt;
local 192.168.1.21 dev lo  src 192.168.1.21 &lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; cache &amp;amp;lt;local&amp;amp;gt;  mtu 16436 advmss 16396 hoplimit 64&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can see here that packets sent to this machine's own address will be routed on the lo device, or the loopback interface, even though the destination address was not 127.0.0.1.&lt;br /&gt;
&lt;br /&gt;
On the other hand, 127.0.0.1 is always the loopback interface.  In fact, all of 127.0.0.0/8 will always route to the loopback interface.  It is quite difficult to assign an address in this range to any other interface.  Likewise, you should encounter quite a bit of difficulty trying to send a packet to 127.0.0.0/8 on any interface other than lo.&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || 1     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || 2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
(1) - Older versions of the kernel and iptables did not provide the &amp;lt;tt&amp;gt;nat/INPUT&amp;lt;/tt&amp;gt; hook.  Check your documentation.&lt;br /&gt;
(2) - &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; will only be available if you installed the [http://xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is simply not tested, which is the same as if it were tested and resulted in a TRUE match.  For example, if you don't specify a protocol, then the rule matches packets of any protocol.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.  You could also specify a netmask of 255.255.255.1 and match all the even or odd addresses in a group of 256.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, notice that we started this ruleset by allowing unlimited traffic on the loopback interface.  But of particular interest is that these rules do not mention the 127.0.0.1 address.  Why not?  Because the loopback interface is used by more than just the 127.0.0.1 address.  In fact, any time you send traffic from the machine to itself, on any IP, it is handled on the loopback interface.  Think about it, how would the computer send packets up to the ethernet adapter, but not actually onto the ethernet cable?  It can't, but it can use the loopback interface instead.&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for default chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Just what is a good scenario in which to use a custom chain?  Whenever you are segregating some portion of your traffic with a common criterion which doesn't apply to the vast majority of unrelated packets.  For example, here is my custom chain for staving off the onslaught of SSH brute force attackers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:SSH-Throttle -&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --set&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --update --seconds 5 --hitcount 2 -j DROP&lt;br /&gt;
-A SSH-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 22 -m conntrack --ctstate NEW -j SSH-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There you have it.  Three rules which don't need to test the protocol, port, or connection tracking state, because this is already done for them by the rule that sent the packets there.&lt;br /&gt;
&lt;br /&gt;
Additionally, here is my custom chain for blocking FTP abusers.  It limits login attempts to ten per minute and sessions to one per source IP.  It also throws some unexpected errors, so programs like hydra get confused and give up after a very short time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:FTP-Throttle -&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --set&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --update --seconds 60 --hitcount 10 -j DROP&lt;br /&gt;
-A FTP-Throttle -m connlimit --connlimit-above 1 -j REJECT --reject-with icmp-admin-prohibited&lt;br /&gt;
-A FTP-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 21 -m conntrack --ctstate NEW -j FTP-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== The Importance Of Organization ==&lt;br /&gt;
&lt;br /&gt;
From all zeros, to all ones, across 32 bits, there are 33 netmasks usable in IPv4 networking.  The ones are always on the left, and the zeros are always on the right.  That's it, 33.  When we line up the bits in a host address with the bits in the netmask, the bits that line up with the ones are the network portion of the address, and the bits that line up with the zeros are the host portion.  The address within the network where all the host bits are zeros (the first address in the network) is the network address.  The address within the network where all the host bits are ones (the last address in the network) is the broadcast address.  When we write a netmask as slash-some-number, like /24, we mean twenty-four ones on the left, and eight zeros on the right.  For every bit you add to the netmask, the size of the network is divided in half.&lt;br /&gt;
&lt;br /&gt;
Now that you understand how to do the math involved in calculating netmasks, network addresses, and broadcast addresses, let's examine how to plan your network.  Let's say you have been given 192.0.2.0/24 as your network allocation.  How are you going to assign addresses to web servers, mail servers, DNS servers, and the like?&lt;br /&gt;
&lt;br /&gt;
The fewer &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules you have, the faster packets will traverse your firewall.  Granted, a single rule takes only microseconds to process, but also your rules will be easier to read if the set is shorter.  So it is beneficial to reduce your rules as much as possible.  And a well planned network will make it easier to reduce your overall rules.&lt;br /&gt;
&lt;br /&gt;
We can divide our network into two /25 networks:  The network addresses will be 192.0.2.0/25 and 192.0.2.128/25.  We can subdivide again into four /26 networks, the last octet will then be 0, 64, 128, and 192.  Keep in mind, we have been allocated all of 192.0.2.0/24, so that's the space that will be routed to us, so we don't need to reserve multiple network and broadcast addresses, we can just use those points as borders between segments.&lt;br /&gt;
&lt;br /&gt;
If we host a lot of commercial web sites, we probably want to provide a lot of our IPs for web hosting.  If we divide up our allocation into four /26 segments, we can cover the two middle allocations with two rules, allowing us 128 web sites.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.64/26  -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.128/26 -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's much better than 128 individual rules allowing web traffic to individual addresses.  Below, we'll also examine how to reduce our rules even further, permitting disparate service allocations in only one rule.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; and hardly a handful of &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Sun, 18 May 2014 20:49:35 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Loopback is more than just 127.0.0.1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Loopback is more than just 127.0.0.1 ==&lt;br /&gt;
&lt;br /&gt;
It seems that a lot of people believe that when a packet is sent to the address assigned to a node's own interface, that packet really goes to that interface.  This is not true, and how could it be?  An interface's job is to put that packet on the wire.  If the packet is addressed to the same machine that sent it, where would it go?  That's the exact job of the loopback interface.&lt;br /&gt;
&lt;br /&gt;
Observe based on the following example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# ip -4 addr ls eth0&lt;br /&gt;
2: eth0: &amp;amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;amp;gt; mtu 1500 qdisc pfifo_fast state UP qlen 1000&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; inet 192.168.1.21/24 brd 192.168.1.255 scope global eth0&lt;br /&gt;
# ip route get 192.168.1.21&lt;br /&gt;
local 192.168.1.21 dev lo  src 192.168.1.21 &lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; cache &amp;amp;lt;local&amp;amp;gt;  mtu 16436 advmss 16396 hoplimit 64&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can see here that packets sent to this machine's own address will be routed on the lo device, or the loopback interface, even though the destination address was not 127.0.0.1.&lt;br /&gt;
&lt;br /&gt;
On the other hand, 127.0.0.1 is always the loopback interface.  In fact, all of 127.0.0.0/8 will always route to the loopback interface.  It is quite difficult to assign an address in this range to any other interface.  Likewise, you should encounter quite a bit of difficulty trying to send a packet to 127.0.0.0/8 on any interface other than lo.&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || +     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || +&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.  Note that &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is only available if you have installed the [http://xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is simply not tested, which is the same as if it were tested and resulted in a TRUE match.  For example, if you don't specify a protocol, then the rule matches packets of any protocol.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.  You could also specify a netmask of 255.255.255.1 and match all the even or odd addresses in a group of 256.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, notice that we started this ruleset by allowing unlimited traffic on the loopback interface.  But of particular interest is that these rules do not mention the 127.0.0.1 address.  Why not?  Because the loopback interface is used by more than just the 127.0.0.1 address.  In fact, any time you send traffic from the machine to itself, on any IP, it is handled on the loopback interface.  Think about it, how would the computer send packets up to the ethernet adapter, but not actually onto the ethernet cable?  It can't, but it can use the loopback interface instead.&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for default chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Just what is a good scenario in which to use a custom chain?  Whenever you are segregating some portion of your traffic with a common criterion which doesn't apply to the vast majority of unrelated packets.  For example, here is my custom chain for staving off the onslaught of SSH brute force attackers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:SSH-Throttle -&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --set&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --update --seconds 5 --hitcount 2 -j DROP&lt;br /&gt;
-A SSH-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 22 -m conntrack --ctstate NEW -j SSH-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There you have it.  Three rules which don't need to test the protocol, port, or connection tracking state, because this is already done for them by the rule that sent the packets there.&lt;br /&gt;
&lt;br /&gt;
Additionally, here is my custom chain for blocking FTP abusers.  It limits login attempts to ten per minute and sessions to one per source IP.  It also throws some unexpected errors, so programs like hydra get confused and give up after a very short time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:FTP-Throttle -&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --set&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --update --seconds 60 --hitcount 10 -j DROP&lt;br /&gt;
-A FTP-Throttle -m connlimit --connlimit-above 1 -j REJECT --reject-with icmp-admin-prohibited&lt;br /&gt;
-A FTP-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 21 -m conntrack --ctstate NEW -j FTP-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== The Importance Of Organization ==&lt;br /&gt;
&lt;br /&gt;
From all zeros, to all ones, across 32 bits, there are 33 netmasks usable in IPv4 networking.  The ones are always on the left, and the zeros are always on the right.  That's it, 33.  When we line up the bits in a host address with the bits in the netmask, the bits that line up with the ones are the network portion of the address, and the bits that line up with the zeros are the host portion.  The address within the network where all the host bits are zeros (the first address in the network) is the network address.  The address within the network where all the host bits are ones (the last address in the network) is the broadcast address.  When we write a netmask as slash-some-number, like /24, we mean twenty-four ones on the left, and eight zeros on the right.  For every bit you add to the netmask, the size of the network is divided in half.&lt;br /&gt;
&lt;br /&gt;
Now that you understand how to do the math involved in calculating netmasks, network addresses, and broadcast addresses, let's examine how to plan your network.  Let's say you have been given 192.0.2.0/24 as your network allocation.  How are you going to assign addresses to web servers, mail servers, DNS servers, and the like?&lt;br /&gt;
&lt;br /&gt;
The fewer &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules you have, the faster packets will traverse your firewall.  Granted, a single rule takes only microseconds to process, but also your rules will be easier to read if the set is shorter.  So it is beneficial to reduce your rules as much as possible.  And a well planned network will make it easier to reduce your overall rules.&lt;br /&gt;
&lt;br /&gt;
We can divide our network into two /25 networks:  The network addresses will be 192.0.2.0/25 and 192.0.2.128/25.  We can subdivide again into four /26 networks, the last octet will then be 0, 64, 128, and 192.  Keep in mind, we have been allocated all of 192.0.2.0/24, so that's the space that will be routed to us, so we don't need to reserve multiple network and broadcast addresses, we can just use those points as borders between segments.&lt;br /&gt;
&lt;br /&gt;
If we host a lot of commercial web sites, we probably want to provide a lot of our IPs for web hosting.  If we divide up our allocation into four /26 segments, we can cover the two middle allocations with two rules, allowing us 128 web sites.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.64/26  -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.128/26 -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's much better than 128 individual rules allowing web traffic to individual addresses.  Below, we'll also examine how to reduce our rules even further, permitting disparate service allocations in only one rule.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; and hardly a handful of &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Sun, 18 May 2014 20:43:48 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Loopback is more than just 127.0.0.1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Loopback is more than just 127.0.0.1 ==&lt;br /&gt;
&lt;br /&gt;
It seems that a lot of people believe that when a packet is sent to the address assigned to a node's own interface, that packet really goes to that interface.  This is not true, and how could it be?  An interface's job is to put that packet on the wire.  If the packet is addressed to the same machine that sent it, that's the exact job of the loopback interface.&lt;br /&gt;
&lt;br /&gt;
Observe based on the following example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# ip -4 addr ls eth0&lt;br /&gt;
2: eth0: &amp;amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;amp;gt; mtu 1500 qdisc pfifo_fast state UP qlen 1000&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; inet 192.168.1.21/24 brd 192.168.1.255 scope global eth0&lt;br /&gt;
# ip route get 192.168.1.21&lt;br /&gt;
local 192.168.1.21 dev lo  src 192.168.1.21 &lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; cache &amp;amp;lt;local&amp;amp;gt;  mtu 16436 advmss 16396 hoplimit 64&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can see here that packets sent to this machine's own address will be routed on the lo device, or the loopback interface, even though the destination address was not 127.0.0.1.&lt;br /&gt;
&lt;br /&gt;
On the other hand, 127.0.0.1 is always the loopback interface.  In fact, all of 127.0.0.0/8 will always route to the loopback interface.  It is quite difficult to assign an address in this range to any other interface.  Likewise, you should encounter quite a bit of difficulty trying to send a packet to 127.0.0.0/8 on any interface other than lo.&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || +     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || +&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.  Note that &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is only available if you have installed the [http://xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is simply not tested, which is the same as if it were tested and resulted in a TRUE match.  For example, if you don't specify a protocol, then the rule matches packets of any protocol.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.  You could also specify a netmask of 255.255.255.1 and match all the even or odd addresses in a group of 256.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, notice that we started this ruleset by allowing unlimited traffic on the loopback interface.  But of particular interest is that these rules do not mention the 127.0.0.1 address.  Why not?  Because the loopback interface is used by more than just the 127.0.0.1 address.  In fact, any time you send traffic from the machine to itself, on any IP, it is handled on the loopback interface.  Think about it, how would the computer send packets up to the ethernet adapter, but not actually onto the ethernet cable?  It can't, but it can use the loopback interface instead.&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for default chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Just what is a good scenario in which to use a custom chain?  Whenever you are segregating some portion of your traffic with a common criterion which doesn't apply to the vast majority of unrelated packets.  For example, here is my custom chain for staving off the onslaught of SSH brute force attackers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:SSH-Throttle -&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --set&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --update --seconds 5 --hitcount 2 -j DROP&lt;br /&gt;
-A SSH-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 22 -m conntrack --ctstate NEW -j SSH-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There you have it.  Three rules which don't need to test the protocol, port, or connection tracking state, because this is already done for them by the rule that sent the packets there.&lt;br /&gt;
&lt;br /&gt;
Additionally, here is my custom chain for blocking FTP abusers.  It limits login attempts to ten per minute and sessions to one per source IP.  It also throws some unexpected errors, so programs like hydra get confused and give up after a very short time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:FTP-Throttle -&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --set&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --update --seconds 60 --hitcount 10 -j DROP&lt;br /&gt;
-A FTP-Throttle -m connlimit --connlimit-above 1 -j REJECT --reject-with icmp-admin-prohibited&lt;br /&gt;
-A FTP-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 21 -m conntrack --ctstate NEW -j FTP-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== The Importance Of Organization ==&lt;br /&gt;
&lt;br /&gt;
From all zeros, to all ones, across 32 bits, there are 33 netmasks usable in IPv4 networking.  The ones are always on the left, and the zeros are always on the right.  That's it, 33.  When we line up the bits in a host address with the bits in the netmask, the bits that line up with the ones are the network portion of the address, and the bits that line up with the zeros are the host portion.  The address within the network where all the host bits are zeros (the first address in the network) is the network address.  The address within the network where all the host bits are ones (the last address in the network) is the broadcast address.  When we write a netmask as slash-some-number, like /24, we mean twenty-four ones on the left, and eight zeros on the right.  For every bit you add to the netmask, the size of the network is divided in half.&lt;br /&gt;
&lt;br /&gt;
Now that you understand how to do the math involved in calculating netmasks, network addresses, and broadcast addresses, let's examine how to plan your network.  Let's say you have been given 192.0.2.0/24 as your network allocation.  How are you going to assign addresses to web servers, mail servers, DNS servers, and the like?&lt;br /&gt;
&lt;br /&gt;
The fewer &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules you have, the faster packets will traverse your firewall.  Granted, a single rule takes only microseconds to process, but also your rules will be easier to read if the set is shorter.  So it is beneficial to reduce your rules as much as possible.  And a well planned network will make it easier to reduce your overall rules.&lt;br /&gt;
&lt;br /&gt;
We can divide our network into two /25 networks:  The network addresses will be 192.0.2.0/25 and 192.0.2.128/25.  We can subdivide again into four /26 networks, the last octet will then be 0, 64, 128, and 192.  Keep in mind, we have been allocated all of 192.0.2.0/24, so that's the space that will be routed to us, so we don't need to reserve multiple network and broadcast addresses, we can just use those points as borders between segments.&lt;br /&gt;
&lt;br /&gt;
If we host a lot of commercial web sites, we probably want to provide a lot of our IPs for web hosting.  If we divide up our allocation into four /26 segments, we can cover the two middle allocations with two rules, allowing us 128 web sites.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.64/26  -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.128/26 -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's much better than 128 individual rules allowing web traffic to individual addresses.  Below, we'll also examine how to reduce our rules even further, permitting disparate service allocations in only one rule.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; and hardly a handful of &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Sun, 18 May 2014 20:29:55 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Loopback is more than just 127.0.0.1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Loopback is more than just 127.0.0.1 ==&lt;br /&gt;
&lt;br /&gt;
It seems that a lot of people believe that when a packet is sent to the address assigned to a node's own interface, that packet really goes to that interface.  This is not true, and how could it be?  An interface's job is to put that packet on the wire.  If the packet is addressed to the same machine that sent it, that's the exact job of the loopback interface.&lt;br /&gt;
&lt;br /&gt;
Observe based on the following example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# ip -4 addr ls eth0&lt;br /&gt;
2: eth0: &amp;amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;amp;gt; mtu 1500 qdisc pfifo_fast state UP qlen 1000&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; inet 192.168.1.21/24 brd 192.168.1.255 scope global eth0&lt;br /&gt;
# ip route get 192.168.1.21&lt;br /&gt;
local 192.168.1.21 dev lo  src 192.168.1.21 &lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; cache &amp;amp;lt;local&amp;amp;gt;  mtu 16436 advmss 16396 hoplimit 64&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can see here that packets sent to this machine's own address will be routed on the lo device, or the loopback interface, even though the destination address was not 127.0.0.1.&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || +     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || +&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.  Note that &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is only available if you have installed the [http://xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is simply not tested, which is the same as if it were tested and resulted in a TRUE match.  For example, if you don't specify a protocol, then the rule matches packets of any protocol.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.  You could also specify a netmask of 255.255.255.1 and match all the even or odd addresses in a group of 256.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, notice that we started this ruleset by allowing unlimited traffic on the loopback interface.  But of particular interest is that these rules do not mention the 127.0.0.1 address.  Why not?  Because the loopback interface is used by more than just the 127.0.0.1 address.  In fact, any time you send traffic from the machine to itself, on any IP, it is handled on the loopback interface.  Think about it, how would the computer send packets up to the ethernet adapter, but not actually onto the ethernet cable?  It can't, but it can use the loopback interface instead.&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for default chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Just what is a good scenario in which to use a custom chain?  Whenever you are segregating some portion of your traffic with a common criterion which doesn't apply to the vast majority of unrelated packets.  For example, here is my custom chain for staving off the onslaught of SSH brute force attackers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:SSH-Throttle -&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --set&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --update --seconds 5 --hitcount 2 -j DROP&lt;br /&gt;
-A SSH-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 22 -m conntrack --ctstate NEW -j SSH-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There you have it.  Three rules which don't need to test the protocol, port, or connection tracking state, because this is already done for them by the rule that sent the packets there.&lt;br /&gt;
&lt;br /&gt;
Additionally, here is my custom chain for blocking FTP abusers.  It limits login attempts to ten per minute and sessions to one per source IP.  It also throws some unexpected errors, so programs like hydra get confused and give up after a very short time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:FTP-Throttle -&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --set&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --update --seconds 60 --hitcount 10 -j DROP&lt;br /&gt;
-A FTP-Throttle -m connlimit --connlimit-above 1 -j REJECT --reject-with icmp-admin-prohibited&lt;br /&gt;
-A FTP-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 21 -m conntrack --ctstate NEW -j FTP-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== The Importance Of Organization ==&lt;br /&gt;
&lt;br /&gt;
From all zeros, to all ones, across 32 bits, there are 33 netmasks usable in IPv4 networking.  The ones are always on the left, and the zeros are always on the right.  That's it, 33.  When we line up the bits in a host address with the bits in the netmask, the bits that line up with the ones are the network portion of the address, and the bits that line up with the zeros are the host portion.  The address within the network where all the host bits are zeros (the first address in the network) is the network address.  The address within the network where all the host bits are ones (the last address in the network) is the broadcast address.  When we write a netmask as slash-some-number, like /24, we mean twenty-four ones on the left, and eight zeros on the right.  For every bit you add to the netmask, the size of the network is divided in half.&lt;br /&gt;
&lt;br /&gt;
Now that you understand how to do the math involved in calculating netmasks, network addresses, and broadcast addresses, let's examine how to plan your network.  Let's say you have been given 192.0.2.0/24 as your network allocation.  How are you going to assign addresses to web servers, mail servers, DNS servers, and the like?&lt;br /&gt;
&lt;br /&gt;
The fewer &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules you have, the faster packets will traverse your firewall.  Granted, a single rule takes only microseconds to process, but also your rules will be easier to read if the set is shorter.  So it is beneficial to reduce your rules as much as possible.  And a well planned network will make it easier to reduce your overall rules.&lt;br /&gt;
&lt;br /&gt;
We can divide our network into two /25 networks:  The network addresses will be 192.0.2.0/25 and 192.0.2.128/25.  We can subdivide again into four /26 networks, the last octet will then be 0, 64, 128, and 192.  Keep in mind, we have been allocated all of 192.0.2.0/24, so that's the space that will be routed to us, so we don't need to reserve multiple network and broadcast addresses, we can just use those points as borders between segments.&lt;br /&gt;
&lt;br /&gt;
If we host a lot of commercial web sites, we probably want to provide a lot of our IPs for web hosting.  If we divide up our allocation into four /26 segments, we can cover the two middle allocations with two rules, allowing us 128 web sites.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.64/26  -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.128/26 -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's much better than 128 individual rules allowing web traffic to individual addresses.  Below, we'll also examine how to reduce our rules even further, permitting disparate service allocations in only one rule.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; and hardly a handful of &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Sun, 18 May 2014 20:17:40 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Loopback is more than just 127.0.0.1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Loopback is more than just 127.0.0.1 ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# ip -4 addr ls eth0&lt;br /&gt;
2: eth0: &amp;amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;amp;gt; mtu 1500 qdisc pfifo_fast state UP qlen 1000&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; inet 192.168.1.21/24 brd 192.168.1.255 scope global eth0&lt;br /&gt;
# ip route get 192.168.1.21&lt;br /&gt;
local 192.168.1.21 dev lo  src 192.168.1.21 &lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; cache &amp;amp;lt;local&amp;amp;gt;  mtu 16436 advmss 16396 hoplimit 64&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || +     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || +&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.  Note that &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is only available if you have installed the [http://xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is simply not tested, which is the same as if it were tested and resulted in a TRUE match.  For example, if you don't specify a protocol, then the rule matches packets of any protocol.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.  You could also specify a netmask of 255.255.255.1 and match all the even or odd addresses in a group of 256.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, notice that we started this ruleset by allowing unlimited traffic on the loopback interface.  But of particular interest is that these rules do not mention the 127.0.0.1 address.  Why not?  Because the loopback interface is used by more than just the 127.0.0.1 address.  In fact, any time you send traffic from the machine to itself, on any IP, it is handled on the loopback interface.  Think about it, how would the computer send packets up to the ethernet adapter, but not actually onto the ethernet cable?  It can't, but it can use the loopback interface instead.&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for default chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Just what is a good scenario in which to use a custom chain?  Whenever you are segregating some portion of your traffic with a common criterion which doesn't apply to the vast majority of unrelated packets.  For example, here is my custom chain for staving off the onslaught of SSH brute force attackers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:SSH-Throttle -&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --set&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --update --seconds 5 --hitcount 2 -j DROP&lt;br /&gt;
-A SSH-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 22 -m conntrack --ctstate NEW -j SSH-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There you have it.  Three rules which don't need to test the protocol, port, or connection tracking state, because this is already done for them by the rule that sent the packets there.&lt;br /&gt;
&lt;br /&gt;
Additionally, here is my custom chain for blocking FTP abusers.  It limits login attempts to ten per minute and sessions to one per source IP.  It also throws some unexpected errors, so programs like hydra get confused and give up after a very short time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:FTP-Throttle -&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --set&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --update --seconds 60 --hitcount 10 -j DROP&lt;br /&gt;
-A FTP-Throttle -m connlimit --connlimit-above 1 -j REJECT --reject-with icmp-admin-prohibited&lt;br /&gt;
-A FTP-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 21 -m conntrack --ctstate NEW -j FTP-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== The Importance Of Organization ==&lt;br /&gt;
&lt;br /&gt;
From all zeros, to all ones, across 32 bits, there are 33 netmasks usable in IPv4 networking.  The ones are always on the left, and the zeros are always on the right.  That's it, 33.  When we line up the bits in a host address with the bits in the netmask, the bits that line up with the ones are the network portion of the address, and the bits that line up with the zeros are the host portion.  The address within the network where all the host bits are zeros (the first address in the network) is the network address.  The address within the network where all the host bits are ones (the last address in the network) is the broadcast address.  When we write a netmask as slash-some-number, like /24, we mean twenty-four ones on the left, and eight zeros on the right.  For every bit you add to the netmask, the size of the network is divided in half.&lt;br /&gt;
&lt;br /&gt;
Now that you understand how to do the math involved in calculating netmasks, network addresses, and broadcast addresses, let's examine how to plan your network.  Let's say you have been given 192.0.2.0/24 as your network allocation.  How are you going to assign addresses to web servers, mail servers, DNS servers, and the like?&lt;br /&gt;
&lt;br /&gt;
The fewer &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules you have, the faster packets will traverse your firewall.  Granted, a single rule takes only microseconds to process, but also your rules will be easier to read if the set is shorter.  So it is beneficial to reduce your rules as much as possible.  And a well planned network will make it easier to reduce your overall rules.&lt;br /&gt;
&lt;br /&gt;
We can divide our network into two /25 networks:  The network addresses will be 192.0.2.0/25 and 192.0.2.128/25.  We can subdivide again into four /26 networks, the last octet will then be 0, 64, 128, and 192.  Keep in mind, we have been allocated all of 192.0.2.0/24, so that's the space that will be routed to us, so we don't need to reserve multiple network and broadcast addresses, we can just use those points as borders between segments.&lt;br /&gt;
&lt;br /&gt;
If we host a lot of commercial web sites, we probably want to provide a lot of our IPs for web hosting.  If we divide up our allocation into four /26 segments, we can cover the two middle allocations with two rules, allowing us 128 web sites.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.64/26  -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.128/26 -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's much better than 128 individual rules allowing web traffic to individual addresses.  Below, we'll also examine how to reduce our rules even further, permitting disparate service allocations in only one rule.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; and hardly a handful of &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Sun, 18 May 2014 20:11:37 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Loopback is more than just 127.0.0.1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Loopback is more than just 127.0.0.1 ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
\# '''ip -4 a ls eth0'''&lt;br /&gt;
2: eth0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc pfifo_fast state UP qlen 1000&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; inet ''192.168.1.21/24'' brd 192.168.1.255 scope global eth0&lt;br /&gt;
\# '''ip r get 192.168.1.21'''&lt;br /&gt;
local 192.168.1.21 ''dev lo''  src 192.168.1.21 &lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; cache &amp;lt;local&amp;gt;  mtu 16436 advmss 16396 hoplimit 64&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || +     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || +&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.  Note that &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is only available if you have installed the [http://xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is simply not tested, which is the same as if it were tested and resulted in a TRUE match.  For example, if you don't specify a protocol, then the rule matches packets of any protocol.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.  You could also specify a netmask of 255.255.255.1 and match all the even or odd addresses in a group of 256.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, notice that we started this ruleset by allowing unlimited traffic on the loopback interface.  But of particular interest is that these rules do not mention the 127.0.0.1 address.  Why not?  Because the loopback interface is used by more than just the 127.0.0.1 address.  In fact, any time you send traffic from the machine to itself, on any IP, it is handled on the loopback interface.  Think about it, how would the computer send packets up to the ethernet adapter, but not actually onto the ethernet cable?  It can't, but it can use the loopback interface instead.&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for default chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Just what is a good scenario in which to use a custom chain?  Whenever you are segregating some portion of your traffic with a common criterion which doesn't apply to the vast majority of unrelated packets.  For example, here is my custom chain for staving off the onslaught of SSH brute force attackers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:SSH-Throttle -&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --set&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --update --seconds 5 --hitcount 2 -j DROP&lt;br /&gt;
-A SSH-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 22 -m conntrack --ctstate NEW -j SSH-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There you have it.  Three rules which don't need to test the protocol, port, or connection tracking state, because this is already done for them by the rule that sent the packets there.&lt;br /&gt;
&lt;br /&gt;
Additionally, here is my custom chain for blocking FTP abusers.  It limits login attempts to ten per minute and sessions to one per source IP.  It also throws some unexpected errors, so programs like hydra get confused and give up after a very short time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:FTP-Throttle -&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --set&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --update --seconds 60 --hitcount 10 -j DROP&lt;br /&gt;
-A FTP-Throttle -m connlimit --connlimit-above 1 -j REJECT --reject-with icmp-admin-prohibited&lt;br /&gt;
-A FTP-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 21 -m conntrack --ctstate NEW -j FTP-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== The Importance Of Organization ==&lt;br /&gt;
&lt;br /&gt;
From all zeros, to all ones, across 32 bits, there are 33 netmasks usable in IPv4 networking.  The ones are always on the left, and the zeros are always on the right.  That's it, 33.  When we line up the bits in a host address with the bits in the netmask, the bits that line up with the ones are the network portion of the address, and the bits that line up with the zeros are the host portion.  The address within the network where all the host bits are zeros (the first address in the network) is the network address.  The address within the network where all the host bits are ones (the last address in the network) is the broadcast address.  When we write a netmask as slash-some-number, like /24, we mean twenty-four ones on the left, and eight zeros on the right.  For every bit you add to the netmask, the size of the network is divided in half.&lt;br /&gt;
&lt;br /&gt;
Now that you understand how to do the math involved in calculating netmasks, network addresses, and broadcast addresses, let's examine how to plan your network.  Let's say you have been given 192.0.2.0/24 as your network allocation.  How are you going to assign addresses to web servers, mail servers, DNS servers, and the like?&lt;br /&gt;
&lt;br /&gt;
The fewer &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules you have, the faster packets will traverse your firewall.  Granted, a single rule takes only microseconds to process, but also your rules will be easier to read if the set is shorter.  So it is beneficial to reduce your rules as much as possible.  And a well planned network will make it easier to reduce your overall rules.&lt;br /&gt;
&lt;br /&gt;
We can divide our network into two /25 networks:  The network addresses will be 192.0.2.0/25 and 192.0.2.128/25.  We can subdivide again into four /26 networks, the last octet will then be 0, 64, 128, and 192.  Keep in mind, we have been allocated all of 192.0.2.0/24, so that's the space that will be routed to us, so we don't need to reserve multiple network and broadcast addresses, we can just use those points as borders between segments.&lt;br /&gt;
&lt;br /&gt;
If we host a lot of commercial web sites, we probably want to provide a lot of our IPs for web hosting.  If we divide up our allocation into four /26 segments, we can cover the two middle allocations with two rules, allowing us 128 web sites.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.64/26  -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.128/26 -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's much better than 128 individual rules allowing web traffic to individual addresses.  Below, we'll also examine how to reduce our rules even further, permitting disparate service allocations in only one rule.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; and hardly a handful of &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Sun, 18 May 2014 20:06:46 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Loopback is more than just 127.0.0.1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Loopback is more than just 127.0.0.1 ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
# '''ip -4 a ls eth0'''&lt;br /&gt;
2: eth0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc pfifo_fast state UP qlen 1000&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; inet ''192.168.1.21/24'' brd 192.168.1.255 scope global eth0&lt;br /&gt;
# '''ip r get 192.168.1.21'''&lt;br /&gt;
local 192.168.1.21 ''dev lo''  src 192.168.1.21 &lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; cache &amp;lt;local&amp;gt;  mtu 16436 advmss 16396 hoplimit 64&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || +     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || +&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.  Note that &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is only available if you have installed the [http://xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is simply not tested, which is the same as if it were tested and resulted in a TRUE match.  For example, if you don't specify a protocol, then the rule matches packets of any protocol.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.  You could also specify a netmask of 255.255.255.1 and match all the even or odd addresses in a group of 256.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, notice that we started this ruleset by allowing unlimited traffic on the loopback interface.  But of particular interest is that these rules do not mention the 127.0.0.1 address.  Why not?  Because the loopback interface is used by more than just the 127.0.0.1 address.  In fact, any time you send traffic from the machine to itself, on any IP, it is handled on the loopback interface.  Think about it, how would the computer send packets up to the ethernet adapter, but not actually onto the ethernet cable?  It can't, but it can use the loopback interface instead.&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for default chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Just what is a good scenario in which to use a custom chain?  Whenever you are segregating some portion of your traffic with a common criterion which doesn't apply to the vast majority of unrelated packets.  For example, here is my custom chain for staving off the onslaught of SSH brute force attackers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:SSH-Throttle -&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --set&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --update --seconds 5 --hitcount 2 -j DROP&lt;br /&gt;
-A SSH-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 22 -m conntrack --ctstate NEW -j SSH-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There you have it.  Three rules which don't need to test the protocol, port, or connection tracking state, because this is already done for them by the rule that sent the packets there.&lt;br /&gt;
&lt;br /&gt;
Additionally, here is my custom chain for blocking FTP abusers.  It limits login attempts to ten per minute and sessions to one per source IP.  It also throws some unexpected errors, so programs like hydra get confused and give up after a very short time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:FTP-Throttle -&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --set&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --update --seconds 60 --hitcount 10 -j DROP&lt;br /&gt;
-A FTP-Throttle -m connlimit --connlimit-above 1 -j REJECT --reject-with icmp-admin-prohibited&lt;br /&gt;
-A FTP-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 21 -m conntrack --ctstate NEW -j FTP-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== The Importance Of Organization ==&lt;br /&gt;
&lt;br /&gt;
From all zeros, to all ones, across 32 bits, there are 33 netmasks usable in IPv4 networking.  The ones are always on the left, and the zeros are always on the right.  That's it, 33.  When we line up the bits in a host address with the bits in the netmask, the bits that line up with the ones are the network portion of the address, and the bits that line up with the zeros are the host portion.  The address within the network where all the host bits are zeros (the first address in the network) is the network address.  The address within the network where all the host bits are ones (the last address in the network) is the broadcast address.  When we write a netmask as slash-some-number, like /24, we mean twenty-four ones on the left, and eight zeros on the right.  For every bit you add to the netmask, the size of the network is divided in half.&lt;br /&gt;
&lt;br /&gt;
Now that you understand how to do the math involved in calculating netmasks, network addresses, and broadcast addresses, let's examine how to plan your network.  Let's say you have been given 192.0.2.0/24 as your network allocation.  How are you going to assign addresses to web servers, mail servers, DNS servers, and the like?&lt;br /&gt;
&lt;br /&gt;
The fewer &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules you have, the faster packets will traverse your firewall.  Granted, a single rule takes only microseconds to process, but also your rules will be easier to read if the set is shorter.  So it is beneficial to reduce your rules as much as possible.  And a well planned network will make it easier to reduce your overall rules.&lt;br /&gt;
&lt;br /&gt;
We can divide our network into two /25 networks:  The network addresses will be 192.0.2.0/25 and 192.0.2.128/25.  We can subdivide again into four /26 networks, the last octet will then be 0, 64, 128, and 192.  Keep in mind, we have been allocated all of 192.0.2.0/24, so that's the space that will be routed to us, so we don't need to reserve multiple network and broadcast addresses, we can just use those points as borders between segments.&lt;br /&gt;
&lt;br /&gt;
If we host a lot of commercial web sites, we probably want to provide a lot of our IPs for web hosting.  If we divide up our allocation into four /26 segments, we can cover the two middle allocations with two rules, allowing us 128 web sites.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.64/26  -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.128/26 -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's much better than 128 individual rules allowing web traffic to individual addresses.  Below, we'll also examine how to reduce our rules even further, permitting disparate service allocations in only one rule.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; and hardly a handful of &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Sun, 18 May 2014 20:05:52 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Loopback is more than just 127.0.0.1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Loopback is more than just 127.0.0.1 ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
# ''ip -4 a ls eth0''&lt;br /&gt;
2: eth0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc pfifo_fast state UP qlen 1000&lt;br /&gt;
    inet '''192.168.1.21/24 brd 192.168.1.255 scope global eth0&lt;br /&gt;
# ''ip r get 192.168.1.21''&lt;br /&gt;
local 192.168.1.21 '''dev lo'''  src 192.168.1.21 &lt;br /&gt;
    cache &amp;lt;local&amp;gt;  mtu 16436 advmss 16396 hoplimit 64&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || +     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || +&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.  Note that &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is only available if you have installed the [http://xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is simply not tested, which is the same as if it were tested and resulted in a TRUE match.  For example, if you don't specify a protocol, then the rule matches packets of any protocol.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.  You could also specify a netmask of 255.255.255.1 and match all the even or odd addresses in a group of 256.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, notice that we started this ruleset by allowing unlimited traffic on the loopback interface.  But of particular interest is that these rules do not mention the 127.0.0.1 address.  Why not?  Because the loopback interface is used by more than just the 127.0.0.1 address.  In fact, any time you send traffic from the machine to itself, on any IP, it is handled on the loopback interface.  Think about it, how would the computer send packets up to the ethernet adapter, but not actually onto the ethernet cable?  It can't, but it can use the loopback interface instead.&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for default chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Just what is a good scenario in which to use a custom chain?  Whenever you are segregating some portion of your traffic with a common criterion which doesn't apply to the vast majority of unrelated packets.  For example, here is my custom chain for staving off the onslaught of SSH brute force attackers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:SSH-Throttle -&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --set&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --update --seconds 5 --hitcount 2 -j DROP&lt;br /&gt;
-A SSH-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 22 -m conntrack --ctstate NEW -j SSH-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There you have it.  Three rules which don't need to test the protocol, port, or connection tracking state, because this is already done for them by the rule that sent the packets there.&lt;br /&gt;
&lt;br /&gt;
Additionally, here is my custom chain for blocking FTP abusers.  It limits login attempts to ten per minute and sessions to one per source IP.  It also throws some unexpected errors, so programs like hydra get confused and give up after a very short time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:FTP-Throttle -&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --set&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --update --seconds 60 --hitcount 10 -j DROP&lt;br /&gt;
-A FTP-Throttle -m connlimit --connlimit-above 1 -j REJECT --reject-with icmp-admin-prohibited&lt;br /&gt;
-A FTP-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 21 -m conntrack --ctstate NEW -j FTP-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== The Importance Of Organization ==&lt;br /&gt;
&lt;br /&gt;
From all zeros, to all ones, across 32 bits, there are 33 netmasks usable in IPv4 networking.  The ones are always on the left, and the zeros are always on the right.  That's it, 33.  When we line up the bits in a host address with the bits in the netmask, the bits that line up with the ones are the network portion of the address, and the bits that line up with the zeros are the host portion.  The address within the network where all the host bits are zeros (the first address in the network) is the network address.  The address within the network where all the host bits are ones (the last address in the network) is the broadcast address.  When we write a netmask as slash-some-number, like /24, we mean twenty-four ones on the left, and eight zeros on the right.  For every bit you add to the netmask, the size of the network is divided in half.&lt;br /&gt;
&lt;br /&gt;
Now that you understand how to do the math involved in calculating netmasks, network addresses, and broadcast addresses, let's examine how to plan your network.  Let's say you have been given 192.0.2.0/24 as your network allocation.  How are you going to assign addresses to web servers, mail servers, DNS servers, and the like?&lt;br /&gt;
&lt;br /&gt;
The fewer &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules you have, the faster packets will traverse your firewall.  Granted, a single rule takes only microseconds to process, but also your rules will be easier to read if the set is shorter.  So it is beneficial to reduce your rules as much as possible.  And a well planned network will make it easier to reduce your overall rules.&lt;br /&gt;
&lt;br /&gt;
We can divide our network into two /25 networks:  The network addresses will be 192.0.2.0/25 and 192.0.2.128/25.  We can subdivide again into four /26 networks, the last octet will then be 0, 64, 128, and 192.  Keep in mind, we have been allocated all of 192.0.2.0/24, so that's the space that will be routed to us, so we don't need to reserve multiple network and broadcast addresses, we can just use those points as borders between segments.&lt;br /&gt;
&lt;br /&gt;
If we host a lot of commercial web sites, we probably want to provide a lot of our IPs for web hosting.  If we divide up our allocation into four /26 segments, we can cover the two middle allocations with two rules, allowing us 128 web sites.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.64/26  -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.128/26 -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's much better than 128 individual rules allowing web traffic to individual addresses.  Below, we'll also examine how to reduce our rules even further, permitting disparate service allocations in only one rule.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; and hardly a handful of &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Sun, 18 May 2014 20:04:18 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Loopback is more than just 127.0.0.1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Loopback is more than just 127.0.0.1 ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;# **ip -4 a ls eth0**&amp;lt;/tt&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;2: eth0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc pfifo_fast state UP qlen 1000&amp;lt;/tt&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; inet ***192.168.1.21/24*** brd 192.168.1.255 scope global eth0&amp;lt;/tt&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;# **ip r get 192.168.1.21**&amp;lt;/tt&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;local 192.168.1.21 ***dev lo***  src 192.168.1.21 &amp;lt;/tt&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; cache &amp;lt;local&amp;gt;  mtu 16436 advmss 16396 hoplimit 64&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || +     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || +&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.  Note that &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is only available if you have installed the [http://xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is simply not tested, which is the same as if it were tested and resulted in a TRUE match.  For example, if you don't specify a protocol, then the rule matches packets of any protocol.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.  You could also specify a netmask of 255.255.255.1 and match all the even or odd addresses in a group of 256.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, notice that we started this ruleset by allowing unlimited traffic on the loopback interface.  But of particular interest is that these rules do not mention the 127.0.0.1 address.  Why not?  Because the loopback interface is used by more than just the 127.0.0.1 address.  In fact, any time you send traffic from the machine to itself, on any IP, it is handled on the loopback interface.  Think about it, how would the computer send packets up to the ethernet adapter, but not actually onto the ethernet cable?  It can't, but it can use the loopback interface instead.&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for default chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Just what is a good scenario in which to use a custom chain?  Whenever you are segregating some portion of your traffic with a common criterion which doesn't apply to the vast majority of unrelated packets.  For example, here is my custom chain for staving off the onslaught of SSH brute force attackers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:SSH-Throttle -&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --set&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --update --seconds 5 --hitcount 2 -j DROP&lt;br /&gt;
-A SSH-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 22 -m conntrack --ctstate NEW -j SSH-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There you have it.  Three rules which don't need to test the protocol, port, or connection tracking state, because this is already done for them by the rule that sent the packets there.&lt;br /&gt;
&lt;br /&gt;
Additionally, here is my custom chain for blocking FTP abusers.  It limits login attempts to ten per minute and sessions to one per source IP.  It also throws some unexpected errors, so programs like hydra get confused and give up after a very short time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:FTP-Throttle -&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --set&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --update --seconds 60 --hitcount 10 -j DROP&lt;br /&gt;
-A FTP-Throttle -m connlimit --connlimit-above 1 -j REJECT --reject-with icmp-admin-prohibited&lt;br /&gt;
-A FTP-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 21 -m conntrack --ctstate NEW -j FTP-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== The Importance Of Organization ==&lt;br /&gt;
&lt;br /&gt;
From all zeros, to all ones, across 32 bits, there are 33 netmasks usable in IPv4 networking.  The ones are always on the left, and the zeros are always on the right.  That's it, 33.  When we line up the bits in a host address with the bits in the netmask, the bits that line up with the ones are the network portion of the address, and the bits that line up with the zeros are the host portion.  The address within the network where all the host bits are zeros (the first address in the network) is the network address.  The address within the network where all the host bits are ones (the last address in the network) is the broadcast address.  When we write a netmask as slash-some-number, like /24, we mean twenty-four ones on the left, and eight zeros on the right.  For every bit you add to the netmask, the size of the network is divided in half.&lt;br /&gt;
&lt;br /&gt;
Now that you understand how to do the math involved in calculating netmasks, network addresses, and broadcast addresses, let's examine how to plan your network.  Let's say you have been given 192.0.2.0/24 as your network allocation.  How are you going to assign addresses to web servers, mail servers, DNS servers, and the like?&lt;br /&gt;
&lt;br /&gt;
The fewer &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules you have, the faster packets will traverse your firewall.  Granted, a single rule takes only microseconds to process, but also your rules will be easier to read if the set is shorter.  So it is beneficial to reduce your rules as much as possible.  And a well planned network will make it easier to reduce your overall rules.&lt;br /&gt;
&lt;br /&gt;
We can divide our network into two /25 networks:  The network addresses will be 192.0.2.0/25 and 192.0.2.128/25.  We can subdivide again into four /26 networks, the last octet will then be 0, 64, 128, and 192.  Keep in mind, we have been allocated all of 192.0.2.0/24, so that's the space that will be routed to us, so we don't need to reserve multiple network and broadcast addresses, we can just use those points as borders between segments.&lt;br /&gt;
&lt;br /&gt;
If we host a lot of commercial web sites, we probably want to provide a lot of our IPs for web hosting.  If we divide up our allocation into four /26 segments, we can cover the two middle allocations with two rules, allowing us 128 web sites.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.64/26  -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.128/26 -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's much better than 128 individual rules allowing web traffic to individual addresses.  Below, we'll also examine how to reduce our rules even further, permitting disparate service allocations in only one rule.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; and hardly a handful of &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Sun, 18 May 2014 19:55:20 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Loopback is more than just 127.0.0.1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Loopback is more than just 127.0.0.1 ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# **ip -4 a ls eth0**&lt;br /&gt;
2: eth0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc pfifo_fast state UP qlen 1000&lt;br /&gt;
    inet ***192.168.1.21/24*** brd 192.168.1.255 scope global eth0&lt;br /&gt;
# **ip r get 192.168.1.21**&lt;br /&gt;
local 192.168.1.21 ***dev lo***  src 192.168.1.21 &lt;br /&gt;
    cache &amp;lt;local&amp;gt;  mtu 16436 advmss 16396 hoplimit 64&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || +     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || +&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.  Note that &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is only available if you have installed the [http://xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is simply not tested, which is the same as if it were tested and resulted in a TRUE match.  For example, if you don't specify a protocol, then the rule matches packets of any protocol.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.  You could also specify a netmask of 255.255.255.1 and match all the even or odd addresses in a group of 256.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, notice that we started this ruleset by allowing unlimited traffic on the loopback interface.  But of particular interest is that these rules do not mention the 127.0.0.1 address.  Why not?  Because the loopback interface is used by more than just the 127.0.0.1 address.  In fact, any time you send traffic from the machine to itself, on any IP, it is handled on the loopback interface.  Think about it, how would the computer send packets up to the ethernet adapter, but not actually onto the ethernet cable?  It can't, but it can use the loopback interface instead.&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for default chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Just what is a good scenario in which to use a custom chain?  Whenever you are segregating some portion of your traffic with a common criterion which doesn't apply to the vast majority of unrelated packets.  For example, here is my custom chain for staving off the onslaught of SSH brute force attackers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:SSH-Throttle -&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --set&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --update --seconds 5 --hitcount 2 -j DROP&lt;br /&gt;
-A SSH-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 22 -m conntrack --ctstate NEW -j SSH-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There you have it.  Three rules which don't need to test the protocol, port, or connection tracking state, because this is already done for them by the rule that sent the packets there.&lt;br /&gt;
&lt;br /&gt;
Additionally, here is my custom chain for blocking FTP abusers.  It limits login attempts to ten per minute and sessions to one per source IP.  It also throws some unexpected errors, so programs like hydra get confused and give up after a very short time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:FTP-Throttle -&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --set&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --update --seconds 60 --hitcount 10 -j DROP&lt;br /&gt;
-A FTP-Throttle -m connlimit --connlimit-above 1 -j REJECT --reject-with icmp-admin-prohibited&lt;br /&gt;
-A FTP-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 21 -m conntrack --ctstate NEW -j FTP-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== The Importance Of Organization ==&lt;br /&gt;
&lt;br /&gt;
From all zeros, to all ones, across 32 bits, there are 33 netmasks usable in IPv4 networking.  The ones are always on the left, and the zeros are always on the right.  That's it, 33.  When we line up the bits in a host address with the bits in the netmask, the bits that line up with the ones are the network portion of the address, and the bits that line up with the zeros are the host portion.  The address within the network where all the host bits are zeros (the first address in the network) is the network address.  The address within the network where all the host bits are ones (the last address in the network) is the broadcast address.  When we write a netmask as slash-some-number, like /24, we mean twenty-four ones on the left, and eight zeros on the right.  For every bit you add to the netmask, the size of the network is divided in half.&lt;br /&gt;
&lt;br /&gt;
Now that you understand how to do the math involved in calculating netmasks, network addresses, and broadcast addresses, let's examine how to plan your network.  Let's say you have been given 192.0.2.0/24 as your network allocation.  How are you going to assign addresses to web servers, mail servers, DNS servers, and the like?&lt;br /&gt;
&lt;br /&gt;
The fewer &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules you have, the faster packets will traverse your firewall.  Granted, a single rule takes only microseconds to process, but also your rules will be easier to read if the set is shorter.  So it is beneficial to reduce your rules as much as possible.  And a well planned network will make it easier to reduce your overall rules.&lt;br /&gt;
&lt;br /&gt;
We can divide our network into two /25 networks:  The network addresses will be 192.0.2.0/25 and 192.0.2.128/25.  We can subdivide again into four /26 networks, the last octet will then be 0, 64, 128, and 192.  Keep in mind, we have been allocated all of 192.0.2.0/24, so that's the space that will be routed to us, so we don't need to reserve multiple network and broadcast addresses, we can just use those points as borders between segments.&lt;br /&gt;
&lt;br /&gt;
If we host a lot of commercial web sites, we probably want to provide a lot of our IPs for web hosting.  If we divide up our allocation into four /26 segments, we can cover the two middle allocations with two rules, allowing us 128 web sites.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.64/26  -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.128/26 -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's much better than 128 individual rules allowing web traffic to individual addresses.  Below, we'll also examine how to reduce our rules even further, permitting disparate service allocations in only one rule.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; and hardly a handful of &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Sun, 18 May 2014 19:52:25 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Loopback is more than just 127.0.0.1 ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
# **ip -4 a ls eth0**&lt;br /&gt;
2: eth0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc pfifo_fast state UP qlen 1000&lt;br /&gt;
    inet ***192.168.1.21/24*** brd 192.168.1.255 scope global eth0&lt;br /&gt;
# **ip r get 192.168.1.21**&lt;br /&gt;
local 192.168.1.21 ***dev lo***  src 192.168.1.21 &lt;br /&gt;
    cache &amp;lt;local&amp;gt;  mtu 16436 advmss 16396 hoplimit 64&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || +     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || +&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.  Note that &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is only available if you have installed the [http://xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is simply not tested, which is the same as if it were tested and resulted in a TRUE match.  For example, if you don't specify a protocol, then the rule matches packets of any protocol.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.  You could also specify a netmask of 255.255.255.1 and match all the even or odd addresses in a group of 256.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, notice that we started this ruleset by allowing unlimited traffic on the loopback interface.  But of particular interest is that these rules do not mention the 127.0.0.1 address.  Why not?  Because the loopback interface is used by more than just the 127.0.0.1 address.  In fact, any time you send traffic from the machine to itself, on any IP, it is handled on the loopback interface.  Think about it, how would the computer send packets up to the ethernet adapter, but not actually onto the ethernet cable?  It can't, but it can use the loopback interface instead.&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for default chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Just what is a good scenario in which to use a custom chain?  Whenever you are segregating some portion of your traffic with a common criterion which doesn't apply to the vast majority of unrelated packets.  For example, here is my custom chain for staving off the onslaught of SSH brute force attackers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:SSH-Throttle -&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --set&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --update --seconds 5 --hitcount 2 -j DROP&lt;br /&gt;
-A SSH-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 22 -m conntrack --ctstate NEW -j SSH-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There you have it.  Three rules which don't need to test the protocol, port, or connection tracking state, because this is already done for them by the rule that sent the packets there.&lt;br /&gt;
&lt;br /&gt;
Additionally, here is my custom chain for blocking FTP abusers.  It limits login attempts to ten per minute and sessions to one per source IP.  It also throws some unexpected errors, so programs like hydra get confused and give up after a very short time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:FTP-Throttle -&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --set&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --update --seconds 60 --hitcount 10 -j DROP&lt;br /&gt;
-A FTP-Throttle -m connlimit --connlimit-above 1 -j REJECT --reject-with icmp-admin-prohibited&lt;br /&gt;
-A FTP-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 21 -m conntrack --ctstate NEW -j FTP-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== The Importance Of Organization ==&lt;br /&gt;
&lt;br /&gt;
From all zeros, to all ones, across 32 bits, there are 33 netmasks usable in IPv4 networking.  The ones are always on the left, and the zeros are always on the right.  That's it, 33.  When we line up the bits in a host address with the bits in the netmask, the bits that line up with the ones are the network portion of the address, and the bits that line up with the zeros are the host portion.  The address within the network where all the host bits are zeros (the first address in the network) is the network address.  The address within the network where all the host bits are ones (the last address in the network) is the broadcast address.  When we write a netmask as slash-some-number, like /24, we mean twenty-four ones on the left, and eight zeros on the right.  For every bit you add to the netmask, the size of the network is divided in half.&lt;br /&gt;
&lt;br /&gt;
Now that you understand how to do the math involved in calculating netmasks, network addresses, and broadcast addresses, let's examine how to plan your network.  Let's say you have been given 192.0.2.0/24 as your network allocation.  How are you going to assign addresses to web servers, mail servers, DNS servers, and the like?&lt;br /&gt;
&lt;br /&gt;
The fewer &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules you have, the faster packets will traverse your firewall.  Granted, a single rule takes only microseconds to process, but also your rules will be easier to read if the set is shorter.  So it is beneficial to reduce your rules as much as possible.  And a well planned network will make it easier to reduce your overall rules.&lt;br /&gt;
&lt;br /&gt;
We can divide our network into two /25 networks:  The network addresses will be 192.0.2.0/25 and 192.0.2.128/25.  We can subdivide again into four /26 networks, the last octet will then be 0, 64, 128, and 192.  Keep in mind, we have been allocated all of 192.0.2.0/24, so that's the space that will be routed to us, so we don't need to reserve multiple network and broadcast addresses, we can just use those points as borders between segments.&lt;br /&gt;
&lt;br /&gt;
If we host a lot of commercial web sites, we probably want to provide a lot of our IPs for web hosting.  If we divide up our allocation into four /26 segments, we can cover the two middle allocations with two rules, allowing us 128 web sites.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.64/26  -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.128/26 -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's much better than 128 individual rules allowing web traffic to individual addresses.  Below, we'll also examine how to reduce our rules even further, permitting disparate service allocations in only one rule.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; and hardly a handful of &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Sun, 18 May 2014 19:51:36 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Custom Chains */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || +     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || +&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.  Note that &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is only available if you have installed the [http://xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is simply not tested, which is the same as if it were tested and resulted in a TRUE match.  For example, if you don't specify a protocol, then the rule matches packets of any protocol.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.  You could also specify a netmask of 255.255.255.1 and match all the even or odd addresses in a group of 256.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, notice that we started this ruleset by allowing unlimited traffic on the loopback interface.  But of particular interest is that these rules do not mention the 127.0.0.1 address.  Why not?  Because the loopback interface is used by more than just the 127.0.0.1 address.  In fact, any time you send traffic from the machine to itself, on any IP, it is handled on the loopback interface.  Think about it, how would the computer send packets up to the ethernet adapter, but not actually onto the ethernet cable?  It can't, but it can use the loopback interface instead.&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for default chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Just what is a good scenario in which to use a custom chain?  Whenever you are segregating some portion of your traffic with a common criterion which doesn't apply to the vast majority of unrelated packets.  For example, here is my custom chain for staving off the onslaught of SSH brute force attackers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:SSH-Throttle -&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --set&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --update --seconds 5 --hitcount 2 -j DROP&lt;br /&gt;
-A SSH-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 22 -m conntrack --ctstate NEW -j SSH-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There you have it.  Three rules which don't need to test the protocol, port, or connection tracking state, because this is already done for them by the rule that sent the packets there.&lt;br /&gt;
&lt;br /&gt;
Additionally, here is my custom chain for blocking FTP abusers.  It limits login attempts to ten per minute and sessions to one per source IP.  It also throws some unexpected errors, so programs like hydra get confused and give up after a very short time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:FTP-Throttle -&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --set&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --update --seconds 60 --hitcount 10 -j DROP&lt;br /&gt;
-A FTP-Throttle -m connlimit --connlimit-above 1 -j REJECT --reject-with icmp-admin-prohibited&lt;br /&gt;
-A FTP-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 21 -m conntrack --ctstate NEW -j FTP-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== The Importance Of Organization ==&lt;br /&gt;
&lt;br /&gt;
From all zeros, to all ones, across 32 bits, there are 33 netmasks usable in IPv4 networking.  The ones are always on the left, and the zeros are always on the right.  That's it, 33.  When we line up the bits in a host address with the bits in the netmask, the bits that line up with the ones are the network portion of the address, and the bits that line up with the zeros are the host portion.  The address within the network where all the host bits are zeros (the first address in the network) is the network address.  The address within the network where all the host bits are ones (the last address in the network) is the broadcast address.  When we write a netmask as slash-some-number, like /24, we mean twenty-four ones on the left, and eight zeros on the right.  For every bit you add to the netmask, the size of the network is divided in half.&lt;br /&gt;
&lt;br /&gt;
Now that you understand how to do the math involved in calculating netmasks, network addresses, and broadcast addresses, let's examine how to plan your network.  Let's say you have been given 192.0.2.0/24 as your network allocation.  How are you going to assign addresses to web servers, mail servers, DNS servers, and the like?&lt;br /&gt;
&lt;br /&gt;
The fewer &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules you have, the faster packets will traverse your firewall.  Granted, a single rule takes only microseconds to process, but also your rules will be easier to read if the set is shorter.  So it is beneficial to reduce your rules as much as possible.  And a well planned network will make it easier to reduce your overall rules.&lt;br /&gt;
&lt;br /&gt;
We can divide our network into two /25 networks:  The network addresses will be 192.0.2.0/25 and 192.0.2.128/25.  We can subdivide again into four /26 networks, the last octet will then be 0, 64, 128, and 192.  Keep in mind, we have been allocated all of 192.0.2.0/24, so that's the space that will be routed to us, so we don't need to reserve multiple network and broadcast addresses, we can just use those points as borders between segments.&lt;br /&gt;
&lt;br /&gt;
If we host a lot of commercial web sites, we probably want to provide a lot of our IPs for web hosting.  If we divide up our allocation into four /26 segments, we can cover the two middle allocations with two rules, allowing us 128 web sites.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.64/26  -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.128/26 -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's much better than 128 individual rules allowing web traffic to individual addresses.  Below, we'll also examine how to reduce our rules even further, permitting disparate service allocations in only one rule.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; and hardly a handful of &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Fri, 11 Apr 2014 07:01:22 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Custom Chains */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || +     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || +&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.  Note that &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is only available if you have installed the [http://xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is simply not tested, which is the same as if it were tested and resulted in a TRUE match.  For example, if you don't specify a protocol, then the rule matches packets of any protocol.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.  You could also specify a netmask of 255.255.255.1 and match all the even or odd addresses in a group of 256.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, notice that we started this ruleset by allowing unlimited traffic on the loopback interface.  But of particular interest is that these rules do not mention the 127.0.0.1 address.  Why not?  Because the loopback interface is used by more than just the 127.0.0.1 address.  In fact, any time you send traffic from the machine to itself, on any IP, it is handled on the loopback interface.  Think about it, how would the computer send packets up to the ethernet adapter, but not actually onto the ethernet cable?  It can't, but it can use the loopback interface instead.&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for default chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Just what is a good scenario in which to use a custom chain?  Whenever you are segregating some portion of your traffic with a common criterion which doesn't apply to the vast majority of unrelated packets.  For example, here is my custom chain for staving off the onslaught of SSH brute force attackers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:SSH-Throttle -&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --set&lt;br /&gt;
-A SSH-Throttle -m recent --name ssh_throttle --update --seconds 5 --hitcount 2 -j DROP&lt;br /&gt;
-A SSH-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 22 -m conntrack --ctstate NEW -j SSH-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There you have it.  Three rules which don't need to test the protocol, port, or connection tracking state, because this is already done for them by the rule that sent the packets there.&lt;br /&gt;
&lt;br /&gt;
Additionally, here is my custom chain for blocking FTP abusers.  It limits connections to ten per minute and one per source IP.  It also throws some unexpected errors, so programs like hydra get confused and give up after a very short time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:FTP-Throttle -&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --set&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --update --seconds 60 --hitcount 10 -j DROP&lt;br /&gt;
-A FTP-Throttle -m connlimit --connlimit-above 1 -j REJECT --reject-with icmp-admin-prohibited&lt;br /&gt;
-A FTP-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 21 -m conntrack --ctstate NEW -j FTP-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== The Importance Of Organization ==&lt;br /&gt;
&lt;br /&gt;
From all zeros, to all ones, across 32 bits, there are 33 netmasks usable in IPv4 networking.  The ones are always on the left, and the zeros are always on the right.  That's it, 33.  When we line up the bits in a host address with the bits in the netmask, the bits that line up with the ones are the network portion of the address, and the bits that line up with the zeros are the host portion.  The address within the network where all the host bits are zeros (the first address in the network) is the network address.  The address within the network where all the host bits are ones (the last address in the network) is the broadcast address.  When we write a netmask as slash-some-number, like /24, we mean twenty-four ones on the left, and eight zeros on the right.  For every bit you add to the netmask, the size of the network is divided in half.&lt;br /&gt;
&lt;br /&gt;
Now that you understand how to do the math involved in calculating netmasks, network addresses, and broadcast addresses, let's examine how to plan your network.  Let's say you have been given 192.0.2.0/24 as your network allocation.  How are you going to assign addresses to web servers, mail servers, DNS servers, and the like?&lt;br /&gt;
&lt;br /&gt;
The fewer &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules you have, the faster packets will traverse your firewall.  Granted, a single rule takes only microseconds to process, but also your rules will be easier to read if the set is shorter.  So it is beneficial to reduce your rules as much as possible.  And a well planned network will make it easier to reduce your overall rules.&lt;br /&gt;
&lt;br /&gt;
We can divide our network into two /25 networks:  The network addresses will be 192.0.2.0/25 and 192.0.2.128/25.  We can subdivide again into four /26 networks, the last octet will then be 0, 64, 128, and 192.  Keep in mind, we have been allocated all of 192.0.2.0/24, so that's the space that will be routed to us, so we don't need to reserve multiple network and broadcast addresses, we can just use those points as borders between segments.&lt;br /&gt;
&lt;br /&gt;
If we host a lot of commercial web sites, we probably want to provide a lot of our IPs for web hosting.  If we divide up our allocation into four /26 segments, we can cover the two middle allocations with two rules, allowing us 128 web sites.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.64/26  -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.128/26 -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's much better than 128 individual rules allowing web traffic to individual addresses.  Below, we'll also examine how to reduce our rules even further, permitting disparate service allocations in only one rule.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; and hardly a handful of &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Fri, 11 Apr 2014 07:00:01 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Custom Chains */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || +     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || +&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.  Note that &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is only available if you have installed the [http://xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is simply not tested, which is the same as if it were tested and resulted in a TRUE match.  For example, if you don't specify a protocol, then the rule matches packets of any protocol.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.  You could also specify a netmask of 255.255.255.1 and match all the even or odd addresses in a group of 256.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, notice that we started this ruleset by allowing unlimited traffic on the loopback interface.  But of particular interest is that these rules do not mention the 127.0.0.1 address.  Why not?  Because the loopback interface is used by more than just the 127.0.0.1 address.  In fact, any time you send traffic from the machine to itself, on any IP, it is handled on the loopback interface.  Think about it, how would the computer send packets up to the ethernet adapter, but not actually onto the ethernet cable?  It can't, but it can use the loopback interface instead.&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for default chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Just what is a good scenario in which to use a custom chain?  Whenever you are segregating some portion of your traffic with a common criterion which doesn't apply to the vast majority of unrelated packets.  For example, here is my custom chain for staving off the onslaught of SSH brute force attackers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:SSH-Throttle -&lt;br /&gt;
-A SSH-Throttle -m recent --set&lt;br /&gt;
-A SSH-Throttle -m recent --update --seconds 5 --hitcount 2 -j DROP&lt;br /&gt;
-A SSH-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 22 -m conntrack --ctstate NEW -j SSH-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There you have it.  Three rules which don't need to test the protocol, port, or connection tracking state, because this is already done for them by the rule that sent the packets there.&lt;br /&gt;
&lt;br /&gt;
Additionally, here is my custom chain for blocking FTP abusers.  It limits connections to ten per minute and one per source IP.  It also throws some unexpected errors, so programs like hydra get confused and give up after a very short time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:FTP-Throttle -&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --set&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --update --seconds 60 --hitcount 10 -j DROP&lt;br /&gt;
-A FTP-Throttle -m connlimit --connlimit-above 1 -j REJECT --reject-with icmp-admin-prohibited&lt;br /&gt;
-A FTP-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 21 -m conntrack --ctstate NEW -j FTP-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== The Importance Of Organization ==&lt;br /&gt;
&lt;br /&gt;
From all zeros, to all ones, across 32 bits, there are 33 netmasks usable in IPv4 networking.  The ones are always on the left, and the zeros are always on the right.  That's it, 33.  When we line up the bits in a host address with the bits in the netmask, the bits that line up with the ones are the network portion of the address, and the bits that line up with the zeros are the host portion.  The address within the network where all the host bits are zeros (the first address in the network) is the network address.  The address within the network where all the host bits are ones (the last address in the network) is the broadcast address.  When we write a netmask as slash-some-number, like /24, we mean twenty-four ones on the left, and eight zeros on the right.  For every bit you add to the netmask, the size of the network is divided in half.&lt;br /&gt;
&lt;br /&gt;
Now that you understand how to do the math involved in calculating netmasks, network addresses, and broadcast addresses, let's examine how to plan your network.  Let's say you have been given 192.0.2.0/24 as your network allocation.  How are you going to assign addresses to web servers, mail servers, DNS servers, and the like?&lt;br /&gt;
&lt;br /&gt;
The fewer &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules you have, the faster packets will traverse your firewall.  Granted, a single rule takes only microseconds to process, but also your rules will be easier to read if the set is shorter.  So it is beneficial to reduce your rules as much as possible.  And a well planned network will make it easier to reduce your overall rules.&lt;br /&gt;
&lt;br /&gt;
We can divide our network into two /25 networks:  The network addresses will be 192.0.2.0/25 and 192.0.2.128/25.  We can subdivide again into four /26 networks, the last octet will then be 0, 64, 128, and 192.  Keep in mind, we have been allocated all of 192.0.2.0/24, so that's the space that will be routed to us, so we don't need to reserve multiple network and broadcast addresses, we can just use those points as borders between segments.&lt;br /&gt;
&lt;br /&gt;
If we host a lot of commercial web sites, we probably want to provide a lot of our IPs for web hosting.  If we divide up our allocation into four /26 segments, we can cover the two middle allocations with two rules, allowing us 128 web sites.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.64/26  -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.128/26 -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's much better than 128 individual rules allowing web traffic to individual addresses.  Below, we'll also examine how to reduce our rules even further, permitting disparate service allocations in only one rule.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; and hardly a handful of &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Fri, 11 Apr 2014 06:57:14 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Custom Chains */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || +     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || +&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.  Note that &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is only available if you have installed the [http://xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is simply not tested, which is the same as if it were tested and resulted in a TRUE match.  For example, if you don't specify a protocol, then the rule matches packets of any protocol.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.  You could also specify a netmask of 255.255.255.1 and match all the even or odd addresses in a group of 256.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, notice that we started this ruleset by allowing unlimited traffic on the loopback interface.  But of particular interest is that these rules do not mention the 127.0.0.1 address.  Why not?  Because the loopback interface is used by more than just the 127.0.0.1 address.  In fact, any time you send traffic from the machine to itself, on any IP, it is handled on the loopback interface.  Think about it, how would the computer send packets up to the ethernet adapter, but not actually onto the ethernet cable?  It can't, but it can use the loopback interface instead.&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for default chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Just what is a good scenario in which to use a custom chain?  Whenever you are segregating some portion of your traffic with a common criterion which doesn't apply to the vast majority of unrelated packets.  For example, here is my custom chain for staving off the onslaught of SSH brute force attackers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:SSH-Throttle -&lt;br /&gt;
-A SSH-Throttle -m recent --set&lt;br /&gt;
-A SSH-Throttle -m recent --update --seconds 5 --hitcount 2 -j DROP&lt;br /&gt;
-A SSH-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 22 -m conntrack --ctstate NEW -j SSH-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There you have it.  Three rules which don't need to test the protocol, port, or connection tracking state, because this is already done for them by the rule that sent the packets there.&lt;br /&gt;
&lt;br /&gt;
Additionally, here is my custom chain for blocking FTP abusers.  It limits connections to ten per minute and one per source IP.  It also throws some unexpected errors, so programs like hydra get confused and give up after a very short time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:FTP-Throttle&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --set&lt;br /&gt;
-A FTP-Throttle -m recent --name ftp_throttle --update --seconds 60 --hitcount 10 -j DROP&lt;br /&gt;
-A FTP-Throttle -m connlimit --connlimit-above 1 -j REJECT --reject-with icmp-admin-prohibited&lt;br /&gt;
-A FTP-Throttle -j ACCEPT&lt;br /&gt;
-A INPUT -i eth0 -p tcp --dport 21 -m conntrack --ctstate NEW -j FTP-Throttle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== The Importance Of Organization ==&lt;br /&gt;
&lt;br /&gt;
From all zeros, to all ones, across 32 bits, there are 33 netmasks usable in IPv4 networking.  The ones are always on the left, and the zeros are always on the right.  That's it, 33.  When we line up the bits in a host address with the bits in the netmask, the bits that line up with the ones are the network portion of the address, and the bits that line up with the zeros are the host portion.  The address within the network where all the host bits are zeros (the first address in the network) is the network address.  The address within the network where all the host bits are ones (the last address in the network) is the broadcast address.  When we write a netmask as slash-some-number, like /24, we mean twenty-four ones on the left, and eight zeros on the right.  For every bit you add to the netmask, the size of the network is divided in half.&lt;br /&gt;
&lt;br /&gt;
Now that you understand how to do the math involved in calculating netmasks, network addresses, and broadcast addresses, let's examine how to plan your network.  Let's say you have been given 192.0.2.0/24 as your network allocation.  How are you going to assign addresses to web servers, mail servers, DNS servers, and the like?&lt;br /&gt;
&lt;br /&gt;
The fewer &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules you have, the faster packets will traverse your firewall.  Granted, a single rule takes only microseconds to process, but also your rules will be easier to read if the set is shorter.  So it is beneficial to reduce your rules as much as possible.  And a well planned network will make it easier to reduce your overall rules.&lt;br /&gt;
&lt;br /&gt;
We can divide our network into two /25 networks:  The network addresses will be 192.0.2.0/25 and 192.0.2.128/25.  We can subdivide again into four /26 networks, the last octet will then be 0, 64, 128, and 192.  Keep in mind, we have been allocated all of 192.0.2.0/24, so that's the space that will be routed to us, so we don't need to reserve multiple network and broadcast addresses, we can just use those points as borders between segments.&lt;br /&gt;
&lt;br /&gt;
If we host a lot of commercial web sites, we probably want to provide a lot of our IPs for web hosting.  If we divide up our allocation into four /26 segments, we can cover the two middle allocations with two rules, allowing us 128 web sites.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.64/26  -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.128/26 -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's much better than 128 individual rules allowing web traffic to individual addresses.  Below, we'll also examine how to reduce our rules even further, permitting disparate service allocations in only one rule.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; and hardly a handful of &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Fri, 11 Apr 2014 06:56:39 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Custom Chains */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || +     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || +&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.  Note that &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is only available if you have installed the [http://xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is simply not tested, which is the same as if it were tested and resulted in a TRUE match.  For example, if you don't specify a protocol, then the rule matches packets of any protocol.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.  You could also specify a netmask of 255.255.255.1 and match all the even or odd addresses in a group of 256.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, notice that we started this ruleset by allowing unlimited traffic on the loopback interface.  But of particular interest is that these rules do not mention the 127.0.0.1 address.  Why not?  Because the loopback interface is used by more than just the 127.0.0.1 address.  In fact, any time you send traffic from the machine to itself, on any IP, it is handled on the loopback interface.  Think about it, how would the computer send packets up to the ethernet adapter, but not actually onto the ethernet cable?  It can't, but it can use the loopback interface instead.&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for default chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== The Importance Of Organization ==&lt;br /&gt;
&lt;br /&gt;
From all zeros, to all ones, across 32 bits, there are 33 netmasks usable in IPv4 networking.  The ones are always on the left, and the zeros are always on the right.  That's it, 33.  When we line up the bits in a host address with the bits in the netmask, the bits that line up with the ones are the network portion of the address, and the bits that line up with the zeros are the host portion.  The address within the network where all the host bits are zeros (the first address in the network) is the network address.  The address within the network where all the host bits are ones (the last address in the network) is the broadcast address.  When we write a netmask as slash-some-number, like /24, we mean twenty-four ones on the left, and eight zeros on the right.  For every bit you add to the netmask, the size of the network is divided in half.&lt;br /&gt;
&lt;br /&gt;
Now that you understand how to do the math involved in calculating netmasks, network addresses, and broadcast addresses, let's examine how to plan your network.  Let's say you have been given 192.0.2.0/24 as your network allocation.  How are you going to assign addresses to web servers, mail servers, DNS servers, and the like?&lt;br /&gt;
&lt;br /&gt;
The fewer &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules you have, the faster packets will traverse your firewall.  Granted, a single rule takes only microseconds to process, but also your rules will be easier to read if the set is shorter.  So it is beneficial to reduce your rules as much as possible.  And a well planned network will make it easier to reduce your overall rules.&lt;br /&gt;
&lt;br /&gt;
We can divide our network into two /25 networks:  The network addresses will be 192.0.2.0/25 and 192.0.2.128/25.  We can subdivide again into four /26 networks, the last octet will then be 0, 64, 128, and 192.  Keep in mind, we have been allocated all of 192.0.2.0/24, so that's the space that will be routed to us, so we don't need to reserve multiple network and broadcast addresses, we can just use those points as borders between segments.&lt;br /&gt;
&lt;br /&gt;
If we host a lot of commercial web sites, we probably want to provide a lot of our IPs for web hosting.  If we divide up our allocation into four /26 segments, we can cover the two middle allocations with two rules, allowing us 128 web sites.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.64/26  -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.128/26 -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's much better than 128 individual rules allowing web traffic to individual addresses.  Below, we'll also examine how to reduce our rules even further, permitting disparate service allocations in only one rule.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; and hardly a handful of &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Fri, 11 Apr 2014 06:28:16 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Anatomy of an iptables rule */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || +     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || +&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.  Note that &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is only available if you have installed the [http://xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is simply not tested, which is the same as if it were tested and resulted in a TRUE match.  For example, if you don't specify a protocol, then the rule matches packets of any protocol.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.  You could also specify a netmask of 255.255.255.1 and match all the even or odd addresses in a group of 256.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, notice that we started this ruleset by allowing unlimited traffic on the loopback interface.  But of particular interest is that these rules do not mention the 127.0.0.1 address.  Why not?  Because the loopback interface is used by more than just the 127.0.0.1 address.  In fact, any time you send traffic from the machine to itself, on any IP, it is handled on the loopback interface.  Think about it, how would the computer send packets up to the ethernet adapter, but not actually onto the ethernet cable?  It can't, but it can use the loopback interface instead.&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for custom chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== The Importance Of Organization ==&lt;br /&gt;
&lt;br /&gt;
From all zeros, to all ones, across 32 bits, there are 33 netmasks usable in IPv4 networking.  The ones are always on the left, and the zeros are always on the right.  That's it, 33.  When we line up the bits in a host address with the bits in the netmask, the bits that line up with the ones are the network portion of the address, and the bits that line up with the zeros are the host portion.  The address within the network where all the host bits are zeros (the first address in the network) is the network address.  The address within the network where all the host bits are ones (the last address in the network) is the broadcast address.  When we write a netmask as slash-some-number, like /24, we mean twenty-four ones on the left, and eight zeros on the right.  For every bit you add to the netmask, the size of the network is divided in half.&lt;br /&gt;
&lt;br /&gt;
Now that you understand how to do the math involved in calculating netmasks, network addresses, and broadcast addresses, let's examine how to plan your network.  Let's say you have been given 192.0.2.0/24 as your network allocation.  How are you going to assign addresses to web servers, mail servers, DNS servers, and the like?&lt;br /&gt;
&lt;br /&gt;
The fewer &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules you have, the faster packets will traverse your firewall.  Granted, a single rule takes only microseconds to process, but also your rules will be easier to read if the set is shorter.  So it is beneficial to reduce your rules as much as possible.  And a well planned network will make it easier to reduce your overall rules.&lt;br /&gt;
&lt;br /&gt;
We can divide our network into two /25 networks:  The network addresses will be 192.0.2.0/25 and 192.0.2.128/25.  We can subdivide again into four /26 networks, the last octet will then be 0, 64, 128, and 192.  Keep in mind, we have been allocated all of 192.0.2.0/24, so that's the space that will be routed to us, so we don't need to reserve multiple network and broadcast addresses, we can just use those points as borders between segments.&lt;br /&gt;
&lt;br /&gt;
If we host a lot of commercial web sites, we probably want to provide a lot of our IPs for web hosting.  If we divide up our allocation into four /26 segments, we can cover the two middle allocations with two rules, allowing us 128 web sites.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.64/26  -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.128/26 -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's much better than 128 individual rules allowing web traffic to individual addresses.  Below, we'll also examine how to reduce our rules even further, permitting disparate service allocations in only one rule.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; and hardly a handful of &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Fri, 11 Apr 2014 06:23:24 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Starting Rules */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || +     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || +&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.  Note that &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is only available if you have installed the [http://xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is implicitly set to match anything.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additionally, notice that we started this ruleset by allowing unlimited traffic on the loopback interface.  But of particular interest is that these rules do not mention the 127.0.0.1 address.  Why not?  Because the loopback interface is used by more than just the 127.0.0.1 address.  In fact, any time you send traffic from the machine to itself, on any IP, it is handled on the loopback interface.  Think about it, how would the computer send packets up to the ethernet adapter, but not actually onto the ethernet cable?  It can't, but it can use the loopback interface instead.&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for custom chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== The Importance Of Organization ==&lt;br /&gt;
&lt;br /&gt;
From all zeros, to all ones, across 32 bits, there are 33 netmasks usable in IPv4 networking.  The ones are always on the left, and the zeros are always on the right.  That's it, 33.  When we line up the bits in a host address with the bits in the netmask, the bits that line up with the ones are the network portion of the address, and the bits that line up with the zeros are the host portion.  The address within the network where all the host bits are zeros (the first address in the network) is the network address.  The address within the network where all the host bits are ones (the last address in the network) is the broadcast address.  When we write a netmask as slash-some-number, like /24, we mean twenty-four ones on the left, and eight zeros on the right.  For every bit you add to the netmask, the size of the network is divided in half.&lt;br /&gt;
&lt;br /&gt;
Now that you understand how to do the math involved in calculating netmasks, network addresses, and broadcast addresses, let's examine how to plan your network.  Let's say you have been given 192.0.2.0/24 as your network allocation.  How are you going to assign addresses to web servers, mail servers, DNS servers, and the like?&lt;br /&gt;
&lt;br /&gt;
The fewer &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules you have, the faster packets will traverse your firewall.  Granted, a single rule takes only microseconds to process, but also your rules will be easier to read if the set is shorter.  So it is beneficial to reduce your rules as much as possible.  And a well planned network will make it easier to reduce your overall rules.&lt;br /&gt;
&lt;br /&gt;
We can divide our network into two /25 networks:  The network addresses will be 192.0.2.0/25 and 192.0.2.128/25.  We can subdivide again into four /26 networks, the last octet will then be 0, 64, 128, and 192.  Keep in mind, we have been allocated all of 192.0.2.0/24, so that's the space that will be routed to us, so we don't need to reserve multiple network and broadcast addresses, we can just use those points as borders between segments.&lt;br /&gt;
&lt;br /&gt;
If we host a lot of commercial web sites, we probably want to provide a lot of our IPs for web hosting.  If we divide up our allocation into four /26 segments, we can cover the two middle allocations with two rules, allowing us 128 web sites.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.64/26  -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.128/26 -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's much better than 128 individual rules allowing web traffic to individual addresses.  Below, we'll also examine how to reduce our rules even further, permitting disparate service allocations in only one rule.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; and hardly a handful of &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Wed, 09 Apr 2014 07:48:44 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Using ipsets */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || +     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || +&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.  Note that &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is only available if you have installed the [http://xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is implicitly set to match anything.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for custom chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== The Importance Of Organization ==&lt;br /&gt;
&lt;br /&gt;
From all zeros, to all ones, across 32 bits, there are 33 netmasks usable in IPv4 networking.  The ones are always on the left, and the zeros are always on the right.  That's it, 33.  When we line up the bits in a host address with the bits in the netmask, the bits that line up with the ones are the network portion of the address, and the bits that line up with the zeros are the host portion.  The address within the network where all the host bits are zeros (the first address in the network) is the network address.  The address within the network where all the host bits are ones (the last address in the network) is the broadcast address.  When we write a netmask as slash-some-number, like /24, we mean twenty-four ones on the left, and eight zeros on the right.  For every bit you add to the netmask, the size of the network is divided in half.&lt;br /&gt;
&lt;br /&gt;
Now that you understand how to do the math involved in calculating netmasks, network addresses, and broadcast addresses, let's examine how to plan your network.  Let's say you have been given 192.0.2.0/24 as your network allocation.  How are you going to assign addresses to web servers, mail servers, DNS servers, and the like?&lt;br /&gt;
&lt;br /&gt;
The fewer &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules you have, the faster packets will traverse your firewall.  Granted, a single rule takes only microseconds to process, but also your rules will be easier to read if the set is shorter.  So it is beneficial to reduce your rules as much as possible.  And a well planned network will make it easier to reduce your overall rules.&lt;br /&gt;
&lt;br /&gt;
We can divide our network into two /25 networks:  The network addresses will be 192.0.2.0/25 and 192.0.2.128/25.  We can subdivide again into four /26 networks, the last octet will then be 0, 64, 128, and 192.  Keep in mind, we have been allocated all of 192.0.2.0/24, so that's the space that will be routed to us, so we don't need to reserve multiple network and broadcast addresses, we can just use those points as borders between segments.&lt;br /&gt;
&lt;br /&gt;
If we host a lot of commercial web sites, we probably want to provide a lot of our IPs for web hosting.  If we divide up our allocation into four /26 segments, we can cover the two middle allocations with two rules, allowing us 128 web sites.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.64/26  -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.128/26 -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's much better than 128 individual rules allowing web traffic to individual addresses.  Below, we'll also examine how to reduce our rules even further, permitting disparate service allocations in only one rule.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; and hardly a handful of &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Wed, 09 Apr 2014 07:39:45 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* The Importance Of Organization */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || +     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || +&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.  Note that &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is only available if you have installed the [http://xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is implicitly set to match anything.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for custom chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== The Importance Of Organization ==&lt;br /&gt;
&lt;br /&gt;
From all zeros, to all ones, across 32 bits, there are 33 netmasks usable in IPv4 networking.  The ones are always on the left, and the zeros are always on the right.  That's it, 33.  When we line up the bits in a host address with the bits in the netmask, the bits that line up with the ones are the network portion of the address, and the bits that line up with the zeros are the host portion.  The address within the network where all the host bits are zeros (the first address in the network) is the network address.  The address within the network where all the host bits are ones (the last address in the network) is the broadcast address.  When we write a netmask as slash-some-number, like /24, we mean twenty-four ones on the left, and eight zeros on the right.  For every bit you add to the netmask, the size of the network is divided in half.&lt;br /&gt;
&lt;br /&gt;
Now that you understand how to do the math involved in calculating netmasks, network addresses, and broadcast addresses, let's examine how to plan your network.  Let's say you have been given 192.0.2.0/24 as your network allocation.  How are you going to assign addresses to web servers, mail servers, DNS servers, and the like?&lt;br /&gt;
&lt;br /&gt;
The fewer &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules you have, the faster packets will traverse your firewall.  Granted, a single rule takes only microseconds to process, but also your rules will be easier to read if the set is shorter.  So it is beneficial to reduce your rules as much as possible.  And a well planned network will make it easier to reduce your overall rules.&lt;br /&gt;
&lt;br /&gt;
We can divide our network into two /25 networks:  The network addresses will be 192.0.2.0/25 and 192.0.2.128/25.  We can subdivide again into four /26 networks, the last octet will then be 0, 64, 128, and 192.  Keep in mind, we have been allocated all of 192.0.2.0/24, so that's the space that will be routed to us, so we don't need to reserve multiple network and broadcast addresses, we can just use those points as borders between segments.&lt;br /&gt;
&lt;br /&gt;
If we host a lot of commercial web sites, we probably want to provide a lot of our IPs for web hosting.  If we divide up our allocation into four /26 segments, we can cover the two middle allocations with two rules, allowing us 128 web sites.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.64/26  -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.128/26 -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's much better than 128 individual rules allowing web traffic to individual addresses.  Below, we'll also examine how to reduce our rules even further, permitting disparate service allocations in only one rule.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an ipset and hardly a handful of iptables rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (-D) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Wed, 09 Apr 2014 07:29:48 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* The Importance Of Organization */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || +     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || +&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.  Note that &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is only available if you have installed the [http://xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is implicitly set to match anything.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for custom chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== The Importance Of Organization ==&lt;br /&gt;
&lt;br /&gt;
From all zeros, to all ones, across 32 bits, there are 33 netmasks usable in IPv4 networking.  The ones are always on the left, and the zeros are always on the right.  That's it, 33.  When we line up the bits in a host address with the bits in the netmask, the bits that line up with the ones are the network portion of the address, and the bits that line up with the zeros are the host portion.  The address within the network where all the host bits are zeros (the first address in the network) is the network address.  The address within the network where all the host bits are ones (the last address in the network) is the broadcast address.  When we write a netmask as slash-some-number, like /24, we mean twenty-four ones on the left, and eight zeros on the right.  For every bit you add to the netmask, the size of the network is divided in half.&lt;br /&gt;
&lt;br /&gt;
Now that you understand how to do the math involved in calculating netmasks, network addresses, and broadcast addresses, let's examine how to plan your network.  Let's say you have been given 192.0.2.0/24 as your network allocation.  How are you going to assign addresses to web servers, mail servers, DNS servers, and the like?&lt;br /&gt;
&lt;br /&gt;
The fewer iptables rules you have, the faster packets will traverse your firewall.  Granted, a single rule takes only microseconds to process, but also your rules will be easier to read if the set is shorter.  So it is beneficial to reduce your rules as much as possible.  And a well planned network will make it easier to reduce your overall rules.&lt;br /&gt;
&lt;br /&gt;
We can divide our network into two /25 networks:  The network addresses will be 192.0.2.0/25 and 192.0.2.128/25.  We can subdivide again into four /26 networks, the last octet will then be 0, 64, 128, and 192.  Keep in mind, we have been allocated all of 192.0.2.0/24, so that's the space that will be routed to us, so we don't need to reserve multiple network and broadcast addresses, we can just use those points as borders between segments.&lt;br /&gt;
&lt;br /&gt;
If we host a lot of commercial web sites, we probably want to provide a lot of our IPs for web hosting.  If we divide up our allocation into four /26 segments, we can cover the two middle allocations with two rules, allowing us 128 web sites.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.64/26  -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.128/26 -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's much better than 128 individual rules allowing web traffic to individual addresses.  Below, we'll also examine how to reduce our rules even further, permitting disparate service allocations in only one rule.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an ipset and hardly a handful of iptables rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (-D) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Wed, 09 Apr 2014 07:27:30 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* The Importance Of Organization */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || +     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || +&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.  Note that &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is only available if you have installed the [http://xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is implicitly set to match anything.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for custom chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== The Importance Of Organization ==&lt;br /&gt;
&lt;br /&gt;
From all zeros, to all ones, across 32 bits, there are 33 netmasks usable in IPv4 networking.  The ones are always on the left, and the zeros are always on the right.  That's it, 33.  When we line up the bits in a host address with the bits in the netmask, the bits that line up with the ones are the network portion of the address, and the bits that line up with the zeros are the host portion.  The address within the network where all the host bits are zeros (the first address in the network) is the network address.  The address within the network where all the host bits are ones (the last address in the network) is the broadcast address.  When we write a netmask as slash-some-number, like /24, we mean twenty-four ones on the left, and eight zeros on the right.  For every bit you add to the netmask, the size of the network is divided in half.&lt;br /&gt;
&lt;br /&gt;
Now that you understand how to do the math involved in calculating netmasks, network addresses, and broadcast addresses, let's examine how to plan your network.  Let's say you have been given 192.0.2.0/24 as your network allocation.  How are you going to assign addresses to web servers, mail servers, DNS servers, and the like?&lt;br /&gt;
&lt;br /&gt;
The fewer iptables rules you have, the faster packets will traverse your firewall.  Granted, a single rule takes only microseconds to process, but also your rules will be easier to read if the set is shorter.  So it is beneficial to reduce your rules as much as possible.  And a well planned network will make it easier to reduce your overall rules.&lt;br /&gt;
&lt;br /&gt;
We can divide our network into two /25 networks:  The network addresses will be 192.0.2.0/25 and 192.0.2.128/25.  We can subdivide again into four /26 networks, the last octet will then be 0, 64, 128, and 192.  Keep in mind, we have been allocated all of 192.0.2.0/24, so that's the space that will be routed to us, so we don't need to reserve multiple network and broadcast addresses, we can just use those points as borders between segments.&lt;br /&gt;
&lt;br /&gt;
If we host a lot of commercial web sites, we probably want to provide a lot of our IPs for web hosting.  If we divide up our allocation into four /26 segments, we can cover the two middle allocations with two rules, allowing us 128 web sites.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.64/26  -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.128/26 -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's much better than 128 individual rules allowing web traffic to individual addresses.  Below, we'll also examine how to reduce our rules even further, permitting disparate service allocations in only one rule.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an ipset and hardly a handful of iptables rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (-D) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Wed, 09 Apr 2014 07:26:44 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* The Importance Of Organization */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || +     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || +&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.  Note that &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is only available if you have installed the [http://xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is implicitly set to match anything.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for custom chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== The Importance Of Organization ==&lt;br /&gt;
&lt;br /&gt;
From all zeros, to all ones, across 32 bits, there are 33 netmasks usable in IPv4 networking.  The ones are always on the left, and the zeros are always on the right.  That's it, 33.  When we line up the bits in a host address with the bits in the netmask, the bits that line up with the ones are the network portion of the address, and the bits that line up with the zeros are the host portion.  The address within the network where all the host bits are zeros (the first address in the network) is the network address.  The address within the network where all the host bits are ones (the last address in the network) is the broadcast address.  When we write a netmask as slash-some-number, like /24, we mean twenty-four ones on the left, and eight zeros on the right.  For every bit you add to the netmask, the size of the network is divided in half.&lt;br /&gt;
&lt;br /&gt;
Now that you understand how to do the math involved in calculating netmasks, network addresses, and broadcast addresses, let's examine how to plan your network.  Let's say you have been given 192.0.2.0/24 as your network allocation.  How are you going to assign addresses to web servers, mail servers, DNS servers, and the like?&lt;br /&gt;
&lt;br /&gt;
The fewer iptables rules you have, the faster packets will traverse your firewall.  Granted, a single rule takes only microseconds to process, but also your rules will be easier to read if the set is shorter.  So it is beneficial to reduce your rules as much as possible.  And a well planned network will make it easier to reduce your overall rules.&lt;br /&gt;
&lt;br /&gt;
We can divide our network into two /25 networks:  The network addresses will be 192.0.2.0/25 and 192.0.2.128/25.  We can subdivide again into four /26 networks, the last octet will then be 0, 64, 128, and 192.  Keep in mind, we have been allocated all of 192.0.2.0/24, so that's the space that will be routed to us, so we don't need to reserve multiple network and broadcast addresses, we can just use those points as borders between segments.&lt;br /&gt;
&lt;br /&gt;
If we host a lot of commercial web sites, we probably want to provide a lot of our IPs for web hosting.  If we divide up our allocation into four /26 segments, we can cover the two middle allocations with two rules, allowing us 128 web sites.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.64/26  -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp -d 192.0.2.128/26 -m multiport --dports 80,443 -m conntrack --ctstate NEW -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's much better than 128 individual rules allowing web traffic to individual addresses.  Below, we'll also examine how to reduce our rules even further, permitting disparate service allocations in only one rule.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an ipset and hardly a handful of iptables rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (-D) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Wed, 09 Apr 2014 07:25:31 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* The Importance Of Organization */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || +     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || +&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.  Note that &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is only available if you have installed the [http://xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is implicitly set to match anything.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for custom chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== The Importance Of Organization ==&lt;br /&gt;
&lt;br /&gt;
From all zeros, to all ones, across 32 bits, there are 33 netmasks usable in IPv4 networking.  The ones are always on the left, and the zeros are always on the right.  That's it, 33.  When we line up the bits in a host address with the bits in the netmask, the bits that line up with the ones are the network portion of the address, and the bits that line up with the zeros are the host portion.  The address within the network where all the host bits are zeros (the first address in the network) is the network address.  The address within the network where all the host bits are ones (the last address in the network) is the broadcast address.  When we write a netmask as slash-some-number, like /24, we mean twenty-four ones on the left, and eight zeros on the right.  For every bit you add to the netmask, the size of the network is divided in half.&lt;br /&gt;
&lt;br /&gt;
Now that you understand how to do the math involved in calculating netmasks, network addresses, and broadcast addresses, let's examine how to plan your network.  Let's say you have been given 192.0.2.0/24 as your network allocation.  How are you going to assign addresses to web servers, mail servers, DNS servers, and the like?&lt;br /&gt;
&lt;br /&gt;
The fewer iptables rules you have, the faster packets will traverse your firewall.  Granted, a single rule takes only microseconds to process, but also your rules will be easier to read if the set is shorter.  So it is beneficial to reduce your rules as much as possible.  And a well planned network will make it easier to reduce your overall rules.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an ipset and hardly a handful of iptables rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (-D) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Wed, 09 Apr 2014 07:02:24 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Using ipsets */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || +     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || +&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.  Note that &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is only available if you have installed the [http://xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is implicitly set to match anything.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for custom chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== The Importance Of Organization ==&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an ipset and hardly a handful of iptables rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (-D) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Wed, 09 Apr 2014 06:37:14 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Math So Basic You Didn't Learn It In Kindergarten */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || +     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || +&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.  Note that &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is only available if you have installed the [http://xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is implicitly set to match anything.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for custom chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#c0c0c0; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an ipset and hardly a handful of iptables rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (-D) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Wed, 09 Apr 2014 06:29:17 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Anatomy of an iptables rule */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || +     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || +&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.  Note that &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is only available if you have installed the [http://xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is implicitly set to match anything.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for custom chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#cccccc; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#cccccc; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#cccccc; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#cccccc; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an ipset and hardly a handful of iptables rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (-D) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Wed, 09 Apr 2014 06:24:29 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Using ipsets */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || +     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || +&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.  Note that &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is only available if you have installed the (((http_//xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is implicitly set to match anything.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for custom chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#cccccc; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#cccccc; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#cccccc; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#cccccc; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an ipset and hardly a handful of iptables rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -A VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (-D) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Mon, 07 Apr 2014 07:09:03 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Using conntrack */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || +     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || +&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.  Note that &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is only available if you have installed the (((http_//xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is implicitly set to match anything.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for custom chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#cccccc; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#cccccc; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#cccccc; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#cccccc; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an ipset and hardly a handful of iptables rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (-D) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
Installing the &amp;lt;tt&amp;gt;conntrack-tools&amp;lt;/tt&amp;gt; package adds three new commands to your Netfilter arsenal:  &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;nfct&amp;lt;/tt&amp;gt; tool allows you to set timeout policies on connection tracking events.  You use &amp;lt;tt&amp;gt;conntrackd&amp;lt;/tt&amp;gt; to syncronize and view the connection tracking table shared between redundant firewalls.  Last, but certainly not least, &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is a command line interface which allows you to manipulate the connection tracking kernel table in real time.&lt;br /&gt;
&lt;br /&gt;
The great thing about &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt; is that most of its commands are identical to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt;.  You can use it to list (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;), add (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;), and delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;) entries on the fly.  Use flags to specify source (&amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;) and destination IP (&amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;), protocol (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), and source (&amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;) and destination (&amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;) ports.&lt;br /&gt;
&lt;br /&gt;
Show all SSH connections (22/tcp):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -L -p tcp --dport 22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delete all connections from host 203.0.113.7:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
conntrack -D -s 203.0.113.7&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, if you are using connection tracking like you should, this connection now becomes &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt;, and depending on how you handle &amp;lt;tt&amp;gt;UNTRACKED&amp;lt;/tt&amp;gt; connections, this client should be terminated.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Mon, 07 Apr 2014 06:49:23 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Using ipsets */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || +     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || +&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.  Note that &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is only available if you have installed the (((http_//xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is implicitly set to match anything.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for custom chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#cccccc; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#cccccc; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#cccccc; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#cccccc; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an ipset and hardly a handful of iptables rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will notice there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named &amp;quot;Blacklist.&amp;quot;  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Any node which attempts to connect to TCP port 23 now gets added to the Blacklist set.  If it tries again, the 24 hour timeout gets reset.  And finally any address in the Blacklist set just gets blocked.&lt;br /&gt;
&lt;br /&gt;
This allows us to have a dynamic list which can change at any moment with no manual intervention on our part, and no changes to the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.  Not only that, but you can delete (-D) an entry from the list manually very easily.&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Mon, 07 Apr 2014 06:22:46 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Using ipsets */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || +     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || +&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.  Note that &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is only available if you have installed the (((http_//xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is implicitly set to match anything.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for custom chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#cccccc; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#cccccc; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#cccccc; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#cccccc; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an ipset and hardly a handful of iptables rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And now for the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of course, again, I'm assuming you are integrating this with previous examples, specifically connection tracking, without which these rules will fail to permit complete connections.&lt;br /&gt;
&lt;br /&gt;
The astute observer will also notice that there is also an &amp;lt;tt&amp;gt;IPSET&amp;lt;/tt&amp;gt; target module.  It can be used to automatically add a host to a set when certain events occur.  For example, if you want to create a blacklist of hosts that attempt to telnet to your server, you could set up the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Blacklist hash:ip --timeout $[60*60*24]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we have an empty set named Blacklist.  Any IP which is added to it will automatically be removed in 24 hours (86400 seconds).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT -p tcp --dport 23 -j SET --add-set Blacklist src --exist&lt;br /&gt;
-A INPUT -m set --match-set Blacklist src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Mon, 07 Apr 2014 06:12:10 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Using ipsets */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || +     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || +&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.  Note that &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is only available if you have installed the (((http_//xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is implicitly set to match anything.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for custom chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#cccccc; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#cccccc; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#cccccc; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#cccccc; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an ipset and hardly a handful of iptables rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Mon, 07 Apr 2014 03:39:09 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Using ipsets */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || +     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || +&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.  Note that &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is only available if you have installed the (((http_//xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is implicitly set to match anything.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for custom chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#cccccc; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#cccccc; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#cccccc; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#cccccc; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a packet, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an ipset and hardly a handful of iptables rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Mon, 07 Apr 2014 03:37:32 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Using ipsets */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || +     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || +&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.  Note that &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is only available if you have installed the (((http_//xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is implicitly set to match anything.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for custom chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#cccccc; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#cccccc; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#cccccc; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#cccccc; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a port, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfy Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an ipset and hardly a handful of iptables rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A FORWARD -p icmp -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p tcp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
-A FORWARD -p udp  -m set --match-set VLAN-to-VLAN src,dst,dst -j ACCEPT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Mon, 07 Apr 2014 03:36:30 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
		<item>
			<title>Things You Should Know About Netfilter</title>
			<link>http://72.14.177.54/SFVLUG/Things_You_Should_Know_About_Netfilter</link>
			<description>&lt;p&gt;Jeff:&amp;#32;/* Using ipsets */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I have been hanging out on FreeNode's #Netfilter channel for quite a while now.  I would guess I'm probably one of the top ten contributors in that channel now.  I have seen a lot of people's iptables setups and I have seen a lot of mistakes as well as a lot of cool tricks.  I want to set some records straight and help get people to the bottom of their problems.  Some of this might be a rehash of advice already given by others, but I haven't yet seen all of this aggregated into one location yet, so here goes.&lt;br /&gt;
&lt;br /&gt;
== net-tools vs. iproute2 ==&lt;br /&gt;
&lt;br /&gt;
I would say the first step people need to take on their road to better understanding of Linux firewalls, and Linux networking in general is to let go of their old tools.  The net-tools package consists of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;route&amp;lt;/tt&amp;gt;, and several others.  All of them are unmaintained and deprecated.  Today we use iproute2 instead of all these tools.  Why?  The net-tools collection still works, right?  Yes, but that's mostly because the userspace interfaces to the kernel haven't changed, which means you're just lucky, not clever, if you still cling to net-tools.&lt;br /&gt;
&lt;br /&gt;
So how do we use these new tools to replace the old ones?  Most of &amp;lt;tt&amp;gt;netstat&amp;lt;/tt&amp;gt;'s functionality can be replaced using &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt;.  For the most part, the flags are the same, too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -antu | fgrep -w 22&lt;br /&gt;
&lt;br /&gt;
ss -antu sport == :22&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But don't use &amp;lt;tt&amp;gt;ss&amp;lt;/tt&amp;gt; to show your routing table like you used to do; use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;'s route commands.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -rn&amp;lt;br/&amp;gt;&lt;br /&gt;
route -n&lt;br /&gt;
&lt;br /&gt;
ip r&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And also use &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to show your IP addresses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
netstat -ie&amp;lt;br/&amp;gt;&lt;br /&gt;
ifconfig&lt;br /&gt;
&lt;br /&gt;
ip a&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, remember the -a flag to &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to see all your interfaces?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig -a&lt;br /&gt;
&lt;br /&gt;
ip l&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;l&amp;quot; is for &amp;quot;link,&amp;quot; and it is the easier way to enumerate your local MAC addresses, as well as set an interface up or down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 up&lt;br /&gt;
&lt;br /&gt;
ip l set eth0 up&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Just about everybody who has manually configured their IP address has used &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; to do it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0 10.11.12.13 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.13/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you can keep adding addresses to an interface without having to create aliases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
ifconfig eth0:14 10.11.12.14 netmask 255.255.240.0&lt;br /&gt;
&lt;br /&gt;
ip a add 10.11.12.14/20 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here's the kicker.  When you call &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; alone, or as &amp;lt;tt&amp;gt;ifconfig eth0&amp;lt;/tt&amp;gt;, you will not see that new address.  Only if you set it up as eth0:14, and call &amp;lt;tt&amp;gt;ifconfig eth0:14&amp;lt;/tt&amp;gt;.  But &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; will list all addresses associated with an interface.  And how about routes?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
route add default gw 10.11.12.1&lt;br /&gt;
&lt;br /&gt;
ip r add default via 10.11.12.1 dev eth0&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt; to set routes, you can configure some very complex routing tables, have multiple default gateways, even route over different interfaces and none of that is possible with the old route command.  Are you sold on iproute2 yet?  How about arp?  Using &amp;lt;tt&amp;gt;ip&amp;lt;/tt&amp;gt;, the arp table is now called the neighbor table, and you can do all the same things you did with the &amp;lt;tt&amp;gt;arp&amp;lt;/tt&amp;gt; command using &amp;lt;tt&amp;gt;ip n&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
arp&lt;br /&gt;
&lt;br /&gt;
ip n&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's all I want to go into on iproute2 at the moment.  You should install the iproute-doc package if your distro separates the documentation into its own package.  Unfortunately a lot of it was written by a Russian programmer so some of it reads like it was passed back and forth through Google Translate a few too many times, but it is ultimately legible and accurate.&lt;br /&gt;
&lt;br /&gt;
== Use iptables-save and iptables-restore ==&lt;br /&gt;
&lt;br /&gt;
As I mentioned before, I have been spending a lot of time in the #Netfilter IRC channel.  One of the worst things visitors sometimes do is upload their shell script to a paste bin site and ask for help debugging it.  At this stage, we're no longer debugging a firewall, we're debugging a shell script.  Don't tell us about your shell script, tell us about the rules you got.  If you want help scripting, join #bash.&lt;br /&gt;
&lt;br /&gt;
But the real reason we recommend people use &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-restore&amp;lt;/tt&amp;gt; is because &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; is atomic; it applies all of your rules all at once and commits them to the kernel.  Applying rules one at a time leaves you with a period of time that your firewall is incomplete.  It is possible that during this brief setup period either the wrong packet could get into your network, or the right one might not get out.  Also, new versions of iptables now have the &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; command which will prompt you if your new rules are ok.  If you lock yourself out of a remote session, &amp;lt;tt&amp;gt;iptables-apply&amp;lt;/tt&amp;gt; will time out and go back to your previous rules and you're back to square one.&lt;br /&gt;
&lt;br /&gt;
Another thing about using the &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; command is that it edits your rules in a very resource-intensive way; every time it makes a change, it copies your current rules, makes a one-line modification to the whole, and reloads that whole.  As your rules get more elaborate, this becomes a more complex procedure.&lt;br /&gt;
&lt;br /&gt;
If you want to use a shell script to configure your rules, it's fine.  Consider something like the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
filter_rules()&lt;br /&gt;
{&lt;br /&gt;
    echo '*filter'&lt;br /&gt;
    echo ':INPUT   ACCEPT'&lt;br /&gt;
    echo ':OUTPUT  ACCEPT'&lt;br /&gt;
    echo ':FORWARD ACCEPT'&lt;br /&gt;
&lt;br /&gt;
    for BLOCK in 192.168.5.0/24 \&lt;br /&gt;
		 172.16.5.0/24  \&lt;br /&gt;
		 10.10.5.0/24 ; do&lt;br /&gt;
	echo -A INPUT   -s $BLOCK -j DROP&lt;br /&gt;
	echo -A OUTPUT  -d $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -s $BLOCK -j DROP&lt;br /&gt;
	echo -A FORWARD -d $BLOCK -j DROP&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
    echo 'COMMIT'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter_rules | iptables-restore&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As we can see here, the anatomy of rules in &amp;lt;tt&amp;gt;iptables-save&amp;lt;/tt&amp;gt; syntax is pretty straight forward.  Every time we work in a table, we start by declaring that table with an asterisk.  When we have completed our rules for that table, we conclude with the keyword &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.  Chains are declared starting with a colon.  Built-in chains also need their policy as the second token.  If you leave out a built-in chain, it defaults to ACCEPT.  You can declare custom chains in the same way, but they do not get a policy; the policy of every custom chain is RETURN.  Just declare a custom chain like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the equivalent of &amp;lt;tt&amp;gt;iptables -N custom-chain&amp;lt;/tt&amp;gt;.  There is a third token which can optionally be included in a chain declaration, which resets packet and byte counters for the chain policy.  Every time the ruleset is reloaded with &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, these are reset unless preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:INPUT ACCEPT [1114455:176852554]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here, {{formatnum:1114455}} is the packet count and {{formatnum:176852554}} is the bytes.&lt;br /&gt;
&lt;br /&gt;
== Anatomy of an iptables rule ==&lt;br /&gt;
&lt;br /&gt;
The predecessor to iptables was ipchains.  Chains are still a vital part of iptables rule sets and indeed it is impossible to configure iptables rules without interacting with chains.&lt;br /&gt;
&lt;br /&gt;
Today, iptables structure is composed of six tables and five default chains.  Not all tables have hooks in all five chains.&lt;br /&gt;
&lt;br /&gt;
The five default chains are:&lt;br /&gt;
&lt;br /&gt;
* PREROUTING&lt;br /&gt;
* POSTROUTING&lt;br /&gt;
* INPUT&lt;br /&gt;
* OUTPUT&lt;br /&gt;
* FORWARD&lt;br /&gt;
&lt;br /&gt;
Likewise, the six tables are:&lt;br /&gt;
&lt;br /&gt;
* raw&lt;br /&gt;
* mangle&lt;br /&gt;
* nat&lt;br /&gt;
* filter&lt;br /&gt;
* security&lt;br /&gt;
* rawpost&lt;br /&gt;
&lt;br /&gt;
And the following table describes how the various chains and tables hook together:&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;text-align: center&amp;quot;&lt;br /&gt;
|- style=&amp;quot;border-bottom: medium solid #000000&amp;quot;&lt;br /&gt;
!  &amp;amp;nbsp;   !! PREROUTING !! INPUT !! FORWARD !! OUTPUT !! POSTROUTING&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| raw      || +          ||       ||	      || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| mangle   || +          || +     || +       || +      || +&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| nat      || +          || +     ||	      || +      || +&lt;br /&gt;
|-&lt;br /&gt;
|| filter   ||            || +     || +       || +      ||&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| security ||            || +     || +       || +      ||&lt;br /&gt;
|-&lt;br /&gt;
|| rawpost  ||            ||       ||         ||        || +&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each chain processes the table hooks as you see them in the chart above, top to bottom.  For example, A packet entering &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; goes through &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt;, in that order.&lt;br /&gt;
&lt;br /&gt;
There are three possible paths a packet can take through kernel iptables-land.  All packets entering this machine will enter &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, and all packets leaving this machine will exit through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  After &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, a routing decision is made and the packet will either enter &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; depending on if the packet is destined for this computer or another one.  Packets never go through both &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.  Packets coming back out of &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; do not go back into the routing decision again, but new packets coming out of &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt; do.  Finally, exiting packets go through &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt;.  Also, connection tracking is handled just after &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The purpose of the &amp;lt;tt&amp;gt;raw&amp;lt;/tt&amp;gt; table is to apply rules to packets before connection tracking.  The &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table is used to alter source and destination addresses and TCP and UDP port numbers.  The &amp;lt;tt&amp;gt;mangle&amp;lt;/tt&amp;gt; table is used to mark packets and make certain alterations to some of the IP or even TCP header information.  Decisions to pass or block a packet are made in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table.  SELinux labels can be applied or altered on a packet in the &amp;lt;tt&amp;gt;security&amp;lt;/tt&amp;gt; table.  And &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is the last chance to apply &amp;lt;tt&amp;gt;RAWNAT&amp;lt;/tt&amp;gt; to a packet.  Note that &amp;lt;tt&amp;gt;rawpost&amp;lt;/tt&amp;gt; is only available if you have installed the (((http_//xtables-addons.sf.net/ xtables-addons] package.&lt;br /&gt;
&lt;br /&gt;
Each rule is specified as a statement to add to a chain, optional selector criteria, and a target.  The most common flag for adding to a chain is &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; for append to the end.  There are also &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; for insert, either at the beginning or at a specified rule number, or &amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt; for replacing a particular rule number.  Rules are numbered starting at one for each table:CHAIN combination.  Likewise, you can use rule numbers to delete a rule with &amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, or by specifying all the rest of the syntax of the rule to be deleted.  Using &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt;, there is no need to use any action other than append.&lt;br /&gt;
&lt;br /&gt;
If you need to insert (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;), delete (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;), or replace (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;) a rule by rule number, you can use this script to number your rules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/gawk -f&lt;br /&gt;
&lt;br /&gt;
# This script reads in iptables-save format from stdin and appends&lt;br /&gt;
# (commented) rule numbers to stdout.&lt;br /&gt;
&lt;br /&gt;
# Tables are declared starting with an asterisk.  Reset all rule&lt;br /&gt;
# numbers on a new table.&lt;br /&gt;
/^\*/ {&lt;br /&gt;
    delete counter&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Rules begin with the APPEND command.  Number these.&lt;br /&gt;
$1 == &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print $0, &amp;quot;#&amp;quot;, ++counter[$2]&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Print all other lines without modification.&lt;br /&gt;
$1 != &amp;quot;-A&amp;quot; {&lt;br /&gt;
    print&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a target, either &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt; for jump, or &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt; for goto.  A target can either be an xtables module or a custom chain.  They mean the same thing for xtables modules, but for custom chains they handle what happens at the end of such a custom chain.  If a custom chain is entered by a jump instruction, and that custom chain exits either due to a &amp;lt;tt&amp;gt;RETURN&amp;lt;/tt&amp;gt; target or because the chain did not hit a terminating rule, the packet will continue traversing the parent chain where ever it left off.  But if a custom chain is entered by a goto instruction, it will return to the end of its parent chain, terminating in the parent chain's policy (which is either &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Targets come in two flavors, terminating and non-terminating.  A few examples of terminating targets are &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;.  After one of these targets is reached in a chain, processing goes on to the next table (except for &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; because then processing simply terminates).  Examples of non-terminating targets are &amp;lt;tt&amp;gt;LOG&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;LED&amp;lt;/tt&amp;gt; (which triggers the keyboard LEDs to blink on matching events).  Some targets can only be used in certain tables.  For example, &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DNAT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;REDIRECT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt; can only be used in &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; chains.  And while technically &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;REJECT&amp;lt;/tt&amp;gt; can be called from any table, it is best to only call them in the &amp;lt;tt&amp;gt;filter&amp;lt;/tt&amp;gt; table, to avoid confusion at a later time.  Finally, you can call &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; in any table, and it simply means stop processing that packet and move on to the next table or chain.&lt;br /&gt;
&lt;br /&gt;
Certainly the most complex parts of most rules are the selector criteria.  Any selector criterion which is not explicitly stated is implicitly set to match anything.  Selectors exist to match interfaces, protocol, source and destination IP, and an almost dizzying array of match modules.  The input interface is specified with &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and is available only in the &amp;lt;tt&amp;gt;PREROUTING&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chains.  The &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flag for output interface is only available in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OUTPUT&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;POSTROUTING&amp;lt;/tt&amp;gt; chains.  This means the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; flags can only be used together in the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain.  Protocol is specified with the &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; option, and specifying &amp;lt;tt&amp;gt;tpc&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; will implicitly load in those corresponding match modules.  And source address is specified with &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt; is for destination address.  Either of these can be given either a single IP address, a CIDR netblock, or a full netmask.  The interesting thing about netmasks is they do not necessarily have to be one of the regular 33 netmasks.  For instance, you can specify a netmask of 255.255.255.253 to specify only the two even or two odd ending addresses in a group of four.&lt;br /&gt;
&lt;br /&gt;
All matches begin with &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; and the module to use in the match.  Most matches include flags of their own, and such flags need to be grouped together immediately after the match directive itself and before a new &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; match.  For example, &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-m udp&amp;lt;/tt&amp;gt; both include the flags &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; to match source or destination ports.  There are match modules to match just about any part of a packet, from addresses in arbitrary ranges, protocols like dscp, dccp, esp, and sctp, the length of a packet, what time of day it happens to be, which CPU in a multi-processor system generated it, which local user is responsible for it, down to how often packets from the same source or in the same flow are being processed.&lt;br /&gt;
&lt;br /&gt;
== Starting Rules ==&lt;br /&gt;
&lt;br /&gt;
Alright, enough theory, let's get in to some practice.  I suggest you start your rules like this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
:INPUT	     ACCEPT&lt;br /&gt;
:OUTPUT	     ACCEPT&lt;br /&gt;
:FORWARD     ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT  -i lo -j ACCEPT&lt;br /&gt;
-A OUTPUT -o lo -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-A INPUT   -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wait a minute!  Those rules won't actually block anything.  What kind of a firewall is this?  Like I said, this is a good place to start.  If this is a single host firewall, try setting the &amp;lt;tt&amp;gt;INPUT&amp;lt;/tt&amp;gt; policy to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Also, notice a couple other things.  First, the old &amp;lt;tt&amp;gt;-m state&amp;lt;/tt&amp;gt; module is deprecated.  Now we use &amp;lt;tt&amp;gt;conntrack&amp;lt;/tt&amp;gt;.  This module adds a lot more to state tracking, as seen below:&lt;br /&gt;
&lt;br /&gt;
;INVALID&lt;br /&gt;
: The packet contains flags indicating it should be part of an established connection, but the origin of the connection never happened.&lt;br /&gt;
;ESTABLISHED&lt;br /&gt;
: The packet is part of an ongoing connection.&lt;br /&gt;
;NEW&lt;br /&gt;
: This packet starts up a new connection in a valid way.&lt;br /&gt;
;RELATED&lt;br /&gt;
: This packet may be on a different port tupple from a valid connection, but it is part of it.  An example is an FTP DATA connection.  Also, ICMP Destination Unreachable messages are RELATED.&lt;br /&gt;
;UNTRACKED&lt;br /&gt;
: The connection tracking information for this packet has been deleted, either in the raw table or manually with the conntrack command line tool.&lt;br /&gt;
;SNAT&lt;br /&gt;
: This packet has been altered by source NAT.&lt;br /&gt;
;DNAT&lt;br /&gt;
: This packet has been altered by destination NAT.&lt;br /&gt;
&lt;br /&gt;
We can put more of this to use.  To protect against various spoof attacks and idle scans, we can filter on the &amp;lt;tt&amp;gt;INVALID&amp;lt;/tt&amp;gt; flag.  Add the following to the above example, just above &amp;lt;tt&amp;gt;COMMIT&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-A INPUT   -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A OUTPUT  -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
-A FORWARD -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
In addition to connection tracking state, there is now also status, which gets even deeper into the meaning of packets.  --ctstatus values are:&lt;br /&gt;
&lt;br /&gt;
;NONE&lt;br /&gt;
: None of the following apply.&lt;br /&gt;
;EXPECTED&lt;br /&gt;
: This connection was set up by a helper module.&lt;br /&gt;
;SEEN_REPLY&lt;br /&gt;
: Packets in both directions have been seen.&lt;br /&gt;
;ASSURED&lt;br /&gt;
: The connection tracking entry won't be expired early.&lt;br /&gt;
;CONFIRMED&lt;br /&gt;
: The originating packet has already been sent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Network Address Translation ==&lt;br /&gt;
&lt;br /&gt;
A lot of users come into #Netfilter with simple requests as to how to make NAT work.  In general, it's pretty easy and there are plenty of other tutorials on the web which illustrate how to make it work.  First, you need to activate IP Forwarding.  There are two ways to do this, either through the filesystem or with &amp;lt;tt&amp;gt;sysctl&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sysctl -w net.ipv4.ip_forward=1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This control allows packets to flow through the FORWARD chain.  In the following examples I will assume the computer in question has two network interfaces, eth0 and eth1, and that eth0 faces the Internet and eth1 faces your internal LAN.  Think 0 for &amp;quot;0utside&amp;quot; and 1 for &amp;quot;1nside.&amp;quot;  Addresses fall into two categories, static or dynamic.  For the simple task of sharing a public IP, you need to know if your address is static or dynamic.&lt;br /&gt;
&lt;br /&gt;
If you have more than one address, it is extremely unlikely that they are dynamic.  If you use PPPoE, your address is most likely dynamic.  In order to share your public address for multiple client computers behind your firewall, if your address is static you are going to use &amp;lt;tt&amp;gt;SNAT&amp;lt;/tt&amp;gt;, and if it is dynamic you are going to use &amp;lt;tt&amp;gt;MASQUERADE&amp;lt;/tt&amp;gt;.  This first example will assume a dynamic address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see in the above example, I am no longer providing complete rulesets.  It is now up to you to edit your own rulesets integrating the changes shown in a manner that best applies to your needs.  This sample simply allows all traffic heading out to the Internet to be masqueraded to your public source address.  In addition, the policy on the &amp;lt;tt&amp;gt;FORWARD&amp;lt;/tt&amp;gt; chain has been set to &amp;lt;tt&amp;gt;DROP&amp;lt;/tt&amp;gt; and an additional rule added which now allows forwarded traffic from the LAN out to the Internet.&lt;br /&gt;
&lt;br /&gt;
You may be thinking, &amp;quot;great, my packets can get out but how do the reply packets get back in?&amp;quot;  This is part of the wonders of connection tracking.  In reality, only &amp;lt;tt&amp;gt;NEW&amp;lt;/tt&amp;gt; packets are examined by the &amp;lt;tt&amp;gt;nat&amp;lt;/tt&amp;gt; table.  Connection tracking takes hold of every &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connection and de-nats the return packet automatically.  This would not be so easy to do without connection tracking.  Also, in the previous section the examples included an &amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt; rule for &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; connections, so replies are going to come back to any request with no problem now.&lt;br /&gt;
&lt;br /&gt;
Next, let's assume you have one static address, 192.0.2.123, and you wish to forward SSH traffic to a computer at 10.1.1.99.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*nat&lt;br /&gt;
-A PREROUTING  -i eth0 -p tcp --dport 22 -j DNAT --to 10.1.1.99&lt;br /&gt;
-A POSTROUTING -o eth0 -j SNAT --to 192.0.2.123&lt;br /&gt;
COMMIT&lt;br /&gt;
&lt;br /&gt;
*filter&lt;br /&gt;
:FORWARD DROP&lt;br /&gt;
-A FORWARD -i eth1 -o eth0 -j ACCEPT&lt;br /&gt;
-A FORWARD -m conntrack --ctstate DNAT -j ACCEPT&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Custom Chains ==&lt;br /&gt;
&lt;br /&gt;
People who are new to Netfilter and iptables often ask when one should use a custom chain.  The answer is that there are a myriad of reasons why a custom chain might be called for.  There are also a ton of reasons not to use a custom chain.&lt;br /&gt;
&lt;br /&gt;
Think of a custom chain as a subroutine or custom function written in a programming language.  Once it exists, you can call it to save time, so you don't have to write the same code over again.  But also, think of a custom chain as an if-condition.  The use of a custom chain means that packets that do not match the initial criteria can skip over unrelated rules.&lt;br /&gt;
&lt;br /&gt;
However, don't create custom chains just because it seems like a good idea at the time.  You will just make your ruleset harder to follow.&lt;br /&gt;
&lt;br /&gt;
A custom chain can be created in &amp;lt;tt&amp;gt;iptables-restore&amp;lt;/tt&amp;gt; syntax by prefixing the name with a colon, and specifying a dash as the policy as illustrated earlier.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:custom-chain -&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom chain can be named any combination of upper and lower case letters, numerals, dash, underscore, and even space if it is quoted.  The only exception is the first character may not be a dash.  For the sake of legibility, I urge you not to use spaces in custom chains.  It is also recommended not to use all upper case characters because that is what is used for custom chains and for target modules &amp;amp;ndash; consider that a rule can jump to either a target module or a custom chain.  Definitely don't name a custom chain something that already exists, like &amp;quot;&amp;lt;tt&amp;gt;ACCEPT&amp;lt;/tt&amp;gt;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Math So Basic You Didn't Learn It In Kindergarten ==&lt;br /&gt;
&lt;br /&gt;
Computers, for all their complexity, are actually pretty simple.  So simple, in fact, that they really only understand two values, zero and one.  Most of the math a computer does is actually based on simply moving ones and zeros around and comparing the results.  There are three operators used quite commonly in these comparisons, commonly referred to as &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt;.  Each of them compares a bit on the left and on the right of the operator and returns a bit.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator returns a one as long as both bits compared are ones.  The presense of a zero on either side results in a zero.  It is represented in most computer languages by the &amp;amp;amp; sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; operator returns a one as long as at least one of the bits is a one.  If both bits are zero the result is zero.  It is represented in most computer languages by the | sign.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; operator returns a one when both bits are opposite.  If both bits are the same, it returns zero.  It is represented in most computer languages by the ^ sign.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#cccccc; padding: 0 1em 0 1em;&amp;quot;| 0 | 0 = 0 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 0 = 0&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 0 &amp;amp; 1 = 0 ||style=&amp;quot;background-color:#cccccc; padding: 0 1em 0 1em;&amp;quot;| 0 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 0 ^ 1 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 0 = 0 ||style=&amp;quot;background-color:#cccccc; padding: 0 1em 0 1em;&amp;quot;| 1 | 0 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 0 = 1&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;padding-right: 1em;&amp;quot;| 1 &amp;amp; 1 = 1 ||style=&amp;quot;background-color:#cccccc; padding: 0 1em 0 1em;&amp;quot;| 1 | 1 = 1 ||style=&amp;quot;padding-left: 1em;&amp;quot;| 1 ^ 1 = 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Why am I bothering to tell you all this?  These operators are the foundation of some core functionality in Netfilter, and indeed in computer networking in general.  For example, have you ever wondered what your netmask is really for?  It tells the computer how many bits are in the network portion of your address, and how many bits are in the host portion.  The one bits always start on the left.  That's why, for example, 255.255.255.0 is sometimes written as /24; there are twenty-four one-bits on the left side of 11111111 11111111 11111111 00000000.  For IPv4, there are only 33 valid netmasks because there are thirty-two bits in an IPv4 address.&lt;br /&gt;
&lt;br /&gt;
Ok, so now we know how many bits are ones in our netmask.  How does this tell us anything?  First we use the &amp;lt;code&amp;gt;AND&amp;lt;/code&amp;gt; operator to determine our network address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 &amp;amp;amp; 255.255.0.0 = 123.45.0.0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We can perform this operation on both the source and destination addresses of a packet.  If the network address is the same for both, we know the packet is going to a computer on the same network.  If it is different, we know the packet needs to be routed and it will be sent to our gateway.&lt;br /&gt;
&lt;br /&gt;
And how do we determine the broadcast address of our network?  First we take the &amp;lt;code&amp;gt;XOR&amp;lt;/code&amp;gt; of our netmask against all ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
255.255.0.0 ^ 255.255.255.255 = 0.0.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; that value with our address.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
123.45.67.89 | 0.0.255.255 = 123.45.255.255&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a computer, this is simple stuff.  Bits go in, bits come out.  Comparisons like this hardly even give it a workout.&lt;br /&gt;
&lt;br /&gt;
== Using ipsets ==&lt;br /&gt;
&lt;br /&gt;
The mainline kernel has included support for ipsets for years now, and most distributions now include that support in their kernel, iptables package, and an ipset package.  This may not be true of older long-term support distros like RHEL 5, but it is available in RHEL 6.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; command allows you to create a single kernel-level object that iptables rules can match against.  This set can contain a large amount of individual IPs and other network information.&lt;br /&gt;
&lt;br /&gt;
As the man page of ipset explains, each set needs to be of a particular type.  The types consist of a storage method and up to three datatypes.  The methods are the following:&lt;br /&gt;
&lt;br /&gt;
; hash&lt;br /&gt;
: A dynamically sized data type that stores the set data as a hash.  Incoming data is tested against the hash for matches, which provides fast lookup.&lt;br /&gt;
; bitmap&lt;br /&gt;
: A fixed sized data type that stores set data as a bitmap covering a range.  Incoming data is mapped to a bit in the map and tested with the &amp;amp;amp; operator.&lt;br /&gt;
; list&lt;br /&gt;
: A fixed sized data type that acts as a superset of other sets.  This allows a single test to match against sets that contain both variable-sized network addresses and fixed-sized host addresses, or sets that contain combinations of address and port data.&lt;br /&gt;
&lt;br /&gt;
The datatypes are:&lt;br /&gt;
&lt;br /&gt;
; ip&lt;br /&gt;
: Matches fixed-width netmask addresses, defaults to 32-bit.  Not all combinations of datatypes allow specifying a netmask, so some of them are fixed at 32-bits.&lt;br /&gt;
; net&lt;br /&gt;
: Matches networks with netmasks specified between 1 and 31 bits.&lt;br /&gt;
; mac&lt;br /&gt;
: Matches the hardware address of a host.&lt;br /&gt;
; port&lt;br /&gt;
: Matches a TCP, UDP, SCTP, or UDPLite port, ICMP or ICMPv6 type/code, or even protocols which have no ports like ESP or GRE.&lt;br /&gt;
; iface&lt;br /&gt;
: Matches the ingress or egress interface of a port, with the same restrictions as the &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;-o&amp;lt;/tt&amp;gt; criteria for a rule.&lt;br /&gt;
&lt;br /&gt;
The following combinations are supported:&lt;br /&gt;
&lt;br /&gt;
* hash:ip&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* bitmap:ip&lt;br /&gt;
* bitmap:ip,mac&lt;br /&gt;
* bitmap:port&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
As of version 6, &amp;lt;tt&amp;gt;ipset&amp;lt;/tt&amp;gt; accepts a much more English-like configuration syntax, but I find the older syntax easier to type out and more similar to &amp;lt;tt&amp;gt;iptables&amp;lt;/tt&amp;gt; syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N Bogons hash:net&lt;br /&gt;
ipset -A Bogons 0.0.0.0/8&lt;br /&gt;
ipset -A Bogons 10.0.0.0/8&lt;br /&gt;
ipset -A Bogons 100.64.0.0/10&lt;br /&gt;
ipset -A Bogons 127.0.0.0/8&lt;br /&gt;
ipset -A Bogons 169.254.0.0/16&lt;br /&gt;
ipset -A Bogons 172.16.0.0/12&lt;br /&gt;
ipset -A Bogons 192.0.0.0/29&lt;br /&gt;
ipset -A Bogons 192.0.2.0/24&lt;br /&gt;
ipset -A Bogons 192.168.0.0/16&lt;br /&gt;
ipset -A Bogons 198.18.0.0/15&lt;br /&gt;
ipset -A Bogons 198.51.100.0/24&lt;br /&gt;
ipset -A Bogons 203.0.113.0/24&lt;br /&gt;
ipset -A Bogons 224.0.0.0/3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above set matches all the IPv4 addresses that are never supposed to be seen on the Internet (at least as source addresses).  Now, assuming that eth0 is your Internet-facing interface:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
*filter&lt;br /&gt;
-A INPUT   -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
-A FORWARD -i eth0 -m set --match-set Bogons src -j DROP&lt;br /&gt;
COMMIT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The syntax for the set match module is just this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
-m set --match-set &amp;amp;lt;set_name&amp;amp;gt; (src|dst)[,(src|dst)[,(src|dst)]]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of src|dst flags used depends on the set type.  A set of type hash:ip only requires one flag.  A set of type hash:ip,port,ip requires all three, to define which field in the set is matched against which part of the packet.&lt;br /&gt;
&lt;br /&gt;
Communication between secure VLANs can be difficult to define.  Let's assume we have an office network with an internal data center.  The entire office uses an internal IP space of 10.1.0.0/16.  Each department and each class of servers has its own VLAN which is assigned a unique set of a thousand IPs as a /22.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!  Network !! Purpose&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.0.0/22 || Web Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.4.0/22 || Mail and DNS Servers &lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.8.0/22 || Database Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.12.0/22 || Application Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.16.0/22 || Administrative Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.64.0/22 || Networking Equipment&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.68.0/22 || Storage Appliances&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.72.0/22 || Lights-Out Consoles&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.96.0/22 || Development Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.100.0/22 || Quality Assurance Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.104.0/22 || Staging Servers&lt;br /&gt;
|- style=&amp;quot;background-color: #c0c0c0&amp;quot;&lt;br /&gt;
|| 10.1.108.0/22 || Finance Department Servers&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.128.0/22 || Guest Wireless Network&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.132.0/22 || Executive Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.136.0/22 || Finance Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.140.0/22 || Marketing Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.144.0/22 || Sales Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.148.0/22 || Operations Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.152.0/22 || Customer Service Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.156.0/22 || Developer Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.160.0/22 || QA Desktops&lt;br /&gt;
|-&lt;br /&gt;
|| 10.1.164.0/22 || Sysadmin Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Now let's examine our services.  Every VLAN contains machines that are reached via SSH (22/tcp).  Every VLAN contains machines that are monitored with SNMP (161/udp) and Nagios (5666/tcp).  The web servers speak HTTP (80/tcp) and HTTPS (443/TCP).  Mail servers speak SMTP (25/tcp), Submission (587/tcp), SMTPS (465/tcp), POP3 (110/tcp), and IMAP (143/tcp) and DNS servers speak DNS (53/udp).  Database servers speak MySQL (3306/tcp).  Application servers speak a variety of protocols, but we'll focus on Tomcat (8080/tcp).  The administrative services include LDAP (389/tcp) and LDAPS (636/tcp), as well as internal DNS for the office (53/udp) and NFS (2049/tcp) and this is the VLAN where our Nagios and Cacti servers will collect data.  The networking equipment does not speak any special protocols that need to exceed the borders of that VLAN, so SSH and SNMP will suffice there.  Storage appliances speak iSCSI (3260/tcp).  Lights out management interfaces speak over SSH, HTTP and HTTPS.  Development, QA, and staging all need access via SSH. HTTP and HTTPS.  The rest of the VLANs are for desktop and laptop computers, all of which can be reached via either SSH or RDP (3389/tcp) &amp;amp;ndash; VNC is tunneled over SSH.&lt;br /&gt;
&lt;br /&gt;
We also need to examine which VLANs need access to the services in other VLANs.  Web and mail servers need access to databases and file stores, and the web servers need to get data from the application servers.  Database servers don't usually need to reach the outside world.  The application servers will also need to reach the database and file stores.  The administrative servers will need to monitor everything.  This is also where the VPN-based bastion host is located so remote admins can jump out with SSH to anywhere from here.  The networking, storage appliances, and lights out remote control devices don't need to initiate contact with the other VLANs.  The development network needs to push to the QA network.  QA sometimes needs to pull from development and push to staging.  And staging needs to pull from QA and push to production.  All of this is handled via SSH, but all these tiers have their own storage and database systems to isolate them.  The guest WiFi is also the same network as the conference rooms, and can only access public resources.  To make the desktop networks simple, we'll just say the finance department can access the financial servers VLAN and the sysadmin desktops can access anything because that's also where the desktop support team is.&lt;br /&gt;
&lt;br /&gt;
Are you ready to start building firewall rules that maintain the highest degree of separation between departments, that even satisfies Sarbannes-Oxley and PCI requirements, possibly even HPPA?  We'll do it with an ipset and a couple iptables rules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ipset -N VLAN-to-VLAN hash:net,port,net&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,icmp:8,10.1.0.0/16&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:80,10.1.0.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:443,10.1.0.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:25,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:465,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:587,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:110,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:143,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.4.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:389,10.1.16.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:636,10.1.16.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,udp:53,10.1.16.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/16,tcp:2049,10.1.16.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/22,tcp:8080,10.1.12.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.0.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.4.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.4.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.12.0/22,tcp:3306,10.1.8.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.12.0/22,tcp:2360,10.1.68.0/22&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.16.0/22,tcp:5666,10.1.0.0/16&lt;br /&gt;
ipset -N VLAN-to-VLAN 10.1.16.0/22,udp:161,10.1.0.0/16&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Using conntrack ==&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[User:Jeff|Jeff]] 07:02, 2 April 2014 (UTC)&lt;/div&gt;</description>
			<pubDate>Mon, 07 Apr 2014 03:28:00 GMT</pubDate>			<dc:creator>Jeff</dc:creator>			<comments>http://72.14.177.54/SFVLUG/Talk:Things_You_Should_Know_About_Netfilter</comments>		</item>
	</channel>
</rss>