Implement Dynamic Bandwidth Throttling with iptables: A Technical Guide for Traffic Shaping


4 views

Many developers encounter scenarios where they need to simulate ISP-style bandwidth throttling - where initial connections get full speed but gradually get throttled after sustained usage. This technique is crucial for:

  • Testing application behavior under limited bandwidth
  • Creating fair usage policies
  • Simulating real-world network conditions
  • Preventing bandwidth hogging by specific processes

Linux offers two primary tools for traffic shaping:

# Basic check for required tools
which iptables tc || echo "Install iproute2 and iptables first"

The real magic happens when we combine iptables for packet marking with tc (Traffic Control) for actual shaping.

Here's a complete solution that throttles TCP connections after they exceed 10MB of transfer:

#!/bin/bash
# Clean existing rules
tc qdisc del dev eth0 root 2>/dev/null
iptables -t mangle -F

# Create HTB hierarchy
tc qdisc add dev eth0 root handle 1: htb
tc class add dev eth0 parent 1: classid 1:1 htb rate 100mbit

# Default class (full speed)
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 100mbit

# Throttled class (1mbit after threshold)
tc class add dev eth0 parent 1:1 classid 1:20 htb rate 1mbit

# SFQ for fairness
tc qdisc add dev eth0 parent 1:10 handle 10: sfq
tc qdisc add dev eth0 parent 1:20 handle 20: sfq

# Mark packets in iptables
iptables -t mangle -A POSTROUTING -o eth0 -p tcp -m connbytes --connbytes 10485760: --connbytes-dir both --connbytes-mode bytes -j CLASSIFY --set-class 1:20

For more precise control, consider these parameters:

# Gradual throttling based on transfer size
iptables -t mangle -A POSTROUTING -o eth0 -p tcp -m connbytes --connbytes 5242880:10485760 --connbytes-dir both --connbytes-mode bytes -j CLASSIFY --set-class 1:30

# Time-based throttling (slow after 30 seconds)
iptables -t mangle -A POSTROUTING -o eth0 -p tcp -m connmark --mark 0x0 -m recent --name slowlink --seconds 30 --set
iptables -t mangle -A POSTROUTING -o eth0 -p tcp -m recent --name slowlink --rcheck -j CLASSIFY --set-class 1:20

Check your traffic shaping with these commands:

# Show current classifications
tc -s class show dev eth0

# Monitor real-time bandwidth
iftop -i eth0 -f 'port 80 or port 443'

# Detailed connection tracking
conntrack -L

If throttling isn't working as expected:

  1. Verify your interface name (eth0 vs enp0s3 etc.)
  2. Check kernel modules: lsmod | grep xt_connbytes
  3. Test basic iptables rules first before adding tc complexity
  4. Consider connection tracking limits in /proc/sys/net/netfilter/

For high-traffic servers:

  • Use connection marking early in mangle table
  • Consider hashlimits instead of connbytes for scale
  • Offload shaping to hardware if available
  • Monitor CPU usage during peak traffic

When it comes to network traffic management on Linux systems, iptables remains one of the most powerful tools in a sysadmin's arsenal. While primarily known for firewall functionality, its combination with tc (traffic control) provides robust bandwidth shaping capabilities.

Static rate limiting is straightforward, but many real-world scenarios require more sophisticated approaches. Consider these use cases:

  • Preventing bandwidth-hogging applications from starving other services
  • Simulating ISP-style throttling for development/testing
  • Implementing fair usage policies in shared environments
  • Creating QoS rules that adapt to network conditions

Here's how to implement dynamic throttling that kicks in after initial bursts:

# Clear existing rules
tc qdisc del dev eth0 root

# Create HTB queuing discipline
tc qdisc add dev eth0 root handle 1: htb default 30

# Add root class
tc class add dev eth0 parent 1: classid 1:1 htb rate 100mbit ceil 100mbit

# Create throttled class (will activate after burst)
tc class add dev eth0 parent 1:1 classid 1:30 htb rate 512kbit ceil 1mbit burst 15k

# Add filter to direct traffic
tc filter add dev eth0 protocol ip parent 1:0 prio 1 handle 1 fw classid 1:30

# Mark packets with iptables
iptables -t mangle -A POSTROUTING -o eth0 -j MARK --set-mark 1

For more sophisticated control, we can implement time-dependent rules:

# Create time-based throttling (9am-5pm work hours)
iptables -t mangle -A POSTROUTING -o eth0 -m time --timestart 09:00 --timestop 17:00 -j MARK --set-mark 1

Verify your settings with these commands:

tc -s qdisc show dev eth0
tc -s class show dev eth0
iptables -t mangle -L -v -n

Some frequent challenges and solutions:

  • Throttle not applying: Check if your interface uses eth0 or another name (ip link show)
  • Rules disappearing: Make sure to persist rules across reboots (consider using iptables-persistent)
  • Unexpected behavior: Double-check burst and ceil values - these significantly impact throttle behavior