- What: Using Zeek with AWS Traffic Mirroring and Kafka
- Impact: IT professionals can enhance network analysis in cloud environments
Using Zeek with AWS Traffic Mirroring and Kafka by Arne Welzel | Feb 24, 2026 | Integrations AWS provides a feature that allows mirroring your infrastructure’s network traffic to a separate system for analysis purposes. This is called AWS Traffic Mirroring . If you’d like to use Zeek’s network traffic analysis capabilities in such a cloudy environment, this blog post explains how to do so using the recently published UDP-based packet source plugin to consume VXLAN encapsulated mirrored traffic and forwarding Zeek logs directly to Kafka. While we focus on AWS Traffic Mirroring, other cloud providers have similar features. For example, GCP’s Network Security Integration uses GENEVE instead of VXLAN, but conceptually should work the same. UDP-based Packet Source In contrast to other packet sources like AF_PACKET, NETMAP, PF_RING, etc. which read packets directly from a raw network interface, the plugin presented in this post provides a packet source component that turns Zeek into a high-performance UDP server, consuming mirrored traffic from a UDP socket. In short, the plugin supports the following interface specification, stripping the VXLAN header and sending the encapsulated payload into Zeek’s packet processing pipeline: zeek -i udp::0.0.0.0:4789:vxlan The udp:: prefix selects the packet source plugin to use. The packet source is initialized with the remainder of the string ( 0.0.0.0:4890:vxlan ) as the interface path. If left out, the built-in libpcap-based packet source is used. Another common prefix is af_packet:: which selects the built-in AF_PACKET packet source on Linux. Support for GENEVE encapsulation, a combination of GENEVE and VXLAN that’s used by AWS GWLB setups or raw and skip configurations exist as well. By default, the data link type (dlt) value of the packet source is set to DLT_EN10MB. Some example usages: zeek -i udp::0.0.0.0:6081:geneve+vxlan zeek -i udp::0.0.0.0:10000:raw zeek -i udp:: [ :: ] :4242:skip =16 :dlt = raw A nice side-effect of using this packet source is that Zeek runs unprivileged. There’s no need for the CAP_NET_RAW capability as we’re not directly accessing a network interface. Further, the packet source strips the encapsulation layer, relieving Zeek from tracking, analyzing and logging VXLAN tunnel connections. This happens in default setups with other packet sources that read raw packets, but logging information about the VXLAN tunnels is generally not very useful. For horizontally scaling Zeek across multiple processes, the packet source sets SO_REUSEPORT on the UDP socket. This, in turn, allows multiple Zeek processes to listen on the same port and the Linux kernel will load-balance packets among the sockets using flow-hashing on the outer IP/UDP header — exactly what Zeek or other DPI systems generally require. See the packet source’s README for a few more details about this load-balancing idea and also the requirements on the packet mirroring infrastructure. The implementation uses recvmmsg() to receive packets. This should provide decent performance. Zeek is a stateful passive networking monitor with fairly heavy Deep Packet Inspection (DPI) and extensive scripting capabilities. The packet path is usually not the bottleneck for Zeek. Further, within AWS, it’s possible to launch additional EC2 instances and use a UDP-based network load balancer (NLB) as a packet broker in front for further horizontal scaling across instances. The plugin also contains an experimental io_uring implementation using io_uring_prep_recvmsg_multishot for further single instance performance experimentation. Different architectures for deploying Zeek with AWS Traffic Mirroring. An additional avenue to explore for performance is to use multiple network interfaces on a single instance with an NLB in front. For production deployments, a dedicated interface for the mirror traffic is recommended. For simplicity we use only a single interface per instance here. The various configurations are depicted in the diagram above. Setting up EC2 instances We assume you have access to an AWS console and a basic understanding of working in such an environment. AWS’s Traffic Mirroring Get started guide is a great way to get familiar with its main concepts. Create the Source EC2 Instance If you already have instances that support traffic mirroring , you may skip this step. Otherwise, create an ephemeral t4g.micro Ubuntu 24.04 instance and ensure you have SSH access and note down the ENI identifier of its NIC. It’ll be used as the mirroring source when creating the Traffic Mirroring Session later. Create an EC2 Instance to run Zeek The second EC2 instance will be running Zeek. Place it in a security group that allows incoming traffic on port 4789/udp (VXLAN) and ensure you have SSH access to it. SSH Add both instances to ~/.ssh/config , named aws-tmt (traffic mirror target) and aws-tms (traffic mirror source). Our console output will use these hostnames: # ~/.ssh/config Host aws-tmt Hostname 18.219.xxx.yyy Us...