Snort 2.9 introduces the DAQ, or Data Acquisition library, for packet I/O. The DAQ replaces direct calls to libpcap functions with an abstraction layer that facilitates operation on a variety of hardware and software interfaces without requiring changes to Snort. It is possible to select the DAQ type and mode when invoking Snort to perform pcap readback or inline operation, etc. The DAQ library may be useful for other packet processing applications and the modular nature allows you to build new modules for other platforms. This README summarizes the important things you need to know to use the DAQ. Building the DAQ Library and DAQ Modules ======================================== The DAQ is bundled with Snort but must be built first using these steps: ./configure make sudo make install This will build and install both static and dynamic DAQ modules. Note that pcap >= 1.0.0 is required. pcap 1.1.1 is available at the time of this writing and is recommended. Also, libdnet is required for IPQ and NFQ DAQs. If you get a relocation error trying to build those DAQs, you may need to reinstall libdnet and configure it with something like this: ./configure "CFLAGS=-fPIC -g -O2" You may also experience problems trying to find the dynamic dnet library because it isn't always named properly. Try creating a link to the shared library (identified by its .x or .x.y etc. extension) with the same name but with ".so" inserted as follows: $ ln -s libdnet.1.1 libdnet.so.1.1 $ ldconfig -Rv /usr/local/lib 2>&1 | grep dnet Adding /usr/local/lib/libdnet.so.1.1 Alternatively, you should be able to fix both issues as follows: libtoolize --copy --force aclocal -I config autoheader autoconf automake --foreign When the DAQ library is built, both static and dynamic flavors will be generated. The various DAQ modules will be built if the requisite headers and libraries are available. You can disable individual modules, etc. with options to configure. For the complete list of configure options, run: ./configure --help PCAP Module =========== pcap is the default DAQ. If snort is run w/o any DAQ arguments, it will operate as it always did using this module. These are equivalent: ./snort -i <device> ./snort -r <file> ./snort --daq pcap --daq-mode passive -i <device> ./snort --daq pcap --daq-mode read-file -r <file> You can specify the buffer size pcap uses with: ./snort --daq pcap --daq-var buffer_size=<#bytes> * The pcap DAQ does not count filtered packets. * AFPACKET Module =============== afpacket functions similar to the pcap DAQ but with better performance: ./snort --daq afpacket -i <device> [--daq-var buffer_size_mb=<#MB>] [--daq-var debug] If you want to run afpacket in inline mode, you must set device to one or more interface pairs, where each member of a pair is separated by a single colon and each pair is separated by a double colon like this: eth0:eth1 or this: eth0:eth1::eth2:eth3 By default, the afpacket DAQ allocates 128MB for packet memory. You can change this with: --daq-var buffer_size_mb=<#MB> Note that the total allocated is actually higher, here's why. Assuming the default packet memory with a snaplen of 1518, the numbers break down like this: * The frame size is 1518 (snaplen) + the size of the AFPacket header (66 bytes) = 1584 bytes. * The number of frames is 128 MB / 1518 = 84733. * The smallest block size that can fit at least one frame is 4 KB = 4096 bytes @ 2 frames per block. * As a result, we need 84733 / 2 = 42366 blocks. * Actual memory allocated is 42366 * 4 KB = 165.5 MB. NFQ Module ========== NFQ is the new and improved way to process iptables packets: ./snort --daq nfq \ [--daq-var device=<dev>] \ [--daq-var proto=<proto>] \ [--daq-var queue=<qid>] <dev> ::= ip | eth0, etc; default is IP injection <proto> ::= ip4 | ip6 |; default is ip4 <qid> ::= 0..65535; default is 0 This module can not run unprivileged so ./snort -u -g will produce a warning and won't change user or group. Notes on iptables are given below. IPQ Module ========== IPQ is the old way to process iptables packets. It replaces the inline version available in pre-2.9 versions built with this: ./configure --enable-inline Note that layer 2 resets are not supported with the IPQ DAQ: config layer2resets[: <mac>] Start the IPQ DAQ as follows: ./snort --daq ipq \ [--daq-var device=<dev>] \ [--daq-var proto=<proto>] \ <dev> ::= ip | eth0, etc; default is IP injection <proto> ::= ip4 | ip6; default is ip4 This module can not run unprivileged so ./snort -u -g will produce a warning and won't change user or group. Notes on iptables are given below. IPFW Module =========== IPFW is available for BSD systems. It replaces the inline version available in pre-2.9 versions built with this: ./configure --enable-ipfw This command line argument is no longer supported: ./snort -J <port#> Instead, start Snort like this: ./snort --daq ipfw [--daq-var port=<port>] <port> ::= 1..65535; default is 8000 * IPFW only supports ip4 traffic. Notes on FreeBSD and OpenBSD are given below. Dump Module =========== The dump DAQ allows you to test the various inline mode features available in 2.9 Snort like injection and normalization. ./snort -i <device> --daq dump ./snort -r <pcap> --daq dump By default a file named inline-out.pcap will be created containing all packets that passed through or were generated by snort. You can optionally specify a different name. ./snort --daq dump --daq-var file=<name> dump uses the pcap daq for packet acquisition. It therefore does not count filtered packets (a pcap limitation). Note that the dump DAQ inline mode is not an actual inline mode. Furthermore, you will probably want to have the pcap DAQ acquire in another mode like this: ./snort -r <pcap> -Q --daq dump --daq-var load-mode=read-file ./snort -i <device> -Q --daq dump --daq-var load-mode=passive Notes on iptables ================= These notes are just a quick reminder that you need to set up iptables to use the IPQ or NFQ DAQs. Doing so may cause problems with your network so tread carefully. The examples below are intentionally incomplete so please read the related documentation first. Here is a blog post by Marty for historical reference: http://archives.neohapsis.com/archives/snort/2000-11/0394.html You can check this out for queue sizing tips: http://www.inliniac.net/blog/2008/01/23/improving-snort_inlines-nfq-performance.html You might find useful IPQ info here: http://snort-inline.sourceforge.net/ Use this to examine your iptables: sudo /sbin/iptables -L Use something like this to set up NFQ: sudo /sbin/iptables -I <table> [<protocol stuff>] [<state stuff>] -j NFQUEUE --queue-num 1 Use something like this to set up IPQ: sudo iptables -I FORWARD -j QUEUE Use something like this to "disconnect" snort: sudo /sbin/iptables -D <table> <rule pos> Be sure to start Snort prior to routing packets through NFQ with iptables. Such packets will be dropped until Snort is started. The queue-num is the number you must give Snort. If you are running on a system with both NFQ and IPQ support, you may experience some start-up failures of the sort: The solution seems to be to remove both modules from the kernel like this: modprobe -r nfnetlink_queue modprobe -r ip_queue and then install the module you want: modprobe ip_queue or: modprobe nfnetlink_queue These DAQs should be run with a snaplen of 65535 since the kernel defrags the packets before queuing. Also, no need to configure frag3. Notes on FreeBSD::IPFW ====================== Check the online manual at: http://www.freebsd.org/doc/handbook/firewalls-ipfw.html. Here is a brief example to divert icmp packets to Snort at port 8000: To enable support for divert sockets, place the following lines in the kernel configuration file: options IPFIREWALL options IPDIVERT (The file in this case was: /usr/src/sys/i386/conf/GENERIC; which is platform dependent.) You may need to also set these to use the loadable kernel modules: /etc/rc.conf: firewall_enable="YES" /boot/loader.conf: ipfw_load="YES" ipdivert_load="YES" $ dmesg | grep ipfw ipfw2 (+ipv6) initialized, divert loadable, nat loadable, rule-based forwarding disabled, default to deny, logging disabled $ kldload -v ipdivert Loaded ipdivert, id=4 $ ipfw add 75 divert 8000 icmp from any to any 00075 divert 8000 icmp from any to any $ ipfw list ... 00075 divert 8000 icmp from any to any 00080 allow icmp from any to any ... * Note that on FreeBSD, divert sockets don't work with bridges! Please refer to the following articles for more information: https://forums.snort.org/forums/support/topics/snort-inline-on-freebsd-ipfw http://freebsd.rogness.net/snort_inline/ NAT gateway can be used with divert sockets if the network environment is conducive to using NAT. The steps to set up NAT with ipfw are as follows: 1. Set up NAT with two interface em0 and em1 by adding the following to /etc/rc.conf gateway_enable="YES" natd_program="/sbin/natd" # path to natd natd_enable="YES" # Enable natd (if firewall_enable == YES) natd_interface="em0" # Public interface or IP Address natd_flags="-dynamic" # Additional flags defaultrouter="" ifconfig_em0="DHCP" ifconfig_em1="inet 192.168.1.2 netmask 255.255.255.0" firewall_enable="YES" firewall_script="/etc/rc.firewall" firewall_type="simple" Here em0 is connected to external network and em1 to host-only LAN. 2. Add the following divert rules to divert packets to Snort above and below the NAT rule in the "Simple" section of /etc/rc.firewall. ... # Inspect outbound packets (those arriving on "inside" interface) # before NAT translation. ${fwcmd} add divert 8000 all from any to any in via ${iif} case ${natd_enable} in [Yy][Ee][Ss]) if [ -n "${natd_interface}" ]; then ${fwcmd} add divert natd all from any to any via ${natd_interface} fi ;; esac ... # Inspect inbound packets (those arriving on "outside" interface) # after NAT translation that aren't blocked for other reasons, # after the TCP "established" rule. ${fwcmd} add divert 8000 all from any to any in via ${oif} Notes on OpenBSD::IPFW ====================== OpenBSD supports divert sockets as of 4.7, so we use the ipfw DAQ. Here is one way to set things up: 1. Configure the system to forward packets: $ sysctl net.inet.ip.forwarding=1 $ sysctl net.inet6.ip6.forwarding=1 (You can also put that in /etc/sysctl.conf to enable on boot.) 2. Set up interfaces $ dhclient vic1 $ dhclient vic2 3. Set up packet filter rules: $ echo "pass out on vic1 divert-packet port 9000 keep-state" > rules.txt $ echo "pass out on vic2 divert-packet port 9000 keep-state" >> rules.txt $ pfctl -v -f rules.txt 4. Analyze packets diverted to port 9000: $ ./snort --daq ipfw --daq-var port=9000 * Note that on OpenBSD, divert sockets don't work with bridges!