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-restore. The tutorial will not worry about saving rulesets.
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
chains. There are three main tables:
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:
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
-LList all rules
-FFlush (erase) all rules
-P <chain> <target>Set the default action for a packet when no rule matches; default is
ACCEPT, better practice is to allow all valid packets and set the policy to
-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
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 --state RELATED,ESTABLISHEDMatch packets that are part of an ongoing connection
-m state --state NEWMatch packets that are trying to establish a new connection
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 ACCEPTAccept / Allow a given packet
-j REJECTReject a packet with a negative response
-j DROPDrop packet on the floor - reject with no response
-j DNATChange the destination address (port forwarding)
-j MASQUERADEChange the source address / ip masquerade
Things to Try
If you have your own VM with root access, try setting up a firewall with these commands. This will help in getting famililar with writing firewall rules. Everyone should do the classwork section though- that is the part that will be taken for a grade.
To start, try setting up your machine to only allow connections to a local netcat server with the following options, and run nmap against your machine.
Establish a netcat server with the following:
nc -l -p 2500
Ensure that your iptables rules are cleared out:
Make sure not to block your own ssh traffic:
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
INPUT policy to drop all inbound packets:
iptables -P INPUT DROP
Notice that this will prevent you from connecting outbound. (Try downloading a webpage.) 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.
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
Now you should be able to visit websites, etc, but nobody externally will be able to initiate a connection to your netcat server. You can try to connect to your own machine with
nc localhost 2500.
To allow connections to your server, add another rule to allow SYN packets with a destination port of 2500.
iptables -A INPUT -p tcp -m state --state NEW --dport 2500 -j ACCEPT
Other rules to experiment with are those such as the following, which port forwards port 2500 to another address:
iptables -A FORWARD -d <destinationip> -p tcp --dport 2500 -j ACCEPT iptables -A PREROUTING -p tcp --dport 2500 -j DNAT --to-destination <destinationip>:2500
Complete the following tasks and check out with TAs.
For this part of the assignment, you will configure a firewall. Your rules will be in the format of iptables command-line switches, in the order that you want them to be applied.
Put your rules in iptables.rules. There is one sample rule to demonstrate the format, which simply drops all inbound packets (cutting off all communication.)
Your firewall must do the following:
- Allow inbound communication to ports 6407, 3506, 2503, and 8505
- Allow inbound communication that is established or related
- Disallow any other inbound connections
- Allow all outbound traffic
For the second part of the assignment, you will write snort rules to detect the fictional Simple Worm.
Your rules should do the following:
- Protect against the worm, which is known to listen on UDP port 4004 or TCP port 8008 with signature "03 0E FE CC A0"
- Display the alert "TCP Simple Worm detected!" or "UDP Simple Worm detected!", whichever is appropriate, upon detection
This link contains all you need to know about Snort.
Deploy part A and part B on your own linux VM, test the rules and show the results to instructors. If you have a Linux VM, you need two additional steps to configure:
- Install snort;
- Confgure network setting to ensure the host and VM can communicate with each other (i.e., can ping each other).
If you would like to install a new VM for this lab, we prepare one based on Kali Linux, which is the most popular Ethical hacking linux distribution and comes with a bunch of hacking tools installed. Here are the steps to install this configured VM (of course, you can download and install the latest Kali VM version and configure iit by yourself.).
- Install VirtualBox 5.4. on your laptop.
- Create a Host-only network: Preferences -> Network -> Host-only Networks -> Add host-only network.
- Copy the image from the following path on hamsa to your laptop: /home/shared/firewall-lab-vm-kali-64bit.ova
- Double clikc the file to install the VM.
- Disable USB 2.0 Controller in the VM settings.
- Start and login the VM with the folllowing credential: username: root password: toor
- Make sure your host and the VM can communicate with each other. If not, select the network as Host-only mode.
- Work on the lab in VM and additional notes are availablein /root/firewalls/ folder.
- Test the your rules by making connections from your host machine (using netcat or telnet) to the VM.