Iptables

From wikinotes


iptables consists of a set of filters that every packet goes through to determine if it is allowed to enter your network, or if it should be routed elsewhere. Tables without rules allow everything through. This isn't comprehensive, you'll want to fall back to the man page. It's just an explanation to get you off the ground.

NOTE:

iptables has been superceeded by nftables, which reads similarly to pf

NOTE:

in iptables, the first matching rule is applied

Configuration

Your iptables setup can be written to/loaded from a file.

iptables-save    > /etc/iptables/iptables.rules
iptables-restore < /etc/iptables/iptables.rules

Usage

iptables -L --line-numbers                       # list table:filter rules with line numbers
iptable  -F                                      # clear table:filter rules
iptables -A   INPUT -p tcp --dport 80 -j ALLOW   # append a new rule to table:filter chain:INPUT
iptables -I 5 INPUT -p tcp --dport 80 -j ALLOW   # insert a rule at index '5'
iptables -P INPUT DROP                           # set INPUT table's default policy to DROP (if not explicitly handled by a rule)

Monitoring

By default, iptables logs nothing. However, you can create a rule that uses --jump LOG to log the event for debugging.

iptables -A INPUT -j LOG                                           # any packets reaching here will be logged
iptables -A INPUT -j LOG --log-prefix "packet_drp" --log-level 4   # more specific log

Then you can watch the log, to get information about the dropped connections:

  • IN input interface (eth0)
  • OUT output interface (eth0)
  • SRC source ip address
  • DST dest ip address
  • LEN
  • TOS
  • PREC
  • TTL
  • ID
  • PROTO networking protocol (tcp, udp, ..)
  • SPT source-port
  • DPT destination-port
tail -f /var/log/messages | grep packet_drp   # ? what OS?
tail -f /var/log/kern.log                     # debian/ubuntu

NOTE:
Check out the archlinux wiki for a neat recommendation of creating a chain just for logging, so all dropped packets automatically get logged

Rule Syntax

Intro

Generally the syntax of an iptables command is:

 iptables <command> <table and chain> <match criterea> <what to do with it>
iptables                                           \
   -A                    `# command (append-rule)` \
   INPUT                 `# chain`                 \
   -p tcp --dport 17500  `# match`                 \
   -j REJECT --reject-with icmp-port-unreachable  `# reject`

List table rules (defaulting to filter) using:

iptables -nL         # filter table
iptables -t nat -nL  # nat table

How it Works
Every packet passes through a series of tables(nat, filter...).
Each table has a collection of packet-matching rules categorized in different (rule-) chains (INPUT, FORWARD, ...).
Each rule is a set of matches, if a packet matches it, a target(ACCEPT, DROP,...) is applied to it and it continues down the rule-chain, then on to the next table.


## iptables -t filter -L -v --line-numbers				
## (Verbosely list contents of table filter (with rule numbers))
##
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
55569   11M ACCEPT     all  --  any    any     anywhere             anywhere            state RELATED,ESTABLISHED
  201 12464 ACCEPT     icmp --  any    any     anywhere             anywhere
    7   484 ACCEPT     all  --  lo     any     anywhere             anywhere
   81  3932 ACCEPT     tcp  --  any    any     anywhere             anywhere            state NEW tcp dpt:ssh
 294K   40M REJECT     all  --  any    any     anywhere             anywhere            reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 REJECT     all  --  any    any     anywhere             anywhere            reject-with icmp-host-prohibited

Chain OUTPUT (policy ACCEPT 49124 packets, 10M bytes)
 pkts bytes target     prot opt in     out     source               destination

Order

Each chain of rules has an order. A packet is routed based on the first rules it matches. This means you should have the most explicit rules at the top, and the least explicit at the bottom.

Commands

The action you are performing

--list -L list all rules in a table
--append -A append a rule to a table
--delete -D delete a rule from the table (by index number)
--replace -R replace an existing rule from the table (by index number)
--insert -I insert rule (after the index number)

Table Structures

tables

filter default table, in most vanilla setups the only table with rules. (last of tables)
nat when packet makes a new connection
mangle
raw
iptables -t filter -L				## list rule-chains for table'filter'

chains
Each table consists of a chain of rules. Rules are a set of constraints to match packets to. If a packet matches, the rule is applied to it.

iptables -t filter -L INPUT		## list rule-chain for chain:INPUT table:filter

Packet Matching (Match Extensions)


The bulk of the contents of each iptables entry are the matching conditions. There are many, many conditions - consult the manpage. Here are some of the more useful ones. Most of the matching conditions seem to require that you specify the match name for a category of matches. ex: -m <match_name> -<matchfilter> <matchfilter_value>.

iptables --append INPUT    -m state --state NEW -m tcp --protocol tcp    --jump ACCEPT


packet-state

INVALID packet is not associated with any known connection
NEW packet is starting new connection
ESTABLISHED packet is associated with a connection that has seen packets in both directions
RELATED packet is starting new connection, but associated with existing connection.
...


other
Some of these are specific to other flags. For instance, --source-port can only be used

--protocol tcp is specified
--destination-port traffic to destination port
--source-port traffic from a particular port

Targets


targets
What to do with a packet once it is matched

ACCEPT let packet through
DROP silently abandon the packet
REJECT drop the packet, and inform the user
QUEUE pass packet to userspace (?)
RETURN break out of this chain, and continue on to the next chain ignoring all rules following it for this packet.
iptables <command> <packet matching rules> --jump ACCEPT



Creating a Policy

iptables -P INPUT DROP   # drop packages by default in chain INPUT

Default Packet Behaviour

  • drop all packets (if flush rules, all packets in transit will be discarded)
  • last rule drops packet (if flush rules, all packets in transit will continue BUT WITHOUT RESTRICTIONS)
  • accept all packets (insecure)

