有了Openvswitch和Docker,終於可以做《TCP/IP詳解》的實驗了!


所有做過網絡編程的程序員,想必都會看《TCP/IP詳解》卷一:協議

 

 

后來出了第二版,但是由於第一版才是Rechard Stevens的原版,本人還是多次看了第一版。

 

對這一版印象最深的就是下面這個拓撲圖

 

 

書上的很多實驗,都是基於這個圖做的,看了實驗結果,很多理論才有真實的感覺。

 

看這本書的時候,不盡感慨Rechard Stevens的天賦英才,他能夠利用工作中當時少於的實驗環境,做了大量的實驗,寫出了普惠程序員的這本書。

 

可是除了看書中的實驗結果,如何能夠模擬這么一個環境,也動手測試一下呢?

 

可是對於大部分的同學來講,是幾乎不可能的事情,除非能夠真的管理實驗室或者機房。

 

后來有了Docker和Openvswitch,發現這個拓撲圖在一個虛擬機里面就能夠模擬完成。

 

接下來我們就看這個過程。

 

一、創建一個Ubuntu的VirtualBox虛擬機

 

 

里面有兩張網卡,一個是NAT,用於訪問公網,一個是Host-only,用於ssh進去配置。

 

二、安裝Docker

 

apt-get remove docker docker-engine docker.io

apt-get update

apt-get install     apt-transport-https     ca-certificates     curl     software-properties-common

curl -fsSL https://download.docker.com/linux/ubuntu/gpg > gpg

apt-key add gpg

apt-key fingerprint 0EBFCD88

add-apt-repository    "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(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: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000

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

 

歡迎關注個人微信公眾號

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM