Detecting Port Scans and Talkative Hosts

Table of contents:


How do I detect when hosts on my network(s) are performing port scans and host scans?


There are actually a couple of answers to that question. This is because Snort developers have gone through several iterations of port scan detectors. The most common is the portscan preprocessor, while the newest is the flow-portscan preprocessor. Finally, portscan2 was supposed to address some of the problems with the portscan preprocessor, such as detection of SYN floods as port scans instead of DoS attacks. All these preprocessors are still compiled into Snort by default, even as late as Version 2.2.0. However, the trend is toward the flow-portscan preprocessor, as this is the first preprocessor to use the flow engine for its data. This section gives some example configurations for all three. The most effort is on the flow-portscan preprocessor, as the other two are no longer part of the default snort.conf file.


This is the oldest and most commonly used of the three preprocessors. However, if you are using ACID (Chapter 5), you might want to pull some port scan information into ACID with little changes. To enable this in your snort.conf file, simply enter this example into the file right below the flow preprocessor.

Preprocessor flow: stats_interval 0 hash 2 


# Legacy Support - Porscan Preprocessor from snort 1.x 

preprocessor portscan: $HOME_NET 4 3 /path/to/logs/portscan.log

When enabled, this preprocessor detects when a source host other than the one in the HOME_NET variable starts more that four port connections within three seconds. When that happens, two events are written: one in the Snort alert file, and the other in the portscan.log file. The alert file notifies the analysts of a possible port scan against one of their resources.

[**] [100:2:1] spp_portscan: portscan status from 1150 

connections across 1 hosts: TCP(1150), UDP(0) [**]

The portscan.log file displays the ports targeted and their respective source port(s), as in the next example:

# quick display of an nmap scan (nmap -sT -F

Aug 29 03:05:48 -> SYN ******S*

Aug 29 03:05:48 -> SYN ******S*

Aug 29 03:05:48 -> SYN ******S*

Aug 29 03:05:48 -> SYN ******S*

Aug 29 03:05:48 -> SYN ******S*

Aug 29 03:05:48 -> SYN ******S*

Aug 29 03:05:48 -> SYN ******S*

Aug 29 03:05:48 -> SYN ******S*

Aug 29 03:05:48 -> SYN ******S*

Aug 29 03:05:48 -> SYN ******S*

One concern of this preprocessor was how to blanket ignore hosts such as your DNS servers that often appeared as portscan attackers. The solution came in the form of another component of the portscan preprocessor: portscan-ignorehosts. This component simply tells the portscan preprocessor to not alert on any traffic from the host(s) and/or network(s) in a given list. An example of that is as follows; more than one entry into this list is space separated.

# Goes in snort.conf file below "preprocessor portscan" line 

Preprocessor portscan-ignorehosts:

This example filters out any port scans coming from either the DNS or web server.


As we mentioned, the portscan preprocessor had some limitations that another group of Snort developers tried to remedy with a rewrite and some added functionality. The portscan2 preprocessor relies on the old conversation tracking preprocessor and can't be enabled when the flow preprocessor is active. Following is an example of a typical conversation and portscan2 configuration.

# First Disable the flow preprocessor 

# preprocessor flow: stats_interval 0 hash 2


# Enable the conversation preprocessor 

preprocessor conversation: allowed_ip_protocols all, timeout 60, 

max_conversations 50000 

# the arguments are:

# allowed IP protocols, either a list of protocol numbers or word "all"

# timeout (seconds) before connections or conversations are rolled 

# out of the preprocessor 

#the max number of conversations that the preprocessor should see 


# Enable the portscan2 preprocessor 

preprocessor portscan2: scanners_max 256, targets_max 256, 

target_limit 3, port_limit 10, timeout 60

# arguments are:

# the max number of scanning hosts to support at once

# the max number of target hosts to support at once

# the number of hosts a scanner must touch before a scan is triggered

# number of ports a scanner must touch before a scan is triggered

# the timeout period (seconds) before a scanners activity is rolled

# out of the preprocessor

When this is enabled, a scan would look like this in your alert file:

[**] [117:1:1] (spp_portscan2) Portscan detected from 

1 targets 11 ports in 0 seconds [**]

