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.
The honeypot utilizes
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:
- HoneyPi low interaction honeypot with PSAD
- DShield Honeypot collects threat intelligence data for the SANS Internet Storm Center (ISC)
- Various Raspi projects, e.g.[1], [2], [3], using Thinkst OpenCanary honeypot to detect and observe technical details of hacking attempts
- PSAD + fwsnort IDS on Raspberry Pi is the "Father" of this project. :-)
What to learn more? - Check out https://adhdproject.github.io
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.
- Download Raspberry Pi OS Lite
- Flash image onto SD card using the BalenaEtcher
- Once the image is created, access the SD card on your Windows or Linux machine using a card reader.
- Copy an empty file named
ssh
into the card's boot folder. - Create
wpa_supplicant.conf
file by running the commands below. Insert the country and your network SSID.
it does not provide a prompt. Just enter the passphrase and hit enter, then it returns to the prompt.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
- Copy the file
wpa_supplicant.conf
into the SD card's boot folder - Insert card into Raspberry Pi and boot up.
- Give it about 5 minutes and try to ssh into the Raspi using the default login (user / pass):
pi / raspberry
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
causeiptables
to exit withno space left on device
message when loading these rules. Theseiptables
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 logiptables
'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
.
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.
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.
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>
#!/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
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