- Go 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| .gitea/workflows | ||
| .gitignore | ||
| .goreleaser.yml | ||
| cli.go | ||
| cli_test.go | ||
| config.go | ||
| config_test.go | ||
| go.mod | ||
| go.sum | ||
| main.go | ||
| main_test.go | ||
| network.go | ||
| network_test.go | ||
| README.md | ||
| tui.go | ||
| tui_test.go | ||
badNet - Network Impairment Simulator
A powerful network simulation tool for testing applications under adverse network conditions using Linux network namespaces and traffic control.
Project Overview
badNet is a network impairment simulation tool designed for testing and validating application behavior under various real-world network conditions. By leveraging Linux network namespaces and the Traffic Control (tc) subsystem with Network Emulation (netem), badNet creates isolated virtual network environments where you can simulate delays, packet loss, corruption, and other network anomalies.
System Architecture
High-Level Architecture
┌─────────────────────────────────────────────────────────────┐
│ Host System │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ badNet Application │ │
│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │
│ │ │ TUI/CLI │ │ Config │ │ tc/netem │ │ │
│ │ │ Interface │ │ Manager │ │ Controller │ │ │
│ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ Client Namespace │ │ Server Namespace │ │
│ │ (client-ns) │ │ (server-ns) │ │
│ │ │ │ │ │
│ │ ┌──────────────┐ │ veth │ ┌──────────────┐ │ │
│ │ │ veth-client │◄──┼──────────┼──►│ veth-server │ │ │
│ │ │ 10.99.0.1/24 │ │ pair │ │ 10.99.0.2/24 │ │ │
│ │ └──────────────┘ │ │ └──────────────┘ │ │
│ │ ▲ │ │ ▲ │ │
│ │ │ tc netem │ │ │ tc netem │ │
│ │ (delay, loss, etc.) │ │ (delay, loss, etc.) │ │
│ └─────────────────────┘ └─────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
Technical Components
Network Namespaces: Linux kernel feature providing network stack isolation, including separate:
- Network interfaces
- Routing tables
- Firewall rules
- Network statistics
Virtual Ethernet (veth) Pairs: Simulated ethernet cables connecting the namespaces, acting as bidirectional pipes for network traffic.
Traffic Control (tc) + Network Emulation (netem): Linux kernel modules that apply quality-of-service rules to network interfaces, enabling precise control over packet behavior.
Data Flow
- Application starts and validates CAP_NET_ADMIN capability
- Configuration loaded from
config.toml(or defaults generated) - User selects operation via TUI or CLI
- Setup creates namespaces, veth pairs, assigns IPs, applies tc rules
- Network traffic flows through veth pair with applied impairments
- Teardown removes namespaces (automatically cleaning all resources)
Installation Guide
Prerequisites
⚠️ IMPORTANT: This tool requires Linux and specific kernel features. It will NOT work on macOS or Windows (even with WSL due to namespace limitations).
- Operating System: Linux (kernel 2.6.24+ for network namespaces, 2.6.23+ for netem)
- Go: Version 1.21 or higher
- Root Access: Required for network namespace operations (sudo or CAP_NET_ADMIN capability)
- Linux Utilities:
ipandtccommands (fromiproute2package)
System Dependencies
Install required packages:
# Debian/Ubuntu
sudo apt-get update
sudo apt-get install iproute2
# RHEL/CentOS/Fedora
sudo dnf install iproute
# Arch Linux
sudo pacman -S iproute2
Building from Source
# Clone the repository
git clone https://gitlab.star.army.mil/emsco/utils/badnet.git
cd badnet
# Download dependencies
go mod download
# Build the binary
go build -o badnet main.go
# Optional: Install system-wide
sudo cp badnet /usr/local/bin/
Granting Capabilities (Alternative to sudo)
For production environments, grant specific capabilities instead of requiring full root:
# Grant CAP_NET_ADMIN to the binary
sudo setcap cap_net_admin+ep ./badnet
# Verify capabilities
getcap ./badnet
# Output: ./badnet = cap_net_admin+ep
💡 Note: With capabilities set, you can run badNet without sudo while still maintaining security.
🚀 Usage Instructions
badNet offers two operational modes: an interactive Terminal User Interface (TUI) and command-line interface (CLI) for scripting.
Interactive TUI Mode
Launch the TUI by running badNet without arguments:
sudo ./badnet
TUI Controls:
- ↑/↓ Arrow Keys: Navigate menu options
- Enter: Select option
- q or Ctrl+C: Quit (automatic cleanup)
Menu Options:
- Setup Network: Creates namespaces and applies network impairments
- Teardown Network: Removes all network configurations
- Quit: Exit application (auto-teardown if network is active)
CLI Mode
For automation and scripting:
Check Network Status
sudo ./badnet status
Example Output:
Network is ACTIVE
# or
Network is DOWN
Setup Network
sudo ./badnet up
Example Output:
Network setup completed successfully
Teardown Network
sudo ./badnet down
Example Output:
Network torn down successfully
Execute Commands in Namespaces
sudo ./badnet exec <client|server> <command> [args...]
Parameters:
<client|server>: Target namespace (clientfor client-ns,serverfor server-ns)<command>: Command to execute in the namespace[args...]: Optional arguments for the command
Example Usage:
# Ping from client to server
sudo ./badnet exec client ping -c 4 10.99.0.2
# Start HTTP server in server namespace
sudo ./badnet exec server python3 -m http.server 8080
# Run custom script in client namespace
sudo ./badnet exec client ./my_test_script.sh
Example Output:
# sudo ./badnet exec client ping -c 2 10.99.0.2
PING 10.99.0.2 (10.99.0.2) 56(84) bytes of data.
64 bytes from 10.99.0.2: icmp_seq=1 ttl=64 time=125 ms
64 bytes from 10.99.0.2: icmp_seq=2 ttl=64 time=98 ms
--- 10.99.0.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 98.123/111.567/125.012/13.444 ms
Testing the Network
Once the network is set up, you can test it by running commands in the namespaces:
Ping Test
# From client namespace to server
sudo ip netns exec client-ns ping -c 4 10.99.0.2
# From server namespace to client
sudo ip netns exec server-ns ping -c 4 10.99.0.1
Example Output with Impairments:
PING 10.99.0.2 (10.99.0.2) 56(84) bytes of data.
64 bytes from 10.99.0.2: icmp_seq=1 ttl=64 time=245 ms
64 bytes from 10.99.0.2: icmp_seq=2 ttl=64 time=132 ms
64 bytes from 10.99.0.2: icmp_seq=4 ttl=64 time=187 ms
(packet 3 lost due to 10% loss configuration)
Run Server in Namespace
# Start a simple HTTP server in server namespace
sudo ip netns exec server-ns python3 -m http.server 8080
Connect from Client Namespace
# Make HTTP request from client namespace
sudo ip netns exec client-ns curl http://10.99.0.2:8080
Docker Network Integration
badNet now supports integration with Docker networks by creating a bridge interface that can be used as a Docker network driver. This allows Docker containers to connect to the impaired network.
Setup Docker Network
After setting up badNet, create a Docker network using the bridge:
# Create Docker network using badNet bridge
sudo docker network create --driver bridge --opt com.docker.network.bridge.name=badnet-br badnet-network
# Or if you want to use a custom bridge name, update config.toml and recreate
sudo docker network create --driver bridge --opt com.docker.network.bridge.name=your-bridge-name your-network-name
Run Containers with Network Impairments
# Run a client container connected to the impaired network
sudo docker run --network badnet-network --name client-app -it ubuntu bash
# Run a server container connected to the impaired network
sudo docker run --network badnet-network --name server-app -p 8080:8080 -it ubuntu bash
# Inside containers, they will experience the network impairments configured in badNet
Example: Testing with Docker
# Setup badNet network
sudo ./badnet up
# Create Docker network
sudo docker network create --driver bridge --opt com.docker.network.bridge.name=badnet-br badnet-network
# Run server container
sudo docker run --network badnet-network --name server -d nginx
# Run client container and test connectivity
sudo docker run --network badnet-network --name client -it alpine sh -c "apk add curl && curl http://server"
# The curl command will experience the network impairments (delay, loss, etc.)
Using Docker Compose
You can also use Docker Compose to define services that connect to the impaired network:
# docker-compose.yml
version: '3.8'
services:
server:
image: nginx:alpine
networks:
- badnet
ports:
- "8080:80"
client:
image: alpine:latest
networks:
- badnet
command: sh -c "apk add curl && sleep 5 && curl http://server"
depends_on:
- server
networks:
badnet:
driver: bridge
driver_opts:
com.docker.network.bridge.name: badnet-br
Usage with Docker Compose:
# Setup badNet network first
sudo ./badnet up
# Run the services
sudo docker-compose up
# Or run in background
sudo docker-compose up -d
# View logs to see the impaired network effects
sudo docker-compose logs client
Cleanup Docker Network
# Stop and remove containers
sudo docker stop client server
sudo docker rm client server
# Or if using compose
sudo docker-compose down
# Remove Docker network
sudo docker network rm badnet-network
# Teardown badNet network
sudo ./badnet down
Automation Example
#!/bin/bash
# automated_test.sh
echo "Setting up impaired network..."
sudo ./badnet up
echo "Running application tests..."
# Your test commands here
sudo ip netns exec client-ns ./run_tests.sh
echo "Cleaning up..."
sudo ./badnet down
⚙️ Configuration Options
badNet uses TOML format for configuration. On first run, a default
config.toml is automatically created.
Configuration File Location
The configuration file must be named config.toml and placed in the same
directory as the badNet executable.
Complete Configuration Reference
# Network Namespace Names
client_ns = "client-ns" # Name for client namespace
server_ns = "server-ns" # Name for server namespace
# Virtual Ethernet Interface Names
client_veth = "veth-client" # Client-side interface name
server_veth = "veth-server" # Server-side interface name
# IP Address Configuration (CIDR notation)
client_ip = "10.99.0.1/24" # Client IP and subnet
server_ip = "10.99.0.2/24" # Server IP and subnet
# Bridge Configuration
bridge_name = "badnet-br" # Bridge name for Docker network integration
# Network Impairment Configuration - Client Side
[netem_client]
delay = "100ms" # Base latency (e.g., "50ms", "1s")
jitter = "20ms" # Variance in delay (distribution)
loss = "10%" # Random packet loss percentage
loss_correlation = "25%" # Correlation between packet losses
duplicate = "1%" # Packet duplication rate
corrupt = "0.5%" # Packet corruption rate
reorder = "5%" # Packet reordering probability
reorder_correlation = "50%" # Correlation in reordering
# Network Impairment Configuration - Server Side
[netem_server]
delay = "100ms"
jitter = "20ms"
loss = "10%"
loss_correlation = "25%"
duplicate = "1%"
corrupt = "0.5%"
reorder = "5%"
reorder_correlation = "50%"
Configuration Parameters Explained
Network Impairment Parameters
| Parameter | Type | Description | Example Values |
|---|---|---|---|
delay |
Duration | Base network latency | "10ms", "100ms", "1s" |
jitter |
Duration | Variation in delay (normal distribution) | "5ms", "20ms" |
loss |
Percentage | Random packet drop rate | "0%", "5%", "25%" |
loss_correlation |
Percentage | Likelihood of consecutive losses | "0%", "25%", "75%" |
duplicate |
Percentage | Packet duplication rate | "0%", "1%", "5%" |
corrupt |
Percentage | Packet corruption rate | "0%", "0.1%", "1%" |
reorder |
Percentage | Packet reordering probability | "0%", "5%", "25%" |
reorder_correlation |
Percentage | Correlation in reorder events | "0%", "50%", "100%" |
Bridge Configuration
| Parameter | Type | Description | Example Values |
|---|---|---|---|
bridge_name |
String | Bridge interface name for Docker network integration | "badnet-br", "docker-br" |