How to Mirror UDP Traffic to Another Host Using Linux Networking Tools


5 views

When debugging network applications or implementing monitoring systems, engineers frequently need to duplicate UDP traffic to secondary hosts. Unlike TCP, UDP's connectionless nature makes packet mirroring more challenging since we can't rely on session-based replication methods.

The most straightforward approach uses Linux's iptables with the TEE target, which clones packets and routes them to another host while maintaining the original traffic flow:

# Basic syntax:
iptables -t mangle -A PREROUTING -p udp --dport 1234 -j TEE --gateway 192.168.1.100

# Practical example with interface specification:
iptables -t mangle -A PREROUTING -i eth0 -p udp --dport 514 -j TEE --gateway 10.0.0.2

Key considerations:

  • Works at the kernel level for minimal overhead
  • Only modifies the mangle table to avoid affecting normal routing
  • Requires root privileges

When iptables isn't available or appropriate, socat provides a flexible userspace solution:

# Mirror UDP port 1234 to secondary host while maintaining local delivery
socat -u UDP4-RECV:1234 UDP4-SENDTO:192.168.1.100:1234,reuseaddr,fork &

For environments with multiple monitoring hosts, consider UDP multicast:

# Convert unicast UDP to multicast
iptables -t mangle -A PREROUTING -p udp --dport 9999 -j TEE --gateway 224.0.0.100

# Configure multicast routing if needed
ip route add 224.0.0.0/4 dev eth0

Always verify your mirroring setup:

# Check iptables rules
iptables -t mangle -L -n -v

# Test with netcat
nc -ul 1234 # On primary host
nc -ul 1234 # On mirror host

# Packet capture verification
tcpdump -i eth0 udp port 1234 -vv -X

For high-volume UDP streams:

  • Consider rate limiting with iptables' limit module
  • Evaluate kernel-level solutions like AF_PACKET socket mirroring
  • Monitor system resources during peak loads

When working with UDP-based services, there are legitimate cases where you'd want to mirror traffic to a secondary host - whether for monitoring, analysis, or redundancy purposes. The standard approach using xtables-addons with TEE target doesn't always work out of the box, especially on older CentOS/RHEL systems.

Here are three production-tested methods:

1. Using tc (Traffic Control) + netem


# Create virtual interface
ip link add name udpclone type dummy
ip link set udpclone up

# Mirror UDP port 514 (example)
tc qdisc add dev eth0 handle ffff: ingress
tc filter add dev eth0 parent ffff: protocol ip u32 match ip protocol 0x11 0xff \
    match ip dport 514 0xffff \
    action mirred egress mirror dev udpclone

2. socat Multicast Forwarding

This method works well for specific UDP ports:


socat -u UDP-RECV:1234,reuseaddr UDP-SENDTO:secondary-host:1234 & 
socat -u UDP-RECV:1234,reuseaddr UDP-SENDTO:primary-destination:1234

3. Raw Socket Approach with Python

For custom packet handling:


import socket
import threading

def udp_tee(port, primary, secondary):
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.bind(('0.0.0.0', port))
    
    while True:
        data, addr = sock.recvfrom(65535)
        threading.Thread(target=sock.sendto, args=(data, primary)).start()
        threading.Thread(target=sock.sendto, args=(data, secondary)).start()

udp_tee(514, ('primary.example.com',514), ('secondary.example.com',514))

When implementing UDP mirroring:

  • Packet loss will occur under high traffic - implement queueing if order matters
  • For multicast applications, consider IGMP snooping
  • Always test with tcpreplay before production deployment

To duplicate DNS queries to a backup server:


iptables -t mangle -A PREROUTING -p udp --dport 53 -j TEE --gateway 192.168.1.100
iptables -t mangle -A PREROUTING -p udp --dport 53 -j ACCEPT

Note: This requires kernel module xt_TEE which may need compiling on older systems.