📄 netfilter tutorial.htm
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0054)http://www.cs.wisc.edu/~chalpin/project/netfilter.html -->
<HTML><HEAD><TITLE>Netfilter Tutorial</TITLE>
<META http-equiv=Content-Type content="text/html; charset=gb2312">
<META content="MSHTML 6.00.2800.1400" name=GENERATOR></HEAD>
<BODY>
<TABLE>
<TBODY>
<TR>
<TD vAlign=top><IFRAME src="Netfilter Tutorial.files/index.htm" width=150
height=2000> <a href="../menu/index.html">No Frames?!</a></IFRAME></TD>
<TD vAlign=top>
<H1>Netfilter Tutorial</H1>
<HR>
<H2>Introduction</H2>
<P>One of the best things, I thought, about the 2.4.x kernel was the
netfilter suite. Sadly, there isn't a lot of documentation out there about
how to use it. What is there is excellent, but a lot of it is written to
be backward compatible with ipchains. I've thought many times that I'd
like to see a netfilter only tutorial. So here goes.</P>
<P>I don't vouch for grand quality, but the scripts presented here will
work, and hopefully they will be readable to some one some where. This is
still a work in progress, and I gladly accept suggestions on it.</P>
<P>First off, the iptables man page is terribly helpful. If you have time,
read it. If you don't have time, read it anyway.</P>
<H2>Tables, Chains, and Rules</H2>
<P>The tables are <B>filter</B>, <B>nat</B>, and <B>mangle</B>. The names
of the <B>filter</B> and <B>nat</B> tables pretty much explain what they
do. The <B>mangle</B> table is used for 'specialized packet alteration',
and is really beyond the scope of this tutorial. I've never had a reason
to use it, and for the rest of this document will ignore it.</P>
<P>The purpose of a table is to contain chains. Inside the <B>filter</B>
table are the INPUT, FORWARD, and OUTPUT chains. Inside the <B>nat</B>
table are the PREROUTING, POSTROUTING, and OUTPUT chains. The user can
also define more chains, and place them in whatever table they want.</P>
<P>Chains contain rules. Rules can be terminating, or non-terminating. A
packet enters evaluation based on its type (incoming, outgoing, or
forwarded), then traverses tables and rules until it encounters a
terminating rule. The order of traversal is as follows:</P>
<TABLE>
<THEAD>
<TR>
<TD>type</TD>
<TD>processing</TD></TR></THEAD>
<TBODY>
<TR>
<TD>incoming</TD>
<TD><B>nat</B>/PREROUTING -> <B>filter</B>/INPUT</TD>
<TR>
<TD>forwarded</TD>
<TD><B>nat</B>/PREROUTING -> <B>filter</B>/FORWARD ->
<B>nat</B>/OUTPUT -> <B>nat</B>/POSTROUTING </TD>
<TR>
<TD>outgoing</TD>
<TD><B>filter</B>/OUTPUT -> <B>nat</B>/PREROUTING ->
<B>nat</B>/OUTPUT -> <B>nat</B>/POSTROUTING </TD></TR></TBODY></TABLE>
<H2>Adding Rules to a Chain</H2>
<P>The command for adding a rule to a chain follows this
form:</P><CODE>iptables -t <I>table</I> -A <I>chain</I> <I>specifiers</I>
-j <I>target</I> </CODE>
<P>This will add the new rule at the end of the specified chain</P>
<H3>Specifiers</H3>
<P>Specifiers include (but are not limited to)</P>
<TABLE>
<THEAD>
<TR>
<TD>Specifier</TD>
<TD>Meaning</TD></TR></THEAD>
<TBODY>
<TR>
<TD>-s ADDR</TD>
<TD>Packet came from source ADDR</TD></TR>
<TR>
<TD>-d ADDR</TD>
<TD>Packet is going to ADDR</TD></TR>
<TR>
<TD>-i IFACE</TD>
<TD>Packet came from interface IFACE</TD></TR>
<TR>
<TD>-o IFACE</TD>
<TD>Packet will leave through IFACE</TD></TR>
<TR>
<TD>-m COND</TD>
<TD>Packet matches the condition COND.</TD></TR>
<TR>
<TD>-p PROTO</TD>
<TD>Packet uses the protocol PROTO</TD></TR></TBODY></TABLE>
<P>Addresses can be fully qualified domain names ("www.crhalpin.org"), IP
addresses ("10.0.0.1"), CIDR style network specifications ("10.0.0.0/24"),
or the logical not of any of those things (ie "! www.crhalpin.org").
<P>Interfaces are eth0, ppp0, tun0, and so on. Protocols are tcp, udp, and
icmp.
<P>Conditions can be a complicated beast, and I won't talk much about
them. For more information, read the 'man iptables'. I only use two
conditions '-m state --state <I>STATES</I>' and '-m limit'.
<P>Possible states for '-m state' are NEW, RELATED, ESTABLISHED, and
INVALID. The names describe the meaning pretty well.</P>
<P>The '-m limit --limit TIME' lets you limit how frequently a given rule
is matched. This is most useful when used with the LOG target, to keep
your system logs from filling up. This pops up in the example script at
the end.</P>
<H3>Targets</H3>
<P>Targets include (but are not limited to)</P>
<TABLE>
<THEAD>
<TR>
<TD>Target</TD>
<TD>Meaning</TD></TR></THEAD>
<TBODY>
<TR>
<TD vAlign=top>ACCEPT</TD>
<TD>Accept this packet.<BR>Terminating<BR>Valid in the filter
table</TD></TR>
<TR>
<TD vAlign=top>DROP</TD>
<TD>Ignore this packet. The sender gets no
notification.<BR>Terminating<BR>Valid in the filter table</TD></TR>
<TR>
<TD vAlign=top>REJECT</TD>
<TD>Reject this packet, and send an icmp message back to the sender
to indicate that this packet died.<BR>Terminating<BR>Valid in the
filter table</TD></TR>
<TR>
<TD vAlign=top>SNAT --to-source ADDR</TD>
<TD>Change the source address of this packet to
ADDR.<BR>Non-terminating<BR>Valid in the nat table</TD></TR>
<TR>
<TD vAlign=top>DNAT --to-destination ADDR</TD>
<TD>Change the destination address of this packet to
ADDR.<BR>Non-terminating<BR>Valid in the nat table.</TD></TR>
<TR>
<TD vAlign=top>LOG</TD>
<TD>Log this packet to syslog.<BR>Non-terminating<BR>Valid in all
tables</TD></TR>
<TR>
<TD vAlign=top><I>CHAIN</I></TD>
<TD>Punt processing of this packet to <I>CHAIN</I><BR>Terminates if
<I>CHAIN</I> contains a terminating rule that matches this
packet<BR>Valid in all tables</TD></TR></TBODY></TABLE>
<H2>Chain Manipulations</H2>
<TABLE>
<THEAD>
<TR>
<TD>command</TD>
<TD>meaning</TD></TR></THEAD>
<TBODY>
<TR>
<TD>iptables -t <I>table</I> -N <I>chain</I></TD>
<TD>Create a new chain called <I>chain</I> inside <I>table</I></TD></TR>
<TR>
<TD>iptables -t <I>table</I> -F <I>chain</I></TD>
<TD>Remove all rules from <I>chain</I> in <I>table</I></TD></TR>
<TR>
<TD>iptables -t <I>table</I> -X <I>chain</I></TD>
<TD>Delete <I>chain</I> from <I>table</I></TD></TR></TBODY></TABLE>
<P>Built-in chains (INPUT, FORWARD, OUTPUT) can also have a 'policy',
which will be invoked if no other rule on the chain matches. These
policies can be ACCEPT, REJECT, or DROP. Policies are set with 'iptables
-t filter -P CHAIN <I>policy</I>'.
<H2>Tips and Style Issues</H2>
<P>Things to keep in mind when using netfilter (mostly style issues):</P>
<UL>
<LI>Always make the table you use explicit<BR> Though this
isn't required, specifying it will make it such that your scripts are
readable to everyone. You won't ever have to worry about getting a rule
or a chain in the wrong table.
<LI>The state matchers are your friend<BR> It's easy to
forget that a lot of outgoing connections will have related incoming
connections, or that outgoing forwards will have corresponding incoming
forwards. While it's possible to write individual allow rules to catch
these, matching based on state "-m state --state RELATED,ESTABLISHED" is
much more concise.
<LI>Write using addresses, not input/output specs<BR> The old
ipchains stuff specified everything in terms of what interface it came
into, and what interface it went out of. iptables does still support
this, but it's easy (at least for me) to get confused in this way.
iptables supports specifying everything in terms of source and
destination addresses, which is somewhat more portable, and <U>much</U>
easier to read.</LI></UL>
<P>If you have suggestions, please <A
href="http://www.cs.wisc.edu/~chalpin/about/connectivity.html">contact
me</A>.</P>
<H2>This example is for a firewall and NAT
box</H2><CODE>#!/bin/bash<BR>IFACE= <FONT color=blue>#the public interface
of your box.</FONT><BR>PUBLIC=`ifconfig $IFACE | grep "inet addr" | cut -d
":" -f 2 | cut -d " " -f 1` <BR><FONT color=blue>#That shell-insanity will
extract the public IP of $IFACE for you.<BR>#This can be useful if you're
on a PPP connection, and don't always know<BR>#What the IP of $IFACE will
be.</FONT><BR>LOCALNET= <FONT color=blue>#The IP ranges of your local net.
Example: 10.0.0.0/24<BR></FONT>/sbin/modprobe -k ip_conntrack_ftp<BR><FONT
color=blue>#Clear all chains, and set default policies.<BR># I consider it
good practice to set your policies to DROP<BR># whenever you are changing
your firewall configuration<BR></FONT>iptables -t filter -P INPUT DROP;
iptables -t filter -F INPUT<BR>iptables -t filter -P FORWARD DROP;
iptables -t filter -F FORWARD<BR>iptables -t nat -F
POSTROUTING<BR><BR><FONT color=blue>#Set up a chain for bad packets.<BR>#
Packets sent here will be logged, no more than five per hour from the<BR>#
same source, and then dropped.<BR></FONT>iptables -F log; iptables -X log;
iptables -N log<BR>iptables -A log -m limit --limit 5/hour -j
LOG<BR>iptables -A log -j DROP<BR><BR><FONT color=blue>#
NAT<BR></FONT>iptables -t nat -A POSTROUTING -s $LOCALNET -d \! $LOCALNET
-j SNAT --to-source $PUBLIC<BR><FONT color=blue>#Packets to accept on the
public interface<BR>#Catch and log 'INVALID' packets<BR></FONT>iptables -t
filter -A INPUT -d $PUBLIC -m state --state INVALID -j log<BR><FONT
color=blue>#Accept packets that are from and to the loopback
interface.<BR></FONT>iptables -t filter -A INPUT -s localhost -d localhost
-j ACCEPT<BR><FONT color=blue>#Accept packets relating to
already-established connections<BR></FONT>iptables -t filter -A INPUT -d
$PUBLIC -m state --state RELATED,ESTABLISHED -j ACCEPT<BR><FONT
color=blue>#Accept ssh connections<BR></FONT>iptables -t filter -A INPUT
-p tcp -d $PUBLIC --dport 22 -j ACCEPT<BR><FONT color=green>#Add entries
for other services that you want to accept here.<BR></FONT><BR><FONT
color=blue>#Anything else gets dropped and logged.<BR></FONT>iptables -t
filter -A INPUT -d $PUBLIC -j log<BR><BR><FONT color=blue>#Packets to
forward from private outward.<BR># Catch and log any INVALID
data.<BR></FONT>iptables -t filter -A FORWARD -m state --state INVALID -j
log<BR><FONT color=blue>#Accept packets related to pre-existing
connections<BR></FONT>iptables -t filter -A FORWARD -d $LOCALNET -m state
--state RELATED,ESTABLISHED -j ACCEPT<BR><FONT color=blue>#Allow the
private network to connect to anything<BR></FONT>iptables -t filter -A
FORWARD -s $LOCALNET -j ACCEPT<BR><FONT color=blue>#Drop and log anything
else<BR></FONT>iptables -t filter -A FORWARD -j log<BR></CODE>
<H2>Common Mistakes (or Don't Follow in my Footsteps)</H2>
<P>More will be added to this as I remember all of the various idiotic
things I've done in the past.</P>
<H3>Overly General Rules</H3>
<P>Consider the following situation: You have a firewall (say it's
10.0.0.1). Behind it is both your private internal network, and your
webserver. You want to redirect traffic on port 80 to the webserver (say
it's 10.0.0.10). You write the following:</P><PRE>iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 10.0.0.10:80
</PRE>
<P>This will redirect traffic from outside to your webserver. However, it
will also redirect traffic from inside to your webserver as well. God help
you if your firewall is your webserver, and you want to go to a website. A
more appropriate rule would be:</P><PRE>iptables -t nat -A PREROUTING -p tcp -s ! 10.0.0.0/24 --dport 80 -j DNAT --to-destination 10.0.0.10:80
</PRE>
<P>Similar kinds of things can happen if you have a web proxy that you
want to redirect traffic from inside thorough. Remember to let traffic
from the proxy out.</P>
<H2>Other References</H2>
<UL>
<LI><A href="http://www.netfilter.org/"
target=_top>http://www.netfilter.org/</A>
<LI><A href="http://killyridols.net/firewall.rules.html"
target=_top>Another example</A></LI></UL>
<HR>
<P><I>$Header:
/u/c/h/chalpin/private/CVS/crh/public_html/project/netfilter.html,v 1.1
2004/01/19 22:36:16 chalpin Exp
$</I></P></TD></TR></TBODY></TABLE></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -