New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Fosscon 2012 firewall workshop
1. Advanced
Netfilter
&
Iptables
Understand the Linux Firewall and make it
do magical tricks
Julien Vehent - Fosscon - July 2012
2. Who am I ?
• Julien Vehent http://jve.linuxwall.info
• Security Engineer, Linux
Sysadmin, and a bit of a Dev
• Love Networks, Packets,
Routers, Firewalls, etc...
• I work for in the Philly suburb
• I write and publish at http://wiki.linuxwall.info
• http://wiki.linuxwall.info/doku.php/en:ressources:dossiers:networking:traffic_control
• http://wiki.linuxwall.info/doku.php/en:ressources:dossiers:dspam
• http://wiki.linuxwall.info/doku.php/en:ressources:dossiers:postfix:dkimproxy
Julien Vehent - jve.linuxwall.info - 2012
3. So you want to use ?
• linux/net/netfilter: 154 files, 1870710 characters (as of last night)
On the Menu today ...
-1 Things you already know: packets, sk_buff and iptables basics
0 Cloud & Firewalls
1 Chains: INPUT, OUTPUT, FORWARD
2 Tables: raw, nat, mangle and filter
3 Connections state: xt-conntrack & /proc/net/ip_conntrack
4 Modules: owner, string, time, connbytes, geoip,....
5 Playing with packets and connections marks
6 Large sets of IPs: first iptables-restore, then IPset
7 Netfilter Hooks: example with nfqueue_recorder
8, 9 & 10 Cloud again, and how to maintain tight control over your
(inbound *and* outbound) firewall using Chef and AFW
Julien Vehent - jve.linuxwall.info - 2012
4. App Everything is packet
T +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
R | Source Port | Destination Port |
A +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
N | Sequence Number |
TCP/IP Model S +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
P | Acknowledgment Number |
O +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
R P| Data | |U|A|P|R|S|F| |
T R| Offset| Reserved |R|C|S|S|Y|I| Window |
Transport O| | |G|K|H|T|N|N| |
C T+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
O O| Checksum | Urgent Pointer |
N C+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
T O| Options | Padding |
R L+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
O | data |
L +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
I +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
N |Version| IHL |Type of Service| Total Length |
T +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
E | Identification |Flags| Fragment Offset |
R +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
N | Time to Live | Protocol | Header Checksum |
Network E +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
T | Source Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
P | Destination Address |
R +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
O | Options | Padding |
T +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
E +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Data Link T | DESTINATION MAC
H +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
ADDRESS |
E | DEST MAC | SOURCE MAC ADDRESS |
R +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
N | SRC MAC ADDRESS | T Y P E |
Physical E +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
T Julien Vehent - jve.linuxwall.info - 2012
5. Linux and sk_buff
struct sk_buff {
/* These two members must be first. */
Linux stores each
struct sk_buff *next; ingress and egress
struct sk_buff *prev;
struct sock *sk; packet into an
struct net_device *dev;
struct nf_conntrack *nfct; instance of the
struct nf_bridge_info *nf_bridge;
union { sk_buff structure.
__u32 mark;
__u32 dropcount;
};
__u32 avail_size; Netfilter applies
__u16 vlan_tci; packet filters on the
sk_buff_data_t transport_header;
sk_buff_data_t network_header; sk_buff structures.
sk_buff_data_t mac_header;
sk_buff_data_t tail;
sk_buff_data_t end;
}; sample from <include/linux/skbuff.h>
Julien Vehent - jve.linuxwall.info - 2012
7. Iptables 101
Stateless firewall
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A OUTPUT -p tcp --sport 80 -j ACCEPT
Stateful version
iptables -I INPUT -p tcp -m conntrack
--ctstate ESTABLISHED -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -m conntrack
--ctstate NEW -j ACCEPT
Logging
iptables -A INPUT -p tcp --dport 80 -m conntrack
--ctstate NEW -j LOG --log-prefix “In HTTP ”
Julien Vehent - jve.linuxwall.info - 2012
8. Firewall vs Cloud
“I like VMs, they are cheap
90s model: “I bought 4 and I can have MANY !”
servers , $25k each, and a
firewall and it does it all”
Versus
Of course I have a firewall, it does:
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
Julien Vehent - jve.linuxwall.info - 2012
10. Introducing Tables
filter: default mangle: for packet
nat: only traversed on alteration
state==NEW raw: to disable conntrack
Julien Vehent - jve.linuxwall.info - 2012
11. Tables
FILTER: implied when nothing specified
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -t filter -A INPUT -p tcp ...
RAW: don’t waste ressources on conntrack
iptables -t raw -I PREROUTING -i lo -j NOTRACK
iptables -t raw -I OUTPUT -o lo -j NOTRACK
iptables -t raw -I PREROUTING -p udp --sport 53
-s 8.8.8.8 -j NOTRACK
MANGLE: manipulate packets right before transmit
iptables -t mangle -A POSTROUTING -o eth0
-p tcp --tcp-flags SYN SYN --dport 443
-j CONNMARK --set-mark 300
Julien Vehent - jve.linuxwall.info - 2012
12. Stateful (conntrack) vs Stateless
• Conntrack knows the state of each TCP & UDP
connection on the system
• When a new packet arrive, conntrack can tell if it is part
of an existing connection
• Downside: maintaining state information can be
expensive for very high traffic system (start worrying
around 10,000 packets per second)
# grep "dport=22 " /proc/net/ip_conntrack
tcp 6 299 ESTABLISHED src=10.1.0.145 dst=10.1.0.25
sport=54656 dport=22 packets=819 bytes=62669
src=10.1.0.25 dst=10.1.0.145 sport=22 dport=54656
packets=436 bytes=251335 [ASSURED] mark=0 secmark=0 use=2
see linux/net/netfilter/nf_conntrack_proto_tcp.c
Julien Vehent - jve.linuxwall.info - 2012
13. Some fun with modules
• Mangle connection based on their “size”
iptables -t mangle -A POSTROUTING -o eth1 -p tcp
-m connbytes --connbytes 10000000: --connbytes-mode bytes
--connbytes-dir both -j CONNMARK --set-mark 999
$ nc -l 1664 < /dev/zero $ nc 192.168.1.222 1664 > /dev/null
# iptables -t mangle -L POSTROUTING -v
Chain POSTROUTING (policy ACCEPT 115K packets, 4715K bytes)
pkts bytes target prot opt in out source destination
111K 4452K CONNMARK tcp -- any eth0 anywhere anywhere connbytes
10000000:18446744073709551615 connbytes mode bytes connbytes direction
both CONNMARK set 0x3e7
# grep mark=999 /proc/net/ip_conntrack
tcp 6 299 ESTABLISHED src=10.0.2.15 dst=192.168.1.222 sport=45234
dport=1664 packets=371355 bytes=14854220 src=192.168.1.222
dst=10.0.2.15 sport=1664 dport=45234 packets=415324 bytes=606265294
[ASSURED] mark=999 use=2
Julien Vehent - jve.linuxwall.info - 2012
14. Some fun with modules
• Mangle packets based on ASCII strings in the payloads
iptables -t filter -A INPUT -i eth1 -p tcp --dport 80
-m string --string "get /admin http/1.1" --icase --algo bm
-m conntrack --ctstate ESTABLISHED -j DROP
$ nc -l 80 $ nc 192.168.1.222 1664
get /hello+world http/1.1 get /hello+world http/1.1
X get /admin http/1.1
# iptables -t filter -L INPUT -v
Chain INPUT (policy ACCEPT 93 packets, 6531 bytes)
pkts bytes target prot opt in out source destination
13 936 DROP tcp -- eth1 any anywhere anywhere
tcp dpt:http STRING match "get /admin http/1.1" ALGO name bm TO
65535 ICASE ctstate ESTABLISHED
Julien Vehent - jve.linuxwall.info - 2012
15. Some fun with modules
• Filter SSH on Christmas
iptables -t filter -A INPUT -p tcp
--dport 22 -m time
--datestart "2012-12-25T00:00:00"
--datestop "2012-12-25T23:59:59"
--utc -j DROP
• Mark the packets of a particular user, and Log
iptables -t filter -o eth0 -A OUTPUT -p tcp
--tcp-flags SYN SYN -m owner --uid-owner 1000
-j CONNMARK --set-mark 1664
iptables -t filter -A OUTPUT -p tcp
--tcp-flags SYN SYN -m connmark --mark 1664
-j LOG --log-prefix "Mark 1664 trigerred "
Aug 11 04:29:15 firewall1 kernel: [ 9895.696205] Mark 1664 trigerred IN= OUT=eth0 SRC=10.0.2.15
DST=173.194.75.106 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=7270 DF PROTO=TCP SPT=50940 DPT=443
WINDOW=14600 RES=0x00 SYN URGP=0
Julien Vehent - jve.linuxwall.info - 2012
16. Hooks Magic
• libnetfilter_queue provides hooks to divert packets from
the normal Netfilter flow, into Userland
• Use case: record outbound traffic from suspicious user
“spongebob” (using https://github.com/jvehent/)
iptables -I OUTPUT -m owner --uid-owner $(id -u spongebob) -j NFQUEUE
root@ossec:~# ./nfqueue_recorder -o spongebob_record.pcap
pcap recording into spongebob_record.pcap
opening pcap file at spongebob_record.pcap
opening library handle
unbinding existing nf_queue handler for AF_INET (if any)
binding nfnetlink_queue as nf_queue handler for AF_INET
binding this socket to queue '0'
setting copy_packet mode
-- New packet received --
hw_protocol=0x0000 hook=3 id=0 outdev=2 payload_len=60 bytes
IP{v=4; ihl=20; tos=0; tot_len=60; id=15388; ttl=64; protocol=17; saddr=10.0.2.15;
daddr=10.0.2.2}
UDP{sport=45374; dport=53; len=10240}
-- New packet received --
hw_protocol=0x0000 hook=3 id=1 outdev=2 payload_len=60 bytes
IP{v=4; ihl=20; tos=0; tot_len=60; id=15391; ttl=64; protocol=17; saddr=10.0.2.15;
daddr=10.0.2.2}
UDP{sport=47435; dport=53; len=10240}
Julien Vehent - jve.linuxwall.info - 2012
18. Better than TCPDump
• TCPDump duplicates traffic at the NIC level.
• Dump incoming traffic and see packets entering but
never reach the application
• Place your hook anywhere within you ruleset to verify
that packets are coming through
application
Socket
nfqueue display:
recorder nothing !
INPUT
DROP
PREROUTING
display:
NIC duplicates
tcpdump
packet packet packet .....
P P P
Julien Vehent - jve.linuxwall.info - 2012
19. Recording traffic on /admin at night
# ./nfqueue_recorder -o night_admin.pcap
pcap recording into night_admin.pcap
opening pcap file at night_admin.pcap
opening library handle
unbinding existing nf_queue handler for AF_INET (if any)
binding nfnetlink_queue as nf_queue handler for AF_INET
binding this socket to queue '0'
setting copy_packet mode
iptables -t filter -A INPUT -i eth1 -p tcp --dport 80
-m string --string "get /admin http/1.1" --icase --algo bm
-m time --timestart "18:00" --timestop "10:00" --utc
-m conntrack --ctstate ESTABLISHED -j CONNMARK --set-mark 666
iptables -t filter -A INPUT
-m connmark --mark 666 -j NFQUEUE
$ nc 10.16.64.11 80
# nc -l 80
get /spongebobsquarepants http/1.1
get /admin http/1.1
get /spongebob
blaaaahhh fooo
Julien Vehent - jve.linuxwall.info - 2012
20. IPSets
• Netfilter uses linear lookups. Each rule is tested against
each packet, until a terminal rule matches the packet.
• Lookup time grows linearily.
• IPSets provides constant time hash lookup in Netfilter.
apt-get install ipset && modprobe ip_set
ipset -N droplist nethash
ipset --add droplist 192.168.1.0/24
iptables -A INPUT -m set --match-set droplist src
-j DROP
#! /bin/bash
ipset -N droplist nethash
wget -q http://www.spamhaus.org/drop/drop.txt -O drop.lasso.$(date +%s)
if [ -e drop.lasso.$(date +%s) ]; then
ipset --flush droplist
for i in $(grep -v -E "^;|^$" drop.lasso.$(date +%s) | awk {'print $1'}); do
echo "insert $i to droplist"
ipset --add droplist $i
done
fi Julien Vehent - jve.linuxwall.info - 2012
21. Ipsets: accounting per country
• Get the list of IP blocks for each country from https://
www.countryipblocks.net/country_selection.php
• Load each country blocks into a separate Ipset
Chain INPUT (policy DROP 20 packets, 5942 bytes)
pkts bytes target
0 0 COUNTRIES [...] match-set nigeria src
367 25797 COUNTRIES [...] match-set france src
10 440 COUNTRIES [...] match-set china src
Julien Vehent - jve.linuxwall.info - 2012
22. Atomic (and fast) Restore
• Most people write their firewall rules in a Bash script. It’s
the best way to start, until you have thousands of rules.
• [ USE IPTABLES-RESTORE ]
# iptables -L INPUT -v -n |grep ACCEPT|wc -l
62511 <= that’s 62,511 individual INPUT rules
# time iptables-restore < iptables-rules.saved
real 0m1.204s
user 0m0.450s
sys 0m0.720s
# time bash rules.iptables.sh
real 41m28.277s <= 42 minutes
user 12m55.300s
sys 32m17.290s <= 32 minutes spent in the kernel
Julien Vehent - jve.linuxwall.info - 2012
23. Aweber FireWall
• Moving away from the massive entry gate logic
• To something a lot more modular
node node node node
node node
node node node node
Julien Vehent - jve.linuxwall.info - 2012
24. Aweber FireWall
• Completely dynamic. Chef creates inbound/outbound
rules for nodes automatically. Convergence takes time.
• Whitelist for outbound connections per system user.
• Rules are stored in /etc/firewall/rules.iptables
-A INPUT -i eth0 -p tcp --dport 80 -s provision -m state --state NEW -j ACCEPT
-A INPUT -i eth0 -p tcp --dport 80 -s 10.1.0.228 -m state --state NEW -j ACCEPT
-A INPUT -i eth0 -p tcp --dport 80 -s 10.1.0.229 -m state --state NEW -j ACCEPT
:www-data - [0:0]
-A OUTPUT -m owner --uid-owner 33 -m state --state NEW -j www-data
-A www-data -j LOG --log-prefix "AFW_www-data_OUTPUT_DROP " --log-uid
-A www-data -j DROP
:ntp - [0:0]
-A OUTPUT -m owner --uid-owner 104 -m state --state NEW -j ntp
-A ntp -o eth0 -p udp --dport 123 -d ntp1 -m state --state NEW -j ACCEPT
-A ntp -o eth0 -p udp --dport 123 -d ntp2 -m state --state NEW -j ACCEPT
-A ntp -j LOG --log-prefix "DROP_AFW_OUTPUT_ntp " --log-uid --log-tcp-sequence
-A ntp -j DROP
Julien Vehent - jve.linuxwall.info - 2012
25. Any
Question ?
Julien Vehent - jve.linuxwall.info - 2012