Snort 2.8.0 new features: IPv6 and port lists

Snort 2.8.0 comes with new features long desired for the open source intrusion detection system, including IPv6, port lists and packet performance monitoring. Learn about the new IPv6 and port lists that VARs and systems integrators can use to optimize their use of the IDS in this latest edition of the Snort Report.

Snort 2.8.0 was recently published with several features long desired by Snort veterans. These new features include IPv6, port lists, packet performance monitoring and control of actions enabled by preprocessor or decoder events. This edition of the Snort Report provides details on IPv6 and port lists that VARs and systems integrators can use to optimize their use of the open source intrusion detection system.

Begin by downloading Snort 2.8.0. The system I use here runs FreeBSD 6.x.

# cd /usr/local/src
# fetch http://www.snort.org/dl/current/snort-2.8.0.tar.gz
# tar -xzf snort-2.8.0.tar.gz

Next, review the RELEASE.NOTES to find new features and see if any special instructions should be followed. On my system the release notes (once extracted) are located in /usr/local/src/snort-2.8.0/RELEASE.NOTES. It's also a good idea to look at the INSTALL document at /usr/local/src/snort-2.8.0/doc/INSTALL.

After looking at the documentation, install Snort. Notice the new switch to enable IPv6 support.

# mkdir /usr/local/snort-2.8.0
# cd snort-2.8.0
# ./configure --enable-ipv6 --enable-dynamic-plugin
# make
# make install

I suggest making two copies of the snort.conf file. The first can be modified for use by Snort, while the second can serve as a reference point.

# cp etc/snort.conf /usr/local/snort-2.8.0/
# cp etc/snort.conf /usr/local/snort-2.8.0/snort.conf.2.8.0

You also need the following files for Snort to run as an IDS or IPS:

# cp etc/unicode.map /usr/local/snort-2.8.0/
# cp etc/classification.config /usr/local/snort-2.8.0/
# cp etc/reference.config /usr/local/snort-2.8.0/
# cd /usr/local/snort-2.8.0/

After installation, execute the Snort binary with the -V flag.

If you forgot to enable IPv6, you'll see the following.

If you don't see mention of IPv6 and you want to inspect IPv6 traffic, re-run the installation process.

Initial test

A configuration file must be specified to test Snort in IDS mode. I recommend creating a configuration file with a single rule. I use the rule I showed in the first Snort Report, Snort IDS installation basics and tips for security resellers, saved as snortconf.test:

alert icmp any any -> any any (msg:"LOCAL ICMP echo test"; itype:8; sid:2000000;)

With that file ready, test the installation in IDS mode, activated by the -c switch.

Now I can run Snort against a live interface, which I'll ping from another host. Tell Snort to send alerts to the console.

Once this alert fires we kill Snort with ctrl-c.

The most interesting aspect of this traffic for me is seeing the IPv6 protocols. Compare the previous listing with the output from the same test run by Snort

Snort versions prior to 2.8.0 recognize far fewer protocols.

IPv6 in Snort 2.8.0

Let's explore a few ways to use Snort 2.8.0 with IPv6 traffic. Create a new rule file to test IPv6 support:

# cat snortconf.6.test
alert ip fe80::20c:29ff:fe00:c6c2 any -> fe80::20c:29ff:fe60:232a any\
(msg:"LOCAL IPv6 Link Local test"; sid:2000001;)

Here fe80::20c:29ff:fe00:c6c2 is the link local address of the FreeBSD system that will be pinging the listening interface of the Snort sensor. (You don't want your listening interface to be Internet-reachable; it should be completely passive. This is only a test.) The other IPv6 address is fe80::20c:29ff:fe60:232a; it's the link local IPv6 address of the Snort sensor.

The first system pings the second to trigger a Snort alert.

$ ping6 -c 1 fe80::20c:29ff:fe60:232a%lnc0
PING6(56=40+8+8 bytes) fe80::20c:29ff:fe00:c6c2%lnc0
--> fe80::20c:29ff:fe60:232a%lnc0

16 bytes from fe80::20c:29ff:fe60:232a%lnc0,
icmp_seq=0 hlim=64 time=8.838 ms

--- fe80::20c:29ff:fe60:232a%lnc0 ping6 statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/std-dev = 8.838/8.838/8.838/0.000 ms

Snort sees the following, correctly identifying the traffic as ICMPv6:

10/03-16:42:01.184159 [**] [1:2000001:0] LOCAL IPv6 Link Local test [**] [Priority: 0] {IPV6-ICMP} fe80:0000:0000:0000:020c:29ff:fe00:c6c2 -> fe80:0000:0000:0000:020c:29ff:fe60:232a

Looking at an excerpt of the protocol breakdown, notice that ICMPv6 was seen:

You cannot currently specify "alert ipv6" or "alert icmp6" but you can use other modifiers like TCP or UDP with Snort and IPv6. For example, look at these two new rules:

alert tcp fe80::20c:29ff:fe00:c6c2 any -> fe80::20c:29ff:fe60:232a 21\
(msg:"LOCAL IPv6 Link Local TCP test"; sid:2000002;)

alert udp fe80::20c:29ff:fe00:c6c2 any -> fe80::20c:29ff:fe60:232a 53\
(msg:"LOCAL IPv6 Link Local UDP test"; sid:2000003;)

Test them with Netcat and Host.

$ nc -6 fe80::20c:29ff:fe60:232a%lnc0 21
$ host -6 www.google.com fe80::20c:29ff:fe60:232a%lnc0

Snort reports the following:

10/03-16:53:54.915928 [**] [1:2000001:0] LOCAL IPv6 Link Local test [**]
[Priority: 0] {TCP} fe80:0000:0000:0000:020c:29ff:fe00:c6c2:49156 ->

10/03-16:53:57.866035 [**] [1:2000001:0] LOCAL IPv6 Link Local test [**]
[Priority: 0] {UDP} fe80:0000:0000:0000:020c:29ff:fe00:c6c2:55694 ->

This is interesting because the first rule fired but not the specific TCP and UDP rules we just added. If we comment out the IP rule and re-run the tests, we get these results:

10/03-16:55:24.778127 [**] [1:2000001:0] LOCAL IPv6 Link Local test [**]
[Priority: 0] {TCP} fe80:0000:0000:0000:020c:29ff:fe00:c6c2:49157 ->

10/03-16:55:27.196656 [**] [1:2000001:0] LOCAL IPv6 Link Local test [**]
[Priority: 0] {UDP} fe80:0000:0000:0000:020c:29ff:fe00:c6c2:55695 ->

Keep this in mind when writing rules.

Port lists in Snort 2.8.0

One of the most exciting aspects of Snort 2.8.0 is the introduction of support for port lists. Older versions of Snort only accepted individual ports or port ranges when specifying TCP or UDP ports in rules.

For example, the README.variables document shipped with Snort 2.8.0 offers the following, which may appear in your snort.conf configuration file. I've added a line number to each for reference purposes; you should never have line numbers in a real snort.conf file.

1. portvar EXAMPLE1 80

2. var EXAMPLE2_PORT [80:90]

3. var PORT_EXAMPLE2 [1]

4. portvar EXAMPLE3 any

5. portvar EXAMPLE4 [!70:90]

6. portvar EXAMPLE5 [80,91:95,100:200]

The first item to notice is the use of "portvar" in lines 1 and 4-6 and "var" in lines 2 and 3. Snort 2.8.0 users should use portvar from now on, as the use of var will be deprecated in a future version. If you decide to use var, observe that the entire variable name ("EXAMPLE2_PORT" or "PORT_EXAMPLE2") must begin with "PORT_" or end with "_PORT". I recommend using portvar.

Line 1 sets EXAMPLE1 to be port 80. Line 2 sets the range 80-90, inclusive, to EXAMPLE2_PORT. Line 3 sets PORT_EXAMPLE2 to port 1. Line 4 sets EXAMPLE3 to any port. Line 5 sets EXAMPLE4 to any port except those in the range 70-90, inclusive. Line 6 sets EXAMPLE5 to port 80, 91-95 inclusive, and 100-200 inclusive.

README.variables offers the following sample rules, again annotated with numbers for reference only.

1. alert tcp any $EXAMPLE1 -> any $EXAMPLE2_PORT (msg:"Example"; sid:1;)

2. alert tcp any $PORT_EXAMPLE2 -> any any (msg:"Example"; sid:2;)

3. alert tcp any 90 -> any [100:1000,9999:20000] (msg:"Example"; sid:3;)

Rule 1 alerts on TCP traffic from any IP, port 80 to any IP, port 80-90 inclusive. Rule 2 alerts on TCP traffic from any IP, port 1 to any IP, any port. Rule 3 alerts on TCP traffic from any IP, port 90, to any IP, ports 100-1000 inclusive and ports 9999-20000, inclusive.

Trying port lists

The great aspect of port lists is the ability to specify a collection of ports which may host similar services. For example, you may run Web servers on a variety of ports. You want to test a rule that alerts when it sees traffic that isn't sent to one of those ports. Create the following port list variable and rule:

portvar MY_HTTP_PORTS [80,81,82,83,88,8000,8008,8080]
alert tcp any any -> any !$MY_HTTP_PORTS (msg:"Example Not"; sid:4;)

To test this variable and rule, use Netcat:

$ nc -v 8000
nc: connect to port 8000 (tcp) failed: Connection refused

Netcat generates this traffic:

16:52:32.370899 IP >
S 3574479912:3574479912(0) win 65535

16:52:32.370903 IP >
R 0:0(0) ack 3574479913 win 0

Snort reports these alerts:

10/08-16:56:26.358386 [**] [1:4:0] Example Not [**]
[Priority: 0] {TCP} ->

10/08-16:56:26.358527 [**] [1:4:0] Example Not [**]
[Priority: 0] {TCP} ->

That doesn't look right. Why did the first alert fire? You don't want to see traffic to port 8000 TCP, but there was an alert. The second alert fired because the RST ACK was sent to port 50970 TCP, which is not in the port variable list.

Let's try another angle in a new snort.conf.

portvar NOT_MY_HTTP_PORTS [!80,!81,!82,!83,!88,!8000,!8008,!8080]
alert tcp any any -> any $NOT_MY_HTTP_PORTS (msg:"Example Not"; sid:5;)

Again use Netcat to generate traffic.

$ nc -v 8000
nc: connect to port 8000 (tcp) failed: Connection refused

It looks like this:

16:56:11.091099 IP >
S 2235929694:2235929694(0) win 65535

16:56:11.095002 IP >
R 0:0(0) ack 2235929695 win 0

This time, Snort reports only one alert:

10/08-17:00:07.050091 [**] [1:5:0] Example Not [**]
[Priority: 0] {TCP} ->

This is the desired behavior. Snort ignored the SYN packet to port 8000 TCP, but it fired on the return traffic.

I discussed this activity in IRC with Snort creator Marty Roesch. He asked me to report it to Sourcefire, since it might be a logic issue.

This edition of the Snort Report looked at Snort 2.8.0 with IPv6 and port lists. In a future edition I will introduce other features found in the latest Snort release.

About the author
Richard Bejtlich is founder of TaoSecurity, author of several books on network security monitoring, including Extrusion Detection: Security Monitoring for Internal Intrusions, and operator of the TaoSecurity blog.

Dig Deeper on Managed network services technology