有了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里面

[email protected]:~# 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里面

[email protected]:~# 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里面

[email protected]:~# 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里面

[email protected]:~# 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/[email protected]

通过配置路由可以连接到下面的二层网络

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

欢迎关注个人微信公众号

原文地址:https://www.cnblogs.com/popsuper1982/p/8492254.html

时间: 2024-11-10 07:51:14

有了Openvswitch和Docker,终于可以做《TCP/IP详解》的实验了!的相关文章

Docker之一----基础介绍和命令详解

一.前言 统称来说,容器是一种工具, 指的 是可以装下其它物品的工具, 以方便人类归纳 放置 物品 .存储和异地运输 具体 来说 比如人类使用的 衣柜 .行李箱.背包等可以成为容器,但今天我们所说的容器是一种IT技术. 容器技术是虚拟化.云计算.大数据之后的一门新兴的并且是炙手可热的新技术, 容器 技术提高了硬件资源利用率. 方便 了 企业 的业务快速横向扩容. 实现了业务宕机自愈功能 , 因此未来数年会 是一个容器愈发流行的 时 代这是 一个对于IT 行业 来说非常有影响和价值的技术,而对于

mysql二进制日志详解及备份恢复、基于mysqldump及lvmsnapshot做备份恢复详解

二进制日志: 时间点恢复 复制 20140411 回顾: 日志文件:6类 一般查询日志:log, general_log, log_output 慢查询日志: 错误日志 二进制日志 中继日志 事务日志 二进制日志:"修改" position:位置 time: 时间 滚动: 1.大小 2.时间 二进制日志的功用: 即时点恢复: 复制: mysql> SHOW MASTER STATUS; mysql> FLUSH LOGS; mysql> SHOW BINARY LOG

linux磁盘管理之LVM逻辑卷认识与管理详解(实验详细,可跟做)

Linux磁盘管理之LVM逻辑卷认识与管理详解 前言 本文接着上篇文章作如下延伸:链接:Linux磁盘管理之磁盘管理与文件系统 什么是LVM?为什么需要LVM? 如何具体进行LVM逻辑卷管理? 什么是磁盘配额?为什么需要磁盘配额? 在Linux中进行磁盘配额的条件是什么呢? 如何具体进行磁盘配额? 下面对以上问题逐一讲解,深入实例进行操作,带你深入理解linux磁盘管理之LVM逻辑卷管理. 一.LVM概述 1.什么是LVM?为什么需要LVM? ? 许多 Linux 使用者安装操作系统时都会遇到这

python在selenium中做自动化测试用法详解

一.环境搭建参考:https://blog.csdn.net/efly2333/article/details/80346426 二.selenium用法详解(https://www.cnblogs.com/themost/p/6900852.html) 1 selenium用法详解 2 selenium主要是用来做自动化测试,支持多种浏览器,爬虫中主要用来解决JavaScript渲染问题. 3 模拟浏览器进行网页加载,当requests,urllib无法正常获取网页内容的时候 4 5 一.声明

DOCKER学习_012:Dockerfile配置指令详解

1 Dockerfile结构 基础镜像信息 镜像操作指令 容器启动时执行指令 2 FROM 指定基础镜像,用于继承其他镜像使用的 FROM ubuntu:14.06 FROM centos FROM nginx:latest 3 LABEL 镜像创建者的基本信息 4 ENV 定义Docker容器内的环境变量 ENV # 只能设置一个变量 ENV = … # 允许一次设置多个变量 ENV <key> <value> 指定一个环境变量,会被后续RUN指令使用,并在容器运行时保持 示例:

Docker之七---Docker存储卷与容器卷详解

1.存储卷介绍 1.1 背景 (1)docker 的 AFUS 分层文件系统 docker镜像由多个只读层叠加而成,启动容器时,docker会加载只读镜像层并在镜像栈顶部加一个读写层: 如果运行中的容器修改了现有的一个已经存在的文件,那该文件将会从读写层下面的只读层复制到读写层,该文件版本仍然存在,只是已经被读写层中该文件的副本所隐藏,此即“写时复制(COW)”机制. 描述:如果一个文件在最底层是可见的,如果在layer1上标记为删除,最高的层是用户看到的Layer2的层,在layer0上的文件

Docker虚拟化技术系列之-命令详解

虚拟化原理:虚拟化解决方案的底部是要进行虚拟化的物理机器.这台机器可能直接支持虚拟化,也可能不会直接支持虚拟化:那么就需要系统管理程序 层的支持.系统管理程序(Virtual machine monitor),或称为 VMM,可以看作是平台硬件和操作系统的抽象化.在某些情况中,这个系统管理程序就是一个操作系统:此时,它就称为主机操作系统. 随着docker不断的学习,我们要想进一步去维护docker,就需要掌握docker日常使用的命令,如下为docker常用命令: 一.容器基础命令 docke

Docker中的镜像分层技术详解

早在集装箱没有出现的时候,码头上还有许多搬运的工人在搬运货物,在集装箱出现以后,码头上看到更多的不是工人,而且集装箱的搬运模式更加单一,更加高效,还有其他的好处,比如:货物多打包在集装箱里面,可以防止货物之前相互影响.并且到了另外一个码头需要转运的话,有了在集装箱以后,直接把它运送到另一个容器内即可,完全可以保证里面的货物是整体的搬迁,并且不会损坏货物本身.那么docker 镜像在IT行业中也扮演着非常重要的形象. 什么是docker 镜像 就是把业务代码,可运行环境进行整体的打包 如何创建do

Docker的安装配置及使用详解

基本概念 Docker 包括三个基本概念 镜像(Image) 容器(Container) 仓库(Repository) 先理解了这三个概念,就理解了 Docker 的整个生命周期. 1.docker安装与启动 yum install -y epel-release yum install docker-io # 安装docker # 配置文件 /etc/sysconfig/docker chkconfig docker on # 加入开机启动 service docker start # 启动d