Skip to content

Instantly share code, notes, and snippets.

@cdeck3r
Last active January 13, 2024 09:27
Show Gist options
  • Save cdeck3r/5151c53b282431158a59091c0e26f27d to your computer and use it in GitHub Desktop.
Save cdeck3r/5151c53b282431158a59091c0e26f27d to your computer and use it in GitHub Desktop.
Setup of low interaction honeypot on a Raspberry Pi Zero W

Low Interaction Honeypot for the Raspberry Pi Zero W

Table of Contents

Goal and Objective

This honeypot system aims at the discovery of malicious activities in private home networks. It passively sits there and logs connection attempts and their network packet options.

The system's objective is to inform the administrator of a private home network about unusual activities, e.g. port scanning or strange connection attempts from computers within the network.

A typical use case is to raise an early red flag, when malicious software tries to find a host.

Disclaimer: Please be aware, this design is only an observer or sensor, when it receives network traffic. It neither guarantees the discovery of malicious events, not it guarantees the absence of such events. It also does not relieve you from all measures related to protect your network and computer systems, e.g. the use of firewalls and virus scanners, regular software updates, and personal awareness of recent security risks.

Approach

The honeypot utilizes

  • PSAD to detect port scans and other suspicious traffic
  • fwsnort to detect application level attacks

PSAD analyzes iptables log messages to detect port scans and other suspicious traffic. fwsnort adds iptables rules generated from SNORT rules. Latter define how malicious traffic looks like in terms of packet content from known attacks exploiting vulnerabilities. Using fwsnort iptables is enabled to inspect packet payloads and test it with SNORT rules. If a rule fires, this will be notified by PSAD.

Related projects:

What to learn more? - Check out https://adhdproject.github.io

Hardware Setup

The honeypot runs on a Raspberry Pi Zero W. It connects via Wifi to your home network.

Tools:

  • SD card flash utility: BalenaEtcher
  • wpa_passphrase utility, AFAIK it only works on Linux
  • ssh, you may use winscp on Windows

If you do not have wpa_passphrase utility, please check Raspi wireless setup for alternative procedures.

  1. Download Raspberry Pi OS Lite
  2. Flash image onto SD card using the BalenaEtcher
  3. Once the image is created, access the SD card on your Windows or Linux machine using a card reader.
  4. Copy an empty file named ssh into the card's boot folder.
  5. Create wpa_supplicant.conf file by running the commands below. Insert the country and your network SSID.
    cat << EOF > wpa_supplicant.conf
    ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
    update_config=1
    country=<Insert 2 letter ISO 3166-1 country code here>
    EOF
    
    wpa_passphrase "<your SSID here>" | grep -v "#psk" >> wpa_supplicant.conf
    
    it does not provide a prompt. Just enter the passphrase and hit enter, then it returns to the prompt.
  6. Copy the file wpa_supplicant.conf into the SD card's boot folder
  7. Insert card into Raspberry Pi and boot up.
  8. Give it about 5 minutes and try to ssh into the Raspi using the default login (user / pass): pi / raspberry

Software Setup

The software setup is sourced from a blog article on https://disloops.com/psad-on-raspberry-pi/. We took the description and created the script below. Copy it (using scp) onto the Raspberry Pi and run it as user pi.

There are some changes from the cited blogpost above:

  • Some rules created by fwsnort cause iptables to exit with no space left on device message when loading these rules. These iptables rules have a very extensive set of parameters. The script excludes the SIDs for snort rules causing this error.
  • Since we use the honeypot from within the home network, iptables's FORWARD chain is unused. fwsnort is called with --no-ipt-FORWARD and will not handle packets from the FORWARD chain.
  • The same reason applies to iptables OUTPUT chain. fwsnort is called with --no-ipt-OUTPUT and will not handle packets from the OUTPUT chain.
  • As a consequence, logging directives for ufw only log iptables's INPUT chain.

Altogether, there are more than 10.000 rules in the fwsnort chains. The script logs some rule stats in /var/log/fwsnort/fwsnort.log.

Honeypot Output

The script creates cronjobs to daily status PSAD status reports at 6am. The report as well as PSAD logs are contained in /var/log/psad/.

The author of the above-mentioned blog created the PSADify tool to convert Port Scan Attack Detector (PSAD) output into HTML. You find the daily report in /home/pi/status.html after it was created at 6am.

Config

The script can be started on a fresh RaspiOS installation. It defines two variables at the beginning:

MY_HOSTNAME="homeserver"
MY_TZ="Europe/Berlin"

Additionally, it requests a password change of the pi user.

Download and Install

You can directly download or even run the script from this gist.

Download script from this gist and redirect stream into honeypot.sh:

curl -sL https://gist.githubusercontent.com/cdeck3r/5151c53b282431158a59091c0e26f27d/raw/HoneyPiZeroW.md | sed -n -e '/^#!\/bin\/bash/,$p' | sed '$d' > honeypot.sh

Run script from this gist:

bash <(curl -sL https://gist.githubusercontent.com/cdeck3r/5151c53b282431158a59091c0e26f27d/raw/HoneyPiZeroW.md | sed -n -e '/^#!\/bin\/bash/,$p' | sed '$d')

Manual installation:

  • Copy and save the script below in file
  • Transfer the file to the Raspberry Pi. You may want to use winscp on Windows
  • Login to the Raspberry Pi with the user pi
  • Run the script file: bash <file>

Script

#!/bin/bash
set -e

MY_HOSTNAME="homeserver"
MY_TZ="Europe/Berlin" # see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones

##################################
# 0. startup check
##################################

echo "Check startup user"

CURR_USER=$(id --user --name)
if [ "${CURR_USER}" != "pi" ]; then
    echo "User mismatch. Script must run as user: pi. Abort."
    exit 1
fi

##################################
# 1. change standard password
##################################

echo "Request password change"

# 1a. Current password: raspberry
# 1b. New password: <enter your new password>
# 1v. Retype new password: <enter your new password again>

passwd 

##################################
# 2. change hostname
##################################

echo "Change hostname to ${MY_HOSTNAME}"

NEW_NAME="${MY_HOSTNAME}"
CURR_HOSTNAME=$(hostname)

sudo -s -- <<EOF 
if [ "${CURR_HOSTNAME}" != "${NEW_NAME}" ]; then
    echo "${NEW_NAME}" >/etc/hostname
    sed -i "s/${CURR_HOSTNAME}/${NEW_NAME}/g" /etc/hosts
    hostname "${NEW_NAME}"
fi
EOF

##################################
# 3. change timezone
##################################

echo "Change timezone to ${MY_TZ}"

sudo -s -- <<EOF 
timedatectl set-timezone "${MY_TZ}"
EOF

##################################
# 4. Install software
##################################

echo "Install software: ufw, psad"

sudo -s -- <<EOF 
apt-get update
apt-get install -y ufw psad
apt-get -y --auto-remove purge avahi-daemon
EOF

##################################
# 5. Setup ufw logging
##################################

echo "Enable ufw"
# we only allow port 22

sudo -s -- <<EOF 
ufw --force reset
ufw allow SSH
ufw --force enable
systemctl enable ufw
systemctl restart ufw
EOF

echo "Configure ufw logs"
# ufw logs only in /var/log/ufw.log
sudo -s -- <<EOF
sed -i "s/^#& stop.*/\& stop/" /etc/rsyslog.d/20-ufw.conf 
systemctl restart rsyslog
EOF

sudo ufw logging on 

echo "Change ufw logging directives"
# change logging directives
LOG_DIRECTIVE1="-A INPUT -j LOG --log-tcp-options"
LOG_DIRECTIVE2="-A FORWARD -j LOG --log-tcp-options"
BEFORE_RULES="before.rules"
BEFORE6_RULES="before6.rules"

sudo -s -- <<EOF 
cat "/etc/ufw/${BEFORE_RULES}" | grep -v -e "${LOG_DIRECTIVE1}" | grep -v -e "${LOG_DIRECTIVE2}" | grep -v "COMMIT" > "${HOME}/${BEFORE_RULES}"
cat "/etc/ufw/${BEFORE6_RULES}" | grep -v -e "${LOG_DIRECTIVE1}" | grep -v -e "${LOG_DIRECTIVE2}" | grep -v "COMMIT" > "${HOME}/${BEFORE6_RULES}"

echo "${LOG_DIRECTIVE1}" >> "${HOME}/${BEFORE_RULES}"
echo "COMMIT" >> "${HOME}/${BEFORE_RULES}"
echo "${LOG_DIRECTIVE1}" >> "${HOME}/${BEFORE6_RULES}"
echo "COMMIT" >> "${HOME}/${BEFORE6_RULES}"

cp "${HOME}/${BEFORE_RULES}" "/etc/ufw/${BEFORE_RULES}"
cp "${HOME}/${BEFORE6_RULES}" "/etc/ufw/${BEFORE6_RULES}"

EOF

sudo ufw reload

# cleanup
rm -rf "${HOME}/before.rules"
rm -rf "${HOME}/before6.rules"

##################################
# 6. Configure PSAD 
##################################

echo "Configure PSAD Port Scan Detection"

sudo -s -- <<EOF
sed -i "s/^HOSTNAME.*/HOSTNAME ${HOSTNAME};/" /etc/psad/psad.conf
sed -i "s/^HOME_NET.*/HOME_NET any;/" /etc/psad/psad.conf
sed -i "s/^ALERTING_METHODS.*/ALERTING_METHODS noemail;/" /etc/psad/psad.conf
sed -i "s/^EXPECT_TCP_OPTIONS.*/EXPECT_TCP_OPTIONS Y;/" /etc/psad/psad.conf
sed -i "s/^AUTO_DETECT_JOURNALCTL.*/AUTO_DETECT_JOURNALCTL N;/" /etc/psad/psad.conf
sed -i "s/^ENABLE_SCAN_ARCHIVE.*/ENABLE_SCAN_ARCHIVE Y;/" /etc/psad/psad.conf
sed -i "s/^IMPORT_OLD_SCANS.*/IMPORT_OLD_SCANS Y;/" /etc/psad/psad.conf
sed -i "s/^IPT_SYSLOG_FILE.*/IPT_SYSLOG_FILE \/var\/log\/ufw.log;/" /etc/psad/psad.conf
EOF

sudo psad --HUP
sudo psad --sig-update

##################################
# 7. Install fwsnort
##################################

# if there is a previous installation
# flush the fwsnort chains
sudo -s -- <<EOF
[[ -x /usr/sbin/fwsnort ]] && { /usr/sbin/fwsnort --ipt-flush; }
EOF

echo "Download and unzip fwsnort"
cd; 
sudo rm -rf Downloads
mkdir -p Downloads && cd Downloads
wget --no-verbose https://github.com/mrash/fwsnort/archive/master.zip
unzip -q master.zip 
cd fwsnort-master
chmod a+x install.pl

echo "Install fwsnort"
# enable auto-yes
sed -i "s/my \$ans = '';/my \$ans = 'n';/g" install.pl
sudo -s -- <<EOF
./install.pl
EOF

echo "Configure fwsnort"
sudo -s -- <<EOF
sed -i "s/^HOME_NET.*/HOME_NET any;/" /etc/fwsnort/fwsnort.conf
EOF

# Create fwsnort startup script /root/fwsnort_startup.sh
sudo -s -- <<EOF
cat << 'FWSNORT' > /root/fwsnort_startup.sh
#!/bin/bash

FWSNORT_LOG=/var/log/fwsnort/fwsnort.log

/usr/sbin/fwsnort --update-rules
# run fwsnort to generate iptables rules
#   - exclude rules for FORWARD and OUTPUT chain
#   - exclude snort rules, which cause iptables to crash on Raspberry Pi Zero W
/usr/sbin/fwsnort --no-ipt-FORWARD --no-ipt-OUTPUT --exclude-sid "2025413,2025412,2025414,2025415,2030901,2031069,2031236,2031299,2032952,2033034,2033152"
/var/lib/fwsnort/fwsnort.sh

##
# some logging to FWSNORT_LOG
##

# Lines in rules file
echo "\$(date) - [Check] Lines in rules file: \$(wc -l /var/lib/fwsnort/fwsnort.save)" >> "\${FWSNORT_LOG}"
# List all fwsnort currently active iptables rules (lists the fwsnort chains). 
echo "\$(date) - [Check] Rules in fwsnort chains: \$(fwsnort --ipt-list | wc -l)" >> "\${FWSNORT_LOG}"
# iptables rules count src: https://serverfault.com/a/868091
echo "\$(date) - [Check] Rules in iptables: \$(iptables -n --list --line-numbers | sed '/^num\|^$\|^Chain/d' | wc -l)" >> "\${FWSNORT_LOG}"

# notify psad about new rules
psad --HUP
FWSNORT

EOF
sudo /root/fwsnort_startup.sh

# return to /home/pi and cleanup
cd; 
sudo rm -rf /home/pi/Downloads

##################################
# 8. Install cronjobs
##################################

echo "Add fwsnort startup script to root crontab"

# remove existing fwsnort startup script from crontab and re-add it
sudo -s -- <<EOF
crontab -l | grep -v 'PATH=' | grep -v 'fwsnort_startup.sh' | grep -v 'shutdown' | grep -v 'psad' | crontab - || { echo "Ignore error: $?"; }
(
    crontab -l
    echo "PATH=/bin:/usr/bin:/usr/local/bin:/usr/sbin"
    echo "@reboot sleep 300 && /root/fwsnort_startup.sh" 
    echo "15 0 * * * /sbin/shutdown -r now"
    echo "0 6 * * * /usr/sbin/psad --Status"
) | crontab - || {
    echo "Error adding cronjob. Code: $?"
}
EOF

sudo systemctl restart cron.service

##################################
# 9. Install PSADify
##################################

# download
echo "Download and unzip PSADify"
cd; 
sudo rm -rf Downloads
mkdir -p Downloads && cd Downloads
wget --no-verbose https://github.com/disloops/psadify/archive/refs/heads/master.zip
unzip -q master.zip 
mv psadify-master psadify

sudo -s -- <<EOF
cp -R psadify /root
chown -R root:root /root/psadify
EOF

echo "Add PSADify cronjob"

# remove existing PSADify cronjob from crontab and re-add it
sudo -s -- <<EOF
crontab -l | grep -v 'psadify.py' | crontab - || { echo "Ignore error: $?"; }
(
    crontab -l
    echo "0 6 * * *  python3 /root/psadify/psadify.py -o /home/pi/status.html && chown pi:pi /home/pi/status.html  >/dev/null 2>&1"
) | crontab - || {
    echo "Error adding cronjob. Code: $?"
}
EOF

sudo systemctl restart cron.service

##################################
# 10. Reduce power consumption
##################################

echo "Deactivate bluetooth"
rfkill block bluetooth

echo "Stop and disable bluetooth services"
declare -a SYSTEMD_SERVICES=("bluetooth" "hciuart")

# iterate through bluetooth services and disable them
for serv in "${SYSTEMD_SERVICES[@]}"; do
    systemctl is-active "${serv}" >/dev/null && {
sudo -s -- <<EOF 
        systemctl stop "${serv}" || { echo "Ignore error when stopping service: ${serv}"; }
        systemctl disable "${serv}" || { echo "Ignore error when disabling service: ${serv}"; }
EOF
    }
done
sudo systemctl daemon-reload

echo "Disable HDMI"
tvservice --off

echo "Disable actitivty LED"
ACT_LED=/sys/class/leds/led0/trigger
echo none | sudo tee "${ACT_LED}"

# disable ACT_LED at bootup
sudo -s -- <<EOF
crontab -l | grep -v "${ACT_LED}" | crontab - || { echo "Ignore error: $?"; }
(
    crontab -l
    echo "@reboot sleep 60 && echo none | tee "${ACT_LED}"" 
) | crontab - || {
    echo "Error adding cronjob. Code: $?"
}
EOF

sudo systemctl restart cron.service


echo "Some vcgencmd info..."
echo "---------------------"
VCGENCMDS="hostname && vcgencmd get_camera; vcgencmd get_throttled ; vcgencmd measure_temp;  vcgencmd measure_temp pmic; vcgencmd measure_volts core; vcgencmd measure_volts sdram_c; vcgencmd measure_volts sdram_i; vcgencmd measure_volts sdram_p; vcgencmd get_config total_mem; vcgencmd get_mem arm; vcgencmd get_mem gpu; vcgencmd mem_oom; vcgencmd display_power -1 0; vcgencmd display_power -1 1; vcgencmd display_power -1 2; vcgencmd display_power -1 3; vcgencmd display_power -1 7"
eval "${VCGENCMDS}"
echo "---------------------"
##################################
# Final cleanup
##################################

# return to /home/pi and cleanup
cd; 
sudo rm -rf /home/pi/Downloads
@disloops
Copy link

Christian,

Update on the question above: I committed a change that addressed the issue and also corrected a rather serious error in the reporting on the "Last Attacks" page.

Please take a look at the commit and incorporate the latest version of the script into your project. I've only done minimal testing so far but I believe the changes are sound. Apologies for the updates as soon as you've finished releasing your project, but your interest in PSADify helped me to discover and correct the issue.

Update here: disloops/psadify@6efb719

@cdeck3r
Copy link
Author

cdeck3r commented Aug 12, 2021

Hi Matt,
I summarized the discussion in the following issue disloops/psadify#3. I will review your code and comment on this issue. Give me a couple of hours.

Christian

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment