Port Scanning Detection
In this article we are going to look at detecting and defending against port scans using the 'PortSentry' utility. The 'PortSentry' utility is capable of detecting stealth scans such as; FIN, NULL, XMAS and many other. The 'PortSentry' utility can also be configured to block hosts either using TCP wrappers or using iptables in this article we will be using TCP Wrappers.
The installation of 'PortSentry' is a little difficult because you will need to compile the source code and edit a certain line within the source code for 'PortSentry' to compile successfully. The first task that you need to do is make sure the development tools have been installed on your SUSE Enterprise Linux Server. This can be done by using the YaST utility which can be run by issuing the yast sw_single command. Once the YaST curses based interface has loaded you will need to select the 'Filter' tab which is located in the top left corner. In the 'Filter' list you will need to select 'Pattens' from there you will need to select the 'C/C++ Compiler and Tools' and install the group.
Once you have installed the 'C/C++ Compiler and Tools' group you will need to download the 'PortSentry' utility  along with its MD5 checksum to check the authenticity of the 'PortSentry' archive . Once you have downloaded both of these files you can issue the md5sum command to check the authenticity of the 'PortSentry' archive as shown in Figure 2.1.
server1:/usr/src # md5sum -c portsentry-1.2.tar.gz.md5
Figure 2.1: Checking authenticity.
Once you have check the authenticity of the 'PortSentry' archive you can begin extracting the archive by issuing the tar command as shown in Figure 2.2. Table 1 explains what each qualifier does that has been supplied with the tar command.
server1:/usr/src # tar zvxf portsentry-1.2.tar.gz
Figure 2.2: Decompressing the 'PortSentry' archive.
||Filter the archive through the gzip utility.
||Verbosely display the files being extracted.
||Extract the files from the archive.
||Use the archive file.
Table 1: tar qualifiers explained.
Once you have decompressed the 'PortSentry' archive you should have a new directory called: 'portsentry_beta/', within this directory you should see a file called: 'portsentry.c' this file needs to be modified in order to compile correctly.
The 'portsentry.c' file has an error on line 1584 which is related to the text being wrapped incorrectly as shown in Figure 2.3. Figure 2.4 shows how the line should look. Figure 2.4 shows how the line should look.
printf ("Copyright 1997-2003 Craig H. Rowland
sourceforget dot net>\n");
Figure 2.3: 'portsentry.c' wrapping error.
printf ("Copyright 1997-2003 Craig H. Rowland \n");
Figure 2.4: Corrected wrapping error.
Once you have corrected the wrapping error you can issue the make linux command which will prepare for the installation and then you will need to issue the make install command to begin the installation as shown in Figure 2.5.
server1:/usr/src/portsentry_beta # make linux
cc -O -Wall -DLINUX -DSUPPORT_STEALTH -o ./portsentry ./portsentry.c \
./portsentry.c: In function ‘PortSentryModeTCP’:
./portsentry.c:1187: warning: pointer targets in passing argument 3 of ‘accept’ differ in signedness
./portsentry.c: In function ‘PortSentryModeUDP’:
./portsentry.c:1384: warning: pointer targets in passing argument 6 of ‘recvfrom’ differ in signedness
server1:/usr/src/portsentry_beta # make install
Creating psionic directory /usr/local/psionic
Setting directory permissions
Creating portsentry directory /usr/local/psionic/portsentry
Setting directory permissions
chmod 700 /usr/local/psionic/portsentry
cp ./portsentry.conf /usr/local/psionic/portsentry
cp ./portsentry.ignore /usr/local/psionic/portsentry
Figure 2.5: Installing 'PortSentry'.
Once 'PortSentry' has been installed successfully you will have a newly created directory called: '/usr/local/psionic/portsentry' which houses the portsentry binary and it's configuration files.
In this section of the article we will look at the 'PortSentry' configuration file. The first two directives that we will look at are 'TCP_PORTS' and 'UDP_PORTS'. These two directives specify what ports 'PortSentry' will listen on, I strongly recommend specifying ports that are not in use but a commonly scanned e.g. Ports 25 and 22 come to mind.
In the 'PortSentry' configuration file by default the hosts are blocked using TCP Wrappers, it is possible to customize the TCP wrappers entry as shown in Figure 3.1.
KILL_HOSTS_DENY="ALL: $TARGET$ : twist /bin/echo %a has been banned from this server for port scanning"
Figure 3.1: Customizing TCP wrappers entry.
The TCP Wrappers entry shown in Figure 3.1 will display a message to the offending host notifying them they have been banned from the server for port scanning. The final directive that we will look at is 'PORT_BANNER', this directive allows you to specify a message that will be displayed to the user when he or she triggers 'PortSentry'.
Once you are happy with your configuration file you can start the 'PortSentry' utility by issuing the portsentry command as shown in Figure 3.2.
||Advanced TCP stealth scan detection.
||Stealth TCP scan detection.
||Advanced "Stealth" UDP scan detection.
||"Stealth" UDP scan detection.
Table 2: 'PortSentry' qualifiers.
Once you have started the 'PortSentry' utility you should have some entires within the /var/log/messages file similar to the messages shown in Figure 3.3.
server1:/usr/local/psionic/portsentry # tail /var/log/messages
Jun 2 09:45:26 server1 portsentry: adminalert: Advanced mode will manually exclude port: 67
Jun 2 09:45:26 server1 portsentry: adminalert: Advanced Stealth scan detection mode activated. Ignored UDP port: 68
Jun 2 09:45:26 server1 portsentry: adminalert: Advanced Stealth scan detection mode activated. Ignored UDP port: 111
Jun 2 09:45:26 server1 portsentry: adminalert: Advanced Stealth scan detection mode activated. Ignored UDP port: 427
Jun 2 09:45:26 server1 portsentry: adminalert: Advanced Stealth scan detection mode activated. Ignored UDP port: 631
Jun 2 09:45:26 server1 portsentry: adminalert: Advanced Stealth scan detection mode activated. Ignored UDP port: 520
Jun 2 09:45:26 server1 portsentry: adminalert: Advanced Stealth scan detection mode activated. Ignored UDP port: 138
Jun 2 09:45:26 server1 portsentry: adminalert: Advanced Stealth scan detection mode activated. Ignored UDP port: 137
Jun 2 09:45:26 server1 portsentry: adminalert: Advanced Stealth scan detection mode activated. Ignored UDP port: 67
Jun 2 09:45:26 server1 portsentry: adminalert: PortSentry is now active and listening.
Figure 3.3: 'PortSentry' log entries.
In this section of the article we will look at performing a stealth scan of the machine running 'PortSentry' using the popular utility nmap. The scan type that we will use is FIN, this type of scan is considered a stealth scan as it does not create any noise so administrators will not find any traces of this type of scan within there log files. Figure 4.1 shows a FIN scan against the host that is running 'PortSentry'.
linux-tz2l:~ # nmap -sF 192.168.2.141
Starting Nmap 4.00 ( http://www.insecure.org/nmap/ ) at 2008-06-02 11:28 BST
Interesting ports on 192.168.2.141:
(The 1666 ports scanned but not shown below are in state: closed)
PORT STATE SERVICE
22/tcp open|filtered ssh
25/tcp open|filtered smtp
111/tcp open|filtered rpcbind
389/tcp open|filtered ldap
427/tcp open|filtered svrloc
631/tcp open|filtered ipp
MAC Address: 00:30:05:47:9A:7A (Fujitsu Siemens Computers)
Nmap finished: 1 IP address (1 host up) scanned in 1.780 seconds
Figure 4.1: Performing a FIN scan against the 'PortSentry' host.
As you can see from Figure 4.1 the results were returned successfully from the FIN scan. However, the host running 'PortSentry' has captured the offending hosts IP address and has added it to the 'hosts.deny' file which is located within the /etc directory as shown in Figure 4.2.
server1:/usr/local/psionic/portsentry # cat /etc/hosts.deny
# See 'man tcpd' and 'man 5 hosts_access' as well as /etc/hosts.allow
# for a detailed description.
http-rman : ALL EXCEPT LOCAL
ALL: 192.168.2.153 : twist /bin/echo %a has been banned from this server for port scanning
Figure 4.2: Checking the 'hosts.deny' file.
Once the offending host has scanned your machine, not only does there IP address get logged but they will not be able to connect to any of your services for example if the attacker tries to connect to the SSH daemon they will be denied access as shown in Figure 4.3.
linux-tz2l:~ # telnet 192.168.2.141 22
Connected to 192.168.2.141.
Escape character is '^]'.
::ffff:192.168.2.153 has been banned from this server for port scanning
Connection closed by foreign host.
Figure 4.3: Trying to connect to the SSH daemon.
In this article we looked at using the 'PortSentry' utility to help detect and defend against port scanning. I strongly recommend deploying 'PortSentry' on highly sensitive systems e.g. Log servers, Web servers etc, I would also recommend reading the documentation that came with the 'PortSentry' archive as it has some useful documents such as: 'README.COMPAT' and 'README.methods'.
Disclaimer: As with everything else at Cool Solutions, this content is definitely not supported by Novell (so don't even think of calling Support if you try something and it blows up).
It was contributed by a community member and is published "as is." It seems to have worked for at least one person, and might work for you. But please be sure to test, test, test before you do anything drastic with it.