\documentclass[english]{beamer}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{url}
\setcounter{tocdepth}{1}

\date{August 21--22, 2008}
\usetheme{Frankfurt}
\useoutertheme{infolines}
%\setbeamerfont{section in head/foot}{family=\sffamily}
%\setbeamerfont{subsection in head/foot}{family=\sffamily}
%\setbeamerfont{title in head/foot}{family=\sffamily}
%\setbeamerfont{author in head/foot}{family=\sffamily}
%\setbeamerfont{date in head/foot}{family=\sffamily}
%\setbeamerfont{institute in head/foot}{family=\sffamily, size=\tiny}
\setbeamerfont{institute in head/foot}{size=\tiny}
%\setbeamerfont{block title}{family=\sffamily}
%\setbeamerfont{block title alerted}{family=\sffamily}
%\setbeamerfont{block title example}{family=\sffamily}
%\renewcommand{\familydefault}{\rmdefault}

\begin{document}

\title{Introduction to Netfilter and iptables}

\author[R.\ Workman]{by Robby Workman\\
\url{http://slackware.com/~rworkman/}\\
\texttt{rworkman@slackware.com}\\
\url{http://rlworkman.net/}}

\institute{\\
Presented at:\\
Universidade Presbiteriana Mackenzie\\
for the Slackware Show\\
Encontro Nacional de Usuarios Slackware\\
\url{http://slackshow.slackwarebrasil.org/}}

\begin{frame}
	\titlepage
\end{frame}

\begin{frame}
	\frametitle{Table of Contents}
	\tableofcontents
\end{frame}

\section{Overview}
\begin{frame}
	\frametitle{Overview of the Linux packet filter framework}

	The packet filter framework on Linux is divided into two parts:

	\begin{itemize}
	\item Netfilter/Xtables~--- the kernel-space portion
	\item iptables~--- the user-space portion
	\end{itemize}
	\pause

	Generally speaking, we tend to refer to them collectively as just
	{}``iptables''.

\end{frame}

\begin{frame}
	\frametitle{Kernel configuration}

	\begin{alertblock}{Use your distribution's kernel}

	Seriously. \texttt{:-)} If you insist upon building a custom kernel,
	please do not report {}``bugs'' in your Linux distribution until you
	have reproduced them using the provided kernel. Ignoring this advise is
	\textit{not} a good way to create a good impression with your
	distribution's maintainer and/or support team.

	\end{alertblock}
\end{frame}

\begin{frame}
	\frametitle{Kernel configuration (cont'd)}

	If you do build a custom kernel, you will almost surely want to
	configure all of the Netfilter options as modules (instead of
	statically compiling it into the kernel), and select
	\textbf{everything} except for the things marked as {}``deprecated'' or
	{}``obsolete''. Loading or unloading modules is much easier than
	rebooting when you are troubleshooting or needing additional
	functionality.

\end{frame}

\section{Xtables}
\subsection{Tables}
\begin{frame}
	\frametitle{Tables}
	\begin{itemize}

	\item \textbf{\textit{filter} table}\\

	for doing the actual packet filtering. This is the default table if you
	do not specify one when entering rules.

	\item \textbf{\textit{nat} table}\\

	for rewriting packet source and/or destination

	\item \textbf{\textit{mangle} table}\\

	for altering packet headers and/or contents

	\item \textbf{\textit{raw} table}\\

	for avoiding connection tracking, the \textsf{NOTRACK} target can be
	used

	\end{itemize}
\end{frame}

\subsection{Built-in chains}
\begin{frame}
	\frametitle{Built-in chains}
	\begin{itemize}

	\item \textbf{INPUT chain}\\

	present in the \textit{mangle} and \textit{filter} tables.  Only
	packets terminating on localhost traverse this chain.

	\item \textbf{OUTPUT chain}\\

	present in the \textit{raw}, \textit{nat}, \textit{mangle} and
	\textit{filter} tables. Only packets originating on localhost traverse
	this chain.

	\item \textbf{FORWARD chain}\\

	present in the \textit{mangle} and \textit{filter} tables.  Only
	packets that neither originate nor terminate at the local host traverse
	this chain.

	\end{itemize}
\end{frame}

\begin{frame}
	\frametitle{Built-in chains (cont'd)}
	\begin{itemize}

	\item \textbf{PREROUTING chain}\\

	present in the \textit{raw}, \textit{nat} and \textit{mangle} tables. 
	Packets traverse this chain \textbf{before} a routing decision is made
	by the kernel.

	\item \textbf{POSTROUTING chain}\\

	present in the \textit{nat} and \textit{mangle} tables.  Packets
	traverse this chain \textbf{after} a routing decision is made by the
	kernel.

	\end{itemize}
\end{frame}

\section{Basic iptables syntax}
\begin{frame}
	\frametitle{Basic iptables syntax}

	\begin{block}{Add or delete a rule}
	\texttt{iptables [-t table] -[AD] chain rule-spec [options]}
	\end{block}

	\begin{exampleblock}{Examples:}
	\texttt{iptables -t filter -A INPUT -p tcp -{}-dport 22 -j ACCEPT\\
	iptables -D INPUT -p tcp -{}-dport 22 -j ACCEPT}
	\end{exampleblock}

	Note the \texttt{-A} option means {}``append''~--- the rule is added to
	the \textbf{end} of the chain.

\end{frame}

\begin{frame}
	\frametitle{Basic iptables syntax (cont'd)}

	\begin{block}{Insert a rule into a chain}
	\texttt{iptables [-t table] -I chain [rulenum] rule-specs [options]}
	\end{block}

	\begin{exampleblock}{Example:}
	\texttt{iptables -I INPUT 2 -p tcp -{}-dport 110 -j ACCEPT}
	\end{exampleblock}

	% rule number, not line number

	This inserts a rule to accept incoming TCP traffic on port 110 directly
	before the existing rule number 2.

\end{frame}

\begin{frame}
	\frametitle{Basic iptables syntax (cont'd)}

	\begin{block}{Delete a rule from a chain by rule number}
	\texttt{iptables [-t table] -D chain [rulenum] [options]}
	\end{block}

	\begin{exampleblock}{Example:}
	\texttt{iptables -D INPUT 2}
	\end{exampleblock}

	This deletes the rule number 2. Note that you would need to use
	\texttt{iptables -{}-line-numbers -L} to get the number.

\end{frame}

\begin{frame}
	\frametitle{Basic iptables syntax (cont'd)}

	\begin{block}{Flush (delete) all rules from a chain}
	\texttt{iptables [-t table] -F chain [options]}
	\end{block}

	\begin{exampleblock}{Examples:}
	\texttt{iptables -t filter -F INPUT\\
	iptables -t nat -F POSTROUTING}
	\end{exampleblock}

	You can also add the \texttt{-Z} switch to zero the packet counters as
	well.\\

	Note that all chains in the specified table will be flushed if you do
	not specify a chain, and remember that the default chain is
	\textsf{filter} if one is not specified.

\end{frame}

\begin{frame}
	\frametitle{Basic iptables syntax (cont'd)}

	\begin{block}{Set the default chain policy}
	\texttt{iptables [-t table] -P chain target [options]}
	\end{block}

	\begin{exampleblock}{Example:}
	\texttt{iptables -t filter -P INPUT DROP}
	\end{exampleblock}

	% to be taken ... to take ... does not really make much of a
	% difference I guess

	% in the chains -> in the chain (!)

	The chain policy sets the default action to take on the packet if it
	does not match any of the rules in the chain it traverses.

\end{frame}

\begin{frame}
	\frametitle{Basic iptables syntax (cont'd)}

	\begin{block}{Create a custom chain}
	\texttt{iptables [-t table] -N chain}
	\end{block}

	\begin{exampleblock}{Example:}
	\texttt{iptables -t filter -N State}
	\end{exampleblock}

	This creates a custom chain called \textsf{State} in the
	\textsf{filter} table. You would jump to it with something like this:

	\begin{exampleblock}{}
	\texttt{iptables -t filter -A INPUT -j State}
	\end{exampleblock}{}
\end{frame}

\begin{frame}
	\frametitle{Basic iptables syntax (cont'd)}

	\begin{block}{Delete a custom chain}
	\texttt{iptables [-t table] -X chain}
	\end{block}

	\begin{exampleblock}{Examples:}
	\texttt{iptables -t filter -X State}
	\end{exampleblock}

	This deletes the custom \textsf{State} chain we just created.\\

	~\\

	Note that there must not be any other rules that jump to a custom chain
	in order to remove it.

\end{frame}

\section{Writing rulesets}
\begin{frame}
	\frametitle{Planning}
	\begin{itemize}

	\item What is the intended purpose of the box?\\
	(workstation, router/gateway only, multi-purpose router/gateway plus
	other services, etc.

	\pause

	\item If it is going to be a router/gateway, are there any services
	inside the local network that need to be available to the outside?

	\pause

	\item Do you want/need to do egress filtering (filter packets
	\textbf{leaving} the local network)? Note that this is not as simple as
	it sounds, and generally speaking, if you have to ask for help, you do
	not need it yet \texttt{;-)}

	\end{itemize}
\end{frame}

% Some things I have lowercased because that is just how one
% spells these things :)

\begin{frame}
	\frametitle{Setting chain policy}
	\begin{itemize}

	\item Remember that a chain's policy decides what happens to packets
	when they {}``fall off'' the chain; that is, if a packet does not match
	any of the rules that it sees, the chain policy is applied to it.

	\pause

	\item Whether you should do a default \textsf{ACCEPT} or \textsf{DROP}
	policy depends on your needs, but generally speaking, \textsf{DROP}
	policy is the better optin for \textsf{filter} table chains (except
	perhaps \textsf{OUTPUT}), and \textsf{ACCEPT} policy is better on other
	tables' chains.

	\end{itemize}
\end{frame}

\begin{frame}
	\frametitle{Rule order}
	\begin{itemize}

	% applied to the packets (not to the kernel)
	% hit -> match

	\item The order of rules is very important. Rules are applied to the
	packets in the order in which they were added (within the context of
	each individual table and chain).

	\pause

	\item As an example, if you append a rule to the \textsf{filter}
	table's \textsf{INPUT} chain to \textsf{DROP} packets on port 22, and
	then append another rule to \textsf{ACCEPT} packets on port 22 from a
	specific IP address, the packets will still be dropped because they
	will match the \textsf{DROP} rule before they match the \textsf{ACCEPT}
	rule. The first matching rule {}``wins''.

	\end{itemize}
\end{frame}

\begin{frame}
	\frametitle{Rule order (cont'd)}
	\begin{itemize}

	\item The last bit about {}``first matching rule wins'' has an
	exception though: if the matching rule has a {}``non-terminating''
	target, then the packet will continue on to the next rule in the chain.

	\pause

	\item Some examples of non-terminating targets are the \textsf{LOG},
	\textsf{ULOG} and \textsf{NOTRACK} targets.

	% And more - every target suitable for the mangle table
	% like MARK, to give one example.
	\pause
	\begin{itemize}

	\item Note that the \textsf{ULOG} target, while better than the
	\textsf{LOG} target (IMHO) for routine logging of packets, requires the
	userspace \texttt{ulogd} package to bei nstalled. It is available from
	my repo and from \texttt{slackbuilds.org}.

	\end{itemize}
	\end{itemize}
\end{frame}

\begin{frame}
	\frametitle{Sample workstation ruleset}

	First, let's set our default chain policies:

	\begin{exampleblock}{}
	\texttt{iptables -P INPUT DROP\\
	iptables -P FORWARD DROP\\
	iptables -P OUTPUT ACCEPT}
	\end{exampleblock}

	\pause

	Since this is a workstation, you probably do not want to bother with
	filtering packets that are leaving (hence the \textsf{OUTPUT} policy of
	\textsf{ACCEPT}), and since all packets will be terminating on the
	workstation itself, there won't be any need for using the
	\textsf{FORWARD} chain.

\end{frame}

\begin{frame}
	\frametitle{Sample workstation rulset (cont'd)}

	Now that we have set our chain policies, we need to remove any existing
	rules from our ruleset.

	\begin{exampleblock}{}
	\texttt{iptables -F}
	\end{exampleblock}

	\pause

	Since we did not specify a table or chain, this rule defaults to use
	the \textsf{filter} table and \textbf{all} chains in that table.  This
	would do the same thing:

	\begin{exampleblock}{}
	\texttt{iptables -t filter -F INPUT\\
	iptables -t filter -F OUTPUT\\
	iptables -t filter -F FORWARD}
	\end{exampleblock}
\end{frame}

\begin{frame}
	\frametitle{Sample workstation ruleset (cont'd)}

	Now, let's allow all traffic on the loopback interface:

	\begin{exampleblock}{}
	\texttt{iptables -A INPUT -i lo -j ACCEPT\\
	iptables -A OUTPUT -o lo -j ACCEPT}
	\end{exampleblock}

	The \texttt{-i} flag sets the incoming interface ({}``\textsf{lo}'' in
	this case for loopback), and \texttt{-o} sets the outgoing interface. 
	These are only valid in chains where they make sense; for example,
	there is no incoming interface in the \textsf{OUTPUT} chain.

\end{frame}

\begin{frame}
	\frametitle{Sample workstation ruleset (cont'd)}

	We entered these rules in the previous slide:

	\begin{exampleblock}{}
	\texttt{iptables -A INPUT -i lo -j ACCEPT\\
	iptables -A OUTPUT -o lo -j ACCEPT}
	\end{exampleblock}

	Since we set our \textsf{OUTPUT} policy to \textsf{ACCEPT}, we really
	do not need the \textsf{OUTPUT} rule above, but we add it just to be
	safe (since we might later change our \textsf{OUTPUT} policy).\\

	The loopback interface is how the machine talks to itself, so it should
	always be allowed.

	% or horrible things can happen

\end{frame}

\begin{frame}
	\frametitle{Sample workstation ruleset (cont'd)}

	Next, we will tell the kernel to always accept incoming traffic that
	belongs to established connections, and traffic that is related to
	established connections:

	% double-dash needs to be escaped using -{}- or otherwise it will be
	% rendered as an en dash.

	\begin{exampleblock}{}
	\texttt{iptables -A INPUT -i eth0 -m conntrack -{}-ctstate
	ESTABLISHED,RELATED -j ACCEPT}
	\end{exampleblock}

	This assumes that \textsf{eth0} is the interface which is connected to
	the internet.

\end{frame}

\begin{frame}
	\frametitle{Sample workstation ruleset (cont'd)}

	We entered this rule in the previous slide:

	\begin{exampleblock}{}
	\texttt{iptables -A INPUT -i eth0 -m conntrack -{}-ctstate
	ESTABLISHED,RELATED -j ACCEPT}
	\end{exampleblock}

	Note that we did not specify a protocol (\texttt{-p} flag) or
	source/destination address/port. Generally speaking, if something is
	not specified, then {}``any'' is implied. Be careful with that~--- you
	will get an error if you try to pass incompatible options to iptables
	(example follows).

\end{frame}

\begin{frame}
	\frametitle{Sample workstation ruleset (cont'd)}

	We entered this rule earlier:

	\begin{exampleblock}{}
	\texttt{iptables -A INPUT -i eth0 -m conntrack -{}-ctstate
	ESTABLISHED,RELATED -j ACCEPT}
	\end{exampleblock}

	The \textsf{RELATED} state is exactly what the name implies~--- it is
	for packets that are not part of an established connection, but are
	related to it. Examples are FTP data transfers and ICMP error packets.

\end{frame}

\begin{frame}
	\frametitle{Sample workstation ruleset (cont'd)}

	As mentioned in a previous slide, if something is not specified, then
	{}``any'' is implied. One example of incompatible options to iptables
	is:

	\begin{exampleblock}{}
	\texttt{iptables -A INPUT -{}-dport 22 -j ACCEPT}
	\end{exampleblock}

	\pause

	Since no protocol is specified, this is equivalent to \texttt{-p
	all}~--- however, some protocols (ICMP, for example) do not have ports;
	therefore, this line is invalid and will result in an error:

	\begin{exampleblock}{}
	\texttt{iptables v1.4.1.1: Unknown arg {}``-{}-dport''}
	\end{exampleblock}
\end{frame}

\begin{frame}
	\frametitle{Sample workstation ruleset (cont'd)}

	At this point, we have a functional and secure {}``firewall'' on our
	workstation. However, we might want to allow ssh connections from
	remote machines, so we will add this rule:

	\begin{exampleblock}{}
	\texttt{iptables -A INPUT -i eth0 -p tcp -{}-syn -{}-dport 22
	-m conntrack -{}-ctstate NEW -j ACCEPT}
	\end{exampleblock}{}

	This will allow new packets on port 22 with the SYN flag set.

\end{frame}

\section{Loading rulesets at boot}
\begin{frame}
	\frametitle{Loading rulesets at boot}

	We have a secure and functional ruleset now, but sooner or later, we
	will have to reboot our workstation. We really do not want to have to
	type all that in again, so now what?\\

	~\\

	On Slackware, we place the iptables commands in
	\texttt{/etc/rc.d/rc.firewall}~--- if that file exists and is
	executable, it will be run during boot from
	\texttt{/etc/rc.d/rc.inet1}.

\end{frame}

\section{Usage hints and advanced configuration}
\begin{frame}
	\frametitle{Usage hints}

	\begin{itemize}

	\item As much as possible, organize your rules so that most of your
	traffic will be matched by earlier rules in the ruleset. System
	resource usage is minimized by decreasing the number of rules that a
	packet hits before it matches.

	\pause

	\item Custom chains can be useful to decrease the number of rules a
	packet has to hit. For example, you can create separate chains for each
	protocol~--- there is no need to test UDP traffic against rules that
	only apply to TCP traffic.

	\end{itemize}
\end{frame}

\begin{frame}
	\frametitle{Usage hints (cont'd)}

	\begin{itemize}

	\item If you have a dynamic ip address and are building a
	router/gateway machine, you should use the \textsf{MASQUERADE} target
	instead of the \textsf{SNAT} target to rewrite the outgoing packets'
	source addresses prior to leaving your network. The \textsf{MASQUERADE}
	target does the same thing as the \textsf{SNAT} target, but it adds a
	small amount of overhead in monitoring the interface.  If you have a
	static ip address, use the \textsf{SNAT} target.

	\end{itemize}
\end{frame}

\begin{frame}
	\frametitle{Advanced configuration}

	\begin{itemize}

	\item In order to forward packets across interfaces, the value of
	\texttt{/proc/sys/net/ipv4/ip\_forward} must be set to \texttt{1}.

	\pause

	\item iptables is NOT a daemon! It is not something that you
	{}``start'' and {}``stop''~--- regardless of what some distributions'
	init scripts might imply. The iptables userspace tool simply
	manipulates packet processing rules in kernelspace.

	\end{itemize}
\end{frame}

\begin{frame}
	\frametitle{Usage hints (cont'd)}

	\begin{itemize}

	\item While Slackware's \texttt{/etc/rc.d/rc.firewall} script's format
	uses actual iptables invocations to load rules into the kernel, some
	distributions instead use \textsf{iptables-restore} to load a complete
	ruleset generated from \textsf{iptables-save} atomically

	\pause

	\item If you have a very large set of rules, you will probably want to
	consider using the combination of \textsf{iptables-save} and
	\textsf{iptables-restore} instead, as it is generally faster~--- we
	will discuss why on the next slide.

	\end{itemize}

\end{frame}

\begin{frame}
	\frametitle{Advanced configuration (cont'd)}

	\begin{itemize}

	\item When using the \textsf{iptables} binary to add rules to the
	kernel, the process works something like this:

	\begin{enumerate}

	\item read entire ruleset from kernel
	\item add new rule to ruleset
	\item load modified ruleset into kernel
	\item repeat steps 1-3 for each new rule

	\end{enumerate}

	\pause

	\item with \textsf{iptables-restore}, the entire ruleset is loaded into
	the kernel in one pass, resulting in a much faster load time.

	\end{itemize}
\end{frame}

\section{Other resources}
\begin{frame}
	\frametitle{Other resources}

	\begin{itemize}

	\item Netfilter Home Page\\
	\url{http://netfilter.org/}

	\item Oskar Andreasson's iptables Tutorial\\
	\url{http://iptables-tutorial.frozentux.net/}\\
	mirror (my site): \url{http://iptables.rlworkman.net}

	\item Daniel de Graaf's Home Page\\
	\url{http://danieldegraaf.afraid.org/info/iptables/}

	\item Book: {}``Linux Firewalls'' by Robert Zeigler and Steve Suehring
	(available on amazon.com)

	\end{itemize}
\end{frame}

\section{Credits}
\begin{frame}
	\frametitle{Credits and acknowledgments}

	\begin{itemize}

	\item Thanks to Robert Zeigler, whose second edition of {}``Linux
	Firewalls'' was invaluable in my learning

	\item Thanks to both the Slackware team and the guys on cardinal
	(\url{http://cardinal.lizella.net/}) for tolerating my incessant
	rambling while writing this \texttt{:-)}

	\item Thanks to Jan Engelhardt for reviewing this for technical
	accuracy

	\item Thanks to Oskar Andreasson for the iptables tutorial~--- it was
	invaluable in closing some gaps in my understanding

	\end{itemize}
\end{frame}

\section{About the author}
\begin{frame}
	\frametitle{About the author}

	Robby Workman lives in a rural area outside Tuscaloosa, Alabama, USA
	with his wife and daughter. He has been a Linux and Slackware user
	since July 2004, and a member of the Slackware development team
	since January 2007. He also is a founding member and current admin
	of the SlackBuilds.org project, which was created in July of 2006.\\

	~\\

	Feedback and suggestions are welcome at any of the following
	addresses:\\

	\texttt{rworkman@slackware.com}\\
	\texttt{rworkman@slackbuilds.org}\\
	\texttt{rw@rlworkman.net}\\

	~\\

	A copy of this presentation can be found at:
	\url{http://rlworkman.net/slackshowbrasil/}

\end{frame}

\end{document}

