All our computers should be using a firewall. Especially those that expose services to the internet.
Firewalls are crucial for mantaining the security of our network and protecting our data from external threats. They serve as a first line of defense against malware, cyber criminals and another threaths.
In this times, it’s a matter of minutes that botnets finds your exposed service and start attacking it. And this could be the beginning of a bad story…
I have an old raspberry pi exposing a SSH service to the internet, I need to connect to it remotely. The SSH access is secured using RSA authentication and fail2ban. But, once botnets discovers the SSH service running, the raspberry begins to receive such amount of petitions that the router is “ddosed” and the internet connection starts to cut. So I decided to set up a firewall to try to avoid network scans, at least those automated ones like those used by the botnets. I decided on iptables due to hardware and software restrictions, and, while I was at it, I also added protections to other kind of attacks and restrictions.
I learned a lot along the way, and that’s why I decided to put a configuration file here that I think it’s a good starting point to harden our systems.
Iptables bash script
Here’s my iptables starting point rules (as bash script):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#!/usr/bin/env bash
bin="/usr/sbin/iptables"
# Deny all
$bin -P INPUT DROP
$bin -P OUTPUT DROP
$bin -P FORWARD DROP
# Scanners
## Drop packages if the connections are too agressive to avoid port scanning.
## Adjust these values to your needs.
$bin -A INPUT -p tcp --syn -m conntrack --ctstate NEW -m hashlimit --hashlimit-name port_scanners --hashlimit-above 5/second --hashlimit-mode srcip -j DROP
$bin -A INPUT -p udp -m conntrack --ctstate NEW -m hashlimit --hashlimit-name port_scanners --hashlimit-above 35/second --hashlimit-mode srcip -j DROP
## Bad flags combinations
$bin -N BAD_FLAGS
$bin -A INPUT -p tcp -j BAD_FLAGS
$bin -A BAD_FLAGS -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
$bin -A BAD_FLAGS -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
$bin -A BAD_FLAGS -p tcp --tcp-flags SYN,FIN,PSH SYN,FIN,PSH -j DROP
$bin -A BAD_FLAGS -p tcp --tcp-flags SYN,FIN,RST SYN,FIN,RST -j DROP
$bin -A BAD_FLAGS -p tcp --tcp-flags SYN,FIN,RST,PSH SYN,FIN,RST,PSH -j DROP
$bin -A BAD_FLAGS -p tcp --tcp-flags FIN FIN -m hashlimit --hashlimit-name port_scanners --hashlimit-above 1/second --hashlimit-mode srcip -j DROP
$bin -A BAD_FLAGS -p tcp --tcp-flags ALL NONE -j DROP
$bin -A BAD_FLAGS -p tcp --tcp-flags ALL ALL -j DROP
$bin -A BAD_FLAGS -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP
$bin -A BAD_FLAGS -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP
# SYN flood
$bin -A INPUT -p tcp --tcp-flags ALL SYN -m hashlimit --hashlimit-name port_scanners --hashlimit-above 1/second --hashlimit-mode srcip -j DROP
$bin -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
$bin -A INPUT -m conntrack --ctstate INVALID -j DROP
## Drop Packet fragments
$bin -A INPUT -f -j DROP
# Spoofing
## Deny incoming traffic that has a source address of an IP address assigned to a local interface.
## Incoming traffic with the source address of your system is going to be spoofed traffic because you know it cannot be generated by the host.
## If you have more than one interface you should especify each interface.
## If your interfaces doesn't have a static ip address (or don't use static DHCP) leave these lines commented.
# $bin -A INPUT -s 192.168.1.1 -j DROP
## Deny outgoing traffic that does not have a source address of an interface on the local host.
# $bin -A OUTPUT ! -s 192.168.1.1 -j DROP
# Block incoming traffic form the Zeroconf address range.
# This range is used by hosts that use DHCP to adquire their IP address.
# An address from this range is asigned when these hosts are unable to find a DHCP server to provide them an address.
# This range is also usded to provide addressing when connecting two devices using a crossover cable,
$bin -A INPUT -s 168.254.0.0/16 -j DROP
# Block incoming traffic coming from TEST-NET
$bin -A INPUT -s 192.0.2.0/24 -j DROP
# Block incoming traffic coming from the reserved class D
$bin -A INPUT -s 224.0.0.0/4 -j DROP
# Block incoming traffic coming from the reserved class E
$bin -A INPUT -s 240.0.0.0/5 -j DROP
# Block incoming traffic coming from the unallocated range
$bin -A INPUT -s 248.0.0.0/5 -j DROP
# Block incoming traffic coming from the loopback and zero addresses
$bin -A INPUT -s 127.0.0.0/8 -j DROP
$bin -A INPUT -s 255.255.255.255/32 -j DROP
$bin -A INPUT -s 0.0.0.0/8 -j DROP
# ICMP
# All ICMP responses should be barred except responses to outgoing connections.
# Allow outbound echo messages and indbound echo reply messages -> Allows the use of ping from the host.
# Allow time exceeded and destination unreaachable messages inbound -> Allow the use of tools such traceroute.
# Avoids ICMP flood, ICMP smurf, Ping of death, ICMP nuke...
$bin -N ICMP_IN
$bin -N ICMP_OUT
$bin -A INPUT -p icmp -j ICMP_IN
$bin -A OUTPUT -p icmp -j ICMP_OUT
$bin -A ICMP_IN -p icmp --icmp-type 8 -j DROP
$bin -A ICMP_IN -p icmp --icmp-type 0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
$bin -A ICMP_IN -p icmp --icmp-type 3 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
$bin -A ICMP_IN -p icmp --icmp-type 11 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
$bin -A ICMP_OUT -p icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT
# Allow all traffic on the loopback interface (the internal 127.0.0.1 address).
$bin -A INPUT -i lo -j ACCEPT
$bin -A OUTPUT -o lo -j ACCEPT
# DNS
$bin -A INPUT -p tcp -m multiport --sports 53,853 -m conntrack --ctstate ESTABLISHED -j ACCEPT
$bin -A OUTPUT -p tcp -m multiport --dports 53,853 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
$bin -A INPUT -p udp -m multiport --sports 53,853 -m conntrack --ctstate ESTABLISHED -j ACCEPT
$bin -A OUTPUT -p udp -m multiport --dports 53,853 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
# SSH
$bin -A INPUT -p tcp --dport ssh -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
$bin -A OUTPUT -p tcp --sport ssh -m conntrack --ctstate ESTABLISHED -j ACCEPT
## Deny SSH outgoing connections
$bin -A OUTPUT -p tcp --dport ssh -j DROP
# NTP
$bin -A INPUT -p udp --sport 123 -m conntrack --ctstate ESTABLISHED -j ACCEPT
$bin -A OUTPUT -p udp --dport 123 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
# HTTP and HTTPS (Allow outgoing http/s connections)
$bin -A INPUT -p tcp -m multiport --sports http,https -m conntrack --ctstate ESTABLISHED -j ACCEPT
$bin -A OUTPUT -p tcp -m multiport --dports http,https -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
# NFSv4
$bin -A INPUT -p tcp --dport 2049 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
$bin -A OUTPUT -p tcp --sport 2049 -m conntrack --ctstate ESTABLISHED -j ACCEPT
Saving iptables rules
If we don’t persist our rules, they will be deleted upon reboot. sudo iptables-save
If you are going to use this as configuration basis rember a few things:
- Check the configuration and set the parameters of your computer (e.g.: set your computer ip address and the packet limits of the rules).
- These are basically protection rules and only allows basic common services as DNS, SSH, NTP and HTTP[S]. Below you have to add the rules that allow legitimate services traffic from your host.
- Think about your computer needs. Every host has needs and they may not be the same as mine.
- I set these rules without specify interfaces.In some hosts different interfaces have different needs.
- In iptables the order of the rules matter.
- Using the
recent
orlimit
modules insteadhashlimit
could improve the performance. - Don’t forget about IPv6. These are rules for IPv4, but changing the
$bin
variable to useip6tables
could apply to IPv6.
I have to say that I am no expert, and, therefore, these rules could be improved in many ways (If this is the case, feel free to contact me and I’ll be happy to update this post :) ).
Thanks to Rodrigo Rega for the tips and annotations :)
Enjoy! ;)