Ubuntu comes with iptables, a configuration utility that allows you to manage rules for Netfilter, the Linux Kernel firewall. Using iptables you can manipulate packets as they leave, enter, or are forwarded across network interfaces on a Linux operating system. Today we’ll look at how to block SSH traffic going through an Ubuntu 20.04 system acting as a router.
I have a basic configuration here with three IP subnets – 192.168.0.0/24 where the SSH client lives, 10.0.0.0/30 is a transit network between routers, and 172.16.0.0/24 where the SSH server lives. We will be configuring
Ubuntu20.04-Firewall with iptables to block SSH traffic.
Iptables requires no external package installation with apt-get or otherwise, it comes stock-and-standard with a fresh Ubuntu 20.04 Server or Desktop OS. You can verify the status of your iptables rules like so:
iptables -S -P INPUT ACCEPT -P FORWARD ACCEPT -P OUTPUT ACCEPT
By default, iptables is configured to pretty much do nothing. No packets are filtered and no NAT (network address translation) is configured.
The syntax for iptables can be quite confusing, and since I myself am not configuring them on a daily basis, I always need to reference documentation (or someone else’s blog) for how to configure something specific. It’s a good idea to take a quick look at the basic syntax though. The command structure looks like this, taken straight from the iptables manual page:
iptables [-t table] [mode] [chain] [rulenum] [rule-specification] [options]
tableis which type of table you want to use. Usually it’s filter for dropping disallowed packets, or nat for translating packets. Filter is default if none is specified.
modeis an action, -A (append), -I (insert), -D (delete), -R (replace), -L (list), -P (set policy, is default action) are all valid modes.
chainis the part of the routing process to which your rule applies, there are five chains – PREROUTING, INPUT, FORWARD, OUTPUT, POSTROUTING.
rulenumgives the rule a sequence, rules are applied one-by-one and when there is a match, the corresponding action is taken and all subsequent rules are ignored.
rule-specificationis the actual rule itself. There are many parameters that can be specified here, like protocol, source, destination, etc.
optionsgive you some customization – for example, you can add
-vfor verbose output.
Now that we have a basic idea of what iptables does, let’s drop some SSH packets.
Verifying what we’re blocking
On Ubuntu20.04-Firewall in my topology, I can see that Ubuntu20.04-SSH_Client at 192.168.0.2 has SSH access to Ubuntu20.04-SSH_Server at 172.16.0.2:
james@client$ssh email@example.com firstname.lastname@example.org's password: james@server$
SSH is an network application protocol that usually uses TCP port 22 to establish an encrypted command-line session between two computers. If we do a quick wireshark betwen the Ubuntu20.04-Firewall and CiscoIOSv15.6(1)T-1 router, we can see this SSH traffic traversing the link:
Starting at the top you can see the TCP handshake on port 22 starting with the SYN flag. A few packets later SSHv2 packets begin. All packets use a randomized source TCP port (source is different per session) and a destination TCP port of 22. So we can safely say that in this experiment, if we drop TCP destination port 22, we will effectively block SSH traffic between the client and server.
Configure the iptables rule
A rule to drop SSH packets on TCP 22 can be configured in one line on Ubuntu20.04-Firewall:
iptables -A FORWARD -p tcp --dport 22 -j DROP
-Aspecifies we are appending a rule.
FORWARDapplies the rule to packets being forwarded from one interface to another
-p tcpis a rule-specification to apply the rule to TCP packets
--dport 22applies the rule to destination TCP port 22
-j DROPtells iptables to drop the packet if the previous conditions match
Let’s see if the client can connect now:
james@client$ ssh email@example.com ssh: connect to host 172.16.0.2 port 22: Connection timed out
It worked! Packets on TCP port 22 are being dropped at the Ubuntu firewall.
Please keep in mind – this is a simple block on TCP destination port 22. TCP and UDP ports use the concept of “well-known” which means servers running protocols use a port that everyone “knows”. This is so that someone connecting to a server for the first time with no previous knowledge of its configuration will be able to connect, since they both assume that TCP port 22 is used for SSH. However if someone configures SSH on the client and server in this example to use any other port, it will go right around the filter.
Reach out if you have issues or something to share!