Instead of ip/netmask. This should be functionally equivalent (for now), and makes it easier to identify the rule as belonging to weave. Unfortunatley we must still match the source with ip/netmask, since we are in the POSTROUTING chain and source interface matches aren't valid there. See also issue #20.
156 lines
4.3 KiB
Bash
Executable File
156 lines
4.3 KiB
Bash
Executable File
#!/bin/sh
|
|
set -e
|
|
|
|
usage() {
|
|
echo "Usage:"
|
|
echo "weave launch <ipaddr>/<subnet> [-passwd <passwd>] <peer_host> ..."
|
|
echo "weave run <ipaddr>/<subnet> <docker run args> ..."
|
|
echo "weave expose <ipaddr>/<subnet>"
|
|
echo "weave hide <ipaddr>/<subnet>"
|
|
echo "weave stop"
|
|
exit 1
|
|
}
|
|
|
|
[ `id -u` = 0 ] || {
|
|
echo "weave must be run as 'root'"
|
|
exit 1
|
|
}
|
|
|
|
[ $# -gt 0 ] || usage
|
|
|
|
BRIDGE=weave
|
|
CONTAINER_IFNAME=ethwe
|
|
MTU=65535
|
|
|
|
COMMAND=$1
|
|
|
|
shift 1
|
|
|
|
create_bridge() {
|
|
[ ! -d /sys/class/net/$BRIDGE ] && {
|
|
ip link add dev $BRIDGE type bridge
|
|
ip link set dev $BRIDGE address 7a:$(od -txC -An -N5 /dev/random | tr \ : | tail -c+2)
|
|
# Attempting to set the bridge MTU to a high value directly
|
|
# fails. Bridges take the lowest MTU of their interfaces. So
|
|
# instead we create a temporary interface with the desired
|
|
# MTU, attach that to the bridge, and then remove it again.
|
|
ip link add name v${CONTAINER_IFNAME}du mtu $MTU type dummy
|
|
ip link set dev v${CONTAINER_IFNAME}du master $BRIDGE
|
|
ip link del dev v${CONTAINER_IFNAME}du
|
|
}
|
|
ip link set dev $BRIDGE up
|
|
}
|
|
|
|
add_nat_rule() {
|
|
if ! iptables -w -t nat -C $1 >/dev/null 2>&1
|
|
then
|
|
iptables -w -t nat -A $1 >/dev/null
|
|
fi
|
|
}
|
|
|
|
setup_masquerading() {
|
|
add_nat_rule "POSTROUTING -o $BRIDGE ! -s $IPADDR -j MASQUERADE"
|
|
add_nat_rule "POSTROUTING -s $IPADDR ! -o $BRIDGE -j MASQUERADE"
|
|
}
|
|
|
|
case "$COMMAND" in
|
|
launch)
|
|
[ $# -gt 0 ] || usage
|
|
IPADDR=$1
|
|
shift 1
|
|
create_bridge
|
|
setup_masquerading
|
|
# We set the router name to the bridge mac since that is
|
|
# stable across re-creations of the containers.
|
|
#
|
|
# TODO use the mac of one of the physical host interfaces
|
|
# (eth0, wlan0, etc) so the name becomes stable across host
|
|
# restarts.
|
|
MACADDR=`cat /sys/class/net/$BRIDGE/address`
|
|
CONTAINER=$(docker run --privileged -d --name=weave -p 6783:6783/tcp -p 6783:6783/udp $WEAVE_DOCKER_ARGS zettio/weave -name $MACADDR "$@")
|
|
echo $CONTAINER
|
|
IFACE=eth0
|
|
;;
|
|
run)
|
|
[ $# -gt 0 ] || usage
|
|
IPADDR=$1
|
|
shift 1
|
|
create_bridge
|
|
CONTAINER=$(docker run -d "$@")
|
|
echo $CONTAINER
|
|
IFACE=$CONTAINER_IFNAME
|
|
;;
|
|
expose)
|
|
[ $# -gt 0 ] || usage
|
|
IPADDR=$1
|
|
shift 1
|
|
if ! ip addr list dev $BRIDGE | grep -qF $IPADDR
|
|
then
|
|
ip addr add dev $BRIDGE $IPADDR
|
|
fi
|
|
exit 0
|
|
;;
|
|
hide)
|
|
[ $# -gt 0 ] || usage
|
|
IPADDR=$1
|
|
shift 1
|
|
if ip addr list dev $BRIDGE | grep -qF $IPADDR
|
|
then
|
|
ip addr del dev $BRIDGE $IPADDR
|
|
fi
|
|
exit 0
|
|
;;
|
|
stop)
|
|
docker kill weave > /dev/null
|
|
docker rm weave > /dev/null
|
|
if command -v conntrack >/dev/null 2>&1
|
|
then
|
|
conntrack -D -p udp --dport 6783 >/dev/null 2>&1
|
|
else
|
|
echo "Cannot find conntrack; please install it. Continuing without it." >&2
|
|
fi
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo "Unknown weave command '$COMMAND'"
|
|
usage
|
|
;;
|
|
esac
|
|
|
|
# the following borrows from https://github.com/jpetazzo/pipework
|
|
|
|
DOCKERPID=$(docker inspect --format='{{ .State.Pid }}' $CONTAINER)
|
|
[ "$DOCKERPID" = 0 ] && {
|
|
echo "Docker inspect returned invalid PID 0"
|
|
exit 1
|
|
}
|
|
[ "$DOCKERPID" = "<no value>" ] && {
|
|
echo "Container $CONTAINER unknown to Docker."
|
|
exit 1
|
|
}
|
|
|
|
NSPID=$DOCKERPID
|
|
|
|
[ ! -d /var/run/netns ] && mkdir -p /var/run/netns
|
|
[ -f /var/run/netns/$NSPID ] && rm -f /var/run/netns/$NSPID
|
|
ln -s /proc/$NSPID/ns/net /var/run/netns/$NSPID
|
|
|
|
LOCAL_IFNAME="v${CONTAINER_IFNAME}pl${NSPID}"
|
|
GUEST_IFNAME="v${CONTAINER_IFNAME}pg${NSPID}"
|
|
ip link add name $LOCAL_IFNAME mtu $MTU type veth peer name $GUEST_IFNAME mtu $MTU
|
|
ip link set $LOCAL_IFNAME master $BRIDGE
|
|
ip link set $LOCAL_IFNAME up
|
|
ip link set $GUEST_IFNAME netns $NSPID
|
|
ip netns exec $NSPID ip link set $GUEST_IFNAME name $CONTAINER_IFNAME
|
|
ip netns exec $NSPID ip addr add $IPADDR dev $CONTAINER_IFNAME
|
|
ip netns exec $NSPID ip link set $CONTAINER_IFNAME up
|
|
|
|
if command -v ethtool >/dev/null 2>&1
|
|
then
|
|
ip netns exec $NSPID ethtool -K $IFACE tx off > /dev/null
|
|
else
|
|
echo "Cannot find ethtool; please install it. Continuing without it." >&2
|
|
fi
|
|
|
|
[ -f /var/run/netns/$NSPID ] && rm -f /var/run/netns/$NSPID
|