shadow.sh revision 6e8cce623b6e4fe0c9e4af605d675dd9d0338c38
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
49set -x
50
51DEV=eth1
52TAP1=tap1
53TAP2=tap2
54
55IP="$(ifconfig $DEV | sed -n 's@.*inet addr:\([^ ]*\).*@\1@gp')"
56MASK="$(ifconfig $DEV | sed -n 's@.*Mask:\([^ ]*\).*@\1@gp')"
57BCAST="$(ifconfig $DEV | sed -n 's@.*Bcast:\([^ ]*\).*@\1@gp')"
58NET=$(route -n | grep $DEV | head -1 | awk '{print $1}')
59DIR=$(dirname "$0")
60
61case "$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  ;;
69esac
70
71SHADOWIP="$(echo $IP | sed 's@[^.]*$@@g')253"
72SHADOWCONF="/tmp/shadowconf.$$"
73cat <<EOF >$SHADOWCONF
74lxc.utsname = shadow
75lxc.network.type = veth
76lxc.network.link = shadowbr
77lxc.network.flags = up
78lxc.network.ipv4 = $SHADOWIP/$MASK_BITS
79lxc.network.ipv4.gateway = $IP
80lxc.kmsg = 0
81EOF
82
83trap "rm $SHADOWCONF" SIGINT SIGTERM EXIT
84LXC_COMMON="-n shadow -f $SHADOWCONF"
85
86case "$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  ;;
119esac
120
121
122