Firewalls
Introduction
Iptables
is a packet filter included in most modern Linux distributions. It includes a lot of useful advanced features to do almost anything necessary at the firewall level, but this tutorial will focus on the basics.
All iptables rules are created and modified via passing command-line options to the iptables binary. There are also GUI utilities in some distributions to do this, but they tend to be much less powerful. For this demo, you must have permission to run iptables as root via sudo. The TAs should be able to do this on netsec-demos but you may want to try it on your own machine.
Iptables saves any rules you create only until the computer is rebooted, and so another solution is needed for permanent rule storage. Most distributions handle this by including two scripts, iptables-save
and iptables-restore
. The tutorial will not worry about saving rulesets.
Rule Basics
Iptables operates based on rules. The rules are applied top-down, with the first match being used. Therefore, more specific rules should be placed above more general rules. For example, a rule to allow all SSH packets should be above/before a rule to reject all packets, so that SSH connections are allowed, but nothing else. Each rule is specified by running the iptables
binary with the desired switches.
The switches specify first what table and chain a rule applies to, what packet characteristics it applies to, and to what target it should jump after determining that there is a match.
Tables and Chains
Iptables allows for different tables
and chains
. There are three main tables: filter
, nat
, and mangle
. Each table has chains specific to their functions.
Users can also append new chains with special rules for different purposes. For example, in Redhat-based distributions, the GUI firewall configuration generates a custom input chain to separate GUI-generated rules from user-created rules.
filter
is the default table if none is specified; this table parses all packets eventually regardless of what we do, and exists to drop or accept packets based on their characteristics. It includes 3 chains by default: INPUT
, OUTPUT
, and FORWARD
. These chains act upon inbound, outbound, and forwarding packets (ie, when the current host is acting as a router).
nat
handles network address translation, and includes two chains: prerouting and postrouting. This allows us to change the source or destination addresses based on packet characteristics. Two very common uses of this table is to allow for port forwarding or sharing an internet connection.
mangle
includes the chains in both of the other tables, and allows for altering packet fields such as TOS, TTL, etc.
Command Line Options
-
-L
List all rules -
-F
Flush (erase) all rules -
-P <chain> <target>
Set the default action for a packet when no rule matches; default isACCEPT
, better practice is to allow all valid packets and set the policy toDROP
-
-A <chain> <rule>
Append a rule to the end of a chain -
-D <chain> <rulenum>
Delete a rule from a chain by number -
-I <chain> <rulenum>
Like append, but insert at rulenum location
Rule Specifications
When adding rules, switches must be used to specify what constitutes a match. The most typical switches typically match based on port, IP address, protocol, and connection state.
These are specified via the following switches:
-
--dport <portnumber>
Match rules by destination port -
--sport <portnumber>
Match by source port -
-d <ipaddress/hostname>
Match rules by destination address -
-s <ipaddress/hostname>
Match rules by source address -
-p <protocol>
Match packets by protocol (tcp, udp, icmp, etc)
Iptables uses the -m
switch to allow for extended matching. This allows the use of specific extensions. A commonly used one is state, which allows for connection tracking.
For example, this allows us to allow only established packets inbound (ie, those that are not SYN packets for TCP), to ensure that we can always connect out but nobody else can initiate inbound connections.
Here are some common ways to use -m state
:
-
-m state --state RELATED,ESTABLISHED
Match packets that are part of an ongoing connection -
-m state --state NEW
Match packets that are trying to establish a new connection
Targets
All rules must end with a target to jump to. This specifies what to do when a rule does match.
Here are some common targets (Not all of these can be used with all tables):
-
-j ACCEPT
Accept / Allow a given packet -
-j REJECT
Reject a packet with a negative response -
-j DROP
Drop packet on the floor - reject with no response -
-j DNAT
Change the destination address (port forwarding) -
-j MASQUERADE
Change the source address / ip masquerade
Things to Try
Start the firewall lab by running firewall-lab.bash
in the labs folder of the student repository. It will tell you the hostname of the system which you will be setting up the firewall for, and also tell you how to connect to it.
On the attacker machine (the one which opens when you run firewall-lab.bash
):
attacker# nmap <lab-hostname> -p 5000-8000
You can see that there are three ports open on this machine which are accessible from outside systems.
On the firewalled machine, we can check the outbound connectivity:
firewall# ping 1.1.1.1
PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
64 bytes from 1.1.1.1: icmp_seq=1 ttl=54 time=13.7 ms
Let's begin configuring the firewall by blocking all inbound packets. Set the INPUT
policy as such:
firewall# iptables -P INPUT DROP
Notice that this will prevent you from connecting outbound. (Try running ping
again) Why? Response SYN-ACKs and DNS responses from remote servers are also dropped, along with all other inbound packets. Next, let's allow all related and established packets to come in, so that we can make outbound connections.
firewall# iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
Now you should be able to download files and ping, but nobody externally will be able to initiate a connection to the three running servers. You can confirm this by running nmap again, or trying to connect to any of them using nc
.
To allow specific connections to the server, add another rule to allow SYN packets with a destination port of 7777.
firewall# iptables -A INPUT -p tcp -m state --state NEW --dport 7777 -j ACCEPT
iptables
is a complicated tool. When in doubt, a web search will tell you how to do whatever it is you are trying to do.
Classwork
After trying the above examples, do the following:
- Block only outbound traffic to 8.8.8.8
- Allow inbound traffic to port 5555, but only from private IP address ranges.
- Redirect incoming traffic destined for port 80 to port 6666
- (Extra credit) While maintaining the above, make sure that port 6666 is still blocked from direct access
To submit and test the lab:
- Launch the attacker container with "firewall-lab.bash".
- Navigate to the directory "/mnt" inside the attacker container. Inside the "/mnt" directory, you will find the script "attacker_test.bash". This script will test a local attacker's view of the firewall.
- Open a terminal on the device that is not connected to the Northwestern VPN or network.
- Run the script "external_firewall_test.bash". The script will test the attacker's view from outside the network. Take a screenshot of the output of this script.
- Next, you need to enter the firewall container. To do this, execute the script "./firewall-connect.bash" to enter the firewall container.
- In the root directory, you will find the scripts "firewall_test.bash" and "firewall_iptable_check.bash".
- Run the script "firewall_test.bash". This script will test the firewall's view of the network. Take a screenshot of the output of this script.
- Run the script "firewall_iptable_check.bash". This script will check if all the required iptables rules for the lab are present. Take a screenshot of the output of this script as well.
- Submit the four screenshots to Canvas as instructed by your instructor.
- If you have any questions or encounter any issues, don't hesitate to ask your instructor or TA for assistance.