08/xx-13:27:32.464097 ->

Tcp TTL:64 TOS:0x0 ID:11424 IpLen:20 DgmLen:60 DF

******S* Seq: 0xEA6B7F8E Ack: 0x0 Win: 0x16D0 TcpLen: 40

TCP Options (5) => MSS: 1460 SackOK TS: 83186478 0 NOP WS: 0

The type of data logged into the default file scan.log in your Snort log directory is much more detailed:

08/xx-13:27:32.464097 TCP src: dst: sport: 3537 

dport: 5232 tgts: 1 ports: 11 flags: ******S* event_id: 0

08/xx-13:27:32.464177 TCP src: dst: sport: 3538 

dport: 5002 tgts: 1 ports: 12 flags: ******S* event_id: 7

08/xx-13:27:32.464256 TCP src: dst: sport: 3539 

dport: 780 tgts: 1 ports: 13 flags: ******S* event_id: 7

08/xx-13:27:32.465642 TCP src: dst: sport: 3540 

dport: 1484 tgts: 1 ports: 14 flags: ******S* event_id: 7

08/xx-13:27:32.465722 TCP src: dst: sport: 3541 

dport: 2002 tgts: 1 ports: 15 flags: ******S* event_id: 7

08/xx-13:27:32.465802 TCP src: dst: sport: 3542 

dport: 214 tgts: 1 ports: 16 flags: ******S* event_id: 7

From this logfile you can immediately determine several facts about this scan:

  • This is a TCP Syn scan, the ******S* is the snort flagging for Syn only packets.
  • The source port is going up and changing every connection, possibly from a tool such as nmap.
  • How many ports per hit our victim was taking from the "ports" tag.


This is the newest preprocessor to detect port scans. This preprocessor is the first to take advantage of the flow preprocessor data. While that is the case, this preprocessor remains one of the hardest preprocessors for people to configure and use.

# for a single IP cable/DSL connection detection config 

# The would be useful for a network that doesn't server many or any services to

# the outside world. 


Note that talkers are hosts that are active on your network such as your workstations for browsing the Web, file sharing, etc. Scanners are hosts that have started communicating with one of your hosts within the learning time of the host over a previously unused port.

preprocessor flow-portscan: 

# the IP space to use for our allowed/learned network(s)

server-watchnet [] 

# The number of seconds to keep port information on your watchnet for example this

# will keep the ports in use on each host for a 1-minute interval before refreshing 

server-learning-time 60 

# the number of requests a port on a host in the watchnet must see before 

# it's treated as a talker rather than a scanner 

server-scanner-limit 50 

# If you have hosts or networks that you want to ignore and not 

# count into the learning time place here

# src-ignore-net [] 

# If you have destination networks or hosts that you want to ignore

# such as your DNS server or POP mail server place here

# dst-ignore-net [] 

# This sets how the alarms will be sent out. The default setting is 

# display the alerts "once" per scan. However, in this case we are going 

# to alarm every time the points go above the threshold.

alert-mode all 

# The tells the preprocessor to send the alarm out in a text message 

# mode as seen below. However, if you want there is "pktkludge" option

# that you can use as well to send to the snort logging system. 

output-mode msg 

# This turns on detection much like the stream4 preprocessor for invalid

# or odd tcp flows. Such as a SYN/FIN flagged flow. 

tcp-penalties on

These settings log something like the following in the alert file. This correctly identifies the nmap hostin this case, However, you don't see what ports it's been probing or the targets.

[**] [121:2:1] Portscan detected from Talker(fixed: 1 sliding: 1) 

Scanner(fixed: 10 sliding: 40) [**] 08/xx-14:29:14.676834

[**] [121:1:1] Portscan detected from Talker(fixed: 1 sliding: 1) 

Scanner(fixed: 15 sliding: 5) [**] 08/xx-14:29:14.676904

[**] [121:1:1] Portscan detected from Talker(fixed: 1 sliding: 1) 

Scanner(fixed: 15 sliding: 20) [**] 08/xx-14:29:14.677102

For monitoring a larger network, you might try the following configuration example:

preprocessor flow-portscan: 

# Network to monitor

server-watchnet [,] 

# Ignore traffic coming from the routers

#src-ignore-net [,] 

# Ignore traffic going for the DNS servers 

#dst-ignore-net [,] 

# the number of requests to a single port such as 80/tcp that a hosts

# in the watchnet must recieve before the port is ignored for portscans

#server-ignore-limit 200 

# Time (seconds) to keep there watchnet servers ports before resetting

server-learning-time 3600 

# the number of requests a port on a host in the watchnet must see before 

# it's treated as a talker rather than a scanner 

server-scanner-limit 50 

# sets the alert mode to alarm on every event over the threshold

alert-mode all 

# Sends a text message to the alert file 

output-mode msg 

# alarm on odd flow tcp flag settings 

tcp-penalties on 

# Used for debugging to dump the contents of all of the flow-portscan

# 3 "tables" of data to the screen on snort exit. Set to 0 to disable.

Dumpall 1



As you might have seen, the portscan preprocessor is still useful when detecting port scans from the flow preprocessor. This, combined with the fact that it's one of the simplest preprocessors to set up, makes it a viable preprocessor, especially if you are using a Snort frontend such as ACID (Chapter 5).

However, the portscan2 preprocessor takes quite a bit of memory and requires disabling and reenabling preprocessors. The worst of these is disabling the flow preprocessor. This causes problems even with the Snort rules engine, as quite a few of the new rules use the flow keyword in their detection patterns. The other concern about this preprocessor is the requirement of the conversation preprocessor, which flow was built to replace. The conversation preprocessor didn't handle state very well. However, one useful keyword that the conversation preprocessor had was alert_odd_protocols. The following conversation preprocessor configuration detects when protocols other than TCP, UDP, or ICMP are in use on your network.

Preprocessor conversation: preprocessor conversation: 

allowed_ip_protocols, 1 6 17,timeout 60, max_conversations 50000,  


Finally, with the new flow-portscan preprocessor, we used a small network and larger network configuration example that should at least get you started on detecting port scans on your network(s). However, the flow-portscan can be tweaked for your network. If you want data from the preprocessor's output, you can apply a patch to Snort to get more data back.

You can change from a port scan log entry like this:

[**] [121:3:1] Portscan detected from Talker(fixed: 15 sliding: 

15) Scanner(fixed: 0 sliding: 0) [**] 08/xx-15:38:21.619113

To a more detailed log like this:

[**] [121:3:1] (flow_ps) Portscan detected from Talker(fixed: 

15 sliding: 15) Scanner(fixed: 0 sliding: 0) [**]

08/xx-16:10:08.174184 ->

TCP TTL:41 TOS:0x0 ID:16080 IpLen:20 DgmLen:40

***A**** Seq: 0xFB200EDB Ack: 0x8FFD88F7 Win: 0x800 TcpLen: 20

If you want to enable this type of logging, just follow these directions to patch and remake your Snort build.

# copy this code into your system 

# create file "flow-portscan_output.patch"


diff -urN snort-2.2.0_orig/src/generators.h snort-2.2.0/src/generators.h

--- snort-2.2.0_orig/src/generators.h 2003-10-20 15:03:19.000000000 +0000

+++ snort-2.2.0/src/generators.h 2004-05-22 23:01:52.000000000 +0000

@@ -316,6 +316,7 @@

 #define DECODE_BAD_TRHMR_STR "(snort_decoder) WARNING: Bad Token Ring MR Header!"



+#define FLOWPS_PREFIX_STR "(flow_ps) Portscan detected from "

 #define SCAN2_PREFIX_STR "(spp_portscan2) Portscan detected from "


 #define CONV_BAD_IP_PROTOCOL_STR "(spp_conversation) Bad IP protocol!"

diff -urN snort-2.2.0_orig/src/preprocessors/flow/portscan/flowps_snort.c 


--- snort-2.2.0_orig/src/preprocessors/flow/portscan/flowps_snort.c 2004-03-31 

18:09:47.000000000 +0000

+++ snort-2.2.0/src/preprocessors/flow/portscan/flowps_snort.c 2004-05-22 

23:04:00.000000000 +0000

@@ -811,6 +811,8 @@

 char buf[1024 + 1];

 u_int32_t event_id;

 u_int32_t event_type; /* the sid for the gid */

+ Event event;


 /* Assign an event type to the display


 if(sep->flags & ALERT_FIXED_SCANNER)

@@ -837,18 +839,21 @@





+ inet_ntoa(*(struct in_addr *) address), "logged using pktkludge."););

 /* log a packet to the output system */

 p = flowps_mkpacket(sep, orig_packet, address, cur);


- snprintf(buf, 1024,

- "Portscan detected from %s Talker(fixed: %u sliding: %u) 

Scanner(fixed: %u sliding: %u)",

+ snprintf(buf, 1024, FLOWPS_PREFIX_STR

+ "%s Talker(fixed: %u sliding: %u) Scanner(fixed: %u sliding: %u)",

 inet_ntoa(*(struct in_addr *) address),

 sep->fixed_talker.score, sep->sliding_talker.score,

 sep->fixed_scanner.score, sep->sliding_scanner.score);

 buf[1024] = '';


- /* p is NULL w/ the VARIABLEMSG fmt */

event_id = GenerateSnortEvent(p,

", buf););


+ event_id = GenerateSnortEvent(orig_packet,

 GENERATOR_FLOW_PORTSCAN,event_type, 1,/* revision */


Once you have this patch in place, patch your Snort code placing this patch file in the same directory where you extracted Snort.

patch -p0 < flow-portscan_output.patch

Check for errors, and then make Snort with your options.


Rerun Snort and run a scan to see the new output format!

An explanation of the how the flow-portscan preprocessor works might prove helpful in understanding how it detects and scores traffic.

First, the preprocessor has three main parts: scoreboards, a uniqueness tracker, and the server statistics tracker. The scoreboardsone for talkers and one for scannerskeep information about each IP address that's come through the preprocessor and the points/scores associated with each IP since Snort started. The uniqueness tracker determines if a flow is new. If the source/destination IP, destination port, or the IP protocol changes, the flow is marked as new and passed to the server statistics tracker for scoring. The server statistics determines each flow's score and place as either talker or scanner.

The server-learning-time setting determines how unique a connection is. For example, with a small network or SOHO connection, if you set the learning time to one minute, this will help detect port scans by making most connections new to the preprocessor. This keeps the port scans that are typically fast and hard when coming through networks very noticeable. If you were on a large network, you might want to adjust that learning time to an hour (3,600 seconds). This allows for dynamic port allocation on such things as file servers to keep them from appearing as scanners.

You might also adjust the server-ignore-limit to a high enough number that your real servers never hit the limit unless under attack/scan. The fine line to dance is how to set your server-scanner-limit low enough to have a scan marked as a scan without hitting the high limit of server-ignore-limit. For example, following are two suggestions, one for small networks and one for high-traffic networks.

# small networks - low traffic and not to many servers/services

Add scanner points to a flow/IP when the number of ports in use is more than 1 and less than 500 within the learning time when the connection is destined for a host in the watchnet.

server-scanner-limit 1 

server-ignore-limit 500 


# larger networks - high traffc high volume of services/servers

Add scanner points to a flow/IP when the number of ports in use is more than 5 and less than 5,000 within the learning time when the connection is destined for a host in the watchnet

server-scanner-limit 5 

server-ignore-limit 5000

If you are still having trouble with the flow-portscan preprocessor, you can always use the dumpall keyword. Setting it to 1 enables it and 0 disables it. This keyword, when enabled, dumps the contents of all three tables to the screen: server, uniqueness, and scoreboards. Using the techniques covered in this section, you could record the information from the screen to a file. If you are having trouble seeing port scans in the Snort logfile, this might help show where your scanning host is getting scored. It also might help show how effective your current configuration is.

See Also

Snort-devel mailing list

Getting Performance Metrics

Installing Snort from Source on Unix

Logging to a File Quickly

How to Build Rules

Detecting Stateless Attacks and Stream Reassembly

Managing Snort Sensors

Generating Statistical Output from Snort Logs

Monitoring Network Performance


Snort Cookbook
Snort Cookbook
ISBN: 0596007914
EAN: 2147483647
Year: 2006
Pages: 167

Similar book on Amazon © 2008-2017.
If you may any questions please contact us: