黑帽联盟

 找回密码
 会员注册
查看: 1562|回复: 0
打印 上一主题 下一主题

[资源教程] linux虚拟化网络之OpenvSwitch,经典实战,全网最全,最完善

[复制链接]

895

主题

38

听众

3323

积分

管理员

Rank: 9Rank: 9Rank: 9

  • TA的每日心情
    无聊
    5 天前
  • 签到天数: 1644 天

    [LV.Master]伴坛终老

    网络架构图:

    Untitled2.png

    环境(centos6.7):(图中从左至右,在下面依次列出主机)
    • 主机1:192.168.66.6(eth0)、172.31.225.247(eth1)
    • 主机2:192.168.66.7(eth0)、192.168.77.1(eth1)
    • 主机3:192.168.66.8(eth0)、192.168.77.2(eth1)
    • 主机4:192.168.66.9(eth0)、192.168.77.254(eth1)、172.31.225.244(eth2)

    • 虚拟交换机:通过openvswitch创建出来
    • 虚拟路由:通过网络namespace创建出来,主机2中的虚拟路由用来当作虚拟机的dhcp服务器,动态分配ip地址;主机4中的虚拟路由用来连接虚拟交换机和物理桥
    • 物理桥:通过brctl命令创建(也可以用openvswitch统一管理),但为了更好的区分openvswitch,就用brctl
    • (vm1、vm2、vm3、vm4):通过qemu-kvm底层工具创建
    • 系统镜像:简单且用来作测试的cirros


    实现目的:
    • 主机2、主机3可以通过主机1上外网,本地安装相关的软件包,诸如:openvswitch等
    • vm1和vm3可以互相通信,vm2和vm4可以互相通信;vm1和vm2不能通信,vm3和vm4不能通信
    • 主机2中的vm1、vm3可以通过主机4和外网互相通信


    目的1实现操作:
    1、让主机2和主机3中的eth0网卡的网关指向主机1的eth0地址
    13.png

    14.png

    2、主机1打开转发功能,并添加一条源地址转换规则
    15.png

    在主机2和主机3上测试外网:
    16.png

    17.png


    目的2实现操作:
    主机2上的操作:
    1、下载openvswitch源码,生成rpm包,安装openvswitch包,我这里的版本为2.3.1
    注:不同版本的openvswitch要求内核也不一样,具体参照链接:https://bbs.cnblackhat.com/thread-2820-1-1.html
    yum install gcc make python-devel openssl-devel kernel-devel graphviz kernel-debug-devel autoconf automake rpm-build redhat-rpm-config libtool
    mkdir -p /root/rpmbuild/SOURCES
    wget https://www.openvswitch.org/releases/openvswitch-2.3.1.tar.gz
    tar xf openvswitch-2.3.1.tar.gz
    cp openvswitch-2.3.1.tar.gz /root/rpmbuild/SOURCES/
    cd openvswitch-2.3.1

    由于安装openvswitch,其依赖kmod-openvswitch-2.3.1-1.el6.x86_64.rpm,但是在编译kmod-openvswitch时,总是报错,网络上也没找到对应的解决方法(这里就忽略掉此依赖包,执行下面的命令),网上提供的解决方法(到github下载对应的源码进行编译),参考链接:https://bbs.cnblackhat.com/thread-2821-1-1.html
    sed 's/openvswitch-kmod, //g' rhel/openvswitch.spec > rhel/openvswitch_no_kmod.spec
    rpmbuild -bb rhel/openvswitch_no_kmod.spec

    编译完成后rpm包位于/root/rpmbuild/RPMS/x86_64/
    rpm -ivh /root/rpmbuild/RPMS/x86_64/openvswitch-2.3.1-1.x86_64.rpm

    启动openvswitch服务
    service openvswitch start

    创建一个桥接br-in
    ovs-vsctl add-br br-in

    创建名称空间r0,创建一对网卡,把名称空间r0和虚拟交换机连接起来,并提供dhcp服务;配置yum源,更新iproute,默认6没有netns
    vim /etc/yum.repos.d/rdo-release.repo
    [openstack-kilo]
    name=OpenStack Kilo Repository
    baseurl=https://repos.fedorapeople.org/repos/openstack/EOL/openstack-icehouse/epel-6/
    skip_if_unavailable=0
    enabled=1
    gpgcheck=0
    gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-RDO-kilo



    yum install iproute
    ip link add sif0 type veth peer name rif0
    ip netns add r0
    ip netns exec r0 dnsmasq -F 10.0.4.200,10.0.4.220,86400 -i rif0

    激活sif0网卡,并添加至br-in桥上
    ip link set sif0 up
    ovs-vsctl add-port br-in sif0

    把rif0添加至名称空间r0内,并激活rif0和本地回环接口lo,配置rif0地址
    ip link set rif0 netns r0
    ip netns exec r0 ip link set rif0 up
    ip netns exec r0 ip link set lo up
    ip netns exec r0 ip addr add 10.0.4.254/24 dev rif0

    由于桥br-in设备是openvswitch创建的,并且不能被brctl管理,所以需要单独写if-up和if-down脚本
    if-up内容如下:
    #!/bin/bash
    #
    bridge="br-in"

    if [ -n "$1" ]; then
            ip link set $1 up
            sleep 1
            ovs-vsctl add-port $bridge $1
            [ $? -eq 0 ] && exit 0 || exit 1
    else
            echo "Error: no port specified."
            exit 2
    fi



    if-down内容如下:
    #!/bin/bash
    #
    bridge=br-in

    if [ -n "$1" ]; then
            ip link set $1 down
            sleep 1
            ovs-vsctl del-port $bridge $1
            [ $? -eq 0 ] && exit 0 }} exit 1
    else
            echo "Error: no port specified."
            exit 2
    fi



    添加执行权限:
    chmod +x /etc/if-up
    chmod +x /etc/if-down

    拷贝这两个脚本文件到主机2上
    scp /etc/if-* root@192.168.66.8:/etc/

    创建镜像保存目录
    mkdir /vm/images/ -pv

    下载cirros镜像至/vm/images下,这里大家可以直接下载我给的,优化过的,下载链接: cirros-0.3.6-x86_64-disk.img (14.69 MB, 下载次数: 0)
    18.png

    19.png

    添加虚拟机vm1和vm2
    qemu-kvm -name vm1 -m 128 -smp 1 --drive file=/vm/images/cirros-0.3.6-x86_64-disk.img,media=disk,if=virtio -net nic,model=virtio,macaddr=52:54:00:00:00:01 -net tap,ifname=vif0.0,script=/etc/if-up,downscript=/etc/if-down --daemonize

    qemu-kvm -name vm2 -m 128 -smp 1 --drive file=/vm/images/cirros-0.3.6-x86_64-disk2.img,media=disk,if=virtio -net nic,model=virtio,macaddr=52:54:00:00:00:05 -net tap,ifname=vif1.0,script=/etc/if-up,downscript=/etc/if-down --daemonize


    通过vncviewer登录进入系统,查看ip地址:
    vm1:10.0.4.200
    vm2:10.0.4.201


    主机3上的操作:
    从主机2上拷贝openvswitch软件包
    scp 192.168.66.7:/root/rpmbuild/RPMS/x86_64/openvswitch-2.3.1-1.x86_64.rpm /root
    rpm -ivm /root/openvswitch-2.3.1-1.x86_64.rpm

    启动openvswitch服务
    service openvswitch start

    接着添加一个桥设备
    ovs-vsctl add-br br-in


    主机3上就不创建网络名称空间了,直接从主机2上的网络名称空间上获取ip地址,由于两边的虚拟机处于在不同的机器上,还不能通信,所以我们这里在eth1上通过gre隧道来实现其互相通信,首先在桥br-in上添加一个端口gre0
    ovs-vsctl add-port br-in gre0

    执行上面这条命令如果报错:ovs-vsctl: Error detected while setting up 'gre0'.  See ovs-vswitchd log for details.,就忽略它,实际上已经添加成功了

    接着在激活gre0,并设置隧道相关配置
    ip link set gre0 up
    ovs-vsctl set interface gre0 type=gre options:remote_ip=192.168.77.1

    主机2上也执行相同的操作,remote_ip设置为主机3上eth1的地址,即192.168.77.2
    ovs-vsctl add-port br-in gre0
    ip link set gre0 up
    ovs-vsctl set interface gre0 type=gre options:remote_ip=192.168.77.2

    此时我们就可以在主机3上创建虚拟机了
    qemu-kvm -name vm3 -m 128 -smp 1 --drive file=/vm/images/cirros-0.3.6-x86_64-disk.img,media=disk,if=virtio -net nic,model=virtio,macaddr=52:54:00:00:a0:03 -net tap,ifname=vif0.0,script=/etc/if-up,downscript=/etc/if-down --daemonize

    qemu-kvm -name vm4 -m 128 -smp 1 --drive file=/vm/images/cirros-0.3.6-x86_64-disk2.img,media=disk,if=virtio -net nic,model=virtio,macaddr=52:54:00:00:a0:02 -net tap,ifname=vif1.0,script=/etc/if-up,downscript=/etc/if-down --daemonize

    通过vncviewer远程连接进入,查得虚拟机ip地址如下:
    vm3:10.0.4.202
    vm4:10.0.4.208


    两台主机通信测试:
    在vm1内部ping其它三台主机,经测试,他们都是可以互相通信的
    20.png

    但这里我们要求vm1不能和vm2通信,vm3不能和vm4通信,所以我们还需要设置vif0.0和vif1.0端口上tag标签,给他们家标签,vm1和vm3设置同一个标签,vm2和vm4设置成同一个标签(分别在两台机器上操作)
    ovs-vsctl set port vif0.0 tag=10
    ovs-vsctl set port vif1.0 tag=10

    这样的话,10.0.4.200(vm1)和10.0.4.202(vm3)可以互相通信;10.0.4.201(vm2)和10.0.4.208(vm4)可以互相通信;其它主机之间也不能互相通信,即使在同一个局域网
    21.png

    22.png


    目的3实现操作:
    这里我们是让主机2和主机4通过隧道实现通信的,我们把主机2和主机3相关的隧道功能配置删除,重新配置,这里直接删除桥br-in上面的端口gre0,并移除tag所赋的值,分别在两台主机上(主机2和主机3)操作
    ovs-vsctl del-port br-in gre0
    ovs-vsctl remove port vif0.0 tag 10
    ovs-vsctl remove port vif1.0 tag 20

    这块我们就不通过gre隧道和vlan来实现了,我们用vxlan来实现,vxlan其也支持gre隧道,同时也比vlan支持的端口数量还要多
    主机2上操作:ovs-vsctl add-port br-in vx0 -- set interface vx0 type=vxlan options:remote_ip=192.168.77.254
    主机4上操作:ovs-vsctl add-port br-in vx0 -- set interface vx0 type=vxlan options:remote_ip=192.168.77.1

    紧接着在主机4上创建虚拟机交换机,安装和启动服务这块我就省略了,上面都已经说过
    ovs-vsctl add-br br-in

    在创建虚拟路由,通过网络名称空间,这台主机是centos7,默认带netns功能,升级操作就省略了,如果你是6版本,按照上面的操作进行升级
    ip netns add r0

    创建一对网卡,用来连接虚拟交换机和虚拟路由
    ip link add sin0 type veth peer name rin0

    在桥br-in设备上添加端口sin0,在网络名称空间r0添加rin0
    ovs-vsctl add-port br-in sin0
    ip link set sin0 up
    ip link set rin0 netns r0
    ip netns exec r0 ip link set rin0 up
    ip netns exec r0 ip addr add 10.0.4.100/24 dev rin0


    主机4上网络名称空间和vm1内ping测试:(已经可以通信了)
    23.png

    24.png

    添加物理桥设备br-ex,并把eth2关联到br-ex桥设备上,这里我是直接添加ifcfg-br-ex,并修改ifcfg-br-ex和ifcfg-eth2配置
    ifcfg-br-ex配置如下:
    TYPE="Ethernet"
    BOOTPROTO="none"
    IPADDR="172.31.225.244"
    NETMASK="255.255.255.0"
    GATEWAY=172.31.225.1
    NAME="br-ex"
    DEVICE="br-ex"
    ONBOOT="yes"
    TYPE=Bridge



    ifcfg-eth2配置如下:
    TYPE="Ethernet"
    BOOTPROTO="none"
    NAME="eth2"
    DEVICE="eth2"
    ONBOOT="yes"
    BRIDGE=br-ex



    重启网络服务
    systemctl restart network

    然后再添加一对网卡,用来连接虚拟路由器和物理桥设备br-ex,并激活这对网卡,配置rex0的ip地址
    ip link add rex0 type veth peer name sex0
    ip link set sex0 up
    brctl addif br-ex sex0
    ip link set rex0 netns r0
    ip netns exec r0 ip link set rex0 up
    ip netns exec r0 ip addr add 172.31.225.248/24 dev rex0

    紧接着在网络名称空间r0内打开转达功能,并配置源地址转换
    25.png

    最后在vm1和vm2上添加默认网关10.0.4.100(rin0)
    26.png

    27.png

    在vm1和vm2内部ping测试,如果ping不通,把之前的网关10.0.4.254给删掉,即route del default gw 10.0.4.254
    28.png

    29.png

    到这里,虚拟机已经可以和外网通信了,但是别人访问不了虚拟机,所以还得在网络名称空间内部做个目标地址转换,并在其内部添加一块网卡专门用来给vm1用
    ip netns exec r0 ifconfig rex0:0 172.31.225.249/24 up
    ip netns exec r0 iptables -t nat -A POSTROUTING -s 10.0.4.200/32 -j SNAT --to-source 172.31.225.249
    ip netns exec r0 iptables -t nat -A PREROUTING -d 172.31.225.249 -j DNAT --to-destination 10.0.4.200


    在物理机器172.31.225.76上测试ping
    30.png

    在主机2上抓包验证
    31.png


    到这里就结束了,原创不易,转载请注明来源
    帖子永久地址: 

    黑帽联盟 - 论坛版权1、本主题所有言论和图片纯属会员个人意见,与本论坛立场无关
    2、本站所有主题由该帖子作者发表,该帖子作者与黑帽联盟享有帖子相关版权
    3、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和黑帽联盟的同意
    4、帖子作者须承担一切因本文发表而直接或间接导致的民事或刑事法律责任
    5、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
    6、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除并致以最深的歉意
    7、黑帽联盟管理员和版主有权不事先通知发贴者而删除本文

    勿忘初心,方得始终!
    您需要登录后才可以回帖 登录 | 会员注册

    发布主题 !fastreply! 收藏帖子 返回列表 搜索
    回顶部