In part 1 of this series, I showed you how to set up and customize a Cowrie honeypot on a Raspberry Pi. In this part, I’ll show how to use iptables to detect nmap scans and attempts to connect to ports other than the honeypot running on port 22.
IPTables is a common Linux firewall tool installed by default on ubuntu and other Debian-based distributions, including Raspbian. It’s available for both ipv4 and ipv6 and is easy to manage via the command line.
There’s a good intro to iptables in the Ubuntu community documentation.
First, you can check what rules you already have in place by running:
$ sudo iptables -L
On a default Raspbian install, you should have no rules, and get something like:
Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination
Iptables organizes rules into chains. The default chains are INPUT, for incoming packets, FORWARD, for packets being forwarded, and OUTPUT for outbound packets. Packets traversing any of the chains work their way down the chain activating each rule it matches until it matches a rule with either an ACCEPT or DROP action, at which point it will either be permitted through the firewall or dropped. Typical conceptual configurations are either “permit all, deny by exception”, for blocking access to certain ports, or “deny all, permit by exception”, for explicitly permitting access to specific ports.
For this network sensor, I took the latter approach (deny all, permit by exception), permitting connections to the honeypot and the real ssh server and denying connections on any other ports, while logging connection attempts and network scans.
The first rule you add should ensure access to the (real) ssh server for management purposes. As configured in part 1 of this series, the actual ssh server isn’t listening on the default port (TCP 22), so to check which port is being used for ssh, grep it out of the sshd config file:
$ grep port /etc/ssh/sshd.conf Port 32232
Now add an iptables rule to ensure the ssh server port remains open at the firewall.
$ sudo iptables -A INPUT -p tcp --dport 32232 -j ACCEPT
Breaking this rule down, it adds a rule to the INPUT chain (-A), that permits tcp packets (-p tcp) coming to port 32232 (–dport 32232) and jumps to ACCEPT (-j ACCEPT).
We should also add a rule to permit established connections to continue (ie, the incoming part of web or ssh connections initiated from our kalipot).
# iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
Again, we’re adding a rule to the INPUT chain (-A INPUT), this time using the ‘state’ module to match packets that are either RELATED or ESTABLISHED (–state RELATED, ESTABLISHED) and jumps to ACCEPT (-j ACCEPT)
Detecting probes of known ports
Next, is to add rules to log connections attempts on specific ports.
$ sudo iptables -A INPUT -p tcp -m limit --limit 5/min -m tcp --dport 22 -j LOG --log-prefix "<IPT> SSH port: "
Here, we’re adding a rule to the input chain, matching packets bound for TCP port 22 (where our honeypot is), using the limit module (-m limit) to limit this rule to matching no more than five times per minute (–limit 5/min) so we don’t fill the log (-j LOG) and start the log entry with “<IPT> SSH port: “ (–log-prefix “<IPT> SSH port:”)
The limit module has some more details to it regarding bursts and recharge rates. A good explanation is here.
We follow this with an ACCEPT rule, because the whole point of running a honeypot is to allow attackers to connect to it. For other ports, we’ll replace this with a DROP rule.
$ sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
So, rules for HTTP (port 80), HTTPS (port 443), SMB (ports 139 and 445) and ADB (Android debugging, port 5555) look like:
$ sudo iptables -A INPUT -p tcp -m limit --limit 5/min -m tcp --dport 80 -j LOG --log-prefix "<IPT> HTTP port: " $ sudo iptables -A INPUT -p tcp --dport 80 -j DROP $ sudo iptables -A INPUT -p tcp -m limit --limit 5/min -m tcp --dport 443 -j LOG --log-prefix "<IPT> HTTPS port: " $ sudo iptables -A INPUT -p tcp --dport 443 -j DROP $ sudo iptables -A INPUT -p tcp -m limit --limit 5/min -m tcp --dport 139 -j LOG --log-prefix "<IPT> SMB port: " $ sudo iptables -A INPUT -p tcp --dport 139 -j DROP $ sudo iptables -A INPUT -p tcp -m limit --limit 5/min -m tcp --dport 445 -j LOG --log-prefix "<IPT> SMB port: " $ sudo iptables -A INPUT -p tcp --dport 445 -j DROP $ sudo iptables -A INPUT -p tcp -m limit --limit 5/min -m tcp --dport 5555 -j LOG --log-prefix "<IPT> ADB port: " $ sudo iptables -A INPUT -p tcp --dport 5555 -j DROP
For each of the specified ports, iptables will log packets destined for those ports, then drop them.
Detecting nmap port scans
I also configured my kalipot to detect and log different types of nmap scans. Nmap allows a user to perform TCP scans with different flags set. From the documentation, this can be used to evade some kinds of non-stateful firewalls or packet filtering routers. Examples include Null scans (no flags set), Xmas scans (three flags set) and FIN scans (only the FIN flag set).
For this, we use the –tcp-flags option, which allows a rule to examine tcp flags.
So, to detect, log, then drop a Xmas scan (so-called because with three flags set it’s lit up like a Christmas tree), the rules are:
$ sudo iptables -A INPUT -p tcp --tcp-flags ALL FIN,PSH,URG -m limit --limit 5/min -j LOG --log-prefix “<IPT> Xmas scan: “ $ sudo iptables -A INPUT -p tcp --tcp-flags ALL FIN,PSH,URG -j DROP
The “–tcp-flags ALL FIN,PSH,URG” section of the rule specifies that iptables should examine all tcp flags (SYN,ACK,FIN,RST,URG,PSH) and match if the FIN, PSH and URG flags are set. For a null scan, it would be “–tcp-flags ALL NONE” while for a FIN scan it would be “–tcp-flags ALL FIN”. You should can also add rules to detect SYN and ACK scans (using ALL SYN and ALL ACK, respectively_.
For completeness’ sake, we add a default deny rule to drop any packets that haven’t matched any rules thus far.
$ sudo iptables -A INPUT -p tcp -j DROP
Once all the rules are in place, we can check the rules by running
$ sudo iptables -L
Now we can save the rules with:
$ sudo /sbin/iptables-save > /etc/iptables.up.rules
You can restore the rules manually with:
$ sudo /sbin/iptables-restore < /etc/iptables.up.rules
Something to be aware of is that rules added with the iptables command only works for ipv4. Thankfully, the rules format is the same for ipv6, just the command changes.
$ sudo /sbin/ip6tables-restore < /etc/iptables.up.rules
To make the rules come up automatically when you bring your network up, you need to add a script to your networking configuration files:
$ sudo vi /etc/network/if-pre-up.d/iptables
#!/bin/sh /sbin/iptables-restore < /etc/iptables.up.rules /sbin/ip6tables-restore < /etc/iptables.up.rules
From another machine, run an nmap scan against your kalipot:
If everything is configured correctly, this should produce the following in /var/log/syslog on your kalipot:
Back on our scanning host, everything but our SSH port is listed as closed: the kalipot’s iptables firewall is dropping all packets. There is one small problem, though. The MAC address is reporting as a Raspberry Pi. That’s no good. That identification is based on the MAC address. The first three octets of the address are the OUI: the Organizationally Unique Identifier. OUIs are assigned to vendors, manufacturers, or other organizations. In this case B8:27:EB is assigned to the Raspberry Pi foundation, which is how nmap was able to identify the kalipot as being on a Pi. MAC addresses can be spoofed, though. On a Pi running Raspbian Stretch (cat /etc/os-release), you can use systemd to change the MAC at boot. Add the following to /etc/systemd/network/00-mac.link
[Match] OriginalName=wlan0 [Link] MACAddress=xx:xx:xx:xx:xx:xx NamePolicy=kernel database onboard slot path
Reboot the pi, and, assuming you’re running DHCP, it’ll likely have a new IP address, as your DHCP server will see it as a new device. Scan it again, and check out the results:
Part three of this series will show how to set up the kalipot to forward data to Splunk via HTTPS and syslog.