Firewalls
Securing the Network
IPtables is the default firewall you'll find in most servers. We'll discuss how to view, add and delete firewall rules.
The situation
Run sudo iptables -L -v to see current firewall rules. You'll likely see something like this:
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
The three rule "chains" here are INPUT, FORWARD, and OUTPUT.
INPUT deals with external network traffic going into the server. OUTPUT is exactly the opposite. The FORWARD chain deals with traffic going between networks within the server.
The default policy is ACCEPT for all three rule chains. We see there are no rules in the three chains, so this server is completely open to all traffic.
We'll deal mostly with the INPUT chain to protect the server against external traffic headed into the server.
We can make the default policy for any chain to DROP or REJECT traffic. Read more about DROP vs REJECT here: http://serverfault.com/questions/157375/reject-vs-drop-when-using-iptables
Persistance
Firewall rules won't persist through reboots out of the box.
However, we can use some basic commands to output the current ruleset as text, and a command that will take that text and apply them as the current ruleset.
# Output rules to stdout
sudo iptables-save
# Set rules based on text input
sudo iptables-restore
For Example, to save iptables rules:
sudo iptables-save > ~/rules.v4
Later, we can restore those rules:
sudo iptables-restore < ~/rules.v4
Persisting Rules through Reboots (Debian/Ubuntu)
Install the iptables-persistent package to persist firewall rules:
sudo apt-get install -y iptables-persistent
sudo service iptables-persistent start
sudo service iptables-persistent save
Firewall Rule Basics
We're ready to create firewall rules for our server.
As mentioned, what we'll do is add to the INPUT chain.
First, we'll handle loopback/localhost data. The following command will allow data between items on the localhost network (loopback interface):
sudo iptables -A INPUT -i lo -j ACCEPT
We're telling iptables to do the following:
- Append (
-A) to INPUT chain - Apply to traffic originating from the loopback interface (
-i) - Jump (
-j) that traffic to the ACCEPT "target", which says to allow that traffic through
Second, a more advanced but necessary command which ensures I don't accidentally cut myself out of the server (it allows my currently established SSH connection):
sudo iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
This will allow/keep current related/established rules.
The command does the following:
- Appends (
-A) to the INPUT chain - Uses the module (
-m) conntrack - Check for state (
--ctstate) 'related', 'established' - JUMP (
-j) to the ACCEPT target
What's this affecting?
Use the command netstat -a to see items with the state ESTABLISHED or RELATED. These items will be near the top of the output:
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 *:ssh *:* LISTEN
tcp 0 324 172.30.0.86:ssh cpe-173-174-200-3:61248 ESTABLISHED
tcp6 0 0 [::]:ssh [::]:* LISTEN
udp 0 0 *:bootpc *:*
udp 0 0 *:40118 *:*
udp6 0 0 [::]:46591 [::]:*
We can see that I have an ESTABLISHED connection to SSH to this server from my local network (my internet connection at home). This connection will not be cut out since I've allowed currently established through the INPUT chain.
Web Server Firewall Rules
We'll continue on and allow in web and SSH traffic:
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
- Append (
-A) to INPUT chain - Apply to protocol (
-p) TCP - Destination port (
--dport) 22 and 80 - Jump to the ACCEPT target
Lastly, we drop all other traffic:
sudo iptables -A INPUT -j DROP
- Append (
-A) to INPUT chain - Jump (
-j) to the DROP target, to drop the network packets
Now investigate the rules we've created:
sudo iptables -L -v
These are explained more in the video - basically what we've done is to create a chain of rules. The first rule to be matched tells the server what to do with the traffic. The last rule essentially is a catch-all, telling the server to block anything that wasn't matched above it.
HTTPS (Insert over Append)
If we need to insert a rule instead of append one to allow other connections, such as https traffic, run the following to Insert (instead of Append) a rule at a specific location in the chain:
sudo iptables -I INPUT 5 -p tcp --dport 443 -j ACCEPT
- Insert (
-I) to INPUT chain, at the 5th position (1-based index) - Protocol (
-p) TCP - Destination port (
--dport) 443 - Jump (
-j) to the ACCEPT target
Delete Rules
These are equivalent. One drops the rule by position, and the other drops the rule by matching the parameters (port, destination port, jump target).
sudo iptables -D INPUT 3
sudo iptables -D INPUT -p tcp --dport 22 -j ACCEPT
Find Rules by Command
We can delete rules by find the command originally used to create them.
To show all the current rules as valid Iptables command, run: sudo iptables -S
You can then copy one of them and then tweak it to delete -D rather than append or insert.
For example, if we copy -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT and edit it, we'll end up with a command like the following:
# Deletes the rule allowing port 22 traffic:
sudo iptables -D INPUT -p tcp -m tcp --dport 22 -j ACCEPT