Home | History | Annotate | Download | only in utility
      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