Network Defense and Monitoring With Suricata


Suricata is a real-time threat detection engine. It helps protect networks against threats by actively monitoring traffic and detecting malicious behavior based on written rules. It can operate in a network security monitoring (NSM) mode and can also be configured as an intrusion prevention system (IPS) or intrusion detection system (IDS).

The Suricata project is free and open-source, and stands out from alternatives such as Snort, Zeek or Sagan, with its native support for multi-threading, HTTP/TLS logging and other useful features. It is a great addition to your network defense solutions, whether the goal is to protect a business or home network.

Why should you use an IDPS?

When network breaches happen, they usually cause lots of problems and damage. What’s even worse, however, are undetected breaches. In these instances, attackers linger undetected in their targeted networks, extracting as much information as possible. By the time these attacks are uncovered, the damage done is often extensive. According to an IBM study, it takes an average of 206 days to detect a cyberattack and another 73 days for vulnerability patching. These results show that breaches with long durations before they are found are still a serious problem.

Intrusion detection and prevention systems (IDPS) are designed to help IT and NetOps teams counter this problem. The primary goal of an IDPS is to identify and block malicious behavior, and to alert system administrators when suspicious traffic is present, or a network intrusion taking place. By providing timely alerts, IDPS solutions enable teams to respond rapidly to the attacks to mitigate them and reduce their damage.

This discussion focuses on Suricata as an example of an IDPS, and walks you through the basics of its operation.

Installation & Setup

Suricata may be available as a package in your distribution’s default repository. However, to ensure that you get the latest version, install it directly from the project’s official Personal Package Archives repository. Here is where that can be found.

sudo add-apt-repository ppa:oisf/suricata-stable 
sudo apt-get update

Install Suricata through the package manager:

sudo apt-get install suricata

Should the installation confirmation menu for libhyperscan4 library appear, simply answer ‘Yes’ and continue.

Installing from source

Alternatively, Suricata may be downloaded and compiled from its source code. This is a longer process but provides more control over the installation and allows you to ensure that the latest version is being installed. Install the required dependencies:

sudo apt-get -y install libpcre3 libpcre3-dbg libpcre3-dev build-essential autoconf automake libtool libpcap-dev libnet1-dev libyaml-0-2 libyaml-dev zlib1g zlib1g-dev libcap-ng-dev libcap-ng0 make libmagic-dev libjansson-dev libjansson4 pkg-config

If you intend to use the IPS capabilities of Suricata, install the following additional libraries:

sudo apt-get -y install libnetfilter-queue-dev libnetfilter-queue1 libnfnetlink-dev libnfnetlink0

The next step is to download and extract the latest source archive:

wget "http://www.openinfosecfoundation.org/download/suricata-current.tar.gz" 
tar -xvzf "suricata-current.tar.gz" 

After you’ve completed the download and extraction, install the suricata-update python tool. You’ll also need to create a soft link to reference and link /usr/local/bin/suricata-update file to /usr/bin/suricata-update so that Suricata can find it:

sudo apt install python-pip 
pip install suricata-update 
ln -s /usr/local/bin/suricata-update /usr/bin/suricata-update

Compile and install Suricata (modify the version accordingly):

cd suricata-5.0.1
./configure --enable-nfqueue --prefix=/usr --sysconfdir=/etc --localstatedir=/var 
make 
make install-full

Configuration

The main configuration file is /etc/suricata/suricata.yaml. Before deployment, Suricata must be configured for the following variables: which network interface to use, which IP range will be identified as the internal network, and which IP range should be considered as the external network.

  • HOME_NET – this variable is used to define the internal network that is to be protected;
  • EXTERNAL_NET – used to define the external network;
  • af-packet interface – the interface variable under af-packet is used to define the network interface that Suricata should use for monitoring.

Even though these variables are defined by default, it’s good practice to ensure that the interface is correctly configured and that the IP addresses provided for HOME_NET and EXTERNAL_NET are as specific as possible. Being precise and accurate with these configuration selections helps Suricata achieve better security and performance.

Logs

Suricata constantly monitors the network and generates events based on alerts, anomalies, metadata, file information and protocol-specific records. Logs of both network events and the health of Suricata are stored in various files and formats within /var/log/suricata. These files can be processed by 3rd party software to create reports and visualizations to better understand how Suricata is behaving.

Extensible Event Format

The primary network event log file is eve.json. This is where events are stored using the EVE (Extensible Event Format) format. Below is an EVE log generated by Suricata during an SSH login.

{ 
	"timestamp":"2019-10-07T23:37:32.964620+0000",
	"flow_id":1154589419900453,
	"in_iface":"eth0", 
	"event_type":"ssh", 
	"src_ip":"192.168.0.121", 
	"src_port":47202, 
	"dest_ip":"192.168.0.15", 
	"dest_port":22, 
	"proto":"TCP", 
	"ssh":{ 
		"client":{ 
			"proto_version":"2.0", 
			"software_version":"libssh-0.6.3" 
		}, 
		"server":{ 
			"proto_version":"2.0", 
			"software_version":"OpenSSH_7.6p1 Ubuntu-4ubuntu0.3" 
		} 
	}
} 

Startup messages

Suricata service messages, including startup and other console messages, are stored in suricata.log, which has the following formatting:

6/10/2019 -- 22:40:00 - <Notice> - This is Suricata version 4.1.5 RELEASE 
6/10/2019 -- 22:40:00 - <Info> - CPUs/cores online: 1 
6/10/2019 -- 22:40:00 - <Warning> - [ERRCODE: SC_ERR_NO_RULES(42)] - No rule files match the pattern /var/lib/suricata/rules/suricata.rules 
6/10/2019 -- 22:52:45 - <Error> - [ERRCODE: SC_ERR_INITIALIZATION(45)] - pid file '/var/run/suricata.pid' exists and Suricata appears to be running. Aborting! 

Fast.log

The fast.log file also contains entries for network events and alerts like eve.json. However, it is single line-formatted for easy integration with common *NIX utilities like grep and awk. Here are example fast.log entries for a rule that logs ICMP and Telnet connections:

10/08/2019-16:24:33.612252 [**] [1:1000003:1] TELNET [**] [Classification: (null)] [Priority: 3] {TCP} 10.135.212.73:42192 -> 10.135.220.63:23 
10/08/2019-16:24:41.584727 [**] [1:1000002:1] ICMP [**] [Classification: (null)] [Priority: 3] {ICMP} 10.135.212.73:8 -> 10.135.220.63:0

Rules

A rule consists of three parts: the action, the header, and the rule options. The action determines what will happen to the packet if it matches with a rule:

  • Pass – let the packet through without generating an alert;
  • Drop – if matched, the packet will be immediately dropped and logged;
  • Reject – similarly to the ‘drop’ action, the packet will be immediately dropped and logged, but both the sender and receiver will receive a reject packet;
  • Alert – the packet is allowed through but an alert will be generated.

The header tells Suricata which protocol the rule is meant for, and specifies the source and destination IP address. When it comes to the protocol, there are three main varieties:

  • TCP
  • UDP
  • ICMP

Suricata also supports a lot of application layer protocols such as: http, tls, ftp, dns, ssh, smtp, and many more.

A rule may also contain ‘IP’ as a protocol, which stands for ‘all’ or ‘any’ and matches all of the protocols.

The second part of the header specifies the IP address and port of both the source and destination, which is structured like this:

"Source IP" "Source port" -> "Destination IP" "Destination port"

It is also possible to match in both directions by replacing ‘->’ with ‘<>’, and to write ‘any’ instead of a range or specific IP address or port. The following line will match all packets that originate from $EXTERNAL_NET IP addresses with any port, directed to $HOME_NET IP addresses with port 23.

$EXTERNAL_NET any -> $HOME_NET 23

The last part of the rule contains options written in key-value pairs or only as keys if the option is only a keyword. Options are separated by semicolons and are entirely enclosed in parentheses. The most common options that can be considered as a baseline for writing rules are:

  • msg – information regarding the signature and alert;
  • sid – unique ID number assigned to each rule;
  • rev – represents the version of the rule. It is incremented by 1 when the rule is updated;

Rule options consisting of only msg, sid and rev may look like the following:

(msg:"Suspicious connection to port 20001"; sid:1252152; rev:1;)

Here is a rule that detects a port scan on port 3306, taken out of the emerging threats ruleset:

alert tcp $EXTERNAL_NET any -> $HOME_NET 3306 (msg:"ET SCAN Suspicious inbound to mySQL port 3306"; flow:to_server; flags:S; threshold: type limit, count 5, seconds 60, track by_src; metadata: former_category POLICY; reference:url,doc.emergingthreats.net/2010937; classtype:bad-unknown; sid:2010937; rev:3; metadata:created_at 2010_07_30, updated_at 2018_03_27;) 

As we can see, the rule analyzes traffic originating from an external network that is directed to port 3306 of any home network IP address.

Writing and activating rules

Suricata rules are stored in /var/lib/suricata/rules by default. Create a file named telnet.rules that contains the following rule:

alert tcp $EXTERNAL_NET any -> $HOME_NET 23 (msg:"Telnet conn to port 23"; sid:1252152; rev:1;)

The above rule matches any telnet connections that originate from external network IP addresses to internal network IP addresses. To activate the rule, go to /etc/suricata/suricata.yaml and add – telnet.rules under the rule-files section, which contains all rule files that Suricata loads at startup.

Test the rule by initiating a telnet connection to the Suricata machine using the following command:

telnet 192.168.0.5

The attempted telnet connection should generate the following alert in /var/log/suricata/fast.log:

10/10/2019-00:39:36.955439 [**] [1:1252152:1] Telnet conn to port 23 [**] [Classification: (null)] [Priority: 3] {TCP} 10.135.212.73:52090 -> 10.135.220.63:23

Updating Rules

Suricata-update is a tool written in python that checks and updates local rulesets based on remote configured sources. In a new installation, there are no additional sources configured, so suricata-update only downloads the emerging threats ruleset. All rulesets downloaded or updated by this tool are placed in /var/lib/suricata/rules, which is the designated directory for active rule management. This directory should not be confused with /etc/suricata/rules which contains rules provided by Suricata out of the box.

The emerging threats ruleset is an actively maintained set of rules written to equip Suricata with the knowledge to detect common threats and malicious activity. It’s good practice to ensure that a freshly installed Suricata instance is already equipped with an up-to-date version of this ruleset.

A ruleset update can be run by simply typing in the command suricata-update without any additional parameters. Using this command will initiate a download of the latest version and will write the rules to /var/lib/suricata/rules/suricata.rules.

root@suricata:~# suricata-update 
8/10/2019 -- 20:02:33 - <Info> -- No sources configured, will use Emerging Threats Open 
8/10/2019 -- 20:02:33 - <Info> -- Fetching https://rules.emergingthreats.net/open/suricata-4.1.5/emerging.rules.tar.gz. 
100% - 2424445/2424445 
8/10/2019 -- 20:02:39 - <Info> -- Creating directory /var/lib/suricata/rules. 
8/10/2019 -- 20:02:39 - <Info> -- Writing rules to /var/lib/suricata/rules/suricata.rules: total: 25511; enabled: 20473; added: 25511; removed 0; modified: 0

Adding additional remote sources

The first step in configuring additional sources for suricata-update is checking what sources are available. That can only be done by obtaining the master index from the Open Information Security Foundation hosts:

suricata-update update-sources

Once you’ve obtained the master index, review what is available:

suricata-update list-sources

To enable a ruleset from the index, enter:

suricata-update enable-source <name>

It is also possible to add a remote source from a URL in the case that it’s not provided in the index:

suricata-update add-source <name> <url>

Similarly, to disable rules use:

suricata-update remove-source <name>

To see which rulesets are currently active, use:

suricata-update list-enabled-sources

Automatically updating rulesets

It is absolutely crucial to keep rulesets up-to-date at all times so that Suricata is able to detect emerging network threats. This is similar to how an anti-virus software automatically updates the signature database in order to detect the newest threats.

A simple cron job that executes suricata-update daily will suffice. To do that, enter crontab -e and add the following line:

0 0 * * * suricata-update

Reloading rulesets

Suricata loads rules only at service startup which means that any newer modifications to rules will not be taken into effect. However, it is possible to send a signal to Suricata to trigger a live ruleset reload without interrupting IPS/IDS operations. This can be done by sending the signal USR2 to the process ID of the running Suricata instance:

kill -USR2 $(pidof suricata)

When the above command returns no output, it is an indication that the signal was successfully sent to the running Suricata instance. The /var/log/suricata/suricata.log file is a great place to look in for confirmation that the rules were successfully loaded.

8/10/2019 -- 21:22:15 - <Notice> - rule reload starting 
8/10/2019 -- 21:22:23 - <Info> - 1 rule files processed. 20473 rules successfully loaded, 0 rules failed 
8/10/2019 -- 21:22:23 - <Info> - Threshold config parsed: 0 rule(s) found 
8/10/2019 -- 21:22:23 - <Info> - 20476 signatures processed. 1197 are IP-only rules, 4846 are inspecting packet payload, 16281 inspect application layer, 103 are decoder event only 
8/10/2019 -- 21:22:31 - <Info> - cleaning up signature grouping structure... complete 
8/10/2019 -- 21:22:31 - <Notice> - rule reload complete 

We previously added a cron job that executes suricata-update daily so that existing rulesets are updated. However, the cron tab must be modified so that the updated rules are also reloaded into Suricata. To do this, enter crontab -e and execute the command to reload rules right after the update:

0 0 * * * /usr/bin/suricata-update && kill -USR2 $(pidof suricata) > /dev/null 2>&1

Detection vs prevention

The rule action is the functional dividing line between an IDS and an IPS. An IDS is only able to identify malicious behavior, as opposed to an IPS which can both identify and block malicious behavior, thereby eliminating network threats.

An IDS instance must be strategically placed in the network so it has visibility for all network activity originating from inside and outside the network. However, when it comes to setting up an IPS, apart from ensuring that Suricata is running in inline (IPS) mode it is also crucial to make sure that the IDS is the entry point to the network for other hosts. Otherwise Suricata will not be able to drop packets.

Conclusion

A properly configured and strategically placed Suricata instance that is regularly maintained can help achieve improved network security by minimizing the potential threats that pose risks to your network.

Shpëtim Ibrani