Iptables
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:
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 logThen 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/ubuntuNOTE:
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 tableHow 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 destinationOrder
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:filterPacket 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 INPUTDefault 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.
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 DROPallow 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 ACCEPTbridge 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 ACCEPTredirect 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 MASQUERADESecurity
help prevent ddos attacks
# help mitigate DDos Attack # ( iptables -A \ INPUT \ -p tcp --dport 80 \ -m limit --limit 20/minute --limit-burst 100 \ -j ACCEPTProtect 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_backloghelp 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-scanblock a specific ip address
sudo iptables -A INPUT -s 15.15.15.51 -j DROPProgram 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 ACCEPTSSH
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 ACCEPTAllow 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 ACCEPTHTTP(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