// "[o.o]"



Let us put the piggy (snort3 in jail. Grab a snack, this is a bit long...

First we create a folder where we keep the jails, and a folder for the new jail (or zfs volume if that is more your cup of tea)
Then we do a very basic install of FreeBSD in that jail.

$ doas mkdir -p /home/jails/snort3
$ doas bsdinstall jail /home/jails/snort3

After that we make some changes to the configs on the host

Add this to the /etc/rc.conf
jail_enable="YES"
jail_sysvipc_allow="YES"
jail_snort3_parameters="allow.raw_sockets=1"
ifconfig_re0_alias1="inet 192.168.0.66 netmask 255.255.255.255"

Add an entry like this, the part between 'snort3 {}', for each jail to your /etc/jail.conf
re0 is your network interface, and after the pipe is the ip of the jail (can ofcourse be a different network)
ip4=inherit;
exec.clean;
mount.devfs;

snort3 {
    host.hostname = jailsnort3;                # Hostname
    ip4.addr = re0|192.168.0.66;               # IP address of the jail
    path = "/home/jails/snort3";               # Path to the jail
    mount.devfs;                               # Mount devfs inside the jail
    devfs_ruleset = 5;
    exec.start = "/bin/sh /etc/rc";            # Start command
    exec.stop = "/bin/sh /etc/rc.shutdown";    # Stop command
}


Then to allow the jail to communicate externally, we add these options in /etc/sysctl.conf
allow.raw_sockets=1
allow.sysvipc=1
security.jail.sysvipc_allowed=1

Lets start the jail (if you run into problems, first try to restart the host then the jail should start automaticly at boot):
$ doas service jail start # you can add your jail name after start if you have several and just want to start one

Upgrade the jail to a new release version:
$ doas freebsd-update -j snort3 -r 13.5-RELEASE upgrade
$ doas freebsd-update -j snort3 -r 13.5-RELEASE install
$ doas service jail restart snort3
$ doas freebsd-update -j snort3 -r 13.5-RELEASE install

Now lets enter the jail we created
$ doas jexec snort3 /bin/sh


Good to know for jail maintainance. There are jail wrappers, but i prefer the basic

Keep the jail updated (can be skipped if pkgbasified):
$ doas freebsd-update -j snort3 fetch install

Keep the jail packages updated:
$ doas pkg -j snort3 update && doas pkg -j snort3 upgrade

Restart a jail: $ doas service jail restart snort3

If you from the host can't remove a old jail folder, first do:
$ doas chflags -R noschg jailfolder/ && doas rm -rf jailfolder

Now lets enter the jail if you are not there already:
$ doas jexec snort3 /bin/sh

Install snort3 and dependencies (followed this more or less: https://www.zenarmor.com/docs/linux-tutorials/how-to-install-and-configure-snort-on-freebsd)
# pkg install snort3 python3 py311-requests lzlib openssl pcre2 lzma libpcap

Get pulledpork3 to update rules automaticly:
# fetch https://github.com/shirkdog/pulledpork3/archive/refs/heads/main.zip
# unzip main.zip


Create folders and copy away pulled pork files:
# mkdir /usr/local/etc/pulledpork/
# cp pulledpork3-main/etc/pulledpork.conf /usr/local/etc/pulledpork/
# mkdir -p /usr/local/bin/pulledpork/lib
# cp pulledpork3-main/pulledpork.py /usr/local/bin/pulledpork/
# cp -r pulledpork3-main/lib/ /usr/local/bin/pulledpork/lib

Test pulledpork:
# python3 /usr/local/bin/pulledpork/pulledpork.py -V
PulledPork v3.0.0.5

    https://github.com/shirkdog/pulledpork3
      _____ ____
     `----,\    )   PulledPork v3.0.0.5
      `--==\\  /    Lowcountry yellow mustard bbq sauce is the best bbq sauce. Fight me.
       `--==\\/
     .-~~~~-.Y|\\_  Copyright (C) 2021 Noah Dietrich, Colin Grady, Michael Shirk
  @_/        /  66\_  and the PulledPork Team!
    |    \   \   _(")
     \   /-| ||'--'   Rules give me wings!
      \_\  \_\\
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


Add this to the config /usr/local/etc/pulledpork/pulledpork.conf
--- edit ---
also add a line with like:
snort_version = 3.9.0.0
This version should replicate a version of snortrules-snapshot-VERSION.tar.gz from https://snort.org/downloads#rules

blocklist_path = /usr/local/lib/snort/intel/default.blocklist
rule_path = /usr/local/lib/snort/rules/pulledpork.rules
sorule_path = /usr/local/lib/snort/rules/
community_ruuleset = true
registered_ruleset = true # you can use the community_ruleset also if you dont want to register to snort.org, but registered gets more rules
oinkcode = 12345666 # your oinkcode from if you registered to snort.org, otherwise leave it as is.
snort_blocklist = true
et_blocklist = true


Add something like this maby once a week in cron:
# crontab -e
13 13 * * * python3 /usr/local/bin/pulledpork/pulledpork.py -c /usr/local/etc/pulledpork/pulledpork.conf

Verify that snort works (look how cute piggy)
# snort -V

   ,,_     -*> Snort++ <*-
  o"  )~   Version 3.8.1.0
   ''''    By Martin Roesch & The Snort Team
           http://snort.org/contact#team
           Copyright (C) 2014-2025 Cisco and/or its affiliates. All rights reserved.
           Copyright (C) 1998-2013 Sourcefire, Inc., et al.
           Using DAQ version 3.0.19
           Using Hyperscan version 5.4.2 2025-08-12
           Using libpcap version 1.10.5
           Using LuaJIT version 2.1.1748459687
           Using LZMA version 5.6.3
           Using OpenSSL 1.1.1w-freebsd  11 Sep 2023
           Using PCRE2 version 10.45 2025-02-05
           Using ZLIB version 1.3.1


configuration of snort:
/usr/local/etc/snort/snort_defaults.lua (edit below)
RULE_PATH = '/usr/local/lib/snort/rules/'
BUILTIN_RULE_PATH = '/usr/local/lib/snort/builtin_rules/'
PLUGIN_RULE_PATH = '/usr/local/lib/snort/so_rules/'

-- If you are using reputation preprocessor set these
WHITE_LIST_PATH = '/usr/local/lib/snort/intel/'
BLACK_LIST_PATH = '/usr/local/lib/snort/intel/'


# tar zxf snortrules-snapshot-xxx.tar.gz (after downloaded latest snapshot or community rules from snort.org)
# mkdir /usr/local/lib/snort/rules
# mkdir /usr/local/lib/snort/so_rules
# mkdir /usr/local/lib/snort/builtins
# cp -r builtins/ /usr/local/lib/snort/builtins/
# cp -r so_rules/ /usr/local/lib/snort/so_rules/
# cp -r rules/ /usr/local/lib/snort/rules/
# cp etc/file_magic.lua /usr/local/etc/snort/

add a row after include in file /usr/local/etc/snort/snort.lua:
include 'file_magic.lua'

# tar zxf openappid-xxxx.tar.gz (after downloaded from snort.org)
# mkdir -p /usr/local/lib/snort/appid/odp
# cp -r odp/ /usr/local/lib/snort/appid/odp
# mkdir /usr/local/lib/snort/intel
# touch /usr/local/lib/snort/intel/ip-whitelist
# touch /usr/local/lib/snort/intel/ip-blacklist

Get a block list from snort https://snort.org/downloads/ip-block-list/terms (you need to use a webbrowser to accept terms)
# cp ip-filter /usr/local/lib/snort/intel/ip-blacklist

Add rules in the ips section in snort.lua, like all snort3*.rules from /usr/local/lib/snort/rules/
you have a line like: variables = default_variables
add a comma after that, then add:
rules = [[
inclue /usr/local/lib/snort/rules/snort3-app-detect.rules
... here you add all the other rules files as includes like the above line
]]

Now try to start snort:
# snort -c /usr/local/etc/snort/snort.lua --daq-dir /usr/local/lib/daq -i re0 -l /var/log/snort -k none

you will see something like 46000 rules loaded

Create rc start script and chmod +x /usr/local/etc/rc.d/snort it after
#!/bin/sh
# Change the interface as necessary
interface="re0"
prog="snort"
pid=`ps ax | awk '{if (match($5, ".*/snort$") || $5 == "snort") print $1}'`
start() {
        if test "$pid" != ""; then
                echo "$prog is already running as pid $pid."
        else
        echo "Starting $prog..."
        # This will run snort as root
        /usr/local/bin/snort -c /usr/local/etc/snort/snort.lua --daq-dir /usr/local/lib/daq -D \
	 -i ${interface} -l /var/log/snort --lua "alert_csv = { file = true } -M"
        # if you dont want snort to log to /var/log/messages when it starts for example, remove -M from above
        # This will run snort as user 'snort' and group 'snort'
        # /usr/local/bin/snort -c /usr/local/etc/snort.lua -D -u snort -g snort -i ${interface} -l /var/log/snort
        fi
}
stop () {
        if test "$pid" != ""; then
                kill $pid
                echo "$prog stopped."
        else
                echo "$prog is not running. Cannot stop."
        fi
        # This is a killall method, regardless of the variable 'pid'
        # /usr/bin/killall snort && echo "$prog stopped."
}
status() {
        if test "$pid" != ""; then
                echo "$prog is running as pid $pid."
        else
                echo "$prog is not running."
        fi
}
case "$1" in
start)
        start
        ;;
stop)
        stop
        ;;
restart)
        stop
        # It seems that killing of snort requires some time
        sleep 5
        # The pid variable has not been cleared when snort is killed,
        # but we don't know if snort is really killed, so check again
        pid=""
        pid=`ps ax | awk '{if (match($5, ".*/snort$") || $5 == "snort") print $1}'`
        start
        ;;
status)
        status
        ;;
*)
        echo $"Usage: $0 {start|stop|restart|status}"
        ;;
esac
exit 0
# end

Verify that the pulledpork script works:
# python3 /usr/local/bin/pulledpork/pulledpork.py -c /usr/local/etc/pulledpork/pulledpork.conf

Running into this bug https://github.com/shirkdog/pulledpork3/issues/57
could it be related to if snort has moved stuff to AWS!?
Just saw that community_ruleset = true fetches things
if it would work for you, be happy. otherwise disable in crontab?
--- edit ---
this was all related to the version of snort that pulledpork uses, as of writing 3.8.1.0
which is not a snortrules-snapshot version on https://snort.org/downloads#rules.
By adding a snort_version = 3.9.0.0 to the pulledpork.conf it worked again.

You can verify that downloading the snortrules work, by running:
fetch 'https://snort.org/rules/snortrules-snapshot-3900.tar.gz?oinkcode=OINKCODE' -o snortrules-snapshot-3900.tar.gz

# mkdir /var/log/snort
# touch /var/log/snort/alert_csv.txt

then finally start the service:
# service snort start

it should write alot of output, then finally end with:
initializing daemon mode
child process is 53623
Commencing packet processing
++ [0] re0

Verify that the snort process is running : ps ax|grep snort


Wowie... this is a beast.
we did it. Oink oink!

Fly piggy flyyy