Snort on OpenWrt: Guarding the SOHO perimeter

4440

Author: Joe Barr

If you’re edgy about security for your SOHO LAN, you might want to consider moving your first line of defense out past your firewall. How about on your router, for example? If your router runs OpenWrt, you can do exactly that, by running Snort, the open source intrusion detection system (IDS) project that has become the most widely deployed IDS in the world. Throw in the firewall that comes out of the box with OpenWrt White Russian, and suddenly the perimeter seems a lot more secure.

Nicholas Thill — known as Nico in the OpenWrt community — maintains three separate packages for Snort in his repository of packages. They include a plain Jane version, without any support for logging to a database, and two database-specific packages: one for MySQL and one for PostgreSQL. All are based on the Snort release 2.3.3-1 and are considered to be in a testing state and not yet included in the official release.

For the sake of simplicity, I’ll discuss the plain Jane installation in this article. Regardless of which version you select, you need to be aware of the fact that you can overload and/or potentially crash your OpenWrt router by running Snort wide-open with all its rule sets and preprocessors (rule sets look for specific signatures, while preprocessors are plugin modules that extend Snort’s capabilities), or simply by logging Snort’s output to the local system and filling up all available space.

OpenWrt is a wonderful distribution, but it often runs on systems with serious memory and/or storage constraints, which you can easily overload by running Snort with all the trimmings.

Syslog remotely

Snort reports its findings in log records, so running Snort without saving them for later analysis is like typing a book without putting paper in the typewriter: you go through a lot of motions but don’t get much of a return for your efforts. Given the typical router’s constraints both in processing power and storage space, it makes sense to log Snort’s findings remotely.

In order to start syslog logging remotely, you’ll need to make changes to your configuration both on the router and on the system where the logging will be done. It’s a snap to set up remote logging on OpenWrt, as explained in this Mini-HOWTO on the OpenWrt wiki.

From the OpenWrt command line, enter the following:

nvram set log_ipaddr=<192.168.1.101>
nvram commit

Change the IP address to match the address of the system running syslogd. Then edit /etc/initab and add these two lines:

::respawn:/sbin/syslogd -n
::respawn:/sbin/klogd -n

And finally, edit /etc/init.d/rcS to add:

mkdir /var/log

To handle the logging on the remote side of the connection, add the -r option to the command line that starts syslogd and you’re good to go. If you’re using Ubuntu, for example, edit /etc/init.d/sysklogd and change the line that reads:

SYSLOGD="-u syslog"

to read:

SYSLOGD="-r -u syslog"

Of course, if you’re like me and think that syslogd is so last generation, you can install syslog-ng instead, which accepts remote logging by default.

Installing and Configuring Snort

The easiest way to install the version of Snort is with the OpenWrt Admin Console. But before you do that, check /etc/ikpg.conf on the router and make sure the repository mentioned above is included as a source. If it’s not, add this line to the file:


src nico-t http://nthill.free.fr/openwrt/ipkg/testing

Then click on System and Installed Software in the OpenWrt Admin Console and refresh the list of available packages by clicking on Update package lists. All that’s left to do then is scroll down the list of packages, find the version of Snort you want, and click on Install next to it.

Before you configure Snort, you’ll need to get some rules from the Snort site. Snort rules define the packets that Snort should identify and take action on, and the actions that should be taken.

Rather than downloading only the rules included in the default OpenWrt snort.conf file, I downloaded a full set and put them in /etc/snort/rules. That way, I don’t have to get new rule sets each time I tweak snort.conf.

You’ll need to define the HOME_NET variable near the top of /etc/snort/snort.conf, and also define an output method near the bottom. Once you’ve done those two things, Snort should be ready to run, except for whatever tweaking you need to do for preprocessors and rules.

The pre-configured version of snort.conf, for example, comes with almost all the preprocessors commented out. To activate them, simply remove the # signs from the beginning of each line of the section for the preprocessor you want. The same thing is true for the rules. Note: Remember to keep an eye on memory usage as you activate preprocessors and rule sets.

My HOME_NET in snort.conf already looked like this, so I kept it:

var HOME_NET 192.168.1.0/24

For the output option, I removed the # from this line:

# output alert_syslog: LOG_AUTH LOG_ALERT

Those two changes made, I started snort running by entering snort -i vlan1 & and it blasted off, producing the following on my OpenWrt console:

root@OpenWrt:~# Running in IDS mode with inferred config file: /etc/snort/snort.conf

Initializing Network Interface vlan1

        --== Initializing Snort ==--
Initializing Output Plugins!
Decoding Ethernet on interface vlan1
Initializing Preprocessors!
Initializing Plug-ins!
Parsing Rules file /etc/snort/snort.conf

+++++++++++++++++++++++++++++++++++++++++++++++++++
Initializing rule chains...
,-----------[Flow Config]----------------------
| Stats Interval:  0
| Hash Method:     2
| Memcap:          10485760
| Rows  :          4099
| Overhead Bytes:  16400(%0.16)
`----------------------------------------------
No arguments to frag2 directive, setting defaults to:
    Fragment timeout: 60 seconds
    Fragment memory cap: 4194304 bytes
    Fragment min_ttl:   0
    Fragment ttl_limit: 5
    Fragment Problems: 0
    Self preservation threshold: 500
    Self preservation period: 90
    Suspend threshold: 1000
    Suspend period: 30
Stream4 config:
    Stateful inspection: ACTIVE
    Session statistics: INACTIVE
    Session timeout: 30 seconds
    Session memory cap: 8388608 bytes
    State alerts: INACTIVE
    Evasion alerts: INACTIVE
    Scan alerts: INACTIVE
    Log Flushed Streams: INACTIVE
    MinTTL: 1
    TTL Limit: 5
    Async Link: 0
    State Protection: 0
    Self preservation threshold: 50
    Self preservation period: 90
    Suspend threshold: 200
    Suspend period: 30
    Enforce TCP State: INACTIVE
    Midstream Drop Alerts: INACTIVE

Stream4_reassemble config:
    Server reassembly: INACTIVE
    Client reassembly: ACTIVE
    Reassembler alerts: ACTIVE
    Zero out flushed packets: INACTIVE
    flush_data_diff_size: 500
    Ports: 21 23 25 53 80 110 111 143 513 1433
    Emergency Ports: 21 23 25 53 80 110 111 143 513 1433
X-Link2State Config:
    Ports: 25 691
112 Snort rules read...
112 Option Chains linked into 57 Chain Headers
0 Dynamic rules
+++++++++++++++++++++++++++++++++++++++++++++++++++

Warning: flowbits key 'tls1.client_hello.request' is checked but not ever set.
Warning: flowbits key 'sslv3.client_hello.request' is checked but not ever set.

+-----------------------[thresholding-config]----------------------------------
| memory-cap : 1048576 bytes
+-----------------------[thresholding-global]----------------------------------
| none
+-----------------------[thresholding-local]-----------------------------------
| none
+-----------------------[suppression]------------------------------------------
| none
+------------------------------------------------------------------------------
Rule application order: ->activation->dynamic->alert->pass->log
Log directory = /var/log/snort

        --== Initialization Complete ==--

   ,,_     -*> Snort! <*-
  o"  )~   Version 2.3.3 (Build 14)
   ''''    By Martin Roesch & The Snort Team: http://www.snort.org/team.html
           (C) Copyright 1998-2004 Sourcefire Inc., et al.

To make sure Snort was logging to the remote machine, I checked the syslog there and found these two new entries in /var/log/syslog:

Mar  2 15:40:44 192.168.1.1 kernel: vlan1: dev_set_promiscuity(master, 1)
Mar  2 15:40:44 192.168.1.1 kernel: device vlan1 entered promiscuous mode

Before making any big changes to the rules or preprocessors, I wanted to have baseline measurement of how much system resources Snort was eating in terms of memory and CPU, so I asked top. Top said:

Mem: 18420K used, 12164K free, 0K shrd, 896K buff, 4664K cached
Load average: 1.00, 1.01, 0.76    (State: S=sleeping R=running, W=waiting)

  PID USER     STATUS   RSS  PPID %CPU %MEM COMMAND
  571 root     R        436     1 98.4  1.4 vi
  899 root     R        412   561  0.7  1.3 top
  898 root     S       7916   561  0.3 25.8 snort
  560 root     S        640   537  0.3  2.0 dropbear
  890 root     S        640   537  0.0  2.0 dropbear
  561 root     S        464   560  0.0  1.5 ash
  891 root     S        460   890  0.0  1.5 ash
  530 nobody   S        436     1  0.0  1.4 dnsmasq
   49 root     S        428     1  0.0  1.3 syslogd
  537 root     S        420     1  0.0  1.3 dropbear
  379 root     S        400     1  0.0  1.3 udhcpc
    1 root     S        392     0  0.0  1.2 init
   55 root     S        392     1  0.0  1.2 init
  541 root     S        388     1  0.0  1.2 httpd
   50 root     S        340     1  0.0  1.1 klogd
  542 root     S        300     1  0.0  0.9 telnetd
    3 root     SWN        0     1  0.0  0.0 ksoftirqd_CPU0
    7 root     SW         0     1  0.0  0.0 mtdblockd
    6 root     SW         0     1  0.0  0.0 kupdated
    4 root     SW         0     1  0.0  0.0 kswapd
   32 root     SWN        0     1  0.0  0.0 jffs2_gcd_mtd4
    5 root     SW         0     1  0.0  0.0 bdflush
    2 root     SW         0     1  0.0  0.0 keventd

Right out of the box, and with only minimal rules in place, Snort was eating 25% of system memory. I added rules and preprocessors, primarily for the detection of scans, but I’ve tried to avoid taking more than 50% of memory or to have less than 1000K free memory. So far, so good, and with no impact on performance of the router. But remember, you can overload the router if you’re not careful, so keep a watchful eye on available resources as you tweak the config.

After I enabled the scan detection preprocessors and added a couple of additional rule sets, Snort’s memory consumption climbed to 49.3% and the amount of free memory had shrunk to just over 5000K. I decided to stop there.

You might consider installing the plain Jane version first, then moving to one of the database-specific versions if you like. But if you do, remember that changing versions requires more than simply changing your snort.conf to indicate the database: you have to remove the plain Jane version of Snort and then install the database version. That process will replace your snort.conf, so if you want to keep your old one, make a copy before you install the new version of Snort.

For further information about Snort on OpenWrt, see this report by David Schwartzburg.

Category:

  • Security