Networking

Build a Security Onion Sensor: Tap, Mirror Port and Two-NIC Box

This post contains affiliate links. If you buy through them, we may earn a small commission at no extra cost to you. Learn more.

I plugged a Security Onion sniff NIC into an ordinary switch port and captured 500 frames. Not one was a unicast conversation between two other hosts. That’s why Security Onion hardware is more than “a PC with two network cards”: the sniff interface only sees what you copy to it, so the tap or mirror port matters as much as the CPU and RAM.

Original content from computingforgeeks.com - post 178857

These notes cover the parts I’d buy for a Security Onion sensor (a gigabit tap, a mirror-port switch, a two-NIC box and the SSD), the CPU check that now decides whether a box qualifies, the sniff NIC setup, and what broke when I gave the install too little memory. I have not had the tap or switch on my bench, so their specs come from the vendors. I ran the software side in October 2026 on a Proxmox VM in my lab, Oracle Linux 9.7 with Security Onion 3.3.0 in Eval mode, and every log line below comes from that box.

Picking the parts in one pass

If you only want the shopping list, here it is. Each line is a role in the build, and the sections further down explain the trade-off behind every pick:

  • Tap for a gigabit uplink: Dualcomm ETAP-2003, USB powered, one monitor port, low $200s
  • Cheapest way to start: TP-Link TL-SG108E as a mirror-port switch, under $30
  • Passive tap for a 100 Mbps link: Throwing Star LAN Tap Pro, sold through Great Scott Gadgets resellers only
  • Small sensor node: Protectli Vault Pro VP2430e, four 2.5GbE ports, under $500 barebones
  • One box that does everything: Minisforum MS-01 with the i9-13900H, 32 GB and 1 TB, $1,200 to $1,300 class
  • PCAP and index storage: Samsung 990 Pro 2TB, rated for 1,200 TBW, roughly $400 to $450

Prices above are the Amazon listings I checked on 28 October 2026, and they move a lot right now, so check the live price before you order. RAM is the line item that hurts in 2026: a 32 GB DDR5 SODIMM kit was listing for roughly $480 to $530, which is more than the SSD. Budget for it before you fall in love with a barebones box.

The diagram shows how the pieces connect. The tap or the switch hands a copy of the traffic to the sniff NIC, and the only interface you ever log in through is the management NIC:

Security Onion sensor architecture diagram: a network tap on the router LAN link or a mirror-port switch feeding the eth1 sniff NIC, management on eth0

The red box is the mistake I made first. An ordinary switch port in place of a tap or mirror only delivers broadcast and multicast frames, so Zeek and Suricata sit there looking healthy while they see almost nothing worth inspecting.

How I tested it, and what I didn’t

The software half was hands-on. I cloned a Rocky Linux 9.7 VM on my Proxmox node (an i7-1165G7 host), gave it 4 vCPUs, 12 GB of RAM, a 220 GB disk and two virtio NICs, converted it to Oracle Linux 9.7, and installed Security Onion 3.3.0 as an Eval node with eth0 for management and eth1 for sniffing. Then I fed eth1 real traffic and checked what Suricata and Zeek recorded.

The hardware half was not hands-on, and I’d rather say that up front than let a spec table imply otherwise. None of the products below has been on my bench (not the taps, the switches, the two boxes or the SSD), so for each part I checked:

  • The vendor’s own product page or datasheet for ports and speeds
  • Intel ARK for CPU instruction sets and memory limits
  • Amazon’s catalogue data for price, stock and seller

Where a vendor page didn’t say something (Dualcomm never says what the ETAP-2003 does on power loss, for example), I’ve left it as unknown instead of filling the gap.

Comparing a tap, a mirror port and a plain port

Security Onion’s own hardware page says it plainly: for production you need a SPAN port on an existing switch or a dedicated tap, and they recommend a tap where possible. The table is how I’d decide between them for a home or small-office link:

OptionWhat the sniff NIC seesLink speedCatch
Plain switch portBroadcast and multicast only (0 unicast in my 500-frame capture)AnyUseless for detection
TL-SG108E mirror portCopies of the ports you pick, ingress, egress or bothGigabitThe switch copies traffic with its own fabric and can drop copies under load
Dualcomm ETAP-2003Both directions of one link on one monitor port10/100/1000Full duplex gigabit can exceed the 1 Gbps monitor port
Throwing Star LAN Tap ProOne direction per monitor portForces the link to 100 MbpsNeeds two sniff NICs to see both directions

For a home network behind one router, I’d put the tap or the mirror on the inside of the router, not the WAN side. The Security Onion docs make the same point: collect inside the NAT boundary so you see real internal addresses instead of everything coming from the router.

Choosing a tap: Dualcomm ETAP-2003

Why buy a tap when the switch you already own might mirror? Because a tap sits on one link and copies only that link, instead of sharing a busy switch’s buffers with every other port. The ETAP-2003 is the tap I’d buy for a gigabit uplink, mostly because it does not slow the link down and it is powered from a USB port on the sensor itself:

Dualcomm ETAP-2003 USB-powered gigabit network tap for a Security Onion sensor
Dualcomm ETAP-2003: two inline gigabit ports and one monitor port, USB powered. Image: Dualcomm.

Per Dualcomm’s product page and selection guide, it has two inline RJ45 ports, one gigabit monitor port, PoE pass-through, 9 KB jumbo frame support and zero-loss inline operation over 200 m of cable. The monitor port blocks ingress by default, which is exactly what you want: the sensor can’t accidentally transmit into the link it’s watching. If you ever need that monitor port to send (some people run an inline tool there), the ETAP-2003R variant drops the block for about $30 more.

Skip it if your uplink regularly runs near a full gigabit in both directions at once. Both directions arrive on that single gigabit monitor port, so up to 2 Gbps of full-duplex traffic has to squeeze into 1 Gbps and the excess is lost before Security Onion ever sees it. I’d also plan for the link going down if the USB power goes, because Dualcomm doesn’t list the ETAP-2003 as failsafe; their ETAP-3105 is the model with that tick. It sat in the low $200s on Amazon and on Dualcomm’s own store when I checked, so check the current ETAP-2003 price before ordering.

Starting with a passive Throwing Star LAN Tap Pro

The Throwing Star is the tap people recommend because it needs no power at all, and that’s true, but read the fine print on speed before buying one for a modern network:

Great Scott Gadgets Throwing Star LAN Tap Pro passive 10/100 network tap
Throwing Star LAN Tap Pro: passive, unpowered, built for 10BASE-T and 100BASE-TX. Image: Great Scott Gadgets.

Great Scott Gadgets designs it for 10BASE-T and 100BASE-TX only, and two capacitors deliberately degrade a gigabit link so the endpoints negotiate down, typically to 100 Mbps. The product page lists no switch or jumper that changes this. Each of its two monitor ports also sees one direction only, so you need two capture NICs. Security Onion handles that part well, since Setup lets you tick several NICs for the monitor interface and bonds them into bond0.

It’s a good pick for a lab segment, a single IoT device or a 100 Mbps WAN, and a bad one for a gigabit uplink. The Amazon results I found under its name were clones from other sellers, so buy it through the resellers Great Scott Gadgets lists.

Using a mirror port on the TL-SG108E

If you’d rather not put anything inline, a managed switch with port mirroring gets you started for under $30. The TL-SG108E is the one I’d pick because TP-Link’s Easy Smart guide documents the mirror options clearly:

TP-Link TL-SG108E 8-port gigabit switch with port mirroring for a SPAN port
TP-Link TL-SG108E: eight gigabit ports, one-to-one or many-to-one port mirroring. Image: TP-Link.

The setup lives under Monitoring, then Port Mirror, in the web UI or the Easy Smart utility. In order:

  1. Enable port mirroring (it’s off by default)
  2. Pick one mirroring port (port 8 in my diagram), cabled to the sensor’s sniff NIC
  3. Tick the mirrored ports, usually the router uplink
  4. Set Ingress and Egress on each, so both directions get copied

Ports in a LAG can’t be mirrored or used as the mirror port, and TP-Link’s guide is written for the whole Easy Smart range, so confirm the menu on your hardware version. The bigger limit is physics: a mirror copies traffic using the switch’s own buffers, and when you mirror a busy gigabit uplink in both directions to one gigabit port, the switch drops copies first. That’s why the Security Onion team prefers taps. For an 8-port alternative, Netgear’s GS308E also does many-to-one mirroring from up to seven source ports, and our roundup of cheap VLAN-capable gigabit switches covers more options.

Building a sensor node on the Protectli VP2430e

For a box that only sniffs and forwards to a separate manager, I like the VP2430e: fanless, four Intel I226-V 2.5GbE ports, and a CPU that clears the new instruction-set bar:

Protectli Vault Pro VP2430e four-port 2.5GbE fanless box as a Security Onion sensor
Protectli VP2430e: Intel N150, four I226-V 2.5GbE ports, fanless. Image: Protectli (VP2430 chassis, identical on the VP2430e).

Intel ARK lists AVX2 for the N150, which matters because of the CPU check in the next section. Four ports means management on one, and up to three sniff interfaces for a tap, a mirror port and a spare. Security Onion’s sensor role wants at least 4 cores, 12 GB and 200 GB, and the N150 has exactly 4 cores.

It’s the wrong box if you want one machine running the whole stack. Intel ARK rates the N150 for 16 GB on one memory channel (Protectli says it tested 64 GB), and after watching Elasticsearch eat a 12 GB VM I wouldn’t run Eval or Standalone on it. The NVMe slot is PCIe Gen3 x2, so a Gen4 drive runs well below its rated speed there. I have not run Security Onion on this box. The Amazon listing is barebones (no RAM, no SSD) at under $500, and its title says SATA storage while Protectli specifies an NVMe slot, so trust Protectli’s page. Then check the VP2430e listing and add memory to the budget. Our pfSense and OPNsense hardware guide covers the same Protectli family as a firewall.

Going standalone on a Minisforum MS-01

If you want one box that sniffs, stores and serves the console, the standalone role asks for 24 GB at minimum and the docs suggest 32 GB once real traffic flows. The MS-01 listing I checked ships with 32 GB already fitted, which sidesteps the RAM price problem:

Minisforum MS-01 mini workstation with 10G SFP+ and 2.5GbE ports for a standalone Security Onion box
Minisforum MS-01: two 10G SFP+ and two 2.5GbE ports, three M.2 slots. Image: Minisforum.

Minisforum lists two 10G SFP+ ports, two 2.5GbE RJ45 ports and three M.2 NVMe slots. The i9-13900H in this listing has 14 cores and 20 threads, AVX2, and Intel rates it for 96 GB of DDR5. That leaves room for one 2.5GbE port as management, the other as the sniff port for a tap, and the SFP+ ports for a faster mirror later. At the docs’ rough 200 Mbps per Suricata or Zeek worker, a saturated gigabit link wants about ten cores for those two engines alone, and this is the only box here that gets close.

For a home uplink under 300 Mbps with a manager already running elsewhere, it’s a lot of machine for a sensor, and I’d save the money. It also isn’t cheap, in the $1,200 to $1,300 class on Amazon for the i9-13900H, 32 GB and 1 TB configuration, so check the MS-01 price first. Our MS-01 against the MS-03 and MS-A2 comparison covers the platform in more detail.

Sizing PCAP storage with a Samsung 990 Pro

Full packet capture is the storage killer. Security Onion’s own example: a link averaging 50 Mbps writes about 540 GB of PCAP a day. The SSD I’d put in the MS-01 is the one rated for that kind of write load:

Samsung 990 Pro 2TB NVMe SSD for Security Onion pcap and Elasticsearch storage
Samsung 990 Pro 2TB: PCIe 4.0 x4, 1,200 TBW warranty. Image: Samsung.

Samsung rates the 2 TB 990 Pro at 1,200 TBW over five years, which at 540 GB a day is about six years of writes, so endurance is not the problem; retention is. Two terabytes holds under four days of PCAP at that 50 Mbps average, before Elasticsearch takes its share. My idle Eval install had already used 50 GB of disk (14 GB in /var/lib/docker, 15 GB in /nsm) before any real traffic. Skip the 990 Pro in the VP2430e, whose Gen3 x2 slot wastes it, and check the 990 Pro 2TB price, which was in the $400s when I looked.

Checking the CPU before you buy anything

This is the check I’d run on any used desktop or mini PC before spending money on it. The Security Onion 3.x release notes carry a known issue: Elastic now needs an x86-64-v3 CPU (AVX2, BMI2, FMA, MOVBE), and if your CPU lacks it they recommend holding off. On any distro with glibc 2.33 or newer (RHEL 9 family, Debian 12, Ubuntu 22.04 and later), the glibc loader tells you in one line:

/lib64/ld-linux-x86-64.so.2 --help | grep -A6 'Subdirectories of glibc-hwcaps'

My VM on the i7-1165G7 host showed v3 as supported, which is the line you need to see:

Subdirectories of glibc-hwcaps directories, in priority order:
  x86-64-v4 (supported, searched)
  x86-64-v3 (supported, searched)
  x86-64-v2 (supported, searched)

Legacy HWCAP subdirectories under library search path directories:
  haswell (AT_PLATFORM; supported, searched)

If x86-64-v3 is missing, so is the box. An older live USB prints nothing for that command, so check the four flags directly instead; all four must appear:

grep -o -w -E 'avx2|bmi2|fma|movbe' /proc/cpuinfo | sort -u

Inside Proxmox, the release notes also say to set the VM’s CPU type to host, because the default emulated CPU model can hide AVX2 from the guest even when the hardware has it. My clone already had cpu: host, which is why v4 showed up.

Preparing the sniff NIC

The sniff interface carries no IP address. Before installing, I wanted to see what that NIC sees on an ordinary switch port, so I stripped its DHCP address, put it in promiscuous mode and captured 500 frames:

sudo nmcli device set eth1 managed no
sudo ip addr flush dev eth1
sudo ip link set eth1 up promisc on
sudo dnf -y install tcpdump
sudo timeout 65 tcpdump -ni eth1 -q -e -c 500

I counted the 500 frames by destination MAC and protocol, and they broke down like this. Every frame was broadcast or multicast, and none was a unicast conversation between other hosts:

209 broadcast IPv4
129 broadcast ARP
17 broadcast STP/LLC
73 multicast IPv4
39 multicast IPv6
32 multicast STP/LLC
1 multicast other
355 total broadcast
145 total multicast
unicast frames: 0 (no frame addressed to a single host MAC; 500 frames in ~60 s)

That’s the plain-port row of the comparison table, measured. It also explains a quirk you’ll see later: my router broadcast-pings the subnet, and those pings were the one thing a plain port did deliver.

Error: “eth1 is unmanaged by Network Manager”

My first Setup run aborted at the monitor interface step with “eth1 is unmanaged by Network Manager. Please remove it from other network management tools then re-run setup.” The managed no from my baseline capture was the cause: Setup expects NetworkManager to own every monitor NIC so it can build bond0 from them. Hand it back before you run Setup:

sudo nmcli device set eth1 managed yes

You do not need to remove the IP or disable offloads yourself. Setup does both, as the next section shows.

Installing Security Onion on the two-NIC box

On real hardware, use the official ISO: it’s the only supported install method, it partitions /nsm for you, and it’s what I’d do on the VP2430e or MS-01. I had no ISO on my Proxmox storage, so I took the network install path, which the docs call unsupported and a last resort, and which on 3.x only names Oracle Linux 9 as a base. Oracle’s migration script turned my Rocky 9.7 VM into Oracle Linux 9.7 in about nine minutes. The script defaults to the UEK kernel, which is what the Security Onion ISO ships, so that’s the form I’d run now:

curl -fsSLO https://raw.githubusercontent.com/oracle/centos2ol/main/migrate-to-oracle-linux.sh
sudo bash migrate-to-oracle-linux.sh -y
sudo systemctl reboot

My own run passed --kernel rhck to keep the Red Hat compatible kernel, and it worked, but the 3.3.0 release notes mention removing non-UEK kernels to cut reboots, so I wouldn’t fight that default again. After the reboot, /etc/os-release read Oracle Linux Server 9.7. Then the documented clone and Setup:

sudo dnf -y install git curl ethtool
git clone -b 3/main https://github.com/Security-Onion-Solutions/securityonion
cd securityonion
sudo bash so-setup-network

Setup is a text UI with no answer-file mode on 3/main. The choices that matter for a two-NIC sensor, in the order it asks:

  • Install type EVAL, then type AGREE for the Elastic License 2.0
  • Hostname box1, set now because certificates are built from it
  • Management NIC eth0 (it warns about DHCP; use a reservation or static IP)
  • Monitor interface: tick eth1, or two NICs for a Throwing Star
  • An email and password for the SOC admin account
  • Allow web access: Yes, from your LAN range, 192.168.1.0/24 here

Then it pulls container images for a long while; the network install docs put the current set at about 30 GB on disk, so give it a fast connection.

What broke: Elasticsearch on 12 GB of RAM

Eval’s documented minimum is 8 GB, and I gave it 12 GB thinking that was generous. It was not. The kernel logged 30 out-of-memory kills of the Elasticsearch JVM during Setup, and the two I printed show it holding close to 5 GB resident when it died. Late in the run I added an 8 GB swapfile, which is my workaround, not something Setup does. Setup still finished with errors, and /root/errors.log said why:

[ERROR   ] Command 'so-elasticsearch-wait' failed with return code: 1
[ERROR   ] stdout: Waiting for value 'green open' at 'https://localhost:9200/_cat/indices/.kibana*' (1/300)
[ERROR   ] Command '/usr/sbin/so-elastic-fleet-urls-update' failed with return code: 1
[ERROR   ] stdout: Failed to query for current Fleet Server URLs...
     Comment: One or more requisite failed: elastalert.enabled.wait_for_elasticsearch

Despite those errors, all 21 containers came up, and so-status gave the all-clear. Elasticsearch had only been up eight minutes, which tells you how recently it had last been killed:

so-status output on a Security Onion 3.3.0 Eval node with all 21 containers running

Idle, after setup, the box used 9.6 GB of its 11 GB with 4 GB already in swap. Elasticsearch alone held 4.4 GB, Kibana 0.96 GB, the SOC console 0.6 GB, and Zeek and Suricata about 0.4 GB each. So my sizing rule is 16 GB as the real floor for Eval and 32 GB for Standalone, which is why the MS-01 configuration with 32 GB fitted is the one I’d buy. If you’re stuck at 12 GB for a trial, add swap before you start Setup rather than halfway through as I did, and expect it to crawl.

The console lives on the management NIC. Browse to https:// followed by that IP (192.168.1.184 in my lab) from an address inside the range you allowed, accept the self-signed certificate, and log in with the email and password you gave Setup.

Proving the sensor sees traffic

Setup built bond0 in balance-rr mode with eth1 as its only slave, MTU 9000, promiscuous, no IP, and it switched off TSO, GSO and GRO, which the hardware docs say it does so Suricata and Zeek see packets as they were on the wire. Both are easy to confirm, along with Suricata’s kernel drop counter:

ethtool showing offloads disabled on the Security Onion sniff NIC and Suricata capture counters with zero kernel drops

With no physical tap in my lab, I stood in for one with a tc mirror. It copies frames entering and leaving the management NIC into bond0’s receive path, which is roughly what a mirror port does, without putting anything on my LAN:

sudo tc qdisc add dev eth0 clsact
sudo tc filter add dev eth0 ingress matchall action mirred ingress mirror dev bond0
sudo tc filter add dev eth0 egress matchall action mirred ingress mirror dev bond0

The classic Security Onion smoke test is to curl testmynids.org and wait for the “id check returned root” alert. That domain is parked now and returns a generic HTML page, so the alert never fired. I served the same uid=0(root) response from a local python3 -m http.server on port 8099 of 127.0.0.1, and mirrored loopback into bond0 as well:

sudo tc qdisc add dev lo clsact
sudo tc filter add dev lo ingress matchall action mirred ingress mirror dev bond0
sudo tc filter add dev lo egress matchall action mirred ingress mirror dev bond0

A curl to that local server produced the alert in Suricata’s eve log:

{"timestamp":"2026-10-28T05:05:21.777311+0000","in_iface":"bond0","event_type":"alert","src_ip":"127.0.0.1","dest_ip":"127.0.0.1","proto":"TCP","app_proto":"http","alert":{"signature_id":2100498,"signature":"GPL ATTACK_RESPONSE id check returned root","severity":2}}

Did Zeek see the ordinary traffic as well, or only the alert? It did. These entries all landed in /nsm/zeek/logs/current/:

  • dns.log: the lookups for kernel.org and www.kernel.org
  • ssl.log: a TLS 1.3 session to the kernel.org CDN
  • http.log: the HTTP 200 from the parked testmynids page
  • conn.log: the flows behind all three

Look closer and the mirror was only half working. The conn.log entry for the testmynids request shows "orig_pkts":0, and ssl.log marks the TLS session "established":false, so Zeek saw the replies but not box1’s own outgoing packets. My best guess is that the egress copies left eth0 before checksum and segmentation offload had finished with them, and Zeek discarded them; I didn’t re-test with eth0’s offloads off. A real tap or switch mirror copies finished frames off the wire, so you shouldn’t hit this, but it’s exactly the symptom to look for in conn.log when a mirror port is configured for ingress only.

Suricata counted 24,983 packets with zero kernel drops and Zeek’s capture loss read 0.0%, which at this trickle of traffic proves the plumbing works, not the box’s ceiling. When you’re done testing, remove both mirrors, or the sensor keeps watching its own management traffic until the next reboot:

sudo tc qdisc del dev eth0 clsact
sudo tc qdisc del dev lo clsact

The SOC Alerts page grouped what it had seen in 24 hours:

Security Onion 3.3.0 SOC Alerts page grouped by rule name showing Suricata ICMP ping, id check returned root and SSH scan alerts

The two ICMP ping signatures fired 636 times each, and when I grouped the *NIX one by address across all the eve.json files, every hit came from a single source: my router sending echo requests to the subnet broadcast address, which is the only “interesting” traffic a plain port delivered before the mirror existed. The two SSH scan alerts were me, opening SSH sessions to box1 over and over while I drove the install. Neither is an attack, and both are the kind of noise you’ll tune out in your first week with any sensor.

The Grid page is the other screen worth a glance after install, because it shows the node’s role, version and health in one row:

Security Onion Grid page showing box1 as an Evaluation node on version 3.3.0 with status OK

Once alerts flow, the work moves from hardware to analysis. If the Suricata side is new to you, our Suricata install guide explains the rule engine on its own, and Wireshark analysis on Kali is the natural next step for reading the PCAP a sensor keeps. For host logs alongside network data, Wazuh on Ubuntu 26.04 pairs well, and the wider cybersecurity home lab hardware builds show where this sensor sits in a full lab.

What I still don’t know

A few questions I couldn’t settle in this lab, and I’d want answers before trusting the build on a busy network:

  • Where the ETAP-2003 starts dropping on a loaded full-duplex gigabit link
  • How many mirrored copies the TL-SG108E loses under the same load
  • Whether 16 GB runs Eval cleanly, or only stops the OOM loop
  • How the N150 holds up as a sensor node past 300 Mbps

The memory one is the question I’d answer first, because it decides whether a sub-$500 barebones box plus one stick is a whole sensor or just half of one. Until I’ve measured it, I’d buy for 32 GB, put the tap inside the router, and check the CPU line before anything else.

Keep reading

UFW Firewall Commands with Examples on Ubuntu 26.04 / 24.04 Security UFW Firewall Commands with Examples on Ubuntu 26.04 / 24.04 PHP2Shell (CVE-2026-109618, CVE-2026-109619): Check and Patch PHP Php PHP2Shell (CVE-2026-109618, CVE-2026-109619): Check and Patch PHP PHP2Shell on End-of-Life PHP 8.1, 8.0 and 7.4 (WHMCS, ionCube) Php PHP2Shell on End-of-Life PHP 8.1, 8.0 and 7.4 (WHMCS, ionCube) Homelab and Sysadmin Gifts by Budget: $25, $50, $100 and $250+ Networking Homelab and Sysadmin Gifts by Budget: $25, $50, $100 and $250+ Best Pentesting Hardware for Kali Linux in 2026 Security Best Pentesting Hardware for Kali Linux in 2026 Best 10GbE NIC for Proxmox and Homelab (2026): SFP+ and RJ45 Picks Networking Best 10GbE NIC for Proxmox and Homelab (2026): SFP+ and RJ45 Picks

Leave a Comment

Press ESC to close