Suricata 2.0beta2 as IPS on Ubuntu 12.04
I've been running Suricata in IDS mode through Security Onion on and off for several years, but I never tried Suricata as an IPS.
I decided I wanted to run Suricata as a bridging IPS, such that it did not route traffic. In other words, I could place a Suricata IPS between, say, a router and a firewall, or between a router and a host, and neither endpoint would know the IPS was present.
Looking at available documentation across the Web, I did not see specific mention of this exact configuration. It's entirely possible I missed something useful, but most people running Linux as a bridge weren't using Suricata.
Those running Linux as a bridge sometimes enabled an IP address for the bridge, which is something I didn't want to do. (True bridges should be invisible to endpoints.)
Of course, to administer the bridge system itself, you ensure the box has a third interface and you assign that interface a management IP address.
I also noticed those using Suricata as an IPS tended to configure it as a router, giving IP addresses to the internal and external IP addresses. I wanted an invisible bridge, not a router.
The hardware I used for the bridge was a 2003-era Shuttle small form factor system with 512 MB RAM, two NICs (eth0 and eth1), and a wireless NIC (wlan0). I installed Ubuntu Server 12.04.3 LTS. I tried installing the 64 bit version but realized the box was too old for 64 bit. Once I tried a 32 bit installation I was working in no time.
The first step I took was to create the bridge. I wanted to deploy the system between a router and an endpoint with IP address 192.168.2.142, like this:
router <-> eth0/Linux bridge/eth1 <-> 192.168.2.142
These are the commands to create the bridge. This how-to was useful.
$ sudo apt-get install bridge-utils $ sudo brctl addbr br0 $ sudo brctl addif br0 eth0 $ sudo brctl addif br0 eth1 $ sudo ifconfig eth0 0.0.0.0 $ sudo ifconfig eth1 0.0.0.0 $ sudo ifconfig br0 up
With the bridge working, I could reach 192.168.2.142, the endpoint host, through the Ubuntu Linux bridge system. If I wanted to, I could watch traffic with Tcpdump on br0, eth0, or eth1.
Next I needed to install Suricata. I decided to use the beta packages published by OISF as described here. I also had to install python-software-properties as shown in order to have add-apt-repository available.
$ sudo apt-get install python-software-properties $ sudo add-apt-repository ppa:oisf/suricata-beta You are about to add the following PPA to your system: Suricata IDS/IPS/NSM beta packages http://www.openinfosecfoundation.org/ http://planet.suricata-ids.org/ http://suricata-ids.org/ Suricata IDS/IPS/NSM - Suricata is a high performance Network IDS, IPS and Network Security Monitoring engine. Open Source and owned by a community run non-profit foundation, the Open Information Security Foundation (OISF). Suricata is developed by the OISF, its supporting vendors and the community. This engine is not intended to just replace or emulate the existing tools in the industry, but will bring new ideas and technologies to the field. This new Engine supports: Multi-Threading - provides for extremely fast and flexible operation on multicore systems. File Extraction, MD5 matching - over 4000 types of file recognition/extraction transmitted live over the wire. TLS/SSL certificate matching/logging Automatic Protocol Detection (IPv4/6, TCP, UDP, ICMP, HTTP, TLS, FTP, SMB ) Gzip Decompression Fast IP Matching Hardware acceleration on CUDA and GPU cards and many more great features - http://suricata-ids.org/features/all-features/ More info: https://launchpad.net/~oisf/+archive/suricata-beta Press [ENTER] to continue or ctrl-c to cancel adding it gpg: keyring `/tmp/tmpqk6Ubk/secring.gpg' created gpg: keyring `/tmp/tmpqk6Ubk/pubring.gpg' created gpg: requesting key 66EB736F from hkp server keyserver.ubuntu.com gpg: /tmp/tmpqk6Ubk/trustdb.gpg: trustdb created gpg: key 66EB736F: public key "Launchpad PPA for Peter Manev" imported gpg: Total number processed: 1 gpg: imported: 1 (RSA: 1) OK $ sudo apt-get updateNow I was ready to install Suricata and Htp, a dependency.
$ sudo apt-get install suricata htp Reading package lists... Done Building dependency tree Reading state information... Done The following extra packages will be installed: libhtp1 libnet1 libnetfilter-queue1 libnspr4 libnss3 libyaml-0-2 The following NEW packages will be installed: htp libhtp1 libnet1 libnetfilter-queue1 libnspr4 libnss3 libyaml-0-2 suricata 0 upgraded, 8 newly installed, 0 to remove and 0 not upgraded. Need to get 2,510 kB of archives. After this operation, 8,394 kB of additional disk space will be used. Do you want to continue [Y/n]? ...snip...With this process done I added rules from Emerging Threats. I found Samiux's blog post helpful.
$ cd /etc/suricata $ sudo wget https://rules.emergingthreatspro.com/open/suricata/emerging.rules.tar.gz $ sudo tar -xzf emerging.rules.tar.gz $ sudo mkdir /var/log/suricata $ sudo touch /etc/suricata/threshold.config
Now I had to edit /etc/suricata/suricata.yaml. The following diff shows the changes I made to the original file.
$ diff -u /etc/suricata/suricata.yaml.orig /etc/suricata/suricata.yaml --- /etc/suricata/suricata.yaml.orig 2014-01-25 21:39:57.542801685 -0500 +++ /etc/suricata/suricata.yaml 2014-01-25 21:41:31.530801055 -0500 @@ -46,7 +46,7 @@ # Default pid file. # Will use this file if no --pidfile in command options. -#pid-file: /var/run/suricata.pid +pid-file: /var/run/suricata.pid # Daemon working directory # Suricata will change directory to this one if provided @@ -208,7 +208,7 @@ # a line based information for dropped packets in IPS mode - drop: - enabled: no + enabled: yes filename: drop.log append: yes #filetype: regular # 'regular', 'unix_stream' or 'unix_dgram' @@ -337,7 +337,7 @@ # You can specify a threshold config file by setting "threshold-file" # to the path of the threshold config file: -# threshold-file: /etc/suricata/threshold.config +threshold-file: /etc/suricata/threshold.config # The detection engine builds internal groups of signatures. The engine # allow us to specify the profile to use for them, to manage memory on an @@ -373,7 +373,7 @@ - inspection-recursion-limit: 3000 # When rule-reload is enabled, sending a USR2 signal to the Suricata process # will trigger a live rule reload. Experimental feature, use with care. - #- rule-reload: true + - rule-reload: true # If set to yes, the loading of signatures will be made after the capture # is started. This will limit the downtime in IPS mode. #- delayed-detect: yesNext I added the following test rule to /etc/suricata/rules/drop.rules. The file location is arbitrary. I wrote a simple rule to alert on ICMP traffic from a test system, 192.168.2.126. All of the following is one line. I just broke it for readability.
alert icmp 192.168.2.126 any -> any any (msg:"ALERT test ICMP ping from 192.168.2.106"; icode:0; itype:8; classtype:trojan-activity; sid:99999998; rev:1;)
Notice I have no iptables rules loaded at this point:
$ sudo iptables -vnL Chain INPUT (policy ACCEPT 5 packets, 392 bytes) pkts bytes target prot opt in out source destination Chain FORWARD (policy ACCEPT 4 packets, 240 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 4 packets, 496 bytes) pkts bytes target prot opt in out source destination
Now I was ready to see if Suricata would at least see and alert on traffic matching my ICMP test rule. First I started Suricata and told it to watch br0, the bridge interface.
$ sudo suricata -c /etc/suricata/suricata.yaml -i br0 25/1/2014 -- 22:44:13 -I don't care about the Warning or Error notices here. I could fix those but they are not germane to demonstrating the main point of this post.- This is Suricata version 2.0beta2 RELEASE 25/1/2014 -- 22:44:16 - - [ERRCODE: SC_ERR_NO_RULES(42)] - No rules loaded from /etc/suricata/rules/emerging-icmp.rules 25/1/2014 -- 22:44:33 - - [ERRCODE: SC_ERR_OPENING_RULE_FILE(41)] - opening rule file /etc/suricata/rules/dns-events.rules: No such file or directory. 25/1/2014 -- 22:44:51 - - [ERRCODE: SC_ERR_PCAP_CREATE(21)] - Using Pcap capture with GRO or LRO activated can lead to capture problems. 25/1/2014 -- 22:44:51 - - all 2 packet processing threads, 3 management threads initialized, engine started.
On a separate system, 192.168.2.126, I pinged 192.168.2.142.
$ ping -c 2 192.168.2.142 PING 192.168.2.142 (192.168.2.142) 56(84) bytes of data. 64 bytes from 192.168.2.142: icmp_req=1 ttl=64 time=5.29 ms 64 bytes from 192.168.2.142: icmp_req=2 ttl=64 time=4.03 ms --- 192.168.2.142 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1001ms rtt min/avg/max/mdev = 4.030/4.663/5.297/0.637 msThen I checked my Suricata logs:
$ ls -al /var/log/suricata/ total 88 drwxr-xr-x 3 root root 4096 Jan 25 22:50 . drwxr-xr-x 11 root root 4096 Jan 25 21:38 .. -rw-r--r-- 1 root root 0 Jan 25 22:15 drop.log -rw-r--r-- 1 root root 392 Jan 25 22:50 fast.log -rw-r--r-- 1 root root 0 Jan 25 21:42 http.log -rw-r--r-- 1 root root 66008 Jan 25 22:50 stats.log drwxr-xr-x 2 root root 4096 Jan 25 22:15 .tmp -rw-r--r-- 1 root root 388 Jan 25 22:50 unified2.alert.1390708237 $ cat /var/log/suricata/fast.log 01/25/2014-22:50:40.510124 [**] [1:99999998:1] ALERT test ICMP ping from 192.168.2.106 [**] [Classification: A Network Trojan was detected] [Priority: 1] {ICMP} 192.168.2.126:8 -> 192.168.2.142:0 01/25/2014-22:50:41.510464 [**] [1:99999998:1] ALERT test ICMP ping from 192.168.2.106 [**] [Classification: A Network Trojan was detected] [Priority: 1] {ICMP} 192.168.2.126:8 -> 192.168.2.142:0That worked as expected. I got alerts on the ICMP traffic matching the test ALERT rule.
Now it was time to drop traffic!
I added a new rule to drop.rules, again broken only for readability here:
drop icmp 192.168.2.126 any -> any any (msg:"DROP test ICMP ping from 192.168.2.106"; icode:0; itype:8; classtype:trojan-activity; sid:99999999; rev:1;)I also disabled the previous ALERT rule by commenting it out.
Next I added iptables rules for the FORWARD chain, for traffic traversing the bridge. This Documentation was helpful.
$ sudo iptables -I FORWARD -j NFQUEUE $ sudo iptables -vnL Chain INPUT (policy ACCEPT 32 packets, 2752 bytes) pkts bytes target prot opt in out source destination Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 0 0 NFQUEUE all -- * * 0.0.0.0/0 0.0.0.0/0 NFQUEUE num 0 Chain OUTPUT (policy ACCEPT 25 packets, 2600 bytes) pkts bytes target prot opt in out source destinationFinally I restarted Suricata, this time telling it to use queue 0, where NFQUEUE was waiting for packets for Suricata.
$ sudo suricata -c /etc/suricata/suricata.yaml -q 0 25/1/2014 -- 22:54:49 -With Suricata running in IPS mode, I tried pinging 192.168.2.142 from 192.168.2.126 as I did earlier.- This is Suricata version 2.0beta2 RELEASE 25/1/2014 -- 22:54:52 - - [ERRCODE: SC_ERR_NO_RULES(42)] - No rules loaded from /etc/suricata/rules/emerging-icmp.rules 25/1/2014 -- 22:55:08 - - [ERRCODE: SC_ERR_OPENING_RULE_FILE(41)] - opening rule file /etc/suricata/rules/dns-events.rules: No such file or directory. 25/1/2014 -- 22:55:26 - - all 3 packet processing threads, 3 management threads initialized, engine started.
$ ping -c 2 192.168.2.142 PING 192.168.2.142 (192.168.2.142) 56(84) bytes of data. --- 192.168.2.142 ping statistics --- 2 packets transmitted, 0 received, 100% packet loss, time 1006msNothing got through! I confirmed that I could ping the same box from another source IP address. In other words, only ICMP from 192.168.2.126 was blocked. Now check the Suricata logs:
$ ls -al /var/log/suricata/ total 152 drwxr-xr-x 3 root root 4096 Jan 25 22:57 . drwxr-xr-x 11 root root 4096 Jan 25 21:38 .. -rw-r--r-- 1 root root 294 Jan 25 22:57 drop.log -rw-r--r-- 1 root root 798 Jan 25 22:57 fast.log -rw-r--r-- 1 root root 0 Jan 25 21:42 http.log -rw-r--r-- 1 root root 125812 Jan 25 22:57 stats.log drwxr-xr-x 2 root root 4096 Jan 25 22:15 .tmp -rw-r--r-- 1 root root 388 Jan 25 22:50 unified2.alert.1390708237 -rw-r--r-- 1 root root 0 Jan 25 22:55 unified2.alert.1390708526 -rw-r--r-- 1 root root 360 Jan 25 22:57 unified2.alert.1390708633 $ cat drop.log 01/25/2014-22:57:17.031400: IN= OUT= SRC=192.168.2.126 DST=192.168.2.142 LEN=84 TOS=0x00 TTL=64 ID=36055 PROTO=ICMP TYPE=8 CODE=0 ID=59729 SEQ=256 01/25/2014-22:57:18.038179: IN= OUT= SRC=192.168.2.126 DST=192.168.2.142 LEN=84 TOS=0x00 TTL=64 ID=36056 PROTO=ICMP TYPE=8 CODE=0 ID=59729 SEQ=512Cool, those are our dropped ICMP packets. Checking fast.log we'll see the original two ALERT test messages, but check out the new DROP test messages too:
$ cat /var/log/suricata/fast.log 01/25/2014-22:50:40.510124 [**] [1:99999998:1] ALERT test ICMP ping from 192.168.2.106 [**] [Classification: A Network Trojan was detected] [Priority: 1] {ICMP} 192.168.2.126:8 -> 192.168.2.142:0 01/25/2014-22:50:41.510464 [**] [1:99999998:1] ALERT test ICMP ping from 192.168.2.106 [**] [Classification: A Network Trojan was detected] [Priority: 1] {ICMP} 192.168.2.126:8 -> 192.168.2.142:0 01/25/2014-22:57:17.031400 [Drop] [**] [1:99999999:1] DROP test ICMP ping from 192.168.2.106 [**] [Classification: A Network Trojan was detected] [Priority: 1] {ICMP} 192.168.2.126:8 -> 192.168.2.142:0 01/25/2014-22:57:18.038179 [Drop] [**] [1:99999999:1] DROP test ICMP ping from 192.168.2.106 [**] [Classification: A Network Trojan was detected] [Priority: 1] {ICMP} 192.168.2.126:8 -> 192.168.2.142:0So that's it.
Note that with this configuration, if you stop Suricata then the host it's "protecting" is totally unreachable. You can restore connectivity by flushing the iptables rules via this command:
$ sudo iptables -FNow the endpoint is reachable while Suricata is not running. To re-enable the IPS, you have to set up the NFQUEUE via iptables again as shown previously.
Following these directions you have the foundation for building a bridged IPS using Suricata on Ubuntu Server 12.04. The next step would be to fix the configuration issues causing the start-up error messages, make the bridge, firewall, and Suricata components available at start-up, and then build your own set of DROP rules. There are probably also optimizations for PF_RING and other performance features. Good luck!
Do you run Suricata as an IPS? How do you do it? Have you tried the new 2.x beta?
Comments
root@suricata:/var/log/suricata# ls -ltr
total 704
-rw-r--r-- 1 root root 0 Nov 21 03:56 http.log
-rw-r--r-- 1 root root 0 Nov 21 05:54 drop.log
-rw-r--r-- 1 root root 0 Nov 21 06:07 fast.log
root@suricata:~/suricata-3.1# suricata -c suricata.yaml --af-packet
21/11/2016 -- 09:53:48 - - Configuration node 'interface' redefined.
21/11/2016 -- 09:53:48 - - This is Suricata version 3.1.2 RELEASE
21/11/2016 -- 09:53:48 - - CPUs/cores online: 1
21/11/2016 -- 09:53:48 - - [ERRCODE: SC_WARN_OPTION_OBSOLETE(233)] - Personality Apache_2_2 no longer supported by libhtp, failing back to Apache2 personality.
21/11/2016 -- 09:53:48 - - [ERRCODE: SC_ERR_DNS_CONFIG(240)] - no DNS UDP config found, enabling DNS detection on port 53.
21/11/2016 -- 09:53:48 - - [ERRCODE: SC_ERR_DNS_CONFIG(240)] - no DNS TCP config found, enabling DNS detection on port 53.
21/11/2016 -- 09:53:48 - - Found an MTU of 1500 for 'eth0'
21/11/2016 -- 09:53:48 - - Found an MTU of 1500 for 'eth1'
21/11/2016 -- 09:53:48 - - 1 rule files processed. 31 rules successfully loaded, 0 rules failed
21/11/2016 -- 09:53:48 - - 31 signatures processed. 0 are IP-only rules, 0 are inspecting packet payload, 31 inspect application layer, 0 are decoder event only
21/11/2016 -- 09:53:48 - - Threshold config parsed: 0 rule(s) found
21/11/2016 -- 09:53:48 - - fast output device (regular) initialized: fast.log
21/11/2016 -- 09:53:48 - - http-log output device (regular) initialized: http.log
21/11/2016 -- 09:53:48 - - dns-log output device (regular) initialized: dns.log
21/11/2016 -- 09:53:48 - - stats output device (regular) initialized: stats.log
21/11/2016 -- 09:53:48 - - drop output device (regular) initialized: drop.log
21/11/2016 -- 09:53:48 - - [ERRCODE: SC_ERR_NIC_OFFLOADING(284)] - NIC offloading on eth0: SG: SET, GRO: SET, LRO: unset, TSO: SET, GSO: SET. Run: ethtool -K eth0 sg off gro off lro off tso off gso off
21/11/2016 -- 09:53:48 - - [ERRCODE: SC_ERR_AFP_CREATE(190)] - Using AF_PACKET with offloading activated leads to capture problems
21/11/2016 -- 09:53:48 - - Going to use 1 thread(s)
21/11/2016 -- 09:53:48 - - [ERRCODE: SC_ERR_NIC_OFFLOADING(284)] - NIC offloading on eth1: SG: SET, GRO: SET, LRO: unset, TSO: SET, GSO: SET. Run: ethtool -K eth1 sg off gro off lro off tso off gso off
21/11/2016 -- 09:53:48 - - [ERRCODE: SC_ERR_AFP_CREATE(190)] - Using AF_PACKET with offloading activated leads to capture problems
21/11/2016 -- 09:53:48 - - Going to use 1 thread(s)
21/11/2016 -- 09:53:48 - - all 2 packet processing threads, 4 management threads initialized, engine started.
21/11/2016 -- 09:53:48 - - All AFP capture threads are running.