以下内容已屏蔽图片优化访问速度 |
---|
所有做过网络编程的程序员,想必都会看《TCP/IP详解》卷一:协议 [IMG] 后来出了第二版,但是由于第一版才是Rechard Stevens的原版,本人还是多次看了第一版。 对这一版印象最深的就是下面这个拓扑图 [IMG] 书上的很多实验,都是基于这个图做的,看了实验结果,很多理论才有真实的感觉。 看这本书的时候,不尽感慨Rechard Stevens的天赋英才,他能够利用工作中当时少于的实验环境,做了大量的实验,写出了普惠程序员的这本书。 可是除了看书中的实验结果,如何能够模拟这么一个环境,也动手测试一下呢? 可是对于大部分的同学来讲,是几乎不可能的事情,除非能够真的管理实验室或者机房。 后来有了Docker和Openvswitch,发现这个拓扑图在一个虚拟机里面就能够模拟完成。 接下来我们就看这个过程。 一、创建一个Ubuntu的VirtualBox虚拟机 [IMG] 里面有两张网卡,一个是NAT,用于访问公网,一个是Host-only,用于ssh进去配置。 二、安装Docker apt-get remove docker docker-engine docker.io apt-get update apt-get install apt-transport-[IMG] ca-certificates curl software-properties-common curl -fsSL [IMG]> gpg apt-key add gpg apt-key fingerprint 0EBFCD88 add-apt-repository "deb [arch=amd64] [IMG]$(lsb_release -cs) stable" apt-get update apt-cache madison docker-ce apt-get install docker-ce=17.03.2~ce-0~ubuntu-xenial 三、安装Openvswitch apt-get install openvswitch-common openvswitch-dbg openvswitch-switch python-openvswitch openvswitch-ipsec openvswitch-pki openvswitch-vtep 安装网桥 apt-get install bridge-utils apt-get install arping 四、创建br-ex,用于gateway连接外网 在虚拟机里面找到NAT的那张网卡 2: enp0s3: link/ether 08:00:27:77:d9:16 brd ff:ff:ff:ff:ff:ff inet 10.0.2.15/24 brd 10.0.2.255 scope global enp0s3 valid_lft forever preferred_lft forever 创建br-ex,将NAT网卡连接到br-ex,然后将IP地址放在br-ex上 brctl addbr br-ex brctl addif br-ex enp0s3 ifconfig enp0s3 0 ifconfig br-ex 10.0.2.15/24 ip route add default via 10.0.2.2 dev br-ex 五、准备一个Ubuntu容器镜像 准备一个Dockerfile FROM hub.c.163.com/public/ubuntu:14.04 RUN apt-get -y update && apt-get install -y iproute2 iputils-arping net-tools arping tcpdump curl telnet iputils-tracepath traceroute ENTRYPOINT /usr/sbin/sshd -D 编译这个Dockerfile docker build -f Dockerfile -t hub.c.163.com/liuchao110119163/ubuntu:1 . 六、创建图中所有的节点,每个一个容器 docker run --privileged=true --net none --name aix -d hub.c.163.com/liuchao110119163/ubuntu:1 docker run --privileged=true --net none --name solaris -d hub.c.163.com/liuchao110119163/ubuntu:1 docker run --privileged=true --net none --name gemini -d hub.c.163.com/liuchao110119163/ubuntu:1 docker run --privileged=true --net none --name gateway -d hub.c.163.com/liuchao110119163/ubuntu:1 docker run --privileged=true --net none --name netb -d hub.c.163.com/liuchao110119163/ubuntu:1 docker run --privileged=true --net none --name sun -d hub.c.163.com/liuchao110119163/ubuntu:1 docker run --privileged=true --net none --name svr4 -d hub.c.163.com/liuchao110119163/ubuntu:1 docker run --privileged=true --net none --name bsdi -d hub.c.163.com/liuchao110119163/ubuntu:1 docker run --privileged=true --net none --name slip -d hub.c.163.com/liuchao110119163/ubuntu:1 七、创建两个网桥,代表两个二层网络 ovs-vsctl add-br net1 ovs-vsctl add-br net2 八、将所有的节点连接到两个网络 在这里我们使用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网络 创建一个peer的两个网卡 ip link add name slipside mtu 1500 type veth peer name bsdiside mtu 1500 把其中一个塞到slip的网络namespace里面 root@k8smaster:~# docker inspect '--format={{ .State.Pid }}' slip 14521 ln -s /proc/14521/ns/net /var/run/netns/14521 ip link set slipside netns 14521 把另一个塞到bsdi的网络的namespace里面 root@k8smaster:~# docker inspect '--format={{ .State.Pid }}' bsdi 14478 ln -s /proc/14478/ns/net /var/run/netns/14478 ip link set bsdiside netns 14478 给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的点对点网络 创建一个peer的网卡对 ip link add name sunside mtu 1500 type veth peer name netbside mtu 1500 一面塞到sun的网络namespace里面 root@k8smaster:~# docker inspect '--format={{ .State.Pid }}' sun 14384 ln -s /proc/14384/ns/net /var/run/netns/14384 ip link set sunside netns 14384 另一面塞到netb的网络的namespace里面 root@k8smaster:~# docker inspect '--format={{ .State.Pid }}' netb 14336 ln -s /proc/14336/ns/net /var/run/netns/14336 ip link set netbside netns 14336 给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 对于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 bash chmod +x proxy-arp ./proxy-arp start 十二、配置上面的二层网络里面所有机器的路由 在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 十三、在gateway里面创建一个网卡连接到br-ex 连接到br-ex用于连接外网 ./pipework br-ex gateway 10.0.2.88/24@10.0.2.2 通过配置路由可以连接到下面的二层网络 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 到此为止,上下的二层网络都能相互访问了,并且可以访问外网。 脚本在这里https://github.com/popsuper1982/tcpipillustrated |