Overview
tcprewrite is a powerful packet capture file editor that is part of the tcpreplay suite of tools. It allows you to modify pcap files by rewriting Layer 2 (MAC addresses, VLAN tags), Layer 3 (IP addresses, TTL), and Layer 4 (TCP/UDP ports, checksums) headers without needing to replay the traffic first. This makes it invaluable for preparing capture files for network testing, anonymizing traffic captures, adapting recorded traffic to different network environments, and creating test scenarios for IDS/IPS validation.
tcprewrite works by reading a pcap file, applying the specified transformations to each packet, and writing the modified packets to a new pcap file. It supports sophisticated IP address remapping using CIDR notation, can randomize source and destination addresses, strip or add VLAN tags, fix broken checksums, and adjust MTU sizes by fragmenting or truncating packets. Combined with tcpreplay for replaying modified captures at controlled rates, tcprewrite forms a complete traffic generation and testing toolkit used by network engineers, security analysts, and QA teams.
Installation
Ubuntu/Debian
sudo apt update
sudo apt install tcpreplay
# Verify
tcprewrite --version
CentOS/RHEL
sudo yum install tcpreplay
macOS
brew install tcpreplay
From Source
wget https://github.com/appneta/tcpreplay/releases/download/v4.5.1/tcpreplay-4.5.1.tar.xz
tar xf tcpreplay-4.5.1.tar.xz
cd tcpreplay-4.5.1
./configure --enable-dynamic-link
make
sudo make install
Core Commands
| Command | Description |
|---|
tcprewrite -i in.pcap -o out.pcap | Basic rewrite (no changes) |
tcprewrite --cachefile=cache -i in -o out | Use cache file for classification |
tcprewrite --fixcsum -i in.pcap -o out.pcap | Fix all checksums |
tcprewrite --mtu=1500 -i in.pcap -o out.pcap | Truncate packets to MTU |
tcprewrite --skipbroadcast -i in -o out | Skip broadcast packets |
Workflow: tcpprep + tcprewrite + tcpreplay
# Step 1: Classify traffic (client vs server)
tcpprep --auto=bridge --pcap=capture.pcap --cachefile=cache.prep
# Step 2: Rewrite headers
tcprewrite --cachefile=cache.prep \
--enet-dmac=00:11:22:33:44:55,00:aa:bb:cc:dd:ee \
--enet-smac=00:66:77:88:99:00,00:ff:ee:dd:cc:bb \
-i capture.pcap -o modified.pcap
# Step 3: Replay modified traffic
tcpreplay --intf1=eth0 --intf2=eth1 modified.pcap
MAC Address Rewriting
# Rewrite destination MAC (primary,secondary interface)
tcprewrite --enet-dmac=00:11:22:33:44:55,00:aa:bb:cc:dd:ee \
--cachefile=cache.prep -i in.pcap -o out.pcap
# Rewrite source MAC
tcprewrite --enet-smac=00:66:77:88:99:00,00:ff:ee:dd:cc:bb \
--cachefile=cache.prep -i in.pcap -o out.pcap
# Rewrite both source and destination MAC
tcprewrite \
--enet-dmac=00:11:22:33:44:55,00:aa:bb:cc:dd:ee \
--enet-smac=00:66:77:88:99:00,00:ff:ee:dd:cc:bb \
--cachefile=cache.prep -i in.pcap -o out.pcap
IP Address Rewriting
Simple Remapping
# Remap client/server IPs using CIDR
tcprewrite --pnat=10.0.0.0/8:192.168.1.0/24 \
--cachefile=cache.prep -i in.pcap -o out.pcap
# Remap both directions
tcprewrite \
--pnat=10.0.0.0/8:192.168.1.0/24,172.16.0.0/12:10.10.0.0/16 \
--cachefile=cache.prep -i in.pcap -o out.pcap
# Pseudo-NAT for client and server separately
tcprewrite \
--srcipmap=10.0.0.0/8:192.168.1.0/24 \
--dstipmap=172.16.0.0/12:10.10.0.0/16 \
-i in.pcap -o out.pcap
Endpoint Rewriting
# Rewrite endpoints (uses cachefile to determine client/server)
tcprewrite --endpoints=192.168.1.1:10.0.0.1 \
--cachefile=cache.prep -i in.pcap -o out.pcap
Randomize IPs
# Randomize all IP addresses (anonymization)
tcprewrite --seed=42 -i in.pcap -o out.pcap
# Different seed = different randomization
tcprewrite --seed=12345 -i in.pcap -o out.pcap
VLAN Operations
# Add VLAN tag
tcprewrite --enet-vlan=add --enet-vlan-tag=100 \
-i in.pcap -o out.pcap
# Add VLAN tag with priority
tcprewrite --enet-vlan=add --enet-vlan-tag=200 --enet-vlan-pri=5 \
-i in.pcap -o out.pcap
# Remove VLAN tag
tcprewrite --enet-vlan=del -i in.pcap -o out.pcap
# Add QinQ (double VLAN tag)
tcprewrite --enet-vlan=add --enet-vlan-tag=100 \
--enet-vlan-cfi=0 --enet-vlan-pri=3 \
-i in.pcap -o out.pcap
Layer 4 Modifications
Port Remapping
# Remap TCP/UDP ports
tcprewrite --portmap=80:8080,443:8443 \
-i in.pcap -o out.pcap
# Remap specific protocol ports
tcprewrite --portmap=22:2222 \
-i in.pcap -o out.pcap
TTL Modification
# Set TTL to specific value
tcprewrite --ttl=set:64 -i in.pcap -o out.pcap
# Add to existing TTL
tcprewrite --ttl=add:10 -i in.pcap -o out.pcap
# Subtract from existing TTL
tcprewrite --ttl=sub:5 -i in.pcap -o out.pcap
TOS/DSCP Modification
# Set TOS byte
tcprewrite --tos=184 -i in.pcap -o out.pcap
# Set DSCP value (EF = 46)
tcprewrite --tos=184 -i in.pcap -o out.pcap
Checksum Operations
# Fix all checksums (IP, TCP, UDP, ICMP)
tcprewrite --fixcsum -i in.pcap -o out.pcap
# Fix checksums with header changes
tcprewrite --pnat=10.0.0.0/8:192.168.0.0/16 --fixcsum \
-i in.pcap -o out.pcap
# Efface (zero out) checksums
tcprewrite --efcs -i in.pcap -o out.pcap
MTU and Fragmentation
# Truncate packets to specific MTU
tcprewrite --mtu=1500 --mtu-trunc -i in.pcap -o out.pcap
# Fragment packets exceeding MTU
tcprewrite --mtu=1500 --fixcsum -i in.pcap -o out.pcap
# Set snap length (truncate packet data)
tcprewrite --fixlen=pad --mtu=1500 -i in.pcap -o out.pcap
# Fix packet length issues
tcprewrite --fixlen=pad -i in.pcap -o out.pcap # Pad short packets
tcprewrite --fixlen=trunc -i in.pcap -o out.pcap # Truncate long packets
Advanced Usage
DLT (Data Link Type) Conversion
# Convert Ethernet to Linux SLL
tcprewrite --dlt=linux_sll -i in.pcap -o out.pcap
# Convert raw IP to Ethernet
tcprewrite --dlt=enet \
--enet-dmac=00:11:22:33:44:55 \
--enet-smac=00:aa:bb:cc:dd:ee \
-i rawip.pcap -o ethernet.pcap
Protocol Stripping
# Remove MPLS headers
tcprewrite --enet-vlan=del -i mpls.pcap -o clean.pcap
Complex Rewriting Scenario
# Full rewrite for test environment
# 1. Classify traffic
tcpprep --auto=client --pcap=prod_capture.pcap --cachefile=test.prep
# 2. Rewrite for test network
tcprewrite --cachefile=test.prep \
--pnat=10.0.0.0/8:192.168.100.0/24 \
--enet-dmac=00:50:56:00:00:01,00:50:56:00:00:02 \
--enet-smac=00:50:56:00:00:03,00:50:56:00:00:04 \
--portmap=80:8080,443:8443 \
--ttl=set:128 \
--fixcsum \
--mtu=1500 \
-i prod_capture.pcap -o test_capture.pcap
# 3. Replay on test interfaces
sudo tcpreplay --intf1=eth1 --intf2=eth2 \
--multiplier=2.0 test_capture.pcap
Batch Processing
# Process multiple pcap files
for f in *.pcap; do
tcpprep --auto=bridge --pcap="$f" --cachefile="${f%.pcap}.prep"
tcprewrite --cachefile="${f%.pcap}.prep" \
--seed=42 --fixcsum \
-i "$f" -o "anonymized_${f}"
done
Configuration
tcpprep Cache Modes
| Mode | Description |
|---|
--auto=bridge | All traffic is bidirectional |
--auto=client | Classify by client/server heuristic |
--auto=server | Classify server-side first |
--auto=router | Classify by routing |
--auto=first | First packet determines direction |
--cidr=10.0.0.0/8 | CIDR-based classification |
--port | Classify by well-known ports |
# Generate cache file
tcpprep --auto=bridge --pcap=input.pcap --cachefile=input.prep
# View cache statistics
tcpprep --print-stats --cachefile=input.prep
Troubleshooting
| Issue | Solution |
|---|
| Invalid pcap file | Verify with capinfos or tcpdump -r |
| Checksum errors after rewrite | Always use --fixcsum with header changes |
| Packets too large after VLAN add | Reduce MTU by 4 bytes for VLAN header |
| Cache file mismatch | Regenerate cache with tcpprep |
| DLT type error | Check input DLT with capinfos, use --dlt |
| Port remap not working | Ensure packets have TCP/UDP headers |
| IP remap creates duplicates | Use larger target CIDR range |
| Output file empty | Check filter doesn’t exclude all packets |
Verification
# Compare input and output
capinfos in.pcap out.pcap
# Verify rewrites with tcpdump
tcpdump -r out.pcap -n -c 10
# Check specific fields
tcpdump -r out.pcap -n -e | head # Check MACs
tcpdump -r out.pcap -n host 192.168.1.1 # Check IPs
tcpdump -r out.pcap -n port 8080 # Check ports
# Detailed packet inspection
tshark -r out.pcap -V -c 5