Thanks for all your error reports, I didn't forget it. I'll cleanup my guide soon. Thanks again!

Exercise 26. Networking: packet filter configuration, iptables

Let me start with quoting Wikipedia on iptables:

Iptables is a user space application program that allows a system administrator to configure the tables provided by the Linux kernel firewall (implemented as different Netfilter modules) and the chains and rules it stores. Different kernel modules and programs are currently used for different protocols; iptables applies to IPv4, ip6tables to IPv6, arptables to ARP, and ebtables to Ethernet frames.

To use it you must understand the following concepts:

  1. LINKTYPE_LINUX_SLLtcpdump pseudo link layer protocol.
  2. Ethernet frame header — A data packet on an Ethernet link is called an Ethernet frame. A frame begins with preamble and start frame delimiter. Following which, each Ethernet frame continues with an Ethernet header featuring destination and source MAC addresses. The middle section of the frame is payload data including any headers for other protocols (e.g. Internet Protocol) carried in the frame. The frame ends with a 32-bit cyclic redundancy check which is used to detect any corruption of data in transit.
  3. IPv4 header — An IP packet consists of a header section and a data section. The IPv4 packet header consists of 14 fields, of which 13 are required. The 14th field is optional and aptly named: options.
  4. TCP segment structure — Transmission Control Protocol accepts data from a data stream, segments it into chunks, and adds a TCP header creating a TCP segment. The TCP segment is then encapsulated into an Internet Protocol (IP) datagram. A TCP segment is “the packet of information that TCP uses to exchange data with its peers.”

I remind you about guides to get them:

  1. Read corresponding Wikipedia articles until you achieve at least superficial understanding (but good old hardcore grinding is of course better).
  2. Watch this videos from http://www.visualland.net/ (another link www.visualland.net.cn):
    1. Expand IP Address tree node in the left of the site and work you way through it.
    2. Expand TCP tree node and do the same.
  3. Read Linux networking concepts introduction. This guide is good because it even acknowledges that The Internet is for porn.

I am not able to describe iptables any better than Peter Harrison's excellent guide. If you never used it, you should check this guide first.

But what I will, however, put theory into practice and show what happens inside of iptalbes step-by-step in a very simple scenario of data exchange. First things first, main concepts:

  1. iptables — program which is used to set up, maintain, and inspect the tables of IPv4 packet filter rules in the Linux kernel. Several different tables may be defined. Each table contains a number of built-in chains and may also contain user-defined chains.
  2. ip6tables — same for IPv6.
  3. chain — list of rules which can match a set of packets. Each rule specifies what to do with a packet that matches. This is called a target, which may be a jump to a user-defined chain in the same table.
  4. target — A firewall rule specifies criteria for a packet and a target. If the packet does not match, the next rule in the chain is the examined; if it does match, then the next rule is specified by the value of the target, which can be the name of a user-defined chain or one of the special values:
    1. ACCEPT — let the packet through.
    2. DROP — drop the packet on the floor.
    3. QUEUE — pass the packet to userspace.
    4. RETURN — stop traversing this chain and resume at the next rule in the previous (calling) chain. If the end of a built-in chain is reached or a rule in a built-in chain with target RETURN is matched, the target specified by the chain policy determines the fate of the packet.

Now let us see what default tables and built-in chains there are:

Table name Built-in chains Description
raw This table is used mainly for configuring exemptions from connection tracking in combination with the NOTRACK target. It registers at the netfilter hooks with higher priority and is thus called before ip_conntrack, or any other IP tables.
PREROUTING For packets arriving via any network interface.
OUTPUT For packets generated by local processes.
mangle This table is used for specialized packet alteration.
PREROUTING For altering incoming packets before routing.
OUTPUT For altering locally-generated packets before routing.
INPUT For packets coming into the box itself.
FORWARD For altering packets being routed through the box.
POSTROUTING For altering packets as they are about to go out.
nat This table is consulted when a packet that creates a new connection is encountered.
PREROUTING For altering packets as soon as they come in.
OUTPUT For altering locally-generated packets before routing.
POSTROUTING For altering packets as they are about to go out.
filter This is the default table (if no -t option is passed).
INPUT For packets destined to local sockets.
FORWARD For packets being routed through the box.
OUTPUT For locally-generated packets.

Okay, we are ready to see how this works in real life. I will send a string Hello world! to vm1 from my home computer using TCP protocol and netcat utility which is just like cat, but over the network. The setup:

1. I forwarded another port, 80, to my home PC running Linux so am able to connect like this:

(My home PC) --> vm1:80

2. I added this rules to iptables to log all what happens with network packets inside iptables:

sudo iptables -t raw -A PREROUTING -p tcp -m tcp --dport 80 -j TRACE
sudo iptables -t raw -A INPUT -p tcp -m tcp --sport 80 -j TRACE

This is my exact iptables ruleset on vm1:

root@vm1:/home/user1# for i in raw mangle nat filter ; do echo -e "\n-----" TABLE: $i '-----' ; iptables -t $i -L ; done
 
----- TABLE: raw -----
Chain PREROUTING (policy ACCEPT)  target     prot opt source               destination
                                  TRACE      tcp  --  anywhere             anywhere            tcp dpt:www
Chain OUTPUT (policy ACCEPT)      target     prot opt source               destination
                                  TRACE      tcp  --  anywhere             anywhere            tcp spt:www
----- TABLE: mangle -----
Chain PREROUTING (policy ACCEPT)  target     prot opt source               destination
Chain INPUT (policy ACCEPT)       target     prot opt source               destination
Chain FORWARD (policy ACCEPT)     target     prot opt source               destination
Chain OUTPUT (policy ACCEPT)      target     prot opt source               destination
Chain POSTROUTING (policy ACCEPT) target     prot opt source               destination
 
----- TABLE: nat -----
Chain PREROUTING (policy ACCEPT)  target     prot opt source               destination
Chain POSTROUTING (policy ACCEPT) target     prot opt source               destination
Chain OUTPUT (policy ACCEPT)      target     prot opt source               destination
 
----- TABLE: filter -----
Chain INPUT (policy ACCEPT)       target     prot opt source               destination
Chain FORWARD (policy ACCEPT)     target     prot opt source               destination
Chain OUTPUT (policy ACCEPT)      target     prot opt source               destination

As you can see, there are no other rules. Another way to look at iptables rules is to use iptables-save utility:

root@vm1:/home/user1# iptables-save
# Generated by iptables-save v1.4.8 on Fri Jul 13 08:09:04 2012
#(1)
*mangle
#(2)        (3)     (4)   (5)
:PREROUTING ACCEPT [15662:802240]
:INPUT ACCEPT [15662:802240]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [12756:3671974]
:POSTROUTING ACCEPT [12756:3671974]
COMMIT
# Completed on Fri Jul 13 08:09:04 2012
# Generated by iptables-save v1.4.8 on Fri Jul 13 08:09:04 2012
*nat
:PREROUTING ACCEPT [18:792]
:POSTROUTING ACCEPT [42:2660]
:OUTPUT ACCEPT [42:2660]
COMMIT
# Completed on Fri Jul 13 08:09:04 2012
# Generated by iptables-save v1.4.8 on Fri Jul 13 08:09:04 2012
*raw
:PREROUTING ACCEPT [15854:814892]
:OUTPUT ACCEPT [12855:3682054]
-A PREROUTING -p tcp -m tcp --dport 80 -j TRACE
-A OUTPUT -p tcp -m tcp --sport 80 -j TRACE
COMMIT
# Completed on Fri Jul 13 08:09:04 2012
# Generated by iptables-save v1.4.8 on Fri Jul 13 08:09:04 2012
*filter
:INPUT ACCEPT [35107:2459066]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [26433:10670628]
COMMIT
# Completed on Fri Jul 13 08:09:04 2012

The iptables-save fiels are as follows:

Field Description
(1) Table name
(2) Chain name
(3) Chain policy
(4) Packet counter
(5) Byte counter

3. I set up nc to listen on port 80:

nc -l 80

4. I sent a string to vm1 using nc:

echo 'Hello, world!' | nc localhost 80

The following exchange between my home pc and vm1 happaned:

08:00:05.655339 IP 10.0.2.2.51534 > 10.0.2.15.80: Flags [S], seq 4164179969, win 65535, options [mss 1460], length 0
08:00:05.655653 IP 10.0.2.15.80 > 10.0.2.2.51534: Flags [S.], seq 4149908960, ack 4164179970, win 5840, options [mss 1460], length 0
08:00:05.655773 IP 10.0.2.2.51534 > 10.0.2.15.80: Flags [.], ack 1, win 65535, length 0
08:00:05.655868 IP 10.0.2.2.51534 > 10.0.2.15.80: Flags [P.], seq 1:15, ack 1, win 65535, length 14
08:00:05.655978 IP 10.0.2.15.80 > 10.0.2.2.51534: Flags [.], ack 15, win 5840, length 0
08:00:10.037978 IP 10.0.2.2.51534 > 10.0.2.15.80: Flags [F.], seq 15, ack 1, win 65535, length 0
08:00:10.038287 IP 10.0.2.15.80 > 10.0.2.2.51534: Flags [F.], seq 1, ack 16, win 5840, length 0
08:00:10.038993 IP 10.0.2.2.51534 > 10.0.2.15.80: Flags [.], ack 2, win 65535, length 0

Let us remember how data is transfered. To do this, let us take apart first packet:

#                  (13)     (15)    (14)      (16)      (20)     (17)            (25)            
08:00:05.655339 IP 10.0.2.2.51534 > 10.0.2.15.80: Flags [S], seq 4164179969, win 65535, 
#        (8)        (9)
options [mss 1460], length 0
#                (1)  (2)  (3)  (4)                 (5)    
#                ____ ____ ____ ___________________ ____
        0x0000:  0000 0001 0006 5254 0012 3502 0000 0800  ......RT..5.....
#                (6)  (7)  (8)  (9)(10,11)(12)  (13)
#                ____ ____ ____ ____ /\/\ ____ _________  
        0x0010:  4500 002c a006 0000 4006 c2b5 0a00 0202  E..,....@.......
#                (14)      (15) (16) (17)      (18)
#                _________ ____ ____ _________ __________ 
        0x0020:  0a00 020f c94e 0050 f834 5801 0000 0000  .....N.P.4X.....
#              (19,20)(21) (22) (23) (24) (25)
#                /\/\ ____ ____ ____ ____ ____ 
        0x0030:  6002 ffff 6641 0000 0204 05b4 0000       `...fA........
`

Field and descriptions in our packet:

DOD model layer OSI model layer Field in Field Description
Link Physical/Data link LINUX_SLL header (1) Packet type.
(2) ARPHRD_ type.
(3) Link-layer (MAC) address length.
(4) Linkk-layer (MAC) source address.
(5) Protocol type (IP).
Internet Network IPv4 header (6) Version, Internet Header Length, Differentiated Services Code Point, Explicit Congestion Notification.
(7) Total Length.
(8) Identification, is primarily used for uniquely identifying fragments of an original IP datagram.
(9) Flags, Fragment offset.
(10) Time to live (TTL).
(11) Protocol number.
(12) Header checksum.
(13) Source IP address.
(14) Destination IP address.
Transport Transport TCP header (15) Source TCP port.
(16) Destination TCP port.
(17) TCP initial sequence number.
(18) ACK number field (empty because it is first packet).
(19)
(20) SYN TCP flag.
(21) TCP window size.
(22) TCP checksum.
(23) Urgent pointer.
(24) Options field start
(25) TCP maximum segment size (maximum transfer unit - 40 bytes).

And now let us see what happens to this packet in iptables:

#(1)(2)        (3)    (4)   (5)     (6)  (7) (8)               (9)               (10)  (11)         (12)
raw:PREROUTING:policy:2     IN=eth0 OUT= MAC=08:00:27:d4:45:68:52:54:00:12:35:02:08:00 SRC=10.0.2.2 DST=10.0.2.15
#                           (13)   (14)     (15)      (16)   (17)     (18)      (19)      (20)
                            LEN=44 TOS=0x00 PREC=0x00 TTL=64 ID=40966 PROTO=TCP SPT=51534 DPT=80
#                           (21)           (22)  (23)         (24)     (25)(26)   (27)
                            SEQ=4164179969 ACK=0 WINDOW=65535 RES=0x00 SYN URGP=0 OPT (020405B4)
mangle:PREROUTING:policy:1  IN=eth0 OUT= MAC=08:00:27:d4:45:68:52:54:00:12:35:02:08:00 SRC=10.0.2.2 DST=10.0.2.15
                            LEN=44 TOS=0x00 PREC=0x00 TTL=64 ID=40966 PROTO=TCP SPT=51534 DPT=80
                            SEQ=4164179969 ACK=0 WINDOW=65535 RES=0x00 SYN URGP=0 OPT (020405B4)
nat:PREROUTING:policy:1     IN=eth0 OUT= MAC=08:00:27:d4:45:68:52:54:00:12:35:02:08:00 SRC=10.0.2.2 DST=10.0.2.15
                            LEN=44 TOS=0x00 PREC=0x00 TTL=64 ID=40966 PROTO=TCP SPT=51534 DPT=80
                            SEQ=4164179969 ACK=0 WINDOW=65535 RES=0x00 SYN URGP=0 OPT (020405B4)
mangle:INPUT:policy:1       IN=eth0 OUT= MAC=08:00:27:d4:45:68:52:54:00:12:35:02:08:00 SRC=10.0.2.2 DST=10.0.2.15
                            LEN=44 TOS=0x00 PREC=0x00 TTL=64 ID=40966 PROTO=TCP SPT=51534 DPT=80
                            SEQ=4164179969 ACK=0 WINDOW=65535 RES=0x00 SYN URGP=0 OPT (020405B4)
filter:INPUT:policy:1       IN=eth0 OUT= MAC=08:00:27:d4:45:68:52:54:00:12:35:02:08:00 SRC=10.0.2.2 DST=10.0.2.15
                            LEN=44 TOS=0x00 PREC=0x00 TTL=64 ID=40966 PROTO=TCP SPT=51534 DPT=80
                            SEQ=4164179969 ACK=0 WINDOW=65535 RES=0x00 SYN URGP=0 OPT (020405B4)

Fields and descrptions of iptables log:

Field Description
(1) Table name.
(2) Chain name.
(3) Type (policy for the policy of the built in chains.
(4) Rule number.
(5) Intput interface.
(6) Output interface (empty, because packet is destinied for vm1 itself)
(7) MAC addresses
(8) Destination (vm1) MAC
(9) Source MAC
(10) Protocol type IP.
(11) Source IP address
(12) Destination IP address
(13) IP packet length in bytes (excluding Link Layer header)
(14) IP type of Service.
(15) IP precedence.
(16) IP time to live.
(17) IP packet ID.
(18) Protocol type TCP.
(19) TCP source port.
(20) TCP destination port.
(21) TCP sequence number.
(22) TCP acknoledgement number.
(23) TCP window size.
(24) TCP reserved bits.
(25) TCP SYN flag is set.
(25) TCP urgent pointer is not set.
(25) TCP options.

Now I will show you this exchange side-by-side (more like paragraph by paragraph) using tcpdump output and iptables log. You task will be to go through this exchange line by line and understand what happens. I recommend you to print this exchange and work through it using pen and paper, you can print it from special page. The questions you need to answer are this:

  1. What does each field mean? Take a pencil and connect field from tcpdump trace to raw packet data in hex to iptables log.
  2. In what order packets are processed? Which table first, which last, why?
  3. Why only first packet is processed through nat table?

This is the output, behold:

08:00:05.655339 IP 10.0.2.2.51534 > 10.0.2.15.80: Flags [S], seq 4164179969, win 65535, options [mss 1460], length 0
        0x0000:  0000 0001 0006 5254 0012 3502 0000 0800  ......RT..5.....
        0x0010:  4500 002c a006 0000 4006 c2b5 0a00 0202  E..,....@.......
        0x0020:  0a00 020f c94e 0050 f834 5801 0000 0000  .....N.P.4X.....
        0x0030:  6002 ffff 6641 0000 0204 05b4 0000       `...fA........
`
raw:PREROUTING:policy:2     IN=eth0 OUT= MAC=08:00:27:d4:45:68:52:54:00:12:35:02:08:00 SRC=10.0.2.2 DST=10.0.2.15
                            LEN=44 TOS=0x00 PREC=0x00 TTL=64 ID=40966 PROTO=TCP SPT=51534 DPT=80
                            SEQ=4164179969 ACK=0 WINDOW=65535 RES=0x00 SYN URGP=0 OPT (020405B4)
mangle:PREROUTING:policy:1  IN=eth0 OUT= MAC=08:00:27:d4:45:68:52:54:00:12:35:02:08:00 SRC=10.0.2.2 DST=10.0.2.15
                            LEN=44 TOS=0x00 PREC=0x00 TTL=64 ID=40966 PROTO=TCP SPT=51534 DPT=80
                            SEQ=4164179969 ACK=0 WINDOW=65535 RES=0x00 SYN URGP=0 OPT (020405B4)
nat:PREROUTING:policy:1     IN=eth0 OUT= MAC=08:00:27:d4:45:68:52:54:00:12:35:02:08:00 SRC=10.0.2.2 DST=10.0.2.15
                            LEN=44 TOS=0x00 PREC=0x00 TTL=64 ID=40966 PROTO=TCP SPT=51534 DPT=80
                            SEQ=4164179969 ACK=0 WINDOW=65535 RES=0x00 SYN URGP=0 OPT (020405B4)
mangle:INPUT:policy:1       IN=eth0 OUT= MAC=08:00:27:d4:45:68:52:54:00:12:35:02:08:00 SRC=10.0.2.2 DST=10.0.2.15
                            LEN=44 TOS=0x00 PREC=0x00 TTL=64 ID=40966 PROTO=TCP SPT=51534 DPT=80
                            SEQ=4164179969 ACK=0 WINDOW=65535 RES=0x00 SYN URGP=0 OPT (020405B4)
filter:INPUT:policy:1       IN=eth0 OUT= MAC=08:00:27:d4:45:68:52:54:00:12:35:02:08:00 SRC=10.0.2.2 DST=10.0.2.15
                            LEN=44 TOS=0x00 PREC=0x00 TTL=64 ID=40966 PROTO=TCP SPT=51534 DPT=80
                            SEQ=4164179969 ACK=0 WINDOW=65535 RES=0x00 SYN URGP=0 OPT (020405B4)
 
08:00:05.655653 IP 10.0.2.15.80 > 10.0.2.2.51534: Flags [S.], seq 4149908960, ack 4164179970, win 5840, options [mss 1460], length 0
        0x0000:  0004 0001 0006 0800 27d4 4568 0000 0800  ........'.Eh....
        0x0010:  4500 002c 0000 4000 4006 22bc 0a00 020f  E..,..@.@.".....
        0x0020:  0a00 0202 0050 c94e f75a 95e0 f834 5802  .....P.N.Z...4X.
        0x0030:  6012 16d0 c224 0000 0204 05b4            `....$......
'
raw:OUTPUT:policy:2         IN= OUT=eth0 SRC=10.0.2.15 DST=10.0.2.2
                            LEN=44 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=80 DPT=51534
                            SEQ=4149908960 ACK=4164179970 WINDOW=5840 RES=0x00 ACK SYN URGP=0 OPT (020405B4) UID=0 GID=0
mangle:OUTPUT:policy:1      IN= OUT=eth0 SRC=10.0.2.15 DST=10.0.2.2
                            LEN=44 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=80 DPT=51534
                            SEQ=4149908960 ACK=4164179970 WINDOW=5840 RES=0x00 ACK SYN URGP=0 OPT (020405B4) UID=0 GID=0
filter:OUTPUT:policy:1      IN= OUT=eth0 SRC=10.0.2.15 DST=10.0.2.2
                            LEN=44 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=80 DPT=51534
                            SEQ=4149908960 ACK=4164179970 WINDOW=5840 RES=0x00 ACK SYN URGP=0 OPT (020405B4) UID=0 GID=0
mangle:POSTROUTING:policy:1 IN= OUT=eth0 SRC=10.0.2.15 DST=10.0.2.2
                            LEN=44 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=80 DPT=51534
                            SEQ=4149908960 ACK=4164179970 WINDOW=5840 RES=0x00 ACK SYN URGP=0 OPT (020405B4) UID=0 GID=0
 
08:00:05.655773 IP 10.0.2.2.51534 > 10.0.2.15.80: Flags [.], ack 1, win 65535, length 0
        0x0000:  0000 0001 0006 5254 0012 3502 0000 0800  ......RT..5.....
        0x0010:  4500 0028 a007 0000 4006 c2b8 0a00 0202  E..(....@.......
        0x0020:  0a00 020f c94e 0050 f834 5802 f75a 95e1  .....N.P.4X..Z..
        0x0030:  5010 ffff f0b1 0000 0000 0000 0000       P.............
 
raw:PREROUTING:policy:2     IN=eth0 OUT= MAC=08:00:27:d4:45:68:52:54:00:12:35:02:08:00 SRC=10.0.2.2 DST=10.0.2.15
                            LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=40967 PROTO=TCP SPT=51534 DPT=80
                            SEQ=4164179970 ACK=4149908961 WINDOW=65535 RES=0x00 ACK URGP=0
mangle:PREROUTING:policy:1  IN=eth0 OUT= MAC=08:00:27:d4:45:68:52:54:00:12:35:02:08:00 SRC=10.0.2.2 DST=10.0.2.15
                            LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=40967 PROTO=TCP SPT=51534 DPT=80
                            SEQ=4164179970 ACK=4149908961 WINDOW=65535 RES=0x00 ACK URGP=0
mangle:INPUT:policy:1       IN=eth0 OUT= MAC=08:00:27:d4:45:68:52:54:00:12:35:02:08:00 SRC=10.0.2.2 DST=10.0.2.15
                            LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=40967 PROTO=TCP SPT=51534 DPT=80
                            SEQ=4164179970 ACK=4149908961 WINDOW=65535 RES=0x00 ACK URGP=0
filter:INPUT:policy:1       IN=eth0 OUT= MAC=08:00:27:d4:45:68:52:54:00:12:35:02:08:00 SRC=10.0.2.2 DST=10.0.2.15
                            LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=40967 PROTO=TCP SPT=51534 DPT=80
                            SEQ=4164179970 ACK=4149908961 WINDOW=65535 RES=0x00 ACK URGP=0
 
08:00:05.655868 IP 10.0.2.2.51534 > 10.0.2.15.80: Flags [P.], seq 1:15, ack 1, win 65535, length 14
        0x0000:  0000 0001 0006 5254 0012 3502 0000 0800  ......RT..5.....
        0x0010:  4500 0036 a008 0000 4006 c2a9 0a00 0202  E..6....@.......
        0x0020:  0a00 020f c94e 0050 f834 5802 f75a 95e1  .....N.P.4X..Z..
        0x0030:  5018 ffff af45 0000 4865 6c6c 6f2c 2077  P....E..Hello,.w
        0x0040:  6f72 6c64 210a                           orld!.
 
raw:PREROUTING:policy:2     IN=eth0 OUT= MAC=08:00:27:d4:45:68:52:54:00:12:35:02:08:00 SRC=10.0.2.2 DST=10.0.2.15
                            LEN=54 TOS=0x00 PREC=0x00 TTL=64 ID=40968 PROTO=TCP SPT=51534 DPT=80
                            SEQ=4164179970 ACK=4149908961 WINDOW=65535 RES=0x00 ACK PSH URGP=0
mangle:PREROUTING:policy:1  IN=eth0 OUT= MAC=08:00:27:d4:45:68:52:54:00:12:35:02:08:00 SRC=10.0.2.2 DST=10.0.2.15
                            LEN=54 TOS=0x00 PREC=0x00 TTL=64 ID=40968 PROTO=TCP SPT=51534 DPT=80
                            SEQ=4164179970 ACK=4149908961 WINDOW=65535 RES=0x00 ACK PSH URGP=0
mangle:INPUT:policy:1       IN=eth0 OUT= MAC=08:00:27:d4:45:68:52:54:00:12:35:02:08:00 SRC=10.0.2.2 DST=10.0.2.15
                            LEN=54 TOS=0x00 PREC=0x00 TTL=64 ID=40968 PROTO=TCP SPT=51534 DPT=80
                            SEQ=4164179970 ACK=4149908961 WINDOW=65535 RES=0x00 ACK PSH URGP=0
filter:INPUT:policy:1       IN=eth0 OUT= MAC=08:00:27:d4:45:68:52:54:00:12:35:02:08:00 SRC=10.0.2.2 DST=10.0.2.15
                            LEN=54 TOS=0x00 PREC=0x00 TTL=64 ID=40968 PROTO=TCP SPT=51534 DPT=80
                            SEQ=4164179970 ACK=4149908961 WINDOW=65535 RES=0x00 ACK PSH URGP=0
 
08:00:05.655978 IP 10.0.2.15.80 > 10.0.2.2.51534: Flags [.], ack 15, win 5840, length 0
        0x0000:  0004 0001 0006 0800 27d4 4568 0000 0800  ........'.Eh....
        0x0010:  4500 0028 377c 4000 4006 eb43 0a00 020f  E..(7|@.@..C....
        0x0020:  0a00 0202 0050 c94e f75a 95e1 f834 5810  .....P.N.Z...4X.
        0x0030:  5010 16d0 d9d3 0000                      P.......
'
raw:OUTPUT:policy:2         IN= OUT=eth0 SRC=10.0.2.15 DST=10.0.2.2
                            LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=14204 DF PROTO=TCP SPT=80 DPT=51534
                            SEQ=4149908961 ACK=4164179984 WINDOW=5840 RES=0x00 ACK URGP=0
mangle:OUTPUT:policy:1      IN= OUT=eth0 SRC=10.0.2.15 DST=10.0.2.2
                            LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=14204 DF PROTO=TCP SPT=80 DPT=51534
                            SEQ=4149908961 ACK=4164179984 WINDOW=5840 RES=0x00 ACK URGP=0
filter:OUTPUT:policy:1      IN= OUT=eth0 SRC=10.0.2.15 DST=10.0.2.2
                            LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=14204 DF PROTO=TCP SPT=80 DPT=51534
                            SEQ=4149908961 ACK=4164179984 WINDOW=5840 RES=0x00 ACK URGP=0
mangle:POSTROUTING:policy:1 IN= OUT=eth0 SRC=10.0.2.15 DST=10.0.2.2
                            LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=14204 DF PROTO=TCP SPT=80 DPT=51534
                            SEQ=4149908961 ACK=4164179984 WINDOW=5840 RES=0x00 ACK URGP=0
 
08:00:10.037978 IP 10.0.2.2.51534 > 10.0.2.15.80: Flags [F.], seq 15, ack 1, win 65535, length 0
        0x0000:  0000 0001 0006 5254 0012 3502 0000 0800  ......RT..5.....
        0x0010:  4500 0028 a00e 0000 4006 c2b1 0a00 0202  E..(....@.......
        0x0020:  0a00 020f c94e 0050 f834 5810 f75a 95e1  .....N.P.4X..Z..
        0x0030:  5011 ffff f0a2 0000 0000 0000 0000       P.............
 
raw:PREROUTING:policy:2     IN=eth0 OUT= MAC=08:00:27:d4:45:68:52:54:00:12:35:02:08:00 SRC=10.0.2.2 DST=10.0.2.15
                            LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=40974 PROTO=TCP SPT=51534 DPT=80
                            SEQ=4164179984 ACK=4149908961 WINDOW=65535 RES=0x00 ACK FIN URGP=0
mangle:PREROUTING:policy:1  IN=eth0 OUT= MAC=08:00:27:d4:45:68:52:54:00:12:35:02:08:00 SRC=10.0.2.2 DST=10.0.2.15
                            LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=40974 PROTO=TCP SPT=51534 DPT=80
                            SEQ=4164179984 ACK=4149908961 WINDOW=65535 RES=0x00 ACK FIN URGP=0
mangle:INPUT:policy:1       IN=eth0 OUT= MAC=08:00:27:d4:45:68:52:54:00:12:35:02:08:00 SRC=10.0.2.2 DST=10.0.2.15
                            LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=40974 PROTO=TCP SPT=51534 DPT=80
                            SEQ=4164179984 ACK=4149908961 WINDOW=65535 RES=0x00 ACK FIN URGP=0
filter:INPUT:policy:1       IN=eth0 OUT= MAC=08:00:27:d4:45:68:52:54:00:12:35:02:08:00 SRC=10.0.2.2 DST=10.0.2.15
                            LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=40974 PROTO=TCP SPT=51534 DPT=80
                            SEQ=4164179984 ACK=4149908961 WINDOW=65535 RES=0x00 ACK FIN URGP=0
 
08:00:10.038287 IP 10.0.2.15.80 > 10.0.2.2.51534: Flags [F.], seq 1, ack 16, win 5840, length 0
        0x0000:  0004 0001 0006 0800 27d4 4568 0000 0800  ........'.Eh....
        0x0010:  4500 0028 377d 4000 4006 eb42 0a00 020f  E..(7}@.@..B....
        0x0020:  0a00 0202 0050 c94e f75a 95e1 f834 5811  .....P.N.Z...4X.
        0x0030:  5011 16d0 d9d1 0000                      P.......
'
raw:OUTPUT:policy:2         IN= OUT=eth0 SRC=10.0.2.15 DST=10.0.2.2
                            LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=14205 DF PROTO=TCP SPT=80 DPT=51534
                            SEQ=4149908961 ACK=4164179985 WINDOW=5840 RES=0x00 ACK FIN URGP=0 UID=0 GID=0
mangle:OUTPUT:policy:1      IN= OUT=eth0 SRC=10.0.2.15 DST=10.0.2.2
                            LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=14205 DF PROTO=TCP SPT=80 DPT=51534
                            SEQ=4149908961 ACK=4164179985 WINDOW=5840 RES=0x00 ACK FIN URGP=0 UID=0 GID=0
filter:OUTPUT:policy:1      IN= OUT=eth0 SRC=10.0.2.15 DST=10.0.2.2
                            LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=14205 DF PROTO=TCP SPT=80 DPT=51534
                            SEQ=4149908961 ACK=4164179985 WINDOW=5840 RES=0x00 ACK FIN URGP=0 UID=0 GID=0
mangle:POSTROUTING:policy:1 IN= OUT=eth0 SRC=10.0.2.15 DST=10.0.2.2
                            LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=14205 DF PROTO=TCP SPT=80 DPT=51534
                            SEQ=4149908961 ACK=4164179985 WINDOW=5840 RES=0x00 ACK FIN URGP=0 UID=0 GID=0
 
08:00:10.038993 IP 10.0.2.2.51534 > 10.0.2.15.80: Flags [.], ack 2, win 65535, length 0
        0x0000:  0000 0001 0006 5254 0012 3502 0000 0800  ......RT..5.....
        0x0010:  4500 0028 a00f 0000 4006 c2b0 0a00 0202  E..(....@.......
        0x0020:  0a00 020f c94e 0050 f834 5811 f75a 95e2  .....N.P.4X..Z..
        0x0030:  5010 ffff f0a1 0000 0000 0000 0000       P.............
 
raw:PREROUTING:policy:2     IN=eth0 OUT= MAC=08:00:27:d4:45:68:52:54:00:12:35:02:08:00 SRC=10.0.2.2 DST=10.0.2.15
                            LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=40975 PROTO=TCP SPT=51534 DPT=80
                            SEQ=4164179985 ACK=4149908962 WINDOW=65535 RES=0x00 ACK URGP=0
mangle:PREROUTING:policy:1  IN=eth0 OUT= MAC=08:00:27:d4:45:68:52:54:00:12:35:02:08:00 SRC=10.0.2.2 DST=10.0.2.15
                            LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=40975 PROTO=TCP SPT=51534 DPT=80
                            SEQ=4164179985 ACK=4149908962 WINDOW=65535 RES=0x00 ACK URGP=0
mangle:INPUT:policy:1       IN=eth0 OUT= MAC=08:00:27:d4:45:68:52:54:00:12:35:02:08:00 SRC=10.0.2.2 DST=10.0.2.15
                            LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=40975 PROTO=TCP SPT=51534 DPT=80
                            SEQ=4164179985 ACK=4149908962 WINDOW=65535 RES=0x00 ACK URGP=0
filter:INPUT:policy:1       IN=eth0 OUT= MAC=08:00:27:d4:45:68:52:54:00:12:35:02:08:00 SRC=10.0.2.2 DST=10.0.2.15
                            LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=40975 PROTO=TCP SPT=51534 DPT=80
                            SEQ=4164179985 ACK=4149908962 WINDOW=65535 RES=0x00 ACK URGP=0

Now you will learn how to set up basic iptables rules and enable iptables logging.

Do this

 1: sudo iptables-save
 2: sudo iptables -t filter -A INPUT -i lo -j ACCEPT
 3: sudo iptables -t filter -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
 4: sudo iptables -t filter -P INPUT DROP
 5: sudo iptables -nt filter -L --line-numbers
 6: ping -c 2 -W 1 10.0.2.2
 7: sudo iptables -t filter -A INPUT --match state --state ESTABLISHED -j ACCEPT
 8: sudo iptables -nt filter -L --line-numbers
 9: ping -c 2 -W 1 10.0.2.2
10: sudo modprobe ipt_LOG
11: sudo iptables -nt raw -L --line-numbers
12: sudo iptables -t raw -A PREROUTING -p udp -m udp --dport 1024 -j TRACE
13: sudo iptables -t raw -A OUTPUT -p udp -m udp --sport 1024 -j TRACE
14: sudo tail -n0 -f /var/log/kern.log | cut -c52-300 &
15: nc -ulp 1024 &
16: echo 'Hello there!' | nc -u localhost 1000
17: <CTRL+C>
18: fg
19: <CTRL+C>
20: fg
21: <CTRL+C>

What you should see

user1@vm1:~$ sudo iptables-save
# Generated by iptables-save v1.4.8 on Mon Jul 16 09:01:32 2012
*mangle
:PREROUTING ACCEPT [45783:3411367]
:INPUT ACCEPT [45783:3411367]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [30409:9552110]
:POSTROUTING ACCEPT [30331:9543294]
COMMIT
# Completed on Mon Jul 16 09:01:32 2012
# Generated by iptables-save v1.4.8 on Mon Jul 16 09:01:32 2012
*nat
:PREROUTING ACCEPT [24:1056]
:POSTROUTING ACCEPT [755:41247]
:OUTPUT ACCEPT [817:45207]
COMMIT
# Completed on Mon Jul 16 09:01:32 2012
# Generated by iptables-save v1.4.8 on Mon Jul 16 09:01:32 2012
*raw
:PREROUTING ACCEPT [3171:197900]
:OUTPUT ACCEPT [1991:1294054]
-A PREROUTING -p udp -m udp --dport 80 -j TRACE
-A OUTPUT -p udp -m udp --sport 80 -j TRACE
COMMIT
# Completed on Mon Jul 16 09:01:32 2012
# Generated by iptables-save v1.4.8 on Mon Jul 16 09:01:32 2012
*filter
:INPUT ACCEPT [54:3564]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [28:2540]
COMMIT
# Completed on Mon Jul 16 09:01:32 2012
user1@vm1:~$ sudo iptables -t filter -A INPUT -i lo -j ACCEPT
user1@vm1:~$ sudo iptables -t filter -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
user1@vm1:~$ sudo iptables -t filter -P INPUT DROP
user1@vm1:~$ sudo iptables -nt filter -L --line-numbers
Chain INPUT (policy DROP)
num  target     prot opt source               destination
1    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0
2    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:22
 
Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination
 
Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination
 
user1@vm1:~$ ping -c 2 -W 1 10.0.2.2
PING 10.0.2.2 (10.0.2.2) 56(84) bytes of data.
 
--- 10.0.2.2 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1008ms
 
user1@vm1:~$ sudo iptables -t filter -A INPUT --match state --state ESTABLISHED -j ACCEPT
user1@vm1:~$ sudo iptables -nt filter -L --line-numbers
Chain INPUT (policy DROP)
num  target     prot opt source               destination
1    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0
2    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:22
3    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           state ESTABLISHED
 
Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination
 
Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination
 
user1@vm1:~$ ping -c 2 -W 1 10.0.2.2
PING 10.0.2.2 (10.0.2.2) 56(84) bytes of data.
64 bytes from 10.0.2.2: icmp_req=1 ttl=63 time=0.385 ms
64 bytes from 10.0.2.2: icmp_req=2 ttl=63 time=0.142 ms
 
--- 10.0.2.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.142/0.263/0.385/0.122 ms
user1@vm1:~$ sudo iptables -nt raw -L --line-numbers
Chain PREROUTING (policy ACCEPT)
num  target     prot opt source               destination
 
Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination
user1@vm1:~$ sudo iptables -t raw -A PREROUTING -p udp -m udp --dport 1024 -j TRACE
user1@vm1:~$ sudo iptables -t raw -A OUTPUT -p udp -m udp --sport 1024 -j TRACE
user1@vm1:~$ sudo iptables -nt raw -L --line-numbers
Chain PREROUTING (policy ACCEPT)
num  target     prot opt source               destination
1    TRACE      udp  --  0.0.0.0/0            0.0.0.0/0           udp dpt:1024
 
Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination
1    TRACE      udp  --  0.0.0.0/0            0.0.0.0/0           udp spt:1024
user1@vm1:~$ sudo tail -n0 -f /var/log/kern.log | cut -c52-300 &
[1] 10249
user1@vm1:~$ nc -ulp 1024 &
[2] 10251
user1@vm1:~$ echo 'Hello there!' | nc -u localhost 1024
Hello there!
raw:PREROUTING:policy:2 IN=lo OUT= MAC=00:00:00:00:00:00:00:00:00:00:00:00:08:00 SRC=127.0.0.1 DST=127.0.0.1 LEN=41 TOS=0x00 PREC=0x00 TTL=64 ID=57898 DF PROTO=UDP SPT=50407 DPT=1024 LEN=21
mangle:PREROUTING:policy:1 IN=lo OUT= MAC=00:00:00:00:00:00:00:00:00:00:00:00:08:00 SRC=127.0.0.1 DST=127.0.0.1 LEN=41 TOS=0x00 PREC=0x00 TTL=64 ID=57898 DF PROTO=UDP SPT=50407 DPT=1024 LEN=21
mangle:INPUT:policy:1 IN=lo OUT= MAC=00:00:00:00:00:00:00:00:00:00:00:00:08:00 SRC=127.0.0.1 DST=127.0.0.1 LEN=41 TOS=0x00 PREC=0x00 TTL=64 ID=57898 DF PROTO=UDP SPT=50407 DPT=1024 LEN=21
filter:INPUT:rule:1 IN=lo OUT= MAC=00:00:00:00:00:00:00:00:00:00:00:00:08:00 SRC=127.0.0.1 DST=127.0.0.1 LEN=41 TOS=0x00 PREC=0x00 TTL=64 ID=57898 DF PROTO=UDP SPT=50407 DPT=1024 LEN=21
 
^C
[2]+  Stopped                 nc -ulp 1024
user1@vm1:~$ fg
nc -ulp 1024
^C
user1@vm1:~$ fg
sudo tail -n0 -f /var/log/kern.log | cut -c52-300
^C
user1@vm1:~$

Explanation

  1. Prints out all iptables rules from all tables. You can see that there are none.
  2. Allows all incoming traffic on lo (loopback) interface.
  3. Allows all incoming traffic to TCP port 22, which is ssh.
  4. Changes default INPUT policy to DROP, forbidding all incoming connections except explicitly allowed to TCP port 22. If you loss connection to vm1 here, it means you did something wrong, reboot it in VirtualBox and try again.
  5. Lists current filter rules. Note: you can delete rules by number, like this: sudo iptables -t filter -D INPUT 2. Notice how policy is totally not the same as rule.
  6. Tries to ping your default gateway, failing to do this. Why it is so if outgoing connections are allowed (Chain OUTPUT (policy ACCEPT))? Well, outgoing packets are being sent to gateway, but reply from gateway is not able to get in.
  7. Adds a rule telling iptables to allow all packets which belong to already established connections, for example to all connections originating from vm1.
  8. Lists current filter rules. You are able to see our new rule.
  9. Pings vm1 default gateway, this time successfully.
  10. Loads Linux kernel module which allows to use packet filter logging facility.
  11. Adds rule to log all incoming packets which are destined to UDP port 1024 of any interface of vm1.
  12. Adds rule to log all outgoing packets which originate from UDP port 1024 of any interface of vm1.
  13. Lists raw table rules.
  14. Starts tail in the background which will print all new lines written to /var/log/kern.log. cut will remove unnecessary prefix of log entries in the beginning. Notice how background process is able to write to your terminal.
  15. Starts nc in server mode, listening on UDP port 1024 on all interfaces of vm1.
  16. Starts nc in client mode, sending string Hello there! to our server mode nc. tail prints out all new lines in kern.log and you are able to see how our single UDP packet goes from table to table inside of Linux kernel packet filter. There is no reply, so only one single packet is being sent and processed.
  17. Kills client mode nc.
  18. Brings server mode nc to foreground.
  19. Kills server mode nc.
  20. Bring sudo tail -n0 -f /var/log/kern.log | cut -c52-300 & to foreground.
  21. Kills it.

Extra credit

  1. This was big by itself. Just print out this log and work through it using pencil until you really understand what is going on in every field of every line. If you will stuck, ask away here. http://nixsrv.com/llthw/ex26/log

Discussion

Navigation

Learn Linux The Hard Way