Skip to content

Instantly share code, notes, and snippets.

@Aposhian
Created March 11, 2021 13:57
Show Gist options
  • Save Aposhian/11741f4b81c4385ad3ca308edb0911f7 to your computer and use it in GitHub Desktop.
Save Aposhian/11741f4b81c4385ad3ca308edb0911f7 to your computer and use it in GitHub Desktop.
Simulate a lossy network connection
#!/usr/bin/env bash
[ "$(id -u)" != "0" ] && echo "Please run as root" && exit 1
function usage {
echo "Usage:
./simulate_bad_connection.sh (-a | --address) <dest-ip-address>
[ -d | --delay ] <delay-in-ms>
[ -t | --timeout ] <timeout-seconds>
"
}
OPTIONS="$(getopt --name simulate_bad_connection --options ha:d:t: --longoptions help,address:,delay:,timeout: -- "$@")"
DELAY=400 # ms
TIMEOUT=300 # seconds
if [ $? != 0 ]; then
# Incorrect options provided
usage
exit 1
fi
eval set -- "$OPTIONS"
while true; do
case "$1" in
-h | --help)
echo "Simulate a bad connection with tc and netem"
usage
exit
;;
-a | --address)
shift
DEST_ADDRESS="$1"
;;
-d | --delay)
shift
DELAY="$1"
;;
-t | --timeout)
shift
TIMEOUT="$1"
;;
--)
shift
break
;;
esac
shift
done
if [ -z "$DEST_ADDRESS" ]; then
echo "Please provide a destination address"
usage
exit 1
fi
NETWORK_INTERFACE="$(arp | grep $DEST_ADDRESS | awk '{ print $5 }')"
if [ -z "$NETWORK_INTERFACE" ]; then
echo "Could not find network interface for address: $DEST_ADDRESS"
exit 1
fi
# This restores the network
function finish {
echo "
Restoring network on interface: $NETWORK_INTERFACE"
# Restore outgoing traffic
tc qdisc delete dev $NETWORK_INTERFACE root netem &> /dev/null
# Restore incoming traffic
tc qdisc delete dev ifb0 root netem &> /dev/null
tc qdisc delete dev $NETWORK_INTERFACE ingress &> /dev/null
ip link set dev ifb0 down &> /dev/null
}
# This makes it run when the script exits, no matter how
trap finish EXIT
echo "Simulating bad connection on interface: $NETWORK_INTERFACE"
# Filter outgoing traffic
tc qdisc add dev $NETWORK_INTERFACE root netem \
delay ${DELAY}ms 20ms distribution normal \
loss 0.5% 25% \
corrupt 0.1% \
reorder 25% 50%
# Filter incoming traffic
# https://wiki.linuxfoundation.org/networking/netem#how_can_i_use_netem_on_incoming_traffic
modprobe ifb
ip link set dev ifb0 up
tc qdisc add dev $NETWORK_INTERFACE ingress
tc filter add dev $NETWORK_INTERFACE parent ffff: protocol ip u32 match u32 0 0 flowid 1:1 action mirred egress redirect dev ifb0
tc qdisc add dev ifb0 root netem \
delay ${DELAY}ms 20ms distribution normal \
loss 0.5% 25% \
corrupt 0.1% \
reorder 25% 50%
# Wait
echo "Network will restore in $TIMEOUT seconds, or when this script exits"
sleep $TIMEOUT
# finish will be called here
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment