This documentation outlines how to run Snort on a Raspberry Pi 3 and use the Pi as a gateway on a network to act as an IDS. We also monitor the resource usage of this approach and test it against SYN flood PCAP files.
We acquired a Raspberry Pi Model 3 B+ and put NOOBs on a 16GB HP MicroSD card. We connected a USB keyboard and mouse and HDMI cable. To provide wired internet access, we connected an ethernet cable into the Pi’s ethernet port. We bought an ethernet-to-USB adapter so we could have two interfaces on the Raspberry Pi, the second being the USB-connected ethernet connected to a Netgear AC1200 router we brought from home, for use as a gateway. After powering on the Pi, we followed the on-screen commands to install Raspbian on the Pi and then proceeded to install Snort.
Our goal was to convert a Raspberry Pi 3 into a network gateway that would filter traffic based on Snort signatures. In addition, we aimed to measure accuracy (using a dataset from web), packet loss (using Wireshark), processor and memory usage (using vcgenmd commands).
Establishing Snort on RPi
We installed snort on a Raspberry Pi 3 using the Snort++ on Ubuntu installation guide on the snort.org website. For simplicity in installing all the required packages for snort, we used a very long combined command. However, we didn’t follow all of the steps on this guide as some of them would cause problems or were not needed.
First, we ran sudo apt-get update && sudo apt-get upgrade to make sure our raspberry pi system was up to date. Then we made a folder for all of our snort files and sub-folders. Then we installed the prerequisite packages specified in the installation guide. For the installation of cmake, we followed the command specified for ubuntu 16 and 18, which was sudo apt-get install -y cmake. Then we installed the optional recommended software, using the following command: sudo apt-get install -y liblzma-dev openssl libssl-dev cpputest libsqlite3-dev uuid-dev. We then installed the prerequisite libraries for snort’s data acquisition library, which are bison and flex. We also installed a package to run snort in inline mode using NFQ using the following command: sudo apt-get install -y libnetfilter-queue-dev. Then we installed safec and gpertools as specified in the installation guide.
We skipped the installation of Hyperscan and flatbuffers since it was giving us an installation error. Additionally, we discovered that the data acquisition library installation specified in the guide was not the right one for Snort 3. We looked on the GitHub repository where the installation package for snort 3 is found and discovered another package called libdaq that is compatible with snort 3. We installed and configured it with the following command: ./bootstrap && ./configure && make && make install. Then we proceeded to install Snort 3 according to the guide and created a link to snort in /usr/local/sbin. After this, we created the environmental variables according to the snort guide.
With the snort installation complete, we began installing the Snort community rules as specified in the guide and enabled built-in rules in our snort configuration file. We also created our own small set of rules in the rules directory specified to alert for ICMP traffic, websites such as Linkedin, and SYN packets.
alert icmp any any -> any any (msg: “ICMP detected”; sid:10000001)
alert tcp any any -> any any (msg: “LinkedIn traffic found”; content:”linkedin.com”; sid:10000002)
alert tcp any any -> any any (msg: “Dropping all packets”; flags:S; sid:10000003)
After the rules file has been saved, return to your home directory and proceed to run Snort using the following command: sudo snort -c /usr/local/etc/snort/snort.lua -R /usr/local/etc/snort/rules/local.rules -i eth0 -A alert_fast -s 65535 -k none. The following command uses the configuration specified in the snort.lua file, uses the rules specified in local.rules, reads packets from the eth0 interface, and produces quick alerts if any of the rules are matched up against incoming traffic. Additionally, the -k none parameter tells Snort to ignore bad checksums and -s 65535 prevents oversized packets from being shortened.
Administering a SYNflood
First we installed TCPReplay on our personal computer with the command sudo apt-get install tcpreplay. Then we downloaded packet capture files from the website MazeBolt. We downloaded the SYN flood pcap file. We then used TCPReplay on our computer to replay those packet captures as traffic to the Raspberry Pi using the command sudo tcpreplay -i enx00e04c681e3e -tK –loop 500 –unique-ip flood.pcap. We used eth0 on Raspberry Pi and connected eth1 to computer. We ran the syn_flood over eth1 and monitored the temperature, core usage, and memory usage on our Pi, as well as packet information with Wireshark.
Using RPi as a gateway
We attempted to follow this online tutorial in order to set up our Raspberry Pi as a gateway to read packets between our router and the network. We tested this by running Wireshark on the Pi and we were able to read packets that were created on our personal devices connected to the AC1200’s WiFi.
We originally used iptables to route traffic from one interface to another. A recommendation we received was the use dnsmasq for the nat since both interfaces are on different subnets. When creating gateway, don’t mess with eth0, it will break the connection.
We used this tutorial to set up an ethernet bridge on the Raspberry Pi (starting at #5). We skipped the portion mentioning setting up the wireless interface and going straight to the ethernet section. Replace any part configuration that mentions eth0 with eth1 (outgoing usb-adaptor ethernet) and wlan0 with eth0 (incoming ethernet). In dnsmasq.conf, don’t include bind-interfaces. A reboot is needed. We include another large command that runs everything at once.
We ran htop, a command line resource monitor, on the Pi to display the CPU usage of the cores and the memory and swap memory usage. In order to keep track of the CPU’s heat, we followed the pattern of this Python script from the web. Our modified script to log CPU usage, CPU temperature, memory usage, and voltage to a file is below. We also borrowed from this guide. An indented Doc with the script is here.
cpu = "cpu=" + str(round(usg, 3)) + "%"
temp = os.popen("vcgencmd measure_temp").readline().rstrip()
mem = "mem=" + ((os.popen("free -h | grep Mem:").readline().rstrip()).split())
volt = os.popen("vcgencmd measure_volts").readline().rstrip()
return (cpu + ", " + temp + ', ' + mem + ', ' + volt)
last_idle = last_total = 0
with open('/proc/stat') as file:
fields = [float(column) for column in file.readline().strip().split()[1:]]
idle,total = fields, sum(fields)
idle_delta, total_delta = idle - last_idle, total - last_total
last_idle, last_total = idle, total
usg = 100.0 * (1.0 - idle_delta / total_delta)