1 #!/bin/sh 2 # Copyright 2014 The Chromium Authors. All rights reserved. 3 # Use of this source code is governed by a BSD-style license that can be 4 # found in the LICENSE file. 5 # 6 # The purpose of this script is to set up all the neccessary magic to 7 # pipe network traffic through a user-space process. That user-space 8 # process can then delay, reorder and drop packets as it pleases to 9 # emulate various network environments. 10 # 11 # The script currently assumes that you communicate with your cast streaming 12 # receiver through eth1. After running "shadow.sh start", your network will 13 # look something like this: 14 # 15 # +--------------------------------------------------+ 16 # | Your linux machine | 17 # | +---------------+ | 18 # cast | |shadowbr bridge| +-------------+ | 19 # streaming <--+-+---> eth1 | |routing table| | 20 # receiver | | tap2 <---+-> tap_proxy <-+-> tap1 | | 21 # | | +->veth | | eth0 <----+--+->internet 22 # | +--+------------+ | lo | | 23 # | | +-------------+ | 24 # | | +------------------+ ^ | 25 # | | |shadow container | | | 26 # | +------+-->veth | chrome | 27 # | | netload.py server| netload.py client| 28 # | +------------------+ | 29 # +--------------------------------------------------+ 30 # 31 # The result should be that all traffic to/from the cast streaming receiver 32 # will go through tap_proxy. All traffic to/from the shadow container 33 # will also go through the tap_proxy. (A container is kind of like a 34 # virtual machine, but more lightweight.) Running "shadow.sh start" does 35 # not start the tap_proxy, so you'll have to start it manually with 36 # the command "tap_proxy tap1 tap2 <network_profile>" where 37 # <network_profile> is one of "perfect", "good", "wifi", "bad" or "evil". 38 # 39 # While testing mirroring, we can now generate TCP traffic through 40 # the tap proxy by talking to the netload server inside the "shadow" 41 # container by using the following command: 42 # 43 # $ netload.py upload IP PORT 44 # 45 # The IP and PORT are printed out by this script when you run 46 # "shadow.sh start", but will generally be the *.*.*.253 address 47 # of the eth1 network, so hopefully that's not already taken... 48 49 set -x 50 51 DEV=eth1 52 TAP1=tap1 53 TAP2=tap2 54 55 IP="$(ifconfig $DEV | sed -n 's@.*inet addr:\([^ ]*\).*@\1@gp')" 56 MASK="$(ifconfig $DEV | sed -n 's@.*Mask:\([^ ]*\).*@\1@gp')" 57 BCAST="$(ifconfig $DEV | sed -n 's@.*Bcast:\([^ ]*\).*@\1@gp')" 58 NET=$(route -n | grep $DEV | head -1 | awk '{print $1}') 59 DIR=$(dirname "$0") 60 61 case "$MASK" in 62 255.255.255.0) MASK_BITS=24 ;; 63 255.255.0.0) MASK_BITS=16 ;; 64 255.0.0.0) MASK_BITS=8 ;; 65 *) 66 echo "Unknown network mask" 67 exit 1 68 ;; 69 esac 70 71 SHADOWIP="$(echo $IP | sed 's@[^.]*$@@g')253" 72 SHADOWCONF="/tmp/shadowconf.$$" 73 cat <<EOF >$SHADOWCONF 74 lxc.utsname = shadow 75 lxc.network.type = veth 76 lxc.network.link = shadowbr 77 lxc.network.flags = up 78 lxc.network.ipv4 = $SHADOWIP/$MASK_BITS 79 lxc.network.ipv4.gateway = $IP 80 lxc.kmsg = 0 81 EOF 82 83 trap "rm $SHADOWCONF" SIGINT SIGTERM EXIT 84 LXC_COMMON="-n shadow -f $SHADOWCONF" 85 86 case "$1" in 87 start) 88 openvpn --mktun --dev $TAP1 89 openvpn --mktun --dev $TAP2 90 ifconfig $TAP1 $IP netmask $MASK broadcast $BCAST up 91 ifconfig $TAP2 up 92 route add -net $NET netmask $MASK $TAP1 93 brctl addbr shadowbr 94 brctl addif shadowbr $TAP2 $DEV 95 ifconfig shadowbr up 96 lxc-create $LXC_COMMON 97 lxc-execute $LXC_COMMON -- \ 98 "$DIRNAME/netload.py listen 9999" >/dev/null </dev/null 2>&1 & 99 echo "Now run: tap_proxy $TAP1 $TAP2 wifi" 100 echo "Data sink/source is available on $SHADOWIP 9999" 101 ;; 102 103 stop) 104 lxc-kill -n shadow 105 sleep 1 106 lxc-destroy $LXC_COMMON 107 ifconfig $TAP1 down 108 ifconfig $TAP2 down 109 ifconfig shadowbr down 110 brctl delbr shadowbr 111 openvpn --rmtun --dev $TAP1 112 openvpn --rmtun --dev $TAP2 113 ;; 114 115 *) 116 echo "$0 start/stop" 117 echo "Read $0 for more information." 118 ;; 119 esac 120 121 122