Drop vs Reject

  • Rejecting is useful to legitimate users. They know right away when something has failed
  • It is also useful to illegitimate users. They can more quickly map out the open ports.

Justin Ellingwood's opinion (which I trust) is that most attacks are scripted, and not time sensitive. They can afford to wait, but your users may not. Default Reject would likely be polite to customers for a negligible loss in security.

Monolithic vs Chain Base Management

At first, a handful of rules in the existing chains is likely fine. If you have a complex firewall, it just makes sense to organize it into your own custom chains.

Other

There is lots more here. My reproduction is doing the original a discredit.

https://www.digitalocean.com/community/tutorials/how-to-choose-an-effective-firewall-policy-to-secure-your-servers



Examples

Most of these shamelessly copied from unixmen.com, or various digital ocean guides.

general

allow all traffic on loopback interface

sudo iptables -A INPUT  -i lo -j ACCEPT
sudo iptables -A OUTPUT -o lo -j ACCEPT


Reject packets by default

if no rule explicitly allows, drop packet from INPUT chain. (Alternatively, you could accept by default).

sudo iptables -P INPUT DROP

allow established in/out traffic (pushed onto other ports)

sudo iptables -A INPUT  -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A OUTPUT -m conntrack --ctstate ESTABLISHED         -j ACCEPT

bridge one interface with another

  • if eth1 is facing WAN
  • and eth0 is local network

This allows eth0 to access WAN.

sudo iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT

redirect traffic from one IP to another IP

Useful during server migrations:

https://www.debuntu.org/how-to-redirecting-network-traffic-to-a-new-ip-using-iptables/

echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A PREROUTING -p tcp --dport 1111 -j DNAT --to-destination 2.2.2.2:1111
iptables -t nat -A POSTROUTING -j MASQUERADE

Security

help prevent ddos attacks

# help mitigate DDos Attack
# (
iptables -A \
    INPUT \
    -p tcp --dport 80 \
    -m limit --limit 20/minute --limit-burst 100 \
    -j ACCEPT

Protect more with this (need to read desc of each)

echo 1 > /proc/sys/net/ipv4/ip_forward
echo 1 > /proc/sys/net/ipv4/tcp_syncookies
echo 0 > /proc/sys/net/ipv4/conf/all/accept_redirects
echo 0 > /proc/sys/net/ipv4/conf/all/accept_source_route
echo 1 > /proc/sys/net/ipv4/conf/all/rp_filter
echo 1 > /proc/sys/net/ipv4/conf/lo/rp_filter
echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 0 > /proc/sys/net/ipv4/icmp_echo_ignore_all
echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout
echo 1800 > /proc/sys/net/ipv4/tcp_keepalive_time
echo 1 > /proc/sys/net/ipv4/tcp_window_scaling 
echo 0 > /proc/sys/net/ipv4/tcp_sack
echo 1280 > /proc/sys/net/ipv4/tcp_max_syn_backlog

help deter portscans

sudo iptables -N block-scan     # create a new rule-chain: block-scan

iptables -A                    `# match portscan traffic (?)` \
    block-scan -p tcp —tcp-flags SYN,ACK,FIN,RST RST \
    -m limit —limit 1/s                              \
    -j RETURN

sudo iptables -A block-scan -j DROP  # drop all traffic matched in block-scan

block a specific ip address

sudo iptables -A INPUT -s 15.15.15.51 -j DROP

Program Traffic

allow database traffic, but only for you

# accept MySQL traffic from 192.168.1.0/24
iptables \
    -A                               \
    INPUT -p tcp --dport 3306        \
    -s 192.168.1.0/24                \
    -m state --state NEW,ESTABLISHED \
    -j ACCEPT

SSH

Allow incoming ssh (initiated from outside)

sudo iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
sudo iptables -A OUTPUT -p tcp --sport 22 -m conntrack --ctstate ESTABLISHED -j ACCEPT

Allow outgoing ssh (initiated from inside)

sudo iptables -A OUTPUT -p tcp --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
sudo iptables -A INPUT  -p tcp --sport 22 -m conntrack --ctstate ESTABLISHED     -j ACCEPT

HTTP(S)

Allow incoming http/https

sudo iptables -A INPUT -p tcp -m multiport  --dports 80,443 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
sudo iptables -A OUTPUT -p tcp -m multiport --dports 80,443 -m conntrack --ctstate ESTABLISHED     -j ACCEPT




Reference

https://www.digitalocean.com/community/tutorials/how-to-set-up-a-firewall-using-iptables-on-ubuntu-14-04 Simple, And Detailed Intro. Must-Read.
https://www.digitalocean.com/community/tutorials/iptables-essentials-common-firewall-rules-and-commands Cookbook of use-cases. Great for coming to terms with syntax and best practices
https://www.digitalocean.com/community/tutorials/how-to-choose-an-effective-firewall-policy-to-secure-your-servers How to choose a firewall Strategy
https://www.howtogeek.com/177621/the-beginners-guide-to-iptables-the-linux-firewall/ A very approchable iptables intro, once you've covered the basics
https://www.unixmen.com/iptables-vs-firewalld/ Great intro to iptables/firewalld, common examples
https://likegeeks.com/linux-iptables-firewall-examples/ good intro tutorial
https://wiki.archlinux.org/index.php/Iptables quick-implementation, and concepts- in typical archlinux-style.
https://github.com/trimstray/iptables-essentials excellent guide to iptables
https://arstechnica.com/gadgets/2016/04/the-ars-guide-to-building-a-linux-router-from-scratch/ linux router from scratch