📄 iptables connection tracking.htm
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0069)http://www.sns.ias.edu/~jns/security/iptables/iptables_conntrack.html -->
<HTML><HEAD><TITLE>IPtables: Connection tracking</TITLE>
<META http-equiv=Content-Type content="text/html; charset=iso-8859-1">
<META content="MSHTML 6.00.2800.1400" name=GENERATOR>
<META content="security, telnet, hijacking, netcat, hunt" name=KeyWords>
<META content="iptables, ipchains" name=Keywords></HEAD>
<BODY>
<CENTER><IMG height=10 src="IPtables Connection tracking.files/blue_marble.gif"
width=556 align=center> <BR>
<P><B><U><FONT size=+3>Connection tracking</FONT></U></B></CENTER>
<P><BR>
<P>If you wish to read some more general information about iptables before
returning, please click <A
href="http://www.sns.ias.edu/~jns/security/iptables/index.html">here</A>.
<BR>
<P><B><U><FONT size=+1>What is connection tracking?</FONT></U></B>
<P>Connection tracking refers to the ability to maintain state information about
a connection in memory tables, such as source and destination ip address and
port number pairs (known as <I>socket pairs</I>), protocol types, connection
state and timeouts. Firewalls that do this are known as <I>stateful</I>.
Stateful firewalling is inherently more secure than its "stateless" counterpart
.... simple packet filtering.
<P>Connection tracking is accomplished with the state option in iptables. From
the iptables manpage:
<P> <FONT color=#000066>state</FONT> <BR><FONT
color=#000066> This module, when combined
with connection tracking, allows access to the</FONT> <BR><FONT
color=#000066> connection tracking state for
this packet.</FONT>
<P><FONT color=#000066> --state state</FONT>
<BR><FONT
color=#000066>
Where state is a comma separated list of the connection states
to</FONT> <BR><FONT
color=#000066>
match. Possible states are </FONT><FONT color=#33cc00>INVALID</FONT><FONT
color=#000066> meaning that the packet is</FONT>
<BR><FONT
color=#000066>
associated with no known connection, </FONT><FONT
color=#33cc00>ESTABLISHED</FONT><FONT color=#000066> meaning that the</FONT>
<BR><FONT
color=#000066>
packet is associated with a connection which has seen packets
in</FONT> <BR><FONT
color=#000066>
both directions, </FONT><FONT color=#33cc00>NEW</FONT><FONT color=#000066>
meaning that the packet has started a new con­</FONT> <BR><FONT
color=#000066>
nection, or otherwise associated with a connection which has
not</FONT> <BR><FONT
color=#000066>
seen packets in both directions, and </FONT><FONT
color=#33cc00>RELATED </FONT><FONT color=#000066>meaning that the</FONT>
<BR><FONT
color=#000066>
packet is starting a new connection, but is associated
with an</FONT> <BR><FONT
color=#000066>
existing connection, such as an FTP data
transfer, or an ICMP</FONT> <BR><FONT
color=#000066>
error.</FONT>
<P>Connection tracking is done either in the <FONT
color=#3333ff>PREROUTING</FONT> chain, or the <FONT color=#3333ff>OUTPUT</FONT>
chain for locally generated packets. <BR>Connection tracking defragments all
packets before tracking their state. This explains why there is no
ip_always_defrag switch as there was in the 2.2 kernel.
<P><FONT color=#000000>The state table for udp and tcp connections is maintained
in <I>/proc/net/ip_conntrack</I>. We will discuss what its contents look
below.</FONT>
<P><FONT color=#000000>The maximum number of connections the state table can
contain is stored in <I>/proc/sys/net/ipv4/ip_conntrack_max</I>. This value is
determined initially by how much physical memory you have (on my 512 Mb machine,
ip_conntrack_max = 32760 by default).</FONT> <BR>
<P><B><U><FONT size=+1>How does connection tracking work?</FONT></U></B>
<P><B><I>A quick overview</I></B>
<P>Lets get our bearings first with respect to the whole netfilter framework
before we delve deeper. For a packet forwarded between interfaces the sequence
of chain negotiation would be:
<P><FONT color=#000000>1)</FONT><FONT color=#3333ff> PREROUTING </FONT><FONT
color=#000000>chain - </FONT>DNAT the packet if necessary. Mangle the packet if
necessary. Connection tracking now defragments and tracks (classifies) the
packet in some way:
<P>If the packet matches a entry in the state table it is part of an <FONT
color=#33cc00>ESTABLISHED</FONT> connection. If it is icmp traffic it might be
<FONT color=#33cc00>RELATED</FONT> to a udp/tcp connection already in the state
table. The packet might be starting a <FONT color=#33cc00>NEW</FONT> connection,
or it might be unrelated to any connection in which case it is deemed <FONT
color=#33cc00>INVALID</FONT>.
<P><FONT color=#000000>2)</FONT><FONT color=#3333ff> FORWARD </FONT><FONT
color=#000000>chain - Compare the packet state against the ruleset in the filter
table until the first match, or until the</FONT> <BR><FONT color=#000000>default
policy of the chain is executed.</FONT>
<P>3) <FONT color=#3333ff>POSTROUTING</FONT> chain - SNAT the packet if
necessary.
<P>Note that all packets are compared against the ruleset in the filter table.
This is easily proved - If you have entries in the state table and you change
the rules to deny all traffic, then although the entries in the state table
remain, all traffic is indeed denied as it should be.
<P><B><I>More detail</I></B>
<P>We will consider each of the three protocols, udp, tcp and icmp in turn.
<P><A name=UDP></A><B>UDP</B>
<P>Because it lacks sequence numbers, udp is known as a "stateless" protocol .
However, this does not mean we can't track udp connections. There is still other
useful information we can utilize. Here is an example state table entry for a
newly formed udp connection:
<P><FONT color=#000066>udp 17 19 src=192.168.1.2
dst=192.168.1.50 sport=1032 dport=53 [UNREPLIED] src=192.168.1.50
dst=192.168.1.2 sport=53 dport=1032 use=1</FONT>
<P><FONT color=#000000>For a ruleset built on top of a deny-based configuration,
this state table entry can only be made if there is an iptables filter rule
specifying </FONT><FONT color=#33cc00>NEW</FONT><FONT color=#000000>
connections, something like the following rule, which allows </FONT><FONT
color=#33cc00>NEW</FONT><FONT color=#000000> connections outbound only (as is
often wise):</FONT>
<P><FONT color=#cc0000>iptables -A </FONT><FONT color=#3333ff>INPUT</FONT><FONT
color=#cc0000> -p udp -m state --state </FONT><FONT
color=#33cc00>ESTABLISHED </FONT><FONT color=#cc0000>-j ACCEPT</FONT> <BR><FONT
color=#cc0000>iptables -A </FONT><FONT color=#3333ff>OUTPUT</FONT><FONT
color=#cc0000> -p udp -m state --state </FONT><FONT
color=#33cc00>NEW,ESTABLISHED</FONT><FONT color=#cc0000> -j ACCEPT</FONT>
<P><FONT color=#000000>Things we can tell from the state table entry are as
follows:</FONT>
<UL>
<LI><FONT color=#000000>The protocol is udp (IP protocol number 17).</FONT>
<LI><FONT color=#000000>The state table entry has 19 seconds until it
expires.</FONT>
<LI><FONT color=#000000>Source and destination addresses and ports of original
query.</FONT>
<LI><FONT color=#000000>Source and destination addresses and ports of expected
reply. The connection is marked UNREPLIED so this has not been received
yet.</FONT> </LI></UL><FONT color=#000000>Udp timeouts are set in
<I>/usr/src/linux/net/ipv4/netfilter/ip_conntrack_proto_udp.c </I></FONT>at
compile time. <BR>Here is the relevant section of code:
<P><FONT color=#000000>#define UDP_TIMEOUT (30*HZ)</FONT> <BR><FONT
color=#000000>#define UDP_STREAM_TIMEOUT (180*HZ)</FONT>
<P>A single request will enter into the state for 30*HZ (generally 30 seconds).
In the example above, where we have 19 seconds left, 11 seconds have already
elapsed without a reply being received. Once a reply is received, and allowed by
a rule permitting <FONT color=#33cc00>ESTABLISHED</FONT> connections, the
timeout is reset to 30 seconds and the UNREPLIED mark is removed. Here we see
the connection a couple of seconds after this has taken place:
<P><FONT color=#000066>udp 17 28 src=192.168.1.2
dst=192.168.1.50 sport=1032 dport=53 src=192.168.1.50 dst=192.168.1.2 sport=53
dport=1032 use=1</FONT>
<P>If multiple requests and replies occur between the same socket pairs, the
entry is considered to be a stream and the timeout changes to 180 seconds. Here
we see the connection a few of seconds after this has taken place:
<P><FONT color=#000066>udp 17 177 src=192.168.1.2
dst=192.168.1.50 sport=1032 dport=53 src=192.168.1.50 dst=192.168.1.2 sport=53
dport=1032 [ASSURED] use=1</FONT>
<P>We can see that the entry is now marked ASSURED. Once connections become
ASSURED they are not dropped under heavy load. If the state table is full for
example and new connections arrive, entries marked UNREPLIED are preferentially
dropped.
<P>There is no absolute timeout for a udp connection (or a tcp connection for
that matter), provided traffic keeps flowing. <BR>
<P><A name=TCP></A><B>TCP</B>
<P>A tcp connection is initiated via a three-way handshake involving a
synchronization request from the client, a synchronization and an
acknowledgement from the server, and finally an acknowledgement from the client.
Subsequent traffic flowing between server and client is acknowledged in all
cases. The sequence looks like
<P>
<U>Client</U>
<U>Server</U>
<P> SYN --->
<BR>
<--- SYN+ACK <BR>
ACK --->
<BR>
<--- ACK
<BR> ACK --->
<BR>
.........
<BR>
.........
<P>SYN and ACK refer to flags set in the tcp header. There are also 32 bit
sequence and acknowledgement numbers stored in the tcp header which are passed
back and forth and updated during the session.
<P>To get connection tracking to work for a tcp connection you need a rule that
looks something like this:
<P><FONT color=#cc0000>iptables -A </FONT><FONT color=#3333ff>INPUT</FONT><FONT
color=#cc0000> -p tcp -m state --state </FONT><FONT
color=#33cc00>ESTABLISHED </FONT><FONT color=#cc0000>-j ACCEPT</FONT> <BR><FONT
color=#cc0000>iptables -A </FONT><FONT color=#3333ff>OUTPUT</FONT><FONT
color=#cc0000> -p tcp -m state --state </FONT><FONT
color=#33cc00>NEW,ESTABLISHED</FONT><FONT color=#cc0000> -j ACCEPT</FONT>
<P><U><FONT color=#000000>Walkthrough</FONT></U>
<P>What we are going to do now is walk and talk through the establishment of a
normal tcp connection and look at the state table at each stage:
<P>1) Once an initial SYN is sent in the <FONT color=#3333ff>OUTPUT</FONT>
chain, and accepted by out rule that allows the <FONT color=#33cc00>NEW</FONT>
connection, the connection table entry may look something like:
<P><FONT color=#000066>tcp 6 119 SYN_SENT
src=140.208.5.62 dst=207.46.230.218 sport=1311 dport=80 [UNREPLIED]
src=207.46.230.218 dst=140.208.5.62 sport=80 dport=1311 use=1</FONT>
<P>The tcp connection status is SYN_SENT and the connection is marked UNREPLIED.
<P>2) We are now waiting for a SYN+ACK to arrive at which point the tcp
connection state changes to SYN_RECV and the UNREPLIED disappears:
<P><FONT color=#000066>tcp 6 57 SYN_RECV
src=140.208.5.62 dst=207.46.230.218 sport=1311 dport=80 src=207.46.230.218
dst=140.208.5.62 sport=80 dport=1311 use=1</FONT>
<P>3) We are now waiting for the final part of the handshake, an ACK. When it is
seen by the connection tracking module, we check that it's sequence number
matches the ACK of the SYN+ACK handshake from the server to the client. The tcp
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -