Repository: popsuper1982/tcpipillustrated Branch: master Commit: 12363c94f1bf Files: 7 Total size: 20.6 KB Directory structure: gitextract_qcg6bjxd/ ├── Dockerfile ├── Openvswitch实验教程.pptx ├── README.md ├── pipework ├── proxy-arp ├── proxy-arp.conf └── setupenv.sh ================================================ FILE CONTENTS ================================================ ================================================ FILE: Dockerfile ================================================ FROM hub.c.163.com/public/ubuntu:14.04 RUN apt-get -y update && apt-get install -y iproute2 iputils-arping net-tools tcpdump curl telnet iputils-tracepath traceroute RUN mv /usr/sbin/tcpdump /usr/bin/tcpdump ENTRYPOINT /usr/sbin/sshd -D ================================================ FILE: README.md ================================================ # tcpipillustrated ================================================ FILE: pipework ================================================ #!/bin/sh # This code should (try to) follow Google's Shell Style Guide # (https://google-styleguide.googlecode.com/svn/trunk/shell.xml) set -e case "$1" in --wait) WAIT=1 ;; esac IFNAME=$1 # default value set further down if not set here CONTAINER_IFNAME= if [ "$2" = "-i" ]; then CONTAINER_IFNAME=$3 shift 2 fi GUESTNAME=$2 IPADDR=$3 MACADDR=$4 case "$MACADDR" in *@*) VLAN="${MACADDR#*@}" VLAN="${VLAN%%@*}" MACADDR="${MACADDR%%@*}" ;; *) VLAN= ;; esac [ "$IPADDR" ] || [ "$WAIT" ] || { echo "Syntax:" echo "pipework [-i containerinterface] /[@default_gateway] [macaddr][@vlan]" echo "pipework [-i containerinterface] dhcp [macaddr][@vlan]" echo "pipework --wait [-i containerinterface]" exit 1 } # Succeed if the given utility is installed. Fail otherwise. # For explanations about `which` vs `type` vs `command`, see: # http://stackoverflow.com/questions/592620/check-if-a-program-exists-from-a-bash-script/677212#677212 # (Thanks to @chenhanxiao for pointing this out!) installed () { command -v "$1" >/dev/null 2>&1 } # Google Styleguide says error messages should go to standard error. warn () { echo "$@" >&2 } die () { status="$1" shift warn "$@" exit "$status" } wait_for_container(){ dockername=$@ while true do status=`docker inspect $dockername | grep Running | awk -F ':' '{print $2}' | tr -d " :,"` if [ $status = "true" ] then break else sleep 1 fi done } wait_for_container $GUESTNAME # First step: determine type of first argument (bridge, physical interface...), # Unless "--wait" is set (then skip the whole section) if [ -z "$WAIT" ]; then if [ -d "/sys/class/net/$IFNAME" ] then if [ -d "/sys/class/net/$IFNAME/bridge" ]; then IFTYPE=bridge BRTYPE=linux elif installed ovs-vsctl && ovs-vsctl list-br|grep -q "^${IFNAME}$"; then IFTYPE=bridge BRTYPE=openvswitch elif [ "$(cat "/sys/class/net/$IFNAME/type")" -eq 32 ]; then # Infiniband IPoIB interface type 32 IFTYPE=ipoib # The IPoIB kernel module is fussy, set device name to ib0 if not overridden CONTAINER_IFNAME=${CONTAINER_IFNAME:-ib0} else IFTYPE=phys fi else case "$IFNAME" in br*) IFTYPE=bridge BRTYPE=linux ;; ovs*) if ! installed ovs-vsctl; then die 1 "Need OVS installed on the system to create an ovs bridge" fi IFTYPE=bridge BRTYPE=openvswitch ;; *) die 1 "I do not know how to setup interface $IFNAME." ;; esac fi fi # Set the default container interface name to eth1 if not already set CONTAINER_IFNAME=${CONTAINER_IFNAME:-eth1} [ "$WAIT" ] && { while true; do # This first method works even without `ip` or `ifconfig` installed, # but doesn't work on older kernels (e.g. CentOS 6.X). See #128. grep -q '^1$' "/sys/class/net/$CONTAINER_IFNAME/carrier" && break # This method hopefully works on those older kernels. ip link ls dev "$CONTAINER_IFNAME" && break sleep 1 done > /dev/null 2>&1 exit 0 } [ "$IFTYPE" = bridge ] && [ "$BRTYPE" = linux ] && [ "$VLAN" ] && { die 1 "VLAN configuration currently unsupported for Linux bridge." } [ "$IFTYPE" = ipoib ] && [ "$MACADDR" ] && { die 1 "MACADDR configuration unsupported for IPoIB interfaces." } # Second step: find the guest (for now, we only support LXC containers) while read _ mnt fstype options _; do [ "$fstype" != "cgroup" ] && continue echo "$options" | grep -qw devices || continue CGROUPMNT=$mnt done < /proc/mounts [ "$CGROUPMNT" ] || { die 1 "Could not locate cgroup mount point." } # Try to find a cgroup matching exactly the provided name. N=$(find "$CGROUPMNT" -name "$GUESTNAME" | wc -l) case "$N" in 0) # If we didn't find anything, try to lookup the container with Docker. if installed docker; then RETRIES=3 while [ "$RETRIES" -gt 0 ]; do DOCKERPID=$(docker inspect --format='{{ .State.Pid }}' "$GUESTNAME") [ "$DOCKERPID" != 0 ] && break sleep 1 RETRIES=$((RETRIES - 1)) done [ "$DOCKERPID" = 0 ] && { die 1 "Docker inspect returned invalid PID 0" } [ "$DOCKERPID" = "" ] && { die 1 "Container $GUESTNAME not found, and unknown to Docker." } else die 1 "Container $GUESTNAME not found, and Docker not installed." fi ;; 1) true ;; *) die 1 "Found more than one container matching $GUESTNAME." ;; esac if [ "$IPADDR" = "dhcp" ]; then # Check for first available dhcp client DHCP_CLIENT_LIST="udhcpc dhcpcd dhclient" for CLIENT in $DHCP_CLIENT_LIST; do installed "$CLIENT" && { DHCP_CLIENT=$CLIENT break } done [ -z "$DHCP_CLIENT" ] && { die 1 "You asked for DHCP; but no DHCP client could be found." } else # Check if a subnet mask was provided. case "$IPADDR" in */*) : ;; *) warn "The IP address should include a netmask." die 1 "Maybe you meant $IPADDR/24 ?" ;; esac # Check if a gateway address was provided. case "$IPADDR" in *@*) GATEWAY="${IPADDR#*@}" GATEWAY="${GATEWAY%%@*}" IPADDR="${IPADDR%%@*}" ;; *) GATEWAY= ;; esac fi if [ "$DOCKERPID" ]; then NSPID=$DOCKERPID else NSPID=$(head -n 1 "$(find "$CGROUPMNT" -name "$GUESTNAME" | head -n 1)/tasks") [ "$NSPID" ] || { die 1 "Could not find a process inside container $GUESTNAME." } fi # Check if an incompatible VLAN device already exists [ "$IFTYPE" = phys ] && [ "$VLAN" ] && [ -d "/sys/class/net/$IFNAME.VLAN" ] && { ip -d link show "$IFNAME.$VLAN" | grep -q "vlan.*id $VLAN" || { die 1 "$IFNAME.VLAN already exists but is not a VLAN device for tag $VLAN" } } [ ! -d /var/run/netns ] && mkdir -p /var/run/netns rm -f "/var/run/netns/$NSPID" ln -s "/proc/$NSPID/ns/net" "/var/run/netns/$NSPID" # Check if we need to create a bridge. [ "$IFTYPE" = bridge ] && [ ! -d "/sys/class/net/$IFNAME" ] && { [ "$BRTYPE" = linux ] && { (ip link add dev "$IFNAME" type bridge > /dev/null 2>&1) || (brctl addbr "$IFNAME") ip link set "$IFNAME" up } [ "$BRTYPE" = openvswitch ] && { ovs-vsctl add-br "$IFNAME" } } MTU=$(ip link show "$IFNAME" | awk '{print $5}') # If it's a bridge, we need to create a veth pair [ "$IFTYPE" = bridge ] && { 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" case "$BRTYPE" in linux) (ip link set "$LOCAL_IFNAME" master "$IFNAME" > /dev/null 2>&1) || (brctl addif "$IFNAME" "$LOCAL_IFNAME") ;; openvswitch) ovs-vsctl add-port "$IFNAME" "$LOCAL_IFNAME" ${VLAN:+tag="$VLAN"} ;; esac ip link set "$LOCAL_IFNAME" up } # Note: if no container interface name was specified, pipework will default to ib0 # Note: no macvlan subinterface or ethernet bridge can be created against an # ipoib interface. Infiniband is not ethernet. ipoib is an IP layer for it. # To provide additional ipoib interfaces to containers use SR-IOV and pipework # to assign them. [ "$IFTYPE" = ipoib ] && { GUEST_IFNAME=$CONTAINER_IFNAME } # If it's a physical interface, create a macvlan subinterface [ "$IFTYPE" = phys ] && { [ "$VLAN" ] && { [ ! -d "/sys/class/net/${IFNAME}.${VLAN}" ] && { ip link add link "$IFNAME" name "$IFNAME.$VLAN" mtu "$MTU" type vlan id "$VLAN" } ip link set "$IFNAME" up IFNAME=$IFNAME.$VLAN } GUEST_IFNAME=ph$NSPID$CONTAINER_IFNAME ip link add link "$IFNAME" dev "$GUEST_IFNAME" mtu "$MTU" type macvlan mode bridge ip link set "$IFNAME" up } ip link set "$GUEST_IFNAME" netns "$NSPID" ip netns exec "$NSPID" ip link set "$GUEST_IFNAME" name "$CONTAINER_IFNAME" [ "$MACADDR" ] && ip netns exec "$NSPID" ip link set dev "$CONTAINER_IFNAME" address "$MACADDR" if [ "$IPADDR" = "dhcp" ] then [ "$DHCP_CLIENT" = "udhcpc" ] && ip netns exec "$NSPID" "$DHCP_CLIENT" -qi "$CONTAINER_IFNAME" -x "hostname:$GUESTNAME" if [ "$DHCP_CLIENT" = "dhclient" ]; then # kill dhclient after get ip address to prevent device be used after container close ip netns exec "$NSPID" "$DHCP_CLIENT" -pf "/var/run/dhclient.$NSPID.pid" "$CONTAINER_IFNAME" kill "$(cat "/var/run/dhclient.$NSPID.pid")" rm "/var/run/dhclient.$NSPID.pid" fi [ "$DHCP_CLIENT" = "dhcpcd" ] && ip netns exec "$NSPID" "$DHCP_CLIENT" -q "$CONTAINER_IFNAME" -h "$GUESTNAME" else ip netns exec "$NSPID" ip addr add "$IPADDR" dev "$CONTAINER_IFNAME" [ "$GATEWAY" ] && { ip netns exec "$NSPID" ip route delete default >/dev/null 2>&1 && true } ip netns exec "$NSPID" ip link set "$CONTAINER_IFNAME" up [ "$GATEWAY" ] && { ip netns exec "$NSPID" ip route get "$GATEWAY" >/dev/null 2>&1 || \ ip netns exec "$NSPID" ip route add "$GATEWAY/32" dev "$CONTAINER_IFNAME" ip netns exec "$NSPID" ip route replace default via "$GATEWAY" } fi # Give our ARP neighbors a nudge about the new interface if installed arping; then IPADDR=$(echo "$IPADDR" | cut -d/ -f1) ip netns exec "$NSPID" arping -c 1 -A -I "$CONTAINER_IFNAME" "$IPADDR" > /dev/null 2>&1 || true else echo "Warning: arping not found; interface may not be immediately reachable" fi # Remove NSPID to avoid `ip netns` catch it. rm -f "/var/run/netns/$NSPID" # vim: set tabstop=2 shiftwidth=2 softtabstop=2 expandtab : ================================================ FILE: proxy-arp ================================================ #! /bin/sh - # # proxy-arp Set proxy-arp settings in arp cache # # chkconfig: 2345 15 85 # description: using the arp command line utility, populate the arp # cache with IP addresses for hosts on different media # which share IP space. # # Copyright (c)2002 SecurePipe, Inc. - http://www.securepipe.com/ # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software Foundation, # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # -- written initially during 1998 # 2002-08-14; Martin A. Brown # - cleaned up and commented extensively # - joined the process parsimony bandwagon, and eliminated # many unnecessary calls to ifconfig and awk # gripe () { echo "$@" >&2; } abort () { gripe "Fatal: $@"; exit 1; } CONFIG=${CONFIG:-/etc/proxy-arp.conf} [ -r "$CONFIG" ] || abort $CONFIG is not readable case "$1" in start) # -- create proxy arp settings according to # table in the config file # grep -Ev '^#|^$' $CONFIG | { while read INTERFACE IPADDR ; do [ -z "$INTERFACE" -o -z "$IPADDR" ] && continue arp -s $IPADDR -i $INTERFACE -D $INTERFACE pub done } ;; stop) # -- clear the cache for any entries in the # configuration file # grep -Ev '^#|^$' /etc/proxy-arp.conf | { while read INTERFACE IPADDR ; do [ -z "$INTERFACE" -o -z "$IPADDR" ] && continue arp -d $IPADDR -i $INTERFACE done } ;; status) arp -an | grep -i perm ;; restart) $0 stop $0 start ;; *) echo "Usage: proxy-arp {start|stop|restart}" exit 1 esac exit 0 # # - end of proxy-arp ================================================ FILE: proxy-arp.conf ================================================ # # Proxy ARP configuration file # # -- This is the proxy-arp configuration file. A sysV init script # (proxy-arp) reads this configuration file and creates the # required arp table entries. # # Copyright (c)2002 SecurePipe, Inc. - http://www.securepipe.com/ # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software Foundation, # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # # -- file was created during 1998 # 2002-08-15; Martin A. Brown # - format unchanged # - added comments # # -- field descriptions: # field 1 this field contains the ethernet interface on which # to advertise reachability of an IP. # field 2 this field contains the IP address for which to advertise # # -- notes # # - white space, lines beginning with a comment and blank lines are ignored # # -- examples # # - each example is commented with an English description of the # resulting configuration # - followed by a pseudo shellcode description of how to understand # what will happen # # -- example #0; advertise for 10.10.15.175 on eth1 # # eth1 10.10.15.175 # # for any arp request on eth1; do # if requested address is 10.10.15.175; then # answer arp request with our ethernet address from eth1 (so # that the reqeustor sends IP packets to us) # fi # done # # -- example #1; advertise for 172.30.48.10 on eth0 # # eth0 172.30.48.10 # # for any arp request on eth0; do # if requested address is 172.30.48.10; then # answer arp request with our ethernet address from eth1 (so # that the reqeustor sends IP packets to us) # fi # done # # -- add your own configuration here eth1 140.252.1.29 netbside 140.252.1.92 netbside 140.252.1.32 netbside 140.252.1.11 netbside 140.252.1.4 # -- end /etc/proxy-arp.conf # ================================================ FILE: setupenv.sh ================================================ #!/bin/bash publiceth=$1 imagename=$2 #预配置环境 systemctl stop ufw systemctl disable ufw /sbin/iptables -P FORWARD ACCEPT echo 1 > /proc/sys/net/ipv4/ip_forward sysctl -p /sbin/iptables -P FORWARD ACCEPT #创建图中所有的节点,每个一个容器 echo "create all containers" docker run --privileged=true --net none --name aix -d ${imagename} docker run --privileged=true --net none --name solaris -d ${imagename} docker run --privileged=true --net none --name gemini -d ${imagename} docker run --privileged=true --net none --name gateway -d ${imagename} docker run --privileged=true --net none --name netb -d ${imagename} docker run --privileged=true --net none --name sun -d ${imagename} docker run --privileged=true --net none --name svr4 -d ${imagename} docker run --privileged=true --net none --name bsdi -d ${imagename} docker run --privileged=true --net none --name slip -d ${imagename} #创建两个网桥,代表两个二层网络 echo "create bridges" ovs-vsctl add-br net1 ip link set net1 up ovs-vsctl add-br net2 ip link set net1 up #brctl addbr net1 #brctl addbr net2 #将所有的节点连接到两个网络 echo "connect all containers to bridges" chmod +x ./pipework ./pipework net1 aix 140.252.1.92/24 ./pipework net1 solaris 140.252.1.32/24 ./pipework net1 gemini 140.252.1.11/24 ./pipework net1 gateway 140.252.1.4/24 ./pipework net1 netb 140.252.1.183/24 ./pipework net2 bsdi 140.252.13.35/27 ./pipework net2 sun 140.252.13.33/27 ./pipework net2 svr4 140.252.13.34/27 #添加从slip到bsdi的p2p网络 echo "add p2p from slip to bsdi" #创建一个peer的两个网卡 ip link add name slipside mtu 1500 type veth peer name bsdiside mtu 1500 #把其中一个塞到slip的网络namespace里面 DOCKERPID1=$(docker inspect '--format={{ .State.Pid }}' slip) ln -s /proc/${DOCKERPID1}/ns/net /var/run/netns/${DOCKERPID1} ip link set slipside netns ${DOCKERPID1} #把另一个塞到bsdi的网络的namespace里面 DOCKERPID2=$(docker inspect '--format={{ .State.Pid }}' bsdi) ln -s /proc/${DOCKERPID2}/ns/net /var/run/netns/${DOCKERPID2} ip link set bsdiside netns ${DOCKERPID2} #给slip这面的网卡添加IP地址 docker exec -it slip ip addr add 140.252.13.65/27 dev slipside docker exec -it slip ip link set slipside up #给bsdi这面的网卡添加IP地址 docker exec -it bsdi ip addr add 140.252.13.66/27 dev bsdiside docker exec -it bsdi ip link set bsdiside up #如果我们仔细分析,p2p网络和下面的二层网络不是同一个网络。 #p2p网络的cidr是140.252.13.64/27,而下面的二层网络的cidr是140.252.13.32/27 #所以对于slip来讲,对外访问的默认网关是13.66 docker exec -it slip ip route add default via 140.252.13.66 dev slipside #而对于bsdi来讲,对外访问的默认网关13.33 docker exec -it bsdi ip route add default via 140.252.13.33 dev eth1 #对于sun来讲,要想访问p2p网络,需要添加下面的路由表 docker exec -it sun ip route add 140.252.13.64/27 via 140.252.13.35 dev eth1 #对于svr4来讲,对外访问的默认网关是13.33 docker exec -it svr4 ip route add default via 140.252.13.33 dev eth1 #对于svr4来讲,要访问p2p网关,需要添加下面的路由表 docker exec -it svr4 ip route add 140.252.13.64/27 via 140.252.13.35 dev eth1 #这个时候,从slip是可以ping的通下面的所有的节点的。 #添加从sun到netb的点对点网络 echo "add p2p from sun to netb" #创建一个peer的网卡对 ip link add name sunside mtu 1500 type veth peer name netbside mtu 1500 #一面塞到sun的网络namespace里面 DOCKERPID3=$(docker inspect '--format={{ .State.Pid }}' sun) ln -s /proc/${DOCKERPID3}/ns/net /var/run/netns/${DOCKERPID3} ip link set sunside netns ${DOCKERPID3} #另一面塞到netb的网络的namespace里面 DOCKERPID4=$(docker inspect '--format={{ .State.Pid }}' netb) ln -s /proc/${DOCKERPID4}/ns/net /var/run/netns/${DOCKERPID4} ip link set netbside netns ${DOCKERPID4} #给sun里面的网卡添加地址 docker exec -it sun ip addr add 140.252.1.29/24 dev sunside docker exec -it sun ip link set sunside up #在sun里面,对外访问的默认路由是1.4 docker exec -it sun ip route add default via 140.252.1.4 dev sunside #在netb里面,对外访问的默认路由是1.4 docker exec -it netb ip route add default via 140.252.1.4 dev eth1 #在netb里面,p2p这面可以没有IP地址,但是需要配置路由规则,访问到下面的二层网络 docker exec -it netb ip link set netbside up docker exec -it netb ip route add 140.252.1.29/32 dev netbside docker exec -it netb ip route add 140.252.13.32/27 via 140.252.1.29 dev netbside docker exec -it netb ip route add 140.252.13.64/27 via 140.252.1.29 dev netbside #对于netb,配置arp proxy echo "config arp proxy for netb" #对于netb来讲,不是一个普通的路由器,因为netb两边是同一个二层网络,所以需要配置arp proxy,将同一个二层网络隔离称为两个。 #配置proxy_arp为1 docker exec -it netb bash -c "echo 1 > /proc/sys/net/ipv4/conf/eth1/proxy_arp" docker exec -it netb bash -c "echo 1 > /proc/sys/net/ipv4/conf/netbside/proxy_arp" #通过一个脚本proxy-arp脚本设置arp响应 #设置proxy-arp.conf #eth1 140.252.1.29 #netbside 140.252.1.92 #netbside 140.252.1.32 #netbside 140.252.1.11 #netbside 140.252.1.4 #将配置文件添加到docker里面 docker cp proxy-arp.conf netb:/etc/proxy-arp.conf docker cp proxy-arp netb:/root/proxy-arp #在docker里面执行脚本proxy-arp docker exec -it netb chmod +x /root/proxy-arp docker exec -it netb /root/proxy-arp start #配置上面的二层网络里面所有机器的路由 echo "config all routes" #在aix里面,默认外网访问路由是1.4 docker exec -it aix ip route add default via 140.252.1.4 dev eth1 #在aix里面,可以通过下面的路由访问下面的二层网络 docker exec -it aix ip route add 140.252.13.32/27 via 140.252.1.29 dev eth1 docker exec -it aix ip route add 140.252.13.64/27 via 140.252.1.29 dev eth1 #同理配置solaris docker exec -it solaris ip route add default via 140.252.1.4 dev eth1 docker exec -it solaris ip route add 140.252.13.32/27 via 140.252.1.29 dev eth1 docker exec -it solaris ip route add 140.252.13.64/27 via 140.252.1.29 dev eth1 #同理配置gemini docker exec -it gemini ip route add default via 140.252.1.4 dev eth1 docker exec -it gemini ip route add 140.252.13.32/27 via 140.252.1.29 dev eth1 docker exec -it gemini ip route add 140.252.13.64/27 via 140.252.1.29 dev eth1 #通过配置路由可以连接到下面的二层网络 docker exec -it gateway ip route add 140.252.13.32/27 via 140.252.1.29 dev eth1 docker exec -it gateway ip route add 140.252.13.64/27 via 140.252.1.29 dev eth1 #到此为止,上下的二层网络都能相互访问了 #配置外网访问 echo "add public network" #创建一个peer的网卡对 ip link add name gatewayin mtu 1500 type veth peer name gatewayout mtu 1500 ip addr add 140.252.104.1/24 dev gatewayout ip link set gatewayout up #一面塞到gateway的网络的namespace里面 DOCKERPID5=$(docker inspect '--format={{ .State.Pid }}' gateway) ln -s /proc/${DOCKERPID5}/ns/net /var/run/netns/${DOCKERPID5} ip link set gatewayin netns ${DOCKERPID5} #给gateway里面的网卡添加地址 docker exec -it gateway ip addr add 140.252.104.2/24 dev gatewayin docker exec -it gateway ip link set gatewayin up #在gateway里面,对外访问的默认路由是140.252.104.1/24 docker exec -it gateway ip route add default via 140.252.104.1 dev gatewayin iptables -t nat -A POSTROUTING -o ${publiceth} -j MASQUERADE ip route add 140.252.13.32/27 via 140.252.104.2 dev gatewayout ip route add 140.252.13.64/27 via 140.252.104.2 dev gatewayout ip route add 140.252.1.0/24 via 140.252.104.2 dev gatewayout