Skip to content disloops

PSAD on Raspberry Pi

I have never gotten a full intrusion detection system (IDS) working correctly on a Raspberry Pi. The two most popular – Snort and Bro IDS – either have problems with their dependencies or the ARM architecture.

I recently came across PSAD – the Port Scan Attack Detector. It is essentially a collection of daemons that analyze iptables logs to identify patterns of malicious traffic. When used in conjunction with fwsnort, PSAD can also correlate blocked traffic with many of the "Emerging Threats" Snort rules.

PSAD was extremely easy to set up on a Raspberry Pi that's deployed as a catch-all DMZ host on my home network. Before diving into the details, you can see live data being collected by that host here: https://psad.disloops.com

Setting up PSAD and UFW

This setup relies on the base configuration for a Raspberry Pi that's described here: https://disloops.com/raspberry-pi-3-basics/

To begin, first install PSAD:

sudo apt-get install psad

In the tutorial above, UFW was set up as a wrapper over iptables. However, UFW logs do not have the level of detail that PSAD requires. Without modifying the logging capabilities, some messages may be discarded before PSAD can analyze them.

First back up the UFW configuration files:

cd /etc/ufw
sudo cp before.rules before.rules.old
sudo cp before6.rules before6.rules.old

Now edit the files above to add the following block just before the lines containing the final COMMIT directive:

# Custom PSAD logging directives
-A INPUT -j LOG --log-tcp-options
-A FORWARD -j LOG --log-tcp-options

These lines will ensure that iptables events are logged properly. The --log-tcp-options argument adds additional data to the log files that can be used to detect certain attacks. The EXPECT_TCP_OPTIONS parameter in the PSAD configuration below corresponds to this setting.

Now PSAD can be configured:

cd /etc/psad
sudo cp psad.conf psad.conf.old
sudo vi psad.conf

Here are some of the parameters that should be modified:

HOSTNAME                       your_host_here;
HOME_NET                       192.168.0.0/16;
ALERTING_METHODS               noemail;

The first two are self-explanatory. The ALERTING_METHODS setting accepts three values: noemail, nosyslog, and ALL. Here it's being set to suppress email alerts.

IPT_SYSLOG_FILE                /var/log/ufw.log;

This just tells PSAD where to acquire iptables log data. The UFW configuration above was modified so that this data would be captured correctly.

EXPECT_TCP_OPTIONS             Y;

Because some scanning tools don't set options in the TCP headers, using this setting allows PSAD to better identify those attacks. PSAD also uses this information to passively fingerprint remote operating systems. This setting depends on the --log-tcp-options argument provided in the UFW configuration files above.

IMPORT_OLD_SCANS               Y;

This tells PSAD to re-import old scan data after a restart instead of moving it to the archive directory, which allows the statistics to remain persistent across reboots.

Lastly, have PSAD download the latest set of modified Snort signatures and reboot:

sudo psad --sig-update
sudo reboot

Setting up fwsnort

The fwsnort tool parses Snort rules and builds an equivalent iptables ruleset for as many rules as possible. Currently, fwsnort downloads and processes the "Emerging Threats" Snort ruleset.

First download and unzip fwsnort:

cd; mkdir Downloads; cd Downloads
wget https://github.com/mrash/fwsnort/archive/master.zip
sudo unzip master.zip -d /usr/local/src
cd /usr/local/src/fwsnort-master

Then run the installation script:

sudo su
./install.pl
exit

Once installed, modify the HOME_NET parameter in /etc/fwsnort/fwsnort.conf so that it matches what was set up in psad.conf above.

Now the Snort rules need to be updated, parsed, and added to iptables:

sudo fwsnort --update-rules
sudo fwsnort --no-ipt-OUTPUT
sudo /var/lib/fwsnort/fwsnort.sh

Update: The --no-ipt-OUTPUT option discards packets that are emitted by the host. This was suggested by @cdeck3r in a honeypot project for the Raspberry Pi Zero W that uses PSADify. The project can be found here. Thanks Christian!

Unfortunately, the iptables rules won't persist across a reboot. To save them, simply add the above script to rc.local so that it's run each time the system starts:

sudo vi /etc/rc.local

Just add the following commands above the line containing the exit command.

sudo fwsnort --update-rules
sudo fwsnort --no-ipt-OUTPUT
/var/lib/fwsnort/fwsnort.sh
sudo psad -H

Note: Every other method of making iptables rules persistent did not work, including iptables-persistent and netfilter-persistent. You can ensure that the Snort rules have been added to iptables by running:

sudo fwsnort --ipt-list

The psad -H command just tells PSAD to grab the new rules. I also added a nightly cronjob to pull down the latest rules and load them into PSAD. Run sudo crontab -e and add the following lines:

PATH=/bin:/usr/bin:/usr/local/bin:/usr/sbin
0 0 * * * fwsnort --update-rules && fwsnort && /var/lib/fwsnort/fwsnort.sh
10 0 * * * psad -H

Then reboot!

Next Steps

The /var/log/psad directory contains some output files that provide data and statistics on incoming traffic. Running the following command will produce a file called status.out that compiles the more interesting details into a presentable format:

sudo psad --Status

There are some visualization tools available for PSAD but nothing that met my needs. Instead, I created a script that generates an HTML page from the data contained in the PSAD output files. You can download it here: PSADify on Github

Take a look at the output data and let me know if you have any observations!

Sources

This article was helpful in getting PSAD to work with UFW:
https://gist.github.com/netson/c45b2dc4e835761fbccc

8 thoughts on “PSAD on Raspberry Pi

  1. sandy

    Thanks for this-I came across it whilst looking for honeypots for Pi.
    My set up is a bit different-I do use a Raspberry Pi (4) as my Internet facing router-but the OS on it is OpenWRT-so I cant really use PSAD in the way you mention. What I do do is forward the syslogs to another devices (Odroid C2) , which collects syslogs for ALL my home devices (including the Rasp Pi 4 OpenWRT router).
    I have set up just PSAD on the Odroid, seems to be running ok-and I have put in the collected log from the Pi 4 as the target log under IPT_SYSLOG_FILE (this file, as well as "normal" syslog, has all the IPTables logs in there as well-so I can see who is trying to attack. I'm not using fwsnort and I've not amended any iptables rules or installed UFW-I just want to use PSAD to monitor and report on the received syslog files-make sense?
    I dont really see much from PSAD in sudo psad --Status -should I? An example from the syslog being monitored on the Odroid below:

    23-08-2020 {omitted] 13:07:42 warning kernel[]: [586075.127655] DROP wan in: IN=eth1 OUT= MAC=00:e0:7c:c8:d3:bc:0c:41:e9:9a:de:eb:08:00 SRC=52.45.208.102 DST=[omitted] LEN=40 TOS=0x00 PREC=0x00 TTL=233 ID=39666 DF PROTO=TCP SPT=443 DPT=51682 WINDOW=0 RES=0x00 RST URGP=0

    I'd be interested in your thoughts

    Cheers
    cabs

    Reply
  2. Paul Wratt

    this is a (reduced) snippet from an NginX error log from Alpine (I dont think its even running iptables, let alone UFW), so its just port 80, but it is rather interesting:

    2021/07/08 13:08:22 [error] *6 open()  failed, request: "POST /api/jsonws/invoke HTTP/1.1"
    2021/07/08 13:08:22 [error] *7 open()  failed, request: "POST /vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php HTTP/1.1"
    2021/07/08 13:08:22 [error] *8 open()  failed, request: "GET /vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php HTTP/1.1"
    2021/07/08 13:08:22 [error] *9 open()  failed, request: "GET /solr/admin/info/system?wt=json HTTP/1.1"
    2021/07/08 13:08:23 [error] *16 open()  failed, request: "GET /wp-content/plugins/wp-file-manager/readme.txt HTTP/1.1"
    2021/07/08 13:08:23 [error] *17  not found, request: "GET /console/ HTTP/1.1"
    2021/07/08 13:08:23 [error] *18 open()  failed, request: "POST /Autodiscover/Autodiscover.xml HTTP/1.1"
    2021/07/08 13:08:24 [error] *19 open()  failed, request: "GET /_ignition/execute-solution HTTP/1.1"
    Reply
    1. matt

      Christian,

      Thanks so much! I am extremely glad that you found the script useful. Please let me know if you find any problems.

      I noticed the issue you submitted to Github and have already made the suggested changes. I also incorporated one of the options you passed to fwsnort into my instructions above (dropping the iptables OUTPUT chain).

      In your project for the Raspberry Pi Zero W, I saw that some rules created by fwsnort cause iptables to exit with a "no space left on device" error. I could not find a similar error message on my Raspberry Pi 3 Model B. I will email you to get more details and will post an update for others if I see it affecting my setup.

      Best of luck, keep in touch!
      Matt - @disloops

      Reply
  3. Richard

    Dear Matt,

    Thank you for this walkthrough.
    When I execute the command: sudo /var/lib/fwsnort/fwsnort.sh
    I'll get an error, and no fwsnort rules are added to the iptables

    Do you know what is going wrong here?

    Thank you in advance,

    Best regards,

    Richard

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *