主頁 > 作業系統 > 【NetDevOps】新一代網工需要了解的那點事兒---云計算中的網路虛擬化(一)

【NetDevOps】新一代網工需要了解的那點事兒---云計算中的網路虛擬化(一)

2020-09-25 02:35:29 作業系統

這篇文章本應該在2018年更詳細的記錄在《docker by F0rGeEk》中,由于那本書正好寫到網路章節時出了點狀況所以沒有繼續寫下去,,,??還是那句老話:出來混早晚都得還??????
本文篇幅較長雖有目錄,為方便閱讀特將本文按章節拆成幾個部分:
【NetDevOps】新一代網工需要了解的那點事兒(一)---網路虛擬化
【NetDevOps】新一代網工需要了解的那點事兒(二)---veth-pair
【NetDevOps】新一代網工需要了解的那點事兒(三)---Linux Bridge
【NetDevOps】新一代網工需要了解的那點事兒(四)---tun/tap
【NetDevOps】新一代網工需要了解的那點事兒(五)---iptables
【NetDevOps】新一代網工需要了解的那點事兒(六)---VTI
【NetDevOps】新一代網工需要了解的那點事兒(七)---VXLAN
【NetDevOps】新一代網工需要了解的那點事兒(八)---Macvlan

目錄
  • 1. 網路虛擬化
    • 1.1 傳統網路虛擬化
    • 1.2 Linux中網路結構
    • 1.3 Linux network namespace
      • 1.3.1 netns各引數意義
      • 1.3.2 創建一個ns
      • 1.3.3 在NS中執行命令
      • 1.3.4 激活ns中的環回介面
      • 1.3.5 查詢并洗掉一個NS
    • 1.4 虛擬網路設備veth-pair
      • 1.4.1 創建veth-pair
      • 1.4.2 veth-pair連通性
      • 1.4.3 在NS中的連通性
      • 1.4.4 NS之間的連通性
    • 1.5 Linux bridge
      • 1.5.1 實作原理
      • 1.5.2 創建bridge
      • 1.5.3 連接兩個NS
    • 1.6 tun/tap
      • 1.6.1 tun/tap概述
      • 1.6.2 典型使用場景
      • 1.6.3 tun與tap的區別
    • 1.7 iptables
      • 1.7.1 iptables基礎
      • 1.7.2 iptables的結構
      • 1.7.3 表鏈關系
      • 1.7.4 iptables Rules
      • 1.7.5 iptables基礎操作
      • 1.7.6 常用命令總結
    • 1.8 隧道技術VTI
      • 1.8.1 技術概述
      • 1.8.2 VTI的實作
    • 1.9 VXLAN
      • 1.9.1 VXLAN概述
      • 1.9.2 VXLAN和VLAN區別
      • 1.9.3 VXLAN網路模型
      • 1.9.4 VXLAN實踐
    • 1.10 MacVLAN
      • 1.10.1 基本原理
      • 1.10.2 作業模式
      • 1.10.3 MacVLAN實踐

1. 網路虛擬化

1.1 傳統網路虛擬化

??隨著云計算、大二層、SDN等等這些名詞的出現,傳統網路架構面臨的挑戰變得越來越迫切,業內曾有人說“要想實作真正的軟體自定義資料中心,網路虛擬化將是最后一公里”從架構上來看確實沒毛病,這時候著急的是傳統網路廠商,如果不與時俱進則很有可能被淘汰,就好比人家都在玩觸屏,你(NOKIA)卻還執意玩按鍵(當然這不是主要原因),其實傳統的網路在前幾年資料中心比較火的時候,也催生出很多虛擬化相關的技術,網路虛擬化其實并不陌生,我們常用的Overlays、VLAN、VPN、VRF、HSRP、MPLS這些都是傳統網路不斷迭代出的虛擬化技術,迫于資料中心、云計算等的需要相繼出現了類似STACK、VSS、VDC、VPC、VEB、VEPA、VN-TAG、VXLAN、MacVLAN等技術,這些技術有的能在有限的物理網路架構中支持多個邏輯網路,有的能將不同的物理硬體整合到一起,有的則類似計算虛擬化將有限的物理資源虛擬出多個邏輯資源,
??最近在看一本書《Kubernetes網路權威指南》,看了部分章節后覺得有必要暫停腳步理一理,首先是感謝作者提供這么一本書,讓傳統網工有機會接觸Linux中的網路虛擬化,感謝這本書中的坑給我機會去了解Linux底層IP路由是如何實作的,其次是要吐槽一下對于Linux底層不了解的讀者來說,第一章可能就暈了!親身經歷?????? 有些地方理解起來和傳統網路還真有差別,下面我將戴著口罩??以一個傳統網工的角度來講解Linux中的網路虛擬化,

1.2 Linux中網路結構

??Linux 虛擬網路的基石都是由一個個的虛擬設備構成的,虛擬化技術沒出現之前,計算機網路系統都只包含物理的網卡設備,通過網卡配接器,線纜介質,連接外部網路,構成龐大的 Internet(如下圖所示),然而,隨著虛擬化技術的出現,網路也隨之被虛擬化,相較于單一的物理網路,虛擬網路變得非常復雜,在一個主機系統里面,需要實作諸如交換、路由、隧道、隔離、聚合等多種網路功能,而實作這些功能的基本元素就是虛擬的網路設備,比如 bridge、tap、tun 和 veth/veth-pair,

                 Physical NIC
               +--------------+
               |  Socket API  |
               +-------+------+
 User Space            |
+------------------------------------------+
 Kernel Space          |
                 raw ethernet
                       |
               +-------+-------+
               | Network Stack |
               +-------+-------+
                       |
               +-------+-------+
               |      eth0     |
               +-------+-------+
                       |
               +-------+-------+
               |      NIC      |
               +-------+-------+
                       |
                      wire

1.3 Linux network namespace

??傳統網路中我們有一個技術叫VRF,一般我們可以將每一個VRF看作是一臺專用的PE設備,它有獨立的路由表、地址空間,有屬于自己的網路介面、路由協議,在Linux中類似VRF的功能被稱作是network namespace,當然Linux還有其他很多的namespace這里就不做過多講解(因為我不專業??),每個network namespce都有自己的網路設備(如IP、路由表、埠范圍、安全策略、/proc/net目錄等),在Linux中維護network namespace主要使用netns這個工具,下面我們逐一展開來講解,

注:下文為方便書寫特將network namespace用NS代替,

1.3.1 netns各引數意義

[root@F0rGeEk ~]# ip netns help             # 該命令可獲取netns相關幫助檔案
Usage: ip netns list                        # 查看系統中的ns
       ip netns add NAME                    # 創建一個ns
       ip netns set NAME NETNSID            # 給某個ns分配ID
       ip [-all] netns delete [NAME]        # 洗掉一個ns
       ip netns identify [PID]              # 查看某個行程的ns
       ip netns pids NAME                   # 查找關于這個ns為主的行程
       ip [-all] netns exec [NAME] cmd ...  # 在某個ns中執行命令
       ip netns monitor                     # 監控對ns的操作
       ip netns list-id                     # 通過list-id顯示ns

1.3.2 創建一個ns

??我們創建一個名為forgeek的NS,其程序如下;當我們創建一個NS時,系統會自動在/var/run/netns目錄中生成一個掛載點,這個掛載點即方便對ns的管理,也是NS在沒有行程運行的情況下依然存在,

[root@F0rGeEk ~]# ip netns add forgeek
[root@F0rGeEk netns]# pwd
/var/run/netns
[root@F0rGeEk netns]# ls -l
total 0
-r--r--r--. 1 root root 0 Mar 17 03:23 forgeek

1.3.3 在NS中執行命令

??在主機中我們可以在NS中執行一些命令,經過實踐發現居然可以在NS中執行bash切換到NS的shell,比較好奇這樣在安全上有沒有風險,這里為了區分兩個shell,我特意將新建的NS中的hostname命名為ns-forgeek:

[root@F0rGeEk ~]# ip netns exec forgeek ip link list
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
[root@F0rGeEk ~]# ip netns exec forgeek bash
[root@ns-forgeek ~]# ip addr
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
[root@ns-forgeek ~]# exit
exit
[root@F0rGeEk ~]#

1.3.4 激活ns中的環回介面

??通過1.2.3實驗程序,我們可以看到當我們創建一個ns后,系統默認會給該ns分配一個loopback介面,并且默認情況下這個介面處于DOWN的狀態,這里我們將其設定為UP,之所以要在這里花費一個小結做這個,是因為如果該介面處于DOWN狀態的話,后期會有很多你想不到的坑在等你!真的是經驗之談??????

#  方法一:
[root@F0rGeEk ~]# ip netns exec forgeek ip link set dev lo up
[root@F0rGeEk ~]# ip netns exec forgeek ip link list
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
# 方法二:
[root@F0rGeEk ~]# ip netns exec forgeek bash
[root@ns-forgeek ~]# ip link set dev lo up
[root@ns-forgeek ~]# ip link list
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

1.3.5 查詢并洗掉一個NS

[root@F0rGeEk ~]# ip netns list
forgeek
[root@F0rGeEk ~]# ip netns delete forgeek
[root@F0rGeEk ~]# ip netns list
[root@F0rGeEk ~]#

1.4 虛擬網路設備veth-pair

??veth從名字上來看是 Virtual Ethernet 的縮寫,veth是成對出現的一種虛擬網路設備,一端連接著協議堆疊,一端連接著彼此,資料從一端出,從另一端進,通常也稱作veth-pair(如下圖所示),它的作用很簡單,就是要把從一個 network namespace 發出的資料包轉發到另一個 namespace中,正因為它的這個特性,常常被用來連接不同的虛擬網路組件,構建大規模的虛擬網路拓撲,比如連接Bridge、OVS、LXC、Docker容器等,很常見的案例就是它被用于Docker網路還有OpenStack Neutron,構建非常復雜的網路形態,

                                Veth Pair
               +--------------+            +--------------+
               |  Socket API  |            |  Socket API  |
               +-------+------+            +-------+------+
                       |                           |
 User Space            |                           |
+------------------------------------------------------------------+
 Kernel Space          +                           +
                 raw ethernet                 raw ethernet
                       +                           +
               +-------+-------+           +-------+-------+
               | Network Stack |           | Network Stack |
               +-------+-------+           +-------+-------+
                       |                           |
               +-------+-------+           +-------+-------+
               |      vethX    |           |     vethX     |
               +-------+-------+           +-------+-------+
                       |                           |
                       +---------------------------+

1.4.1 創建veth-pair

??我們通過"ip link"相關命令,創建一對虛擬網卡veth0和veth1,其中給veth0配置IP為12.1.1.1/24,veth1配置IP為12.1.1.2/24,并激活這一對虛擬網卡,"ip link"命令相關引數比較多,可以使用"ip link help"查看這里就不做過多解釋,最后通過"ip link list"查看虛擬網卡相關狀態,連接圖及創建程序如下:

+--------------------------------------------------------------------------------------+
|             +-------------------------------------------------------------+          |
|             |                     Network Protocol Stack                  |          |
|             +------+------------------------+-----------------------+-----+          |
|                    ^                        ^                       ^                |
|                    |                        |                       |                |
+--------------------------------------------------------------------------------------+
|                    |                        |                       |                |
|                    v                        v                       v                |
|            +-------+------+           +-----+-----+           +-----+-----+          |
|            |     Eth0     |           |   Veth0   |           |   Veth1   |          |
|            +-------+------+           +-----+-----+           +------+----+          |
|                    ^                        ^                        ^               |
|      10.10.10.137  |             12.1.1.1/24|                        |12.1.1.2/24    |
|                    |                        +------------------------+               |
|                    |                                                                 |
+--------------------v-----------------------------------------------------------------+
|           Physical Network                                           By:[F0rGeEk]    |
+--------------------------------------------------------------------------------------+
  • 創建一對veth
[root@d1 ~]# ip link add veth0 type veth peer name veth1
# 查看是否創建成功
[root@d1 ~]# ip link list
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 00:0c:29:97:0f:70 brd ff:ff:ff:ff:ff:ff
3: veth1@veth0: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 12:64:bd:95:4f:40 brd ff:ff:ff:ff:ff:ff
4: veth0@veth1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 96:10:c9:07:77:d9 brd ff:ff:ff:ff:ff:ff
  • 為虛擬網卡配置IP
[root@d1 ~]# ip addr add 12.1.1.1/24 dev veth0
[root@d1 ~]# ip addr add 12.1.1.2/24 dev veth1
 # 查看是否配置成功
[root@d1 ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:97:0f:70 brd ff:ff:ff:ff:ff:ff
    inet 10.10.10.137/24 brd 10.10.10.255 scope global noprefixroute dynamic ens33
       valid_lft 5444486sec preferred_lft 5444486sec
    inet6 fe80::d956:a6bf:6a6e:b6a7/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
3: veth1@veth0: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 12:64:bd:95:4f:40 brd ff:ff:ff:ff:ff:ff
    inet 12.1.1.2/24 scope global veth1
       valid_lft forever preferred_lft forever
4: veth0@veth1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 96:10:c9:07:77:d9 brd ff:ff:ff:ff:ff:ff
    inet 12.1.1.1/24 scope global veth0
       valid_lft forever preferred_lft forever
  • 激活這一對虛擬網卡
[root@d1 ~]# ip link set veth0 up
[root@d1 ~]# ip link set veth1 up
 # 查看是否激活
[root@d1 ~]# ip link list
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 00:0c:29:97:0f:70 brd ff:ff:ff:ff:ff:ff
3: veth1@veth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether 12:64:bd:95:4f:40 brd ff:ff:ff:ff:ff:ff
4: veth0@veth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether 96:10:c9:07:77:d9 brd ff:ff:ff:ff:ff:ff

1.4.2 veth-pair連通性

??接1.4.1步驟這一對虛擬網卡IP地址在同一段且均已激活,這里我們用veth0 ping veth1,查看網路是否可以連通,測驗程序如下:

[root@d1 ~]# ping 12.1.1.2 -c 3 -I veth0
PING 12.1.1.2 (12.1.1.2) from 12.1.1.1 veth0: 56(84) bytes of data.

--- 12.1.1.2 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 1999ms

??由上面步驟可以看出,實際上這一對虛擬網卡并不能互相通信,可是依據理論來講,他們是可以互相通信的,這里我們通過抓包來分析一下原因,首先從veth0長pingveth1,然后分別抓veth0和veth1這兩個虛擬網卡的包:

  • veth0
[root@d1 ~]# tcpdump -nnt -i veth0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on veth0, link-type EN10MB (Ethernet), capture size 262144 bytes
ARP, Request who-has 12.1.1.2 tell 12.1.1.1, length 28
ARP, Request who-has 12.1.1.2 tell 12.1.1.1, length 28
ARP, Request who-has 12.1.1.2 tell 12.1.1.1, length 28
  • veth1
[root@d1 ~]# tcpdump -nnt -i veth1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on veth1, link-type EN10MB (Ethernet), capture size 262144 bytes
ARP, Request who-has 12.1.1.2 tell 12.1.1.1, length 28
ARP, Request who-has 12.1.1.2 tell 12.1.1.1, length 28
ARP, Request who-has 12.1.1.2 tell 12.1.1.1, length 28

??通過以上抓包分析:veth0和veth1處于同一網段12.1.1.0/24,由于是第一次通信會通過ARP來確定MAC,可是在兩個網卡的抓包情況來看,只有veth0發出的Request包并沒有veth1回應的Raply包,有一定傳統網路Trouble Shooting功底的您,看到這種現象肯定會想這肯定是防火墻策略阻止了吧??您的猜測完全正確,經過查閱相關檔案得知:大部分發行版Linux在默認情況下,內核中關于ARP是有一定限制的,所以為了使這一對虛擬網卡在根NS能直接互通,必須要修改默認的策略:

 # 修改IP路由默認策略及默認ARP策略
[root@d1 ~]# echo 1 > /proc/sys/net/ipv4/conf/veth1/accept_local
[root@d1 ~]# echo 1 > /proc/sys/net/ipv4/conf/veth0/accept_local
[root@d1 ~]# echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter
[root@d1 ~]# echo 0 > /proc/sys/net/ipv4/conf/veth0/rp_filter
[root@d1 ~]# echo 0 > /proc/sys/net/ipv4/conf/veth1/rp_filter
 # 接下來再測驗連通性
[root@d1 ~]# ping 12.1.1.2 -c 3 -I veth0
PING 12.1.1.2 (12.1.1.2) from 12.1.1.1 veth0: 56(84) bytes of data.
64 bytes from 12.1.1.2: icmp_seq=1 ttl=64 time=0.037 ms
64 bytes from 12.1.1.2: icmp_seq=2 ttl=64 time=0.051 ms
64 bytes from 12.1.1.2: icmp_seq=3 ttl=64 time=0.045 ms

--- 12.1.1.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2034ms
rtt min/avg/max/mdev = 0.037/0.044/0.051/0.005 ms

注:至于為什么修改上述策略才能通信,過兩天還是單獨寫一篇文章來解釋吧,

1.4.3 在NS中的連通性

??接下來我們將veth1關聯到1.3章節中創建的NS,然后看看和veth0通信的程序,

[root@d1 ~]# ip link set veth1 netns forgeek
[root@d1 ~]# ip netns exec forgeek ifconfig veth1 12.1.1.2/24
[root@d1 ~]# ip netns exec forgeek ip link set dev veth1 up
[root@d1 ~]# ping 12.1.1.2 -c 3 -I veth0
PING 12.1.1.2 (12.1.1.2) from 12.1.1.1 veth0: 56(84) bytes of data.
64 bytes from 12.1.1.2: icmp_seq=1 ttl=64 time=0.115 ms
64 bytes from 12.1.1.2: icmp_seq=2 ttl=64 time=0.066 ms
64 bytes from 12.1.1.2: icmp_seq=3 ttl=64 time=0.072 ms

--- 12.1.1.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 0.066/0.084/0.115/0.023 ms

1.4.4 NS之間的連通性

??之前我們說veth-pair主要是用來解決不同NS之間通信的,那么接下來我們來創建兩個NS:ns1,ns2,然后將veth0
加入到ns1中,veth1加入到ns2中,分別給veth0和veth1配置IP地址如下圖所示:

+------------------------------------------------------------------+
|                                                                  |
| +-----------------+                          +-----------------+ |
| |      NS1        |                          |       NS2       | |
| |              +--+         Veth pair        +--+              | |
| |              |  +--------------------------+  |              | |
| |              +--+veth0                veth1+--+              | |
| |   Name Space    |12.1.1.1          12.1.1.2|    Name Space   | |
| +-----------------+                          +-----------------+ |
|                                                                  |
|                             Linux Server                         |
|                                                     By:[F0rGeEk] |
+------------------------------------------------------------------|

操作程序如下:

[root@d1 ~]# ip netns add ns1
[root@d1 ~]# ip netns add ns2
[root@d1 ~]# ip link set veth0 netns ns1
[root@d1 ~]# ip link set veth1 netns ns2
 # 驗證網卡是否加入對應的NS中
[root@d1 ~]# ip netns exec ns1 ip link ls
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
6: veth0@if5: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 02:77:ea:e8:3a:30 brd ff:ff:ff:ff:ff:ff link-netnsid 0
[root@d1 ~]# ip netns exec ns2 ip link ls
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
7: veth1@if8: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether ce:47:33:1f:90:fe brd ff:ff:ff:ff:ff:ff link-netnsid 0
 # 激活相應的網卡
[root@d1 ~]# ip netns exec ns1 ip link set dev veth0 up
[root@d1 ~]# ip netns exec ns2 ip link set dev veth1 up
 # 為網卡配置IP地址
[root@d1 ~]# ip netns exec ns1 ifconfig veth0 12.1.1.1/24
[root@d1 ~]# ip netns exec ns2 ifconfig veth1 12.1.1.2/24
 # 測驗連通性
[root@d1 ~]# ip netns exec ns1 ping 12.1.1.2 -c 3 -I veth0
PING 12.1.1.2 (12.1.1.2) from 12.1.1.1 veth0: 56(84) bytes of data.
64 bytes from 12.1.1.2: icmp_seq=1 ttl=64 time=0.051 ms
64 bytes from 12.1.1.2: icmp_seq=2 ttl=64 time=0.057 ms
64 bytes from 12.1.1.2: icmp_seq=3 ttl=64 time=0.052 ms

--- 12.1.1.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 0.051/0.053/0.057/0.006 ms

1.5 Linux bridge

??和veth-pari一樣,Linux bridge也是一種虛擬網路設備,這里可以將bridge看作是一個普通的二層交換機,因為它具備二層交換機的所有功能,對于普通的物理設備來說一般只有兩端,從一端進來的資料會從另一端出去,比如物理網卡從外面網路中收到的資料會轉發到內核協議堆疊中,而從協議堆疊過來的資料會轉發到外面的物理網路中,而bridge有多個埠,資料可以從多個埠進,也可以從多個埠出去,Bridge的這個特性使得它主要被用于和其他網路設備接入使用,比如虛擬網路設備、物理網卡等,
?? bridge是建立在從設備上(物理設備、虛擬設備、vlan設備等,即attach一個從設備,類似于現實世界中的交換機和一個用戶終端之間連接了一根網線),并且可以為bridge配置一個IP(參考LinuxBridge MAC地址行為),這樣該主機就可以通過這個bridge設備與網路中的其他主機進行通信了,另外它的從設備被虛擬化為埠port,它們的IP及MAC都不在可用,且它們被設定為接受任何包,最終由bridge設備來決定資料包的去向:接收到本機、轉發、丟棄、廣播,

1.5.1 實作原理

??Bridge的功能主要在內核里實作,當一個從設備被 attach 到 Bridge 上時,相當于現實世界里交換機的埠被插入了一根連有終端設備的網線,這時在內核程式里,一個用于接受資料的回呼函式(netdev_rx_handler_register())被注冊,以后每當這個從設備收到資料時都會呼叫這個函式用來把資料轉發到Bridge上,當Bridge接收到此資料時,br_handle_frame()被呼叫,進行一個和現實世界中的交換機類似的處理程序:判斷包的類別(廣播/單點),查找內部MAC埠映射表,定位目標埠號,將資料轉發到目標埠或丟棄,自動更新內部 MAC 埠映射表以自我學習,
??Bridge和一般的二層交換機有一個區別:資料被直接發到 Bridge上,而不是從一個埠接收,這種情況可以看做 Bridge自己有一個MAC可以主動發送報文,或者說Bridge自帶了一個隱藏埠和宿主Linux系統自動連接,Linux上的程式可以直接從這個埠向Bridge上的其他埠發資料,所以當一個Bridge擁有一個網路設備時,如 bridge0 加入了 eth0 時,實際上bridge0擁有兩個有效MAC地址,一個是bridge0的,一個是eth0的,他們之間可以通訊,這里還有一個有意思的事情是,Bridge可以設定IP地址,通常來說IP地址是三層協議的內容,不應該出現在二層設備Bridge上,但是Linux里Bridge是通用網路設備抽象的一種,只要是網路設備就能夠設定IP地址,當一個bridge0擁有IP后,Linux便可以通過路由表或者IP表規則在三層定位bridge0,此時相當于Linux擁有了另外一個隱藏的虛擬網卡和Bridge的隱藏埠相連,這個網卡就是名為bridge0的通用網路設備,IP可以看成是這個網卡的,當有符合此IP的資料到達bridge0時,內核協議堆疊認為收到了一包目標為本機的資料,此時應用程式可以通過Socket接收到它,一個更好的對比例子是現實世界中的帶路由的交換機設備,它也擁有一個隱藏的MAC地址,供設備中的三層協議處理程式和管理程式使用,設備里的三層協議處理程式,對應名為bridge0的通用網路設備的三層協議處理程式,即宿主Linux系統內核協議堆疊程式,設備里的管理程式,對應bridge0所在宿主Linux 系統里的應用程式,
??Bridge的實作在當前有一個限制:當一個設備被attach到Bridge上時,那個設備的IP會變的無效,Linux不再使用那個IP在三層接收資料,舉例如下:如果 veth0 本來的IP是 12.1.1.2,此時如果收到一個目標地址是12.1.1.2 的資料,Linux的應用程式能通過Socket操作接收到它,而當veth0被attach到一個bridge0后,盡管veth0的IP還在,但應用程式是無法接收到上述資料的,此時若想收到該資料則應該把IP 12.1.1.2 賦bridge0,

1.5.2 創建bridge

??如下圖所示,我們創建一對veth-pari:veth0、veth1;然后創建一個Bridge:br0,其中veth0配置IP地址為12.1.1.1/24,veth1配置IP地址為12.1.1.2/24,然后我們將veth0加入到br0中,此時我們在veth1上ping12.1.1.1測驗網路是否連通,為驗證1.5.1中介紹原理,我們將veth0的IP地址移至br0,此時再通過veth1去ping12.1.1.1測驗網路是否連通,實驗程序如下:


+----------------------------------------------------------+
|                                             By:[f0rGeEk] |
|   +--------------------------------------------------+   |
|   |                                                  |   |
|   |              Network Protocal Stack              |   |
|   |                                                  |   |
|   +---+--------------+--------------+------------+---+   |
|       ^              ^              |            ^       |
|       |              |              |            |       |
+----------------------------------------------------------+
|       |              |              |            |       |
|       |              |              |            |       |
|       v              v              v            v       |
|    +--+---+     +----+---+       +--+---+     +--+---+   |
|    |      |     |        |       |      |     |      |   |
|    | eth0 |     |  br0   |<----->+ veth0|     | veth1|   |
|    |      |     |12.1.1.1/24     |      |     |12.1.1.2/24
|    +---+--+     +--------+       +--+---+     +---+--+   |
|        ^                            ^             ^      |
|        |                            |             |      |
|        |                            +-------------+      |
|        |                                                 |
+----------------------------------------------------------+
         |
         v
 Physical Network
  • 創建veth-pair、bridge
[root@d1 ~]# ip link add veth0 type veth peer name veth1
[root@d1 ~]# ip link set dev veth0 up
[root@d1 ~]# ip link set dev veth1 up
[root@d1 ~]# ip addr add 12.1.1.1/24 dev veth0
[root@d1 ~]# ip addr add 12.1.1.2/24 dev veth1
 # 創建并激活一個bridge
[root@d1 ~]# ip link add name br0 type bridge
[root@d1 ~]# ip link set br0 up
[root@d1 ~]# ip link list br0
9: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/ether a2:47:b8:b7:21:9d brd ff:ff:ff:ff:ff:ff
 # 將veth0加入bridge中
[root@d1 ~]# ip link set dev veth0 master br0
[root@d1 ~]# ip link list br0
9: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether 22:d0:1d:fd:5d:9b brd ff:ff:ff:ff:ff:ff
 # 查看橋接資訊
[root@d1 ~]# bridge link
8: veth0 state UP @veth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master br0 state forwarding priority 32 cost 2
 # 首先修改各虛擬網路設備的access_local和rp_filter
[root@d1 ~]# echo 1 > /proc/sys/net/ipv4/conf/br0/accept_local
[root@d1 ~]# echo 1 > /proc/sys/net/ipv4/conf/veth1/accept_local
[root@d1 ~]# echo 0 > /proc/sys/net/ipv4/conf/br0/rp_filter
[root@d1 ~]# echo 0 > /proc/sys/net/ipv4/conf/veth1/rp_filter
[root@d1 ~]# echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter
[root@d1 ~]# echo 0 > /proc/sys/net/ipv4/conf/default/rp_filter

??仔細觀察上述程序,我們發現一個有趣的現象,當veth0加入bridge br0后,br0的MAC地址則變成了veth0的MAC地址,下面我們在veth1上ping12.1.1.1測驗連通性:

  • 測驗
[root@d1 ~]# ping -c 3 -I veth1 12.1.1.1
ping: Warning: source address might be selected on device other than veth1.
PING 12.1.1.1 (12.1.1.1) from 10.10.10.137 veth1: 56(84) bytes of data.

--- 12.1.1.1 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2009ms
  • 為bridge配置IP地址
[root@d1 ~]# ip addr del 12.1.1.1/24 dev veth0
[root@d1 ~]# ip addr add 12.1.1.1/24 dev br0
  • 測驗
[root@d1 ~]# ping -c 2 -I veth1 12.1.1.1
PING 12.1.1.1 (12.1.1.1) from 12.1.1.2 veth1: 56(84) bytes of data.
64 bytes from 12.1.1.1: icmp_seq=1 ttl=64 time=0.049 ms
64 bytes from 12.1.1.1: icmp_seq=2 ttl=64 time=0.072 ms

1.5.3 連接兩個NS

??如下圖所示,我們創建兩個NS:ns1、ns2,同時創建兩對veth-pari:veth0>br-veth0;veth>br-veth1,創建一個bridge:br0,并將veth0和veth1加入至br0然后為br-veth0和br-veth1分別配置IP地址,最后在br-veth0介面上ping12.1.1.2測驗網路是否連通,

+-----------------------------------------------------------------------------+
|                                                                By:[F0rGeEk] |
|                          Linux Bridge connetc NS                            |
| +--------------------+                                +-------------------+ |
| |       NameSpace NS1|                                |      NameSpace NS2| |
| |                    |                                |                   | |
| |      br-veth1      |                                |      br-veth0     | |
| |       +---+        |                                |        +---+      | |
| |       |   |        |                                |        |   |      | |
| +-------+---+--------+                                +--------+---+------+ |
|           |12.1.1.2/24                                12.1.1.1/24|          |
|           |                                                      |          |
|           |                  +---------------+                   |          |
|           | veth-pari        |               |         veth-pari |          |
|           |                  +--+         +--+                   |          |
|           +------------------+  |         |  +-------------------+          |
|                         veth1+--+         +--+ veth0                        |
|                              |   Bridge 0    |                              |
|                              +---------------+                              |
+-----------------------------------------------------------------------------+
  • 創建ns1、ns2、br0 兩對veth-pair
[root@d1 ~]# ip netns add ns1
[root@d1 ~]# ip netns add ns2
[root@d1 ~]# ip link add veth0 type veth peer name br-veth0
[root@d1 ~]# ip link add veth1 type veth peer name br-veth1
[root@d1 ~]# ip link add name br0 type bridge
[root@d1 ~]# ip link set dev veth0 up
[root@d1 ~]# ip link set dev veth1 up
[root@d1 ~]# ip link set dev br-veth0 up
[root@d1 ~]# ip link set dev br-veth1 up
[root@d1 ~]# ip link set dev br0 up
  • 將veth-pair分別加入NS和bridge中,并激活NS中的所有介面
[root@d1 ~]# ip link set br-veth0 netns ns2
[root@d1 ~]# ip link set br-veth1 netns ns1
[root@d1 ~]# ip link set dev veth0 master br0
[root@d1 ~]# ip link set dev veth1 master br0
 # 激活NS中的介面
[root@d1 ~]# ip netns exec ns1 ifconfig br-veth1 up
[root@d1 ~]# ip netns exec ns2 ifconfig br-veth0 up
  • 配置IP地址
[root@d1 ~]# ip netns exec ns1 ifconfig br-veth1 12.1.1.1/24
[root@d1 ~]# ip netns exec ns2 ifconfig br-veth0 12.1.1.2/24
  • 檢查上述配置
 # 查看NS中網卡IP配置
[root@d1 ~]# ip netns exec ns1 ip addr show br-veth1
5: br-veth1@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 1a:36:ef:1e:8b:98 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 12.1.1.1/24 brd 12.1.1.255 scope global br-veth1
       valid_lft forever preferred_lft forever
    inet6 fe80::1836:efff:fe1e:8b98/64 scope link
       valid_lft forever preferred_lft forever
[root@d1 ~]# ip netns exec ns2 ip addr show br-veth0
3: br-veth0@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether d2:45:60:46:ab:77 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 12.1.1.2/24 brd 12.1.1.255 scope global br-veth0
       valid_lft forever preferred_lft forever
    inet6 fe80::d045:60ff:fe46:ab77/64 scope link
       valid_lft forever preferred_lft forever
 # 檢查bridge配置
[root@d1 ~]# bridge link
4: veth0 state UP @(null): <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master br0 state forwarding priority 32 cost 2
6: veth1 state UP @(null): <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master br0 state forwarding priority 32 cost 2
  • 測驗兩個NS之間的連通性
 # ipv4連通測驗
[root@d1 ~]# ip netns exec ns2 ping 12.1.1.1 -c3 -I br-veth0
PING 12.1.1.1 (12.1.1.1) from 12.1.1.2 br-veth0: 56(84) bytes of data.
64 bytes from 12.1.1.1: icmp_seq=1 ttl=64 time=0.058 ms
64 bytes from 12.1.1.1: icmp_seq=2 ttl=64 time=0.062 ms
64 bytes from 12.1.1.1: icmp_seq=3 ttl=64 time=0.064 ms

--- 12.1.1.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 0.058/0.061/0.064/0.006 ms
 # ipv6連通測驗
[root@d1 ~]# ip netns exec ns2 ping6 fe80::1836:efff:fe1e:8b98 -c 3 -I br-veth0
PING fe80::1836:efff:fe1e:8b98(fe80::1836:efff:fe1e:8b98) from fe80::d045:60ff:fe46:ab77%br-veth0 br-veth0: 56 data bytes
64 bytes from fe80::1836:efff:fe1e:8b98%br-veth0: icmp_seq=1 ttl=64 time=0.057 ms
64 bytes from fe80::1836:efff:fe1e:8b98%br-veth0: icmp_seq=2 ttl=64 time=0.067 ms
64 bytes from fe80::1836:efff:fe1e:8b98%br-veth0: icmp_seq=3 ttl=64 time=0.069 ms

--- fe80::1836:efff:fe1e:8b98 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 0.057/0.064/0.069/0.008 ms

1.6 tun/tap

??虛擬網路設備也歸內核的網路設備管理子系統管理,對于Linux內核網路設備管理模塊來說,虛擬設備和物理設備沒有區別,都是網路設備,都能配置IP,從網路設備來的資料,都會轉發給協議堆疊,協議堆疊過來的資料,也會交由這些網路設備發送出去,至于是如何發送、發送到哪,這都由設備驅動來完成,跟Linux內核就沒關系了,

1.6.1 tun/tap概述

??從Linux檔案系統來看,它們是用戶可以用檔案來操作的字符設備;但是從網路虛擬化的角度來看,它們是虛擬網卡,一端是APP一端是網路協議堆疊,與普通的網路接受發資料不同,tun/tap設備比較特殊,它是通過檔案來收發資料包,如下圖所示,tunX 和上面的 eth0 在邏輯上面是等價的, tunX 也代表了一個網路介面,雖然這個介面是系統通過軟體所模擬出來的,網卡介面 tunX 所代表的虛擬網卡通過檔案 /dev/tunX 與我們的應用程式(App) 相連,應用程式每次使用 write 之類的系統呼叫將資料寫入該檔案,這些資料會以網路層資料包的形式,通過該虛擬網卡,經由網路介面 tunX 傳遞給網路協議堆疊,同時該應用程式也可以通過 read 之類的系統呼叫,經由檔案 /dev/tunX 讀取到協議堆疊向 tunX 傳遞的所有資料包,其實這里的tunX和其他普通網卡基本一樣,唯獨的區別是這個虛擬網卡沒有MAC地址,由于tunX僅能虛擬到網路層,所以要MAC地址也沒用,但如果是tapX網卡則不同,因為它比runX更深入一層,對于協議堆疊來看tapX和物理網卡是沒有區別的,

 +-------------------------------------------------------------------------------+
 |                                                                               |
 |            +--------------+                             +---------------+     |
 |            |     APP      |                             |  Socket API   |     |
 |            |              |                             |               |     |
 |            +------+-------+                             +------+--------+     |
 |                   |                                            |              |
 |                   |                                            |              |
 | USER       +------+--------+                                   |              |
 +------------+  /dev/tunX    +--------------------------------------------------+
 |LINUX KERNEL|               |                                   |              |
 |            +-------+-------+                    +--------------+-----------+  |
 |                    |                            |                          |  |
 |                    |                            |  Network Protocal Stack  |  |
 |                    |                            |                          |  |
 |                    |                            +--------------+-----------+  |
 |                    |                                           |              |
 |                    |                                           |              |
 |                    |                                           |              |
 |                    |                                           |              |
 |                    |         +--------------+                  |              |
 |                    |         |              |                  |              |
 |                    +---------+     tunX     +------------------+              |
 |                              |              |                                 |
 |                              +--------------+                  By:[F0rGeEk]   |
 |                                                                               |
++-------------------------------------------------------------------------------+

1.6.2 典型使用場景

??較為常見的tun/tap使用場景有資料加密、資料壓縮等,這里我們主要講解最常用的VPN,它是利用tun設備做UDP的VPN,如下圖所示,在用戶層有兩個APP1和APP2,Linux內核層有socket、網路協議站、網路設備,其中socket實質上是網路協議堆疊的一部分,這里我們將eth0的IP設定為10.8.8.11,eth0網路的網關為10.8.8.254;tun0的IP設定為12.1.1.11,我們這里假設VPN用戶是eth0網路10.8.8.0/24中的某一臺主機,這臺主機本地有12.1.1.0/24網路,我們的目的是通過APP 1能與VPN主機本地網路中的成員進行通訊,

+--------------------------------------------------------------------------+
|   +---------------------+           +-----------------------+            |
|   |                     |           |                       |            |
|   |        AAP 1        |           |         APP 2         <-------+    |
|   |                     |           |                       |       |    |
|   +---------+-----------+           +-----------+-----------+       |    |
|             |                                   |                   |    |
|             |                                   |                   |    |
+--------------------------------------------------------------------------+
|             |                                   |                   |    |
|             |                                   |                   |    |
|             v                                   v                   |    |
|      +------+------+                     +------+------+            |    |
|      |             |                     |             |            |    |
|      |   Socket 1  |                     |  Socket 2   |            |    |
|      |             |                     |             |            |    |
|   +--+-------------+---------------------+-------------+-----+      |    |
|   |                                                          |      |    |
|   |                  Network Protocal Stack                  |      |    |
|   |                                                          |      |    |
|   +---------+-----------------------------------+------------+      |    |
|             |                                   |                   |    |
|             |                                   |                   |    |
|             |                                   |                   |    |
|     +-------v------+                     +------v-------+           |    |
|     |              |                     |              |           |    |
|     |     eth0     |                     |     tun0     |           |    |
|     |              |                     |              |           |    |
|     +-------+------+                     +------+-------+           |    |
|             | 10.8.8.11/24                      | 12.1.1.11/24      |    |
|             |                                   +-------------------+    |
|             |                                                            |
|             |                                             By:[F0rGeEk]   |
+--------------------------------------------------------------------------+
              v
       Physical Network

這里假設10.8.8.33要與12.1.1.33通過VPN互訪,下面我們來看看資料包的流程:

  1. 首選APP 1通過socket 1發送了一個目的地為12.1.1.33的資料包,socket將該資料包轉發給網路協議堆疊;
  2. 協議堆疊收到該資料包后,根據本地路由規則進行匹配,將該資料包扔給tun0處理;
  3. tun0收到資料包后,由于另一端連著APP 2,所以它會直接將資料包轉發至APP 2;
  4. APP 2收到資料包后,根據需要進行重構,重構時會將原有的資料包原封不動的包在新資料包中,然后再有APP 2發送出去,新資料包的源地址會變成eth0的地址10.8.8.11,而目的地址將會變成10.8.8.33;
  5. Socket收到由APP 2發出的資料包后,會直接轉發給協議堆疊;
  6. 協議堆疊收到資料包后,匹配本地路由規則,將資料包轉發給eth0;
  7. eth0收到資料包后,會直接通過物理網路將資料包發送出去;
  8. 當10.8.8.33收到資料包后,首先是打開資料包讀取里面的原始資料,并將該資料包轉發給12.1.1.33;如果12.1.1.33收到資料包并且回復的話,那么當收到12.1.1.33回復的資料包后進行資料包的重構,同樣將原始資料封裝在新的資料包中,再由原路回傳;
  9. 這樣最終APP 1即通過VPN完成了與12.1.1.33的通信,

1.6.3 tun與tap的區別

??通過1.6.2小節的通信流程來看,tun/tap設備的用處是將協議堆疊中的部分資料包轉發給用戶空間的應用程式,再由用戶空間的程式來處理這個資料包,tun/tap設備不僅能做基于DUP的VPN,類似的tunnel以及IPSec都是比較常用的場景,雖然它們的作業方式完全相同,但還是有一些區別:

  • 戶層程式通過tun設備只能讀寫IP資料包,而通過tap設備能讀寫鏈路層資料包;
  • tun設備相當于是一個三層設備,,它無法與物理網卡做 bridge,但是可以通過三層交換(如 ip_forward)與物理網卡連通,可以使用ifconfig之類的命令給該設備設定 IP 地址;
  • tap設備則相當于是一個二層設備,可以作業在資料鏈路層,擁有 MAC 層功能,可以與物理網卡做 bridge,支持 MAC 層廣播,可以通過ifconfig之類的命令給該設備設定 IP 地址,甚至還可以給它設定 MAC 地址,

1.7 iptables

??有人說在Linux中iptables就是防火墻,其實它并不是真正的防火墻,一般情況我們可以通過類似"service iptables start"命令啟動iptables,但iptables并沒有守護行程,所以它還不能算真正意義上的服務,如果非要給iptables給一個定義,那么稱它為Linux內核提供的功能一點不為過,而Linux中真正的防火墻是netfilter,它位于Linux內核空間,netfilter/iptables與大多數的Linux軟體一樣,這個包過濾防火墻也是免費的,它可以完成防火墻的基本功能,比如包過濾、包的重定向、NAT等,

1.7.1 iptables基礎

??實際上iptables是執行我們設定的rules,而這些預設的rules一般都是由相關管理員來設定,這些rules都存盤在內核空間的資訊包過濾表中,這些rules不僅需要指定源地址、目的地址、傳輸協議、源服務型別、目標協議,還需要指定如果資料包匹配到rules后如何操作,一般有accept、drop和reject,說到這里其實有關iptables的操作和傳統網路防火墻比較類似,日常的維護無外乎就是增刪改查這些rules,
??如下圖所示,當我們啟用了防火墻功能后,資料包在進入我們的主機時會經過如下各種"關卡",如果客戶端發來的請求報文目的地是本機,那么由Prerouting、Postrouting、Input和Output"關卡"來負責資料包的放行與轉發,那么如果客戶端發來的請求報文目的地不是本機,這時會由Prerouting、Forward、Postrouting"關卡"來負責資料包的放行與轉發,在Linux的iptables中我們提到的這些"關卡"被稱作Chains(也就是常說的鏈),
??這五個鏈中,Prerouting鏈主要處理剛到達本機并在路由轉發前的資料包,通常用于DNAT;Input鏈主要處理來自外部的資料;Output鏈主要處理向外發送的資料;Forward鏈主要處理資料轉發;Postrouting鏈主要處理即將離開本機的資料包,通常用于SNAT,

1.7.2 iptables的結構

??iptables的結構:iptables -> Tables -> Chains -> Rules,也就是說tables由chains組成而chains又由rules組成,他們之間是互相包含的關系,如下圖所示:

                        +-----------------------------------------------------------------------------------+
                        |                                     IPTABLES                                      |
                        |                                                                                   |
                        |  +------------------------------+              +------------------------------+   |
                        |  | Table 1                      |              | Table N                      |   |
                        |  |                              |              |                              |   |
                        |  | +-------------------------+  |              | +-------------------------+  |   |
                        |  | | Chain 1                 |  |              | | Chain 1                 |  |   |
                        |  | |  +-------------------+  |  |              | |  +-------------------+  |  |   |
                        |  | |  |      Rule 1       |  |  |              | |  |      Rule 1       |  |  |   |
                        |  | |  +-------------------+  |  |              | |  +-------------------+  |  |   |
                        |  | |                         |  |              | |                         |  |   |
                        |  | |  +-------------------+  |  |              | |  +-------------------+  |  |   |
                        |  | |  |      Rule 2       |  |  |              | |  |      Rule 2       |  |  |   |
                        |  | |  +-------------------+  |  |              | |  +-------------------+  |  |   |
                        |  | +-------------------------+  |  .........   | +-------------------------+  |   |
                        |  |                              |              |          .........           |   |
                        |  | +-------------------------+  |              | +-------------------------+  |   |
                        |  | | Chain 2                 |  |              | | Chain N                 |  |   |
                        |  | |  +-------------------+  |  |              | |  +-------------------+  |  |   |
                        |  | |  |      Rule 1       |  |  |              | |  |      Rule 1       |  |  |   |
                        |  | |  +-------------------+  |  |              | |  +-------------------+  |  |   |
                        |  | |                         |  |              | |                         |  |   |
                        |  | |  +-------------------+  |  |              | |  +-------------------+  |  |   |
                        |  | |  |      Rule 2       |  |  |              | |  |      Rule 2       |  |  |   |
                        |  | |  +-------------------+  |  |              | |  +-------------------+  |  |   |
                        |  | +-------------------------+  |              | +-------------------------+  |   |
                        |  +------------------------------+              +------------------------------+   |
                        |                                                                     By:[F0rGeEk]  |
                        +-----------------------------------------------------------------------------------+
  • Rules
    ??所謂的規則主要是相關管理員定義的準入條件,這個規則的主旨是:如果資料包符合xx條件,那么就將這個資料包yy,一般rules需要制定源地址、目的地之、傳輸協議、服務型別或埠等,而資料包匹配規則后的操作則有accept、reject或drop,這里的rules就好比物理防火墻中的一條條安全策略,只不過在物理防火墻中資料被匹配后的動作是permit、deny和drop其實意義都一樣,

  • Chains
    ??上文中我們說將這些決定資料包流向的"關卡"稱為"鏈",為什么要稱為鏈呢?一般情況下,防火墻的作用就是對經過的資料報文進行規則匹配,然后執行相應的動作,所以當一個資料包要經過防火墻時,那么它就要進行規則的匹配,而現實情況是一個關卡可能會有很多的規則,這些規則又是串聯在一起的,由于形似所以就被稱為,這里我們也可以把它可以理解為物理防火墻中的策略組,一般情況下一個策略組中我們也會做很多類似的"規則",

  • Tables
    ??Iptables中的表也比較好理解,試想我們對于每條鏈上都有很多的rule,但這些rule可能會有一些相似的,比如均是開啟80埠或者都是拒絕SSH等,那么如果每個鏈都需要這樣的策略,如果有很多個鏈需要修改的話那管理員的煩惱就來了,所以這里引入表,所謂的表就是可以將相同功能的rule放在一起的合集,看到這里網工又開心了,這部就是物理防火墻中的策略表嘛??????當然可以這樣理解,物理防火墻根據性能不同可以創建N多個策略表,但是Iptables為我們內建了4種表(fiter、nat、mangle、raw),而我們定義的每條rule也都離不開這四種表,

1.7.3 表鏈關系

??現在我們已經知道iptables有四個內建表:Filter表、NAT表、Mangle表和Raw表,它還有五個鏈:PREROUTING鏈、INPUT鏈、OUTPUT鏈、FORWARD鏈、POSTROUTING鏈,下面我們就簡單來說說這"四表五鏈"之間的關系,

  • Filter表
    ??Filter表為iptables的默認表,也就是說如果你沒有自定義表,那么默認就使用Filter表,它主要負責報文過濾,內核模塊為iptables_filter,它具有3個內建鏈:INPUT鏈、OUTPUT鏈 、FORWARD鏈 ,

  • NAT表
    ??眾所周知NAT為Network Address Translation的縮寫,主要提供網路地址轉換功能,其內核模塊為iptables_nat,它具有3個內建鏈:PREROUTING鏈、POSTROUTING鏈 、OUTPUT鏈,

  • Mangle表
    ??Mangle表主要用于指定如何處理資料包,拆解并作出修改,然后重新封裝的功能,其內核模塊為iptables_mangle,它具有5個內建鏈:PREROUTING鏈、OUTPUT鏈、FORWARD鏈、INPUT鏈和POSTROUTING鏈,

  • Raw表
    ??Raw表主要用于處理例外,可以關閉NAT表上啟用的連接追蹤機制,它的內核模塊為iptables_raw,它具有2個內建鏈:PREROUTING鏈和OUTPUT鏈,
    ??這時我們在看資料報文經過防火墻的流程就更清晰了:

??這里我們需要注意一點,那就是當這四個表都在一個鏈時,它們被匹配也是有順序的:raw-->mangle-->nat-->filter,由上圖我們也可以看出,有些鏈是不能使用某些表中的規則,目前僅有OUTPUT鏈可以同時匹配四張表中的規則,為了方便管理員的管理,iptables支持自定義鏈,這一點就好比物理防火墻中針對某個應用創建的策略組,這里需要注意iptables中自定義的鏈不能直接使用,它只能被某個默認的鏈當作執行動作去呼叫,

1.7.4 iptables Rules

??上文我們說過,所謂的規則就是制定匹配條件然匹配每個經過的資料報文,一旦匹配成功則進行預設的動作,如果匹配為成功則判斷下一條rule,所以對于任何一個rule來說,它的結構則是由匹配條件和執行動作來組成,

  • 匹配條件
    ??匹配條件一般包含源地址(SOURCE IP)和目的地址(DESTINATION IP),以及擴展條件,這些擴展條件實際上是netfiler中的一部分,比如源埠、目的埠、協議等,

  • 執行動作
    ??執行動作在iptables中被稱為target,一般的執行動作有ACCEPT(允許資料包通過)、REJECT(拒絕資料包通過,必要是回復客戶端拒絕回應資訊)、DROP(拒絕資料包通過并直接丟棄不回復任何回應資訊),在實際應用中我們還經常會使用一些擴展動作:SNAT(源地址轉換,比如局域網用戶使用同一個公網IP上網)、DNAT(目的地址轉換,可用來保護內網重要資訊)、REDIRECT(在本地進行埠映射)、MASQUERADE(SNAT的一種特殊形式,適用于動態IP)以及LOG(僅對資料包進行記錄不做任何操作),

1.7.5 iptables基礎操作

  1. 查詢防火墻可用規則
 # 以下輸出說明當前系統沒有啟用防火墻,僅有默認的filter表以及默認的鏈,
[root@d1 ~]# iptables --list
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
  1. 查詢某個表
 # 用法iptables -t 表名 --list
 # 如下查詢nat表
[root@d1 ~]# iptables -t nat --list
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
  1. 清空所有rules
[root@d1 ~]# iptables --flush
 # 或者
[root@d1 ~]# iptables -F
 # 執行完以上兩條命令,并不意味著所有規則都清空了
 # 因為在有的Linux版本中,通過以上命令不會清空NAT表,所以最好手動清空NAT:
[root@d1 ~]# iptables -t NAT -F
  1. 保存修改
[root@d1 ~]# iptables-save
 # Generated by iptables-save v1.8.4 on Fri Mar  27 15:26:45 2020
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT
 # Completed on Fri Mar  27 15:26:45 2020
 # Generated by iptables-save v1.8.4 on Fri Mar  27 15:26:45 2020
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT
 # Completed on Fri Mar  27 15:26:45 2020
  • 追加規則
    ??首先我們來了解一下iptables的常用引數:
引數 描述 引數 描述
-p 指定協議 -A 追加到鏈
-s 指定源地址 -C 檢查存在的rule
-d 指定目的地址 -D 從指定鏈中洗掉rule
-j 指定執行target -I 通過指定rulenum插入rule
-i 指定入介面 -R 替換指定rulenum的rule
-o 指定出介面 -F 清空所有rules
-t 指定要操作的表 -N 創建一個自定義鏈
-g 跳轉到指定的鏈 -P 修改指定鏈中的策略
-m 匹配擴展模塊 -X 洗掉用戶自定義的鏈

??還有一些擴展引數:

引數 描述
--sport 源埠,默認匹配所有埠
--dport 目的埠,與--sport類似
--tcp-flags TCP標志,一般有SYN、ACK、FIN、RST、URG、PSH
--icmp-type ICMP型別,一般0表示echo reply,1表示echo
--timestart 根據起始時間匹配資料
--timestop 和timestart配合使用,用來指定一個時間段
--connlimit-above 限制每個IP地址鏈接到server的鏈接數

比如我們將一臺Linux做成SSH跳板機,這時我們可以使用iptables來做一些限制:

 # 發出的資料包目的埠為22
[root@d1 ~]# iptables -A OUTPUT -o eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT

 # 接收的資料包源埠為22
[root@d1 ~]# iptables -A INPUT -i eth0 -p tcp--sport 22 -m state --state ESTABLISHED -j ACCEPT

1.7.6 常用命令總結

  • 將12.1.1.1訪問10.1.1.1的所有包都拒絕
[root@d1 ~]# iptables -t filter -I INPUT -s 12.1.1.1 -d 10.1.1.1 -j DROP
[root@d1 ~]# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 DROP       all  --  *      *       12.1.1.1             10.1.1.1
  • 所有訪問12.1.1.1的包均拒絕
[root@d1 ~]# iptables -t filter -I INPUT -d 12.1.1.1 -j DROP
[root@d1 ~]# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 DROP       all  --  *      *       0.0.0.0/0            12.1.1.1
  • 允許12.1.1.1SSH10.1.1.1
[root@d1 ~]# iptables -t filter -I INPUT -s 12.1.1.1 -d 10.1.1.1 -p tcp --sport 22 -j ACCEPT
[root@d1 ~]# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     tcp  --  *      *       12.1.1.1             10.1.1.1             tcp spt:22
  • 拒絕由某網卡流入的icmp
[root@d1 ~]# iptables -t filter -I INPUT -i ens33 -p icmp -j DROP
[root@d1 ~]# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 DROP       icmp --  ens33  *       0.0.0.0/0            0.0.0.0/0
  • 允許任意源訪問10.1.1.1的80、443埠
[root@d1 ~]# iptables -t filter -I INPUT -d 10.1.1.1 -p tcp -m multiport --dports 80,443 -j ACCEPT
[root@d1 ~]# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            10.1.1.1             multiport dports 80,443
  • 將所有filter表以序號標記顯示
[root@d1 ~]# iptables -nL -t filter --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination
1    ACCEPT     tcp  --  0.0.0.0/0            10.1.1.1             multiport dports 80,443
2    DROP       icmp --  0.0.0.0/0            0.0.0.0/0
3    ACCEPT     tcp  --  12.1.1.1             10.1.1.1             tcp spt:22
4    DROP       all  --  0.0.0.0/0            12.1.1.1
5    DROP       all  --  12.1.1.1             10.1.1.1
6    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
7    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0
8    INPUT_direct  all  --  0.0.0.0/0            0.0.0.0/0
9    INPUT_ZONES_SOURCE  all  --  0.0.0.0/0            0.0.0.0/0
10   INPUT_ZONES  all  --  0.0.0.0/0            0.0.0.0/0
11   DROP       all  --  0.0.0.0/0            0.0.0.0/0            ctstate INVALID
12   REJECT     all  --  0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited
  • 洗掉已添加的rule
[root@d1 ~]# iptables -D INPUT 5
[root@d1 ~]# iptables -nL -t filter --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination
1    ACCEPT     tcp  --  0.0.0.0/0            10.1.1.1             multiport dports 80,443
2    DROP       icmp --  0.0.0.0/0            0.0.0.0/0
3    ACCEPT     tcp  --  12.1.1.1             10.1.1.1             tcp spt:22
4    DROP       all  --  0.0.0.0/0            12.1.1.1
5    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
6    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0
7    INPUT_direct  all  --  0.0.0.0/0            0.0.0.0/0
8    INPUT_ZONES_SOURCE  all  --  0.0.0.0/0            0.0.0.0/0
9    INPUT_ZONES  all  --  0.0.0.0/0            0.0.0.0/0
10   DROP       all  --  0.0.0.0/0            0.0.0.0/0            ctstate INVALID
11   REJECT     all  --  0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited
  • 清除已有的rules
[root@d1 ~]# iptables -F
[root@d1 ~]# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 19 packets, 1852 bytes)
 pkts bytes target     prot opt in     out     source               destination

1.8 隧道技術VTI

??VTI對于網工來說比較好理解,所以就拿它開刀好了,除VTI外,現在的Linux原生支持下列5種L3隧道:

  1. ipip:也稱為ipv4 in ipv4,就是說在一個ipv4的報文基礎上再封裝一個ipv4報文;
  2. GRE:全稱通用路由封裝,在數通中這個技術非常常見,主要就是在任意的網路協議上封裝其他任意一種網路協議,比如OSPF封裝在EGP中可以跨區域;
  3. sit:sit和ipip類似,區別是sit是將ipv6報文封裝在ipv4中,有點像ipv6toipv4技術;
  4. ISATAP:全稱站內自動隧道尋址協議,主要是用于ipv6的隧道封裝;
  5. VTI:全稱虛擬隧道介面,對于網工來說應該很熟悉吧,這是Cisco提出的一種關于IPSec隧道技術;
    ??以上這5中隧道協議,它們的底層實作都離不開1.6章節介紹過的tun設備,就目前市面上常用的VPN軟硬體,其底層實作都離不開這5中隧道協議,下面我們以VTI為例來看看它是如何實作的,其實其他4中隧道協議也都大同小異,

1.8.1 技術概述

??這里我們主要講解Cisco的VTI,從本質上說它就是完全虛擬的網卡,但和OpenVPN不同的是它在內核中就完成了幾乎所有的功能,這一點雖然增加了性能,但是靈活性卻相對減少了,控制明文的特性應該被配置到VTI介面上,控制密文的特性應該被運用到物理介面上,當我們使用IPsec VTI技術,我們可以對明文和加密后流量分開運用NAT,ACL和QoS等特性,如果我們運用傳統的cryptomap技術,運用這些加密特性和IPsec隧道就會變的非常麻煩,VTI介面一般分為兩種:靜態VTI(SVTI)和動態VTI(DVTI)

1.8.2 VTI的實作

??對于VTI的實作不要覺得有多么的復雜,其實很簡單就把它想象成在GRE引擎上使用IPSec協議來封裝資料報文,也就是說虛擬網卡是GRE實作的,而對于虛擬網卡內部資料封裝格式則使用的是IPSec,下面我們主要介紹SVTI的實作程序:

實驗環境出了點問題,后續更新,,,,

1.9 VXLAN

1.9.1 VXLAN概述

??VXLAN(Virtual eXtensible Local Area Network,虛擬擴展局域網),是由IETF定義的NVO3(Network Virtualization over Layer 3)標準技術之一,采用L2 over L4(MAC-in-UDP)的報文封裝模式,將二層報文用三層協議進行封裝,可實作二層網路在三層范圍內進行擴展,VXLAN 本質上是一種隧道封裝技術,它使用 TCP/IP 協議堆疊的慣用手法——封裝/解封裝技術,將二層的以太網幀(Ethernet frames)封裝成四層的 UDP 資料報(datagrams),然后在三層的網路中傳輸,效果就像 L2 的以太網幀在一個廣播域中傳輸一樣,實際上是跨越了 L3 網路,但卻感知不到三層網路的存在,VXLAN 是應網路虛擬化技術而生的,隨著資料中心網路不斷擴增,Cisco、VMware 和 Arista Networks 這些巨頭發現,傳統的 VLAN 隔離已經無法應對網路虛擬化技術所帶來的成千上萬的設備增長,于是便聯合起草了這個協議,一直到 2014 年才定稿,由RFC 7348所定義,

1.9.2 VXLAN和VLAN區別

??首先我們知道VLAN是二層網路設備或者虛擬化設備用來隔離廣播域的一種技術,同時我們也知道VLAN本身被限制最多只能有4094個,在以前較為簡單的IT基礎架構中使用VLAN來隔離廣播域顯得綽綽有余,但是在現如今云計算基礎架構中動則數百萬的虛擬設備中,要隔離這些廣播域如果使用VLAN就顯得捉襟見肘了,所以這里迭代出VXLAN技術通過網路虛擬化來解決超大型廣播域隔離的問題,
??其次是資源的問題,傳統網路使用VLAN來隔離廣播域,為避免二層環路一般會使用STP來管理網路鏈路,那么在使用STP時我們知道,它是通過STP的根來負責轉發,一般會根據優先級以及鏈路成本來選擇一條最優的鏈路進行資料轉發,其余鏈路均作為備份鏈路,雖然這樣即避免了環路也增強了鏈路可用性,但這里有一點就是鏈路的使用率卻沒有提高,明明有多條鏈路可以使用實際上始終只能用其中一條,所以我們通過VXLAN來解決在大流量情況下實作鏈路負載和提升資料傳輸能力,還有一點是MAC地址表的限制,傳統二層網路都需要交換機的MAC地址表進行轉發,不同性能的交換機所能支持的MAC地址表條目書不同,那么一般資料中心用TOR交換機來連接物理服務器,如果一臺服務器虛擬出上百臺虛擬機時,TOR交換機的一個物理口就要對應上百個MAC地址,在交換機MAC地址表條目數量有限的情況下,這可能會造成網路接入的瓶頸,如果這里使用VXLAN就會解決這個問題,VXLAN使用VTEP封裝二層幀并在三層網路中傳輸,所以一臺物理機對應一個VTEP,而這個VTEP可以被這臺物理機上的所有虛機使用,那么對于TOR交換機來說,一個物理口對應一臺物理機對應一個VETP資訊即可,這樣就解決了因為虛擬化帶來的交換機MAC地址表爆增的問題,
??最后是關于網路靈活性,傳統基于VLAN的網路環境是不存在overlay的,僅僅是underlay網路,物理網路與虛擬機屬于同VLAN的資料可以互訪,這就使得虛擬機所在的網路無法打破物理網路的界限,比如說在虛擬機的部署和遷移,傳統網路僅支持在相同VLAN的網路中進行內部的操作,如果跨網段部署和遷移就顯得非常麻煩,通過 VXLAN 的封裝,在一個三層網路上構建了 二層 網路,或者說基于 underlay 網路的 overlay 網路,虛擬機的資料可以打破傳統二層網路的限制,在三層網路上傳輸,虛擬機的部署和遷移也不受物理網路的限制,可以靈活部署和遷移,使得整個資料中心保持一個平均的利用率,
??從以上幾點來看,VXLAN 相比 VLAN 有很多的優勢,不過至少現在還不能完全替代 VLAN,這需要根據使用場景具體分析,VXLAN 的優勢更多體現大規模環境下,如果網路設備規模,不論是虛擬的還是物理的,只有百十臺的樣子,那么直接使用 VLAN 就足夠了,另外一個 VXLAN 的封裝解封裝機制也會影響性能,所以需要綜合考慮,

1.9.3 VXLAN網路模型

??如下圖所示,左右兩邊是 Layer2 廣播域,中間跨越一個 L3 網路,VTEP 是 VXLAN 隧道端點(VxLAN Tunnel Point),當 Layer2 以太網幀到達 VTEP 的時候,通過 VxLAN 的封裝,跨越 Layer3 層網路完成通信,由于 VXLAN 的封裝"屏蔽"了 Layer3 網路的存在,所以整個程序就像在同一個 Layer2 廣播域中傳輸一樣,

+----------------------------------------------------------------------------------------------+
|                +-----------+                                   +------------+                |
| +--------+     |           |      +--------------------+       |            |     +--------+ |
| |        +-----+           +------+    VXLAN Tunnel    +-------+            +-----+        | |
| | Host A |     |  VTEP A   |      +--------------------+       |   VTEP B   |     | Host B | |
| +--------+     |           |          L3 IP Fabric             |            |     +--------+ |
|                +-----------+                                   +------------+                |
|                                                                                              |
| +                          +                                   +                           + |
| |                          |                                   |                           | |
| |         Layer 2          |              Layer 3              |           Layer 2         | |
| +<------------------------>-<--------------------------------->-<------------------------->+ |
| |                          |                                   |                           | |
| +                          +                                   +                           + |
|                                                                               By:[F0rGeEk]   |
+----------------------------------------------------------------------------------------------+

??傳統網路中的交換機會根據本地的FDB地址表進行轉發,FDB表存盤的是MAC地址、vlan id和介面的對應關系,那么在VXLAN網路中,交換機則需要維護一張VTEP的資訊表,這張表中主要內容是MAC地址、VNI、VTEP IP之間的對應關系,

  • VTEP(VXLAN Tunnel Endpoints,VXLAN隧道端點)
    VXLAN網路的邊緣設備,是VXLAN隧道的起點和終點,VXLAN報文的相關處理均在這上面進行,總之,它是VXLAN網路中絕對的主角,VTEP既可以是一***立的網路設備(比如華為的CE系列交換機),也可以是虛擬機所在的服務器,那它究竟是如何發揮作用的呢?答案稍候揭曉,

  • VNI(VXLAN Network Identifier,VXLAN 網路識別符號)
    上文提到,以太網資料幀中VLAN本身被限制最多只能有4094個,這使得VLAN的隔離能力在資料中心網路中力不從心,而VNI的出現,就是專門解決這個問題的,VNI是一種類似于VLAN ID的標識,一個VNI代表了一個租戶,屬于不同VNI的虛擬機之間不能直接進行二層通信,VXLAN報文封裝時,給VNI分配了足夠的空間使其可以支持海量租戶的隔離,詳細的實作,我們將在后文中介紹,

  • VXLAN Tunnel
    “隧道”是一個邏輯上的概念,它并不新鮮,比如大家熟悉的GRE,說白了就是將原始報文“變身”后再加以“包裝”,好讓它可以在承載網路(比如IP網路)上傳輸,從主機的角度看,就好像原始報文的起點和終點之間,有一條直通的鏈路一樣,而這個看起來直通的鏈路,就是“隧道”,顧名思義,“VXLAN隧道”便是用來傳輸經過VXLAN封裝的報文的,它是建立在兩個VTEP之間的一條虛擬通道,

??上圖就是VXLAN的報文格式,VTEP對VM發送的原始以太幀(Original L2 Frame)進行了以下“包裝”: + **VXLAN Header** 增加VXLAN頭(8位元組),其中包含24位元的VNI欄位,用來定義VXLAN網路中不同的租戶,此外,還包含VXLAN Flags(8位元,取值為00001000)和兩個保留欄位(分別為24位元和8位元),
  • UDP Header
    VXLAN頭和原始以太幀一起作為UDP的資料,UDP頭中,目的埠號(VXLAN Port)固定為4789,源埠號(UDP Src. Port)是原始以太幀通過哈希演算法計算后的值,

  • Outer IP Header
    封裝外層IP頭,其中,源IP地址(Outer Src. IP)為源VM所屬VTEP的IP地址,目的IP地址(Outer Dst. IP)為目的VM所屬VTEP的IP地址,

  • Outer MAC Header
    封裝外層以太頭,其中,源MAC地址(Src. MAC Addr.)為源VM所屬VTEP的MAC地址,目的MAC地址(Dst. MAC Addr.)為到達目的VTEP的路徑上下一跳設備的MAC地址,

1.9.4 VXLAN實踐

??本次關于VXLAN的實踐均是在Linux中進行,主要分為兩個實驗:1. 點對點VXLAN通信;2.容器環境中跨物理機通信

  • 1. 點對點VXLAN
    ??點對點VXLAN是最簡單的一種實踐方式,它有助于我們理解上文講的那些干貨,如下圖所示,我們在兩臺server上各創建一個vxlan型別的介面,其中VXLAN1和VXLAN2為它們所在物理機的VTEP設備,我們制定VXLAN介面IP地址為10.1.1.0/24網段中,最終我們在VTEP設備之間構建一條VXLAN Tunnel,然后將10.1.1.0/24這個網路通過該隧道打通,
               +------------------------------------------------------------------------+
               |                                                                        |
               |          SERVER A                                     SERVER B         |
               |   +-------------------+                        +-------------------+   |
               |   |     10.1.1.1      |                        |     10.1.1.2      |   |
               |   |     +------+      |     VXLAN Tunnel       |     +------+      |   |
               |   |     |VXLAN1| +---------------------------------+ |VXLAN2|      |   |
               |   |     +---+--+ +---------------------------------+ +---+--+      |   |
               |   |         |         |                        |         |         |   |
               |   |         |         |                        |         |         |   |
               |   |    +----+----+    |                        |    +----+----+    |   |
               |   |    |  ens33  |    |                        |    |  ens33  |    |   |
               |   +----+----+----+----+                        +----+----+----+ ---+   |
               |             | 172.16.116.131/24        172.16.116.132/24 |             |
               |             |                                            |             |
               |             +--------------------------------------------+             |
               |                                                                        |
               |                                                          By:[F0rGeEk]  |
               +------------------------------------------------------------------------+

其實作還是非常簡單的,具體操作程序如下:

 # 設備OS版本資訊
[root@d1 ~]# uname -r
3.10.0-957.el7.x86_64
[root@d1 ~]# cat /etc/centos-release
CentOS Linux release 7.6.1810 (Core)
  • SERVER A上的配置
[root@d1 ~]# ip link add vxlan1 type vxlan id 33 remote 172.16.116.132 dstport 4789 dev ens33
[root@d1 ~]# ip link set vxlan1 up
[root@d1 ~]# ip addr add 10.1.1.1/24 dev vxlan1
 # 查看創建的vxlan1網路設備資訊
[root@d1 ~]# ifconfig vxlan1
vxlan1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 10.1.1.1  netmask 255.255.255.0  broadcast 0.0.0.0
        inet6 fe80::58d9:3eff:fed9:659d  prefixlen 64  scopeid 0x20<link>
        ether 5a:d9:3e:d9:65:9d  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 8  bytes 544 (544.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
 # 查看關于10.1.1.0/24網路路由情況
[root@d1 ~]# route -n | grep 10.1.1.0
10.1.1.0        0.0.0.0         255.255.255.0   U     0      0        0 vxlan1
  • SERVER B上的配置
[root@d2 ~]# ip link add vxlan2 type vxlan id 33 remote 172.16.116.131 dstport 4789 dev ens33
[root@d2 ~]# ip link set vxlan2 up
[root@d2 ~]# ip addr add 10.1.1.2/24 dev vxlan2
 # 查看創建的vxlan2網路設備資訊
[root@d2 ~]# ifconfig vxlan2
vxlan2: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 10.1.1.2  netmask 255.255.255.0  broadcast 0.0.0.0
        inet6 fe80::a8fd:5bff:fed4:7cb2  prefixlen 64  scopeid 0x20<link>
        ether aa:fd:5b:d4:7c:b2  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 8  bytes 544 (544.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
 # 查看關于10.1.1.0/24網路路由情況
[root@d2 ~]# route -n | grep 10.1.1.0
10.1.1.0        0.0.0.0         255.255.255.0   U     0      0        0 vxlan2
  • 測驗連通性
 # 為方便測驗這里將CentOS的防火墻關閉
[root@d1 ~]# systemctl stop firewalld
[root@d1 ~]# ping 10.1.1.2 -c 3
PING 10.1.1.2 (10.1.1.2) 56(84) bytes of data.
64 bytes from 10.1.1.2: icmp_seq=1 ttl=64 time=0.826 ms
64 bytes from 10.1.1.2: icmp_seq=2 ttl=64 time=0.973 ms
64 bytes from 10.1.1.2: icmp_seq=3 ttl=64 time=1.00 ms
  • 抓包分析
 # 在SERVER  A上針對物理介面進行抓包
[root@d1 ~]# tcpdump -i ens33 -w vxlan.pcap
tcpdump: listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
^C90 packets captured
92 packets received by filter
0 packets dropped by kernel
 # 在SERVER B上ping10.1.1.1
[root@d2 ~]# ping 10.1.1.1 -c 3
PING 10.1.1.1 (10.1.1.1) 56(84) bytes of data.
64 bytes from 10.1.1.1: icmp_seq=1 ttl=64 time=0.991 ms
64 bytes from 10.1.1.1: icmp_seq=2 ttl=64 time=1.30 ms
64 bytes from 10.1.1.1: icmp_seq=3 ttl=64 time=1.21 ms
  • 2. 跨主機容器之間的VXLAN
    ??實驗環境是在兩臺SERVER上分別部署一個docker容器,兩個容器均在同一個網段,最終實作不同宿主機上的同一網段的容器之間可以互訪,熟悉K8S的朋友可能要說,這個在K8S里部署docker時默認就可以互通啊,是的沒錯,這里我們就是將底層是如何實作的來做個講解,
             +------------------------------------------------------------------------+
             |                                                                        |
             |          SERVER A                                     SERVER B         |
             |   +-------------------+                        +-------------------+   |
             |   |                   |                        |                   |   |
             |   |    +---------+    |                        |    +---------+    |   |
             |   |    | Docker A|    |                        |    | Docker B|    |   |
             |   |    +---------+    |                        |    +---------+    |   |
             |   |    172.33.1.11    |                        |    172.33.1.12    |   |
             |   |         |         |                        |         |         |   |
             |   |  +------+------+  |                        |  +------+------+  |   |
             |   |  |    Bridge1  |  |                        |  |    Bridge2  |  |   |
             |   |  +------+------+  |                        |  +------+------+  |   |
             |   |         |         |                        |         |         |   |
             |   |  +------+------+  |                        |  +------+------+  |   |
             |   |  |VXLAN_DockerA|  |                        |  |VXLAN_DockerB|  |   |
             |   |  +------+------+  |                        |  +------+------+  |   |
             |   |         |         |                        |         |         |   |
             |   |    +----+----+    |                        |    +----+----+    |   |
             |   |    |  ens33  |    |                        |    |  ens33  |    |   |
             |   +----+---------+----+                        +----+---------+----+   |
             |     172.16.116.131/24                            172.16.116.132/24     |
             |             |                                            |             |
             |             +--------------------------------------------+             |
             |                                                           By:[F0rGeEk] |
             +------------------------------------------------------------------------+

這里需要說明一點,當啟動docker服務后,系統默認會創建一個docker0的網路,默認是172.17.0.0/16這個網段,啟動容器時默認會從172.17.0.2開始自動分配給容器,按照實驗環境的需求,我們這里需要指定容器的ip地址,docker默認的docker0是不允許被指定IP給容器的,只有在用戶定義的網路上才支持用戶指定容器的IP地址,所以這里我們需要創建一個自定義的網路,

  • 自定義網路
[root@d1 ~]# docker network create bridge1 \
 -o com.docker.network.bridge.name=bridge1 \
 --subnet 172.33.1.0/24
 # 驗證是否成功創建網路
[root@d1 ~]# docker network list
NETWORK ID          NAME                DRIVER              SCOPE
0b57d2a226b4        bridge              bridge              local
eab6c2991f09        bridge1             bridge              local
a96c8a04be60        host                host                local
8f8172bcf173        none                null                local
[root@d1 ~]# ifconfig
bridge1: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.33.1.1  netmask 255.255.255.0  broadcast 172.33.1.255
        ether 02:42:aa:6d:ae:45  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
  • 創建并啟動容器
 # SERVER A
[root@d1 ~]# docker run -itd --net bridge1 --ip 172.33.1.11 busybox
 # 驗證容器是否成功創建
[root@d1 ~]# docker ps
CONTAINER ID   IMAGE      COMMAND    CREATED      STATUS       PORTS        NAMES
b3b055b49d4c   busybox    "sh"     5 seconds ago  Up 3 seconds          quizzical_mestorf
 #檢查新創建容器的IP地址
[root@d1 ~]# docker exec -it b3b055b49d4c sh
/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:AC:21:01:0B
          inet addr:172.33.1.11  Bcast:172.33.1.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:16 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:1312 (1.2 KiB)  TX bytes:0 (0.0 B)
 # SERVER B
[root@d2 ~]# docker run -itd --net bridge2 --ip 172.33.1.12 busybox
00bb21c402f00fabe576b88841116515475a1b54fd660debccefc1d00ec464d0
[root@d2 ~]# docker ps
CONTAINER ID   IMAGE   COMMAND   CREATED       STATUS       PORTS        NAMES
00bb21c402f0  busybox   "sh"   4 seconds ago   Up 2 seconds           elated_mirzakhani
 #檢查新創建容器的IP地址
[root@d2 ~]# docker exec -it 00bb21c402f0 sh
/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:AC:21:01:0C
          inet addr:172.33.1.12  Bcast:172.33.1.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:16 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:1312 (1.2 KiB)  TX bytes:0 (0.0 B)
  • 創建VXLAN介面并加入docker網橋
 # SERVER A
[root@d1 ~]# ip link add VXLAN_DockerA type vxlan id 33 remote 172.16.116.132 dstport 4789 dev ens33
[root@d1 ~]# ip link set VXLAN_DockerA up
[root@d1 ~]# brctl addif bridge1 VXLAN_DockerA
 # 查看VXLAN資訊
[root@d1 ~]# ip -d link show VXLAN_DockerA
12: VXLAN_DockerA: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue master bridge1 state UNKNOWN mode DEFAULT group default qlen 1000
    link/ether 5a:6e:12:f7:02:9c brd ff:ff:ff:ff:ff:ff promiscuity 1
    vxlan id 33 remote 172.16.116.132 dev ens33 srcport 0 0 dstport 4789 ageing 300 noudpcsum noudp6zerocsumtx noudp6zerocsumrx
    bridge_slave state forwarding priority 32 cost 100 hairpin off guard off root_block off fastleave off learning on flood on port_id 0x8002 port_no 0x2 designated_port 32770 designated_cost 0 designated_bridge 8000.2:42:aa:6d:ae:45 designated_root 8000.2:42:aa:6d:ae:45 hold_timer    0.00 message_age_timer    0.00 forward_delay_timer    0.00 topology_change_ack 0 config_pending 0 proxy_arp off proxy_arp_wifi off mcast_router 1 mcast_fast_leave off mcast_flood on addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
 # SERVER B
[root@d2 ~]# ip link add VXLAN_DockerB type vxlan id 33 remote 172.16.116.131 dstport 4789 dev ens33
[root@d2 ~]# ip link set VXLAN_DockerB up
[root@d2 ~]# brctl addif bridge2 VXLAN_DockerB
 # 查看VXLAN資訊
[root@d2 ~]# ip -d link show VXLAN_DockerB
10: VXLAN_DockerB: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue master bridge2 state UNKNOWN mode DEFAULT group default qlen 1000
    link/ether fa:8b:b6:00:70:1e brd ff:ff:ff:ff:ff:ff promiscuity 1
    vxlan id 33 remote 172.16.116.131 dev ens33 srcport 0 0 dstport 4789 ageing 300 noudpcsum noudp6zerocsumtx noudp6zerocsumrx
    bridge_slave state forwarding priority 32 cost 100 hairpin off guard off root_block off fastleave off learning on flood on port_id 0x8002 port_no 0x2 designated_port 32770 designated_cost 0 designated_bridge 8000.2:42:c2:0:9:dd designated_root 8000.2:42:c2:0:9:dd hold_timer    0.00 message_age_timer    0.00 forward_delay_timer    0.00 topology_change_ack 0 config_pending 0 proxy_arp off proxy_arp_wifi off mcast_router 1 mcast_fast_leave off mcast_flood on addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
  • 連通性測驗
 # SERVER A
[root@d1 ~]# docker exec -it b3b055b49d4c sh
/ # ping 172.33.1.12 -c 3
PING 172.33.1.12 (172.33.1.12): 56 data bytes
64 bytes from 172.33.1.12: seq=0 ttl=64 time=1.793 ms
64 bytes from 172.33.1.12: seq=1 ttl=64 time=0.598 ms
64 bytes from 172.33.1.12: seq=2 ttl=64 time=1.511 ms
--- 172.33.1.12 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.598/1.300/1.793 ms
 # SERVER B
[root@d2 ~]# tcpdump -n -i ens33 icmp -w docker_vxlan.pcap
tcpdump: listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
^C4 packets captured
4 packets received by filter
0 packets dropped by kernel
[root@d2 ~]# sz docker_vxlan.pcap

1.10 MacVLAN

??前面的章節介紹了幾種 Linux 虛擬網路設備:tap/tun、veth-pair、bridge等它們本質上是Linux內核提供的網路虛擬化解決方案,本章節要講的MacVLAN也是其中的一種,準確說這是一種網卡虛擬化的解決方案,因為MacVLAN這種技術能將 一塊物理網卡虛擬成多塊虛擬網卡 ,由一個變多個(前提是網卡要打開混雜模式),針對每一個虛擬網卡都可以分配一個獨立的MAC地址和IP地址,這就相當于多個虛擬網卡通過一塊物理網卡連接到物理網路中,

1.10.1 基本原理

??macvlan是 Linux內核支持的一項特性,支持的版本有 v3.9-3.19 和 4.0+,推薦比較穩定的版本4.0+,它一般是以內核模塊的形式存在,我們可以通過以下方法判斷當前系統是否支持:

[root@d1 ~]# modprobe macvlan
[root@d1 ~]# lsmod | grep macvlan
macvlan                19239  0

??如果以上命令報錯或者沒有回顯,那么說明您的系統暫時不支持macvlan,對于網工肯定糾結macvlan和vlan有啥區別,其實只是長得有點像實作機制是真心不一樣啊,通過macvlan虛擬出來的子介面和原來的物理介面是完全獨立的,這些macvlan虛擬介面可以單獨配置MAC地址和IP地址,而vlan子介面和主介面需共用相同的MAC地址,vlan主要用來劃分廣播域,而 macvlan本身就是在同一個廣播域中,macvlan通過不同的子介面來做到流量的隔離,一般通過收到報文的目的MAC來判斷這個包需要交給哪個虛擬網卡轉發,虛擬網卡再將資料包交給上層協議堆疊來處理,

                    +------------------------------------------------------------------------+
                    |                                                                        |
                    |                                           +-------------------------+  |
                    |                                  Eth0     |     Network Stack       |  |
                    |                              +------------+                         |  |
                    |                              |            +----------------+---+--+-+  |
                    |                              |                             |   |  |    |
                    |Physical Network              |                             |   |  |    |
                    |       +                      |                             |   |  |    |
                    |       |                      |       AA   +------------+   |   |  |    |
                    |       |                      |   +--------+  Macvlan A +---+   |  |    |
                    |       |                      |   |        +------------+       |  |    |
                    |       |                      |   |                             |  |    |
                    |  +----+----+                 |   |                             |  |    |
                    |  |         |         +-------+---+   BB   +-------------+      |  |    |
                    |  |  Eth 0  +--------+if dst mac is+-------+  Macvlan B  +------+  |    |
                    |  |         |         +-----------+        +-------------+         |    |
                    |  +---------+                     |                                |    |
                    |                                  |                                |    |
                    |                                  |   CC   +-------------+         |    |
                    |                                  +--------+  Macvlan C  +---------+    |
                    |                                           +-------------+              |
                    |                                                           By:[F0rGeEk] |
                    +------------------------------------------------------------------------+

1.10.2 作業模式

??macvlan子介面之間的通信模式,macvlan分為以下四種網路模式,其中最常用的是bridge模式,

  • 1. privite
    ??在private模式下,同一主介面下的子介面之間彼此隔離不能通信,即使從外部的物理網路引流,也不能互相通信,
  • 2. vepa
    ??在vepa模式下,子介面之間的通信流量需要引流到外部支持802.1Qbg/VPEA功能的交換機上(可以是物理的或者虛擬的交換機),經由外部交換機轉發再繞回來,這里所說的支持802.1Qbg/VPEA功能的交換機是指支持"埠回流"功能或者叫"支持hairpin模式",也就是說資料包從一個埠收到后還能通過這個埠再轉發出去,
  • 3. bridge
    ??這bridge式下,主要是模擬Linux bridge的功能,但比bridge要好的一點的是每個介面的MAC地址是已知的,不用學習,所以在這種模式下,子介面之間默認就可以互相通信,
  • 4. passthru
    ??這種模式只允許單個子介面連接主介面,且必須設定成混雜模式,一般用于子介面橋接和創建 VLAN 子介面的場景,

1.10.3 MacVLAN實踐

??這里我們也分兩部分來進行實踐,一種實在普通的Linux網路環境下,另一種實在Docker容器環境中實踐,在Docker網路環境中還可以分為兩種,一種是相同macvlan之間的通信還有一種是不同macvlan之間的通信,其中不同vlan之間的通信類似數通中的單臂路由,因為二層是不通的所以需要借助三層網路通信,這里就需要通過一臺路由設備(也可以是開啟ip_forward的Linux主機)來進行路由轉發,本文就介紹最基礎最底層的實踐方式,不同macvlan之間的通信相信對于網工的你來說簡直easy的不要不要的,

  • MacVLAN連接連個不同的NS
                           +-------------------------------------+
                           |   +-------+             +-------+   |
                           |   |  NS1  |             |  NS2  |   |
                           |   +---+---+             +---+---+   |
                           |       |                     |       |
                           |       |       XXXXXXX       |       |
                           |       |     XX       XX     |       |
                           |       +---+X  MacVLAN  X+---+       |
                           |             XX       XX             |
                           |               XXXXXXX               |
                           |               +     +               |
                           |               |     |               |
                           |         +-----+--+--+-----+         |
                           | 12.1.1.1|  Mac1  |  Mac2  |12.1.1.2 |
                           |         +--------+--------+         |
                           |         |      ens33      |         |
                           |         +-----------------+         |
                           |                        By:[F0rGeEk] |
                           +-------------------------------------+

??這里我們的實驗環境是將兩個不同的Name Space之間通過macvlan連通,如上圖所示為物理介面ens33創建兩個macvlan子介面,使用bridge模式,并配置IP地址然后將它們分別加入到兩個不同的NS中,最后測驗連通性,具體程序如下:

 # 創建兩個macvlan子介面
[root@d1 ~]# ip link add link ens33 dev mac1 type macvlan mode bridge
[root@d1 ~]# ip link add link ens33 dev mac2 type macvlan mode bridge
 # 創建兩個NS
[root@d1 ~]# ip netns add ns1
[root@d1 ~]# ip netns add ns2
 # 將兩個macvlan子介面分別加入ns1和ns2
[root@d1 ~]# ip link set mac1 netns ns1
[root@d1 ~]# ip link set mac2 netns ns2
 # 為兩個macvlan子介面配置IP地址并激活
[root@d1 ~]# ip netns exec ns1 ip addr add 12.1.1.1/24 dev mac1
[root@d1 ~]# ip netns exec ns1 ip link set mac1 up
[root@d1 ~]# ip netns exec ns2 ip addr add 12.1.1.2/24 dev mac2
[root@d1 ~]# ip netns exec ns2 ip link set mac2 up
 # 查看兩個ns中的macvlan子介面配置資訊
[root@d1 ~]# ip netns exec ns1 ip -d link show mac1
3: mac1@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/ether 42:e3:dc:fc:32:54 brd ff:ff:ff:ff:ff:ff link-netnsid 0 promiscuity 0
    macvlan mode bridge addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
[root@d1 ~]# ip netns exec ns2 ip -d link show mac2
4: mac2@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/ether fa:9e:76:06:1a:dd brd ff:ff:ff:ff:ff:ff link-netnsid 0 promiscuity 0
    macvlan mode bridge addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
 [root@d1 ~]# ip netns exec ns1 ip addr show mac1
3: mac1@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000
    link/ether 42:e3:dc:fc:32:54 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 12.1.1.1/24 scope global mac1
       valid_lft forever preferred_lft forever
    inet6 fe80::40e3:dcff:fefc:3254/64 scope link
       valid_lft forever preferred_lft forever
[root@d1 ~]# ip netns exec ns2 ip addr show mac2
4: mac2@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000
    link/ether fa:9e:76:06:1a:dd brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 12.1.1.2/24 scope global mac2
       valid_lft forever preferred_lft forever
    inet6 fe80::f89e:76ff:fe06:1add/64 scope link
       valid_lft forever preferred_lft forever
 # 測驗連通性
[root@d1 ~]# ip netns exec ns1 ping 12.1.1.2 -c 3
PING 12.1.1.2 (12.1.1.2) 56(84) bytes of data.
64 bytes from 12.1.1.2: icmp_seq=1 ttl=64 time=0.035 ms
64 bytes from 12.1.1.2: icmp_seq=2 ttl=64 time=0.037 ms
64 bytes from 12.1.1.2: icmp_seq=3 ttl=64 time=0.037 ms

--- 12.1.1.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 0.035/0.036/0.037/0.005 ms

抓包分析 ICMP 報文

[root@d1 ~]# tcpdump -i ens33 -w macvlan.pcap
tcpdump: listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
^C18 packets captured
19 packets received by filter
0 packets dropped by kernel
[root@d1 ~]# sz macvlan.pcap A
  • 容器網路環境中相同macvlan之間
    ??在docker容器網路環境中,macvlan也是一種非常常見且重要的跨主機網路模型,下面我們就針對容器網路進行相同macvlan在不同主機之間通信的實踐,實驗環境為兩臺server:Server A和Server B;分別啟用一個自定義網路172.33.1.0/24名稱為mac1和mac2;分別創建兩個容器并指定IP地址;最后測驗兩個容器之間的網路連通性,
                         +------------------------------------------------------------------------+
                         |                                                                        |
                         |   +-------------------+                        +-------------------+   |
                         |   |Server A           |                        |Server B           |   |
                         |   |    +---------+    |                        |    +---------+    |   |
                         |   |    | Docker A|    |                        |    | Docker B|    |   |
                         |   |    +---------+    |                        |    +---------+    |   |
                         |   |    172.33.1.11    |                        |    172.33.1.12    |   |
                         |   |         |         |                        |         |         |   |
                         |   |  +------+------+  |                        |  +------+------+  |   |
                         |   |  |    Mac 1    |  |                        |  |    Mac 2    |  |   |
                         |   |  +------+------+  |                        |  +------+------+  |   |
                         |   |         |         |                        |         |         |   |
                         |   |    +----+----+    |                        |    +----+----+    |   |
                         |   |    |  ens33  |    |                        |    |  ens33  |    |   |
                         |   +----+---------+----+                        +----+---------+----+   |
                         |     172.16.116.131/24                            172.16.116.132/24     |
                         |             |                                            |             |
                         |             +--------------------------------------------+             |
                         |                                                           By:[F0rGeEk] |
                         +------------------------------------------------------------------------+

具體實踐程序如下:

 # 啟動docker服務
[root@d1 ~]# service docker start
Redirecting to /bin/systemctl start docker.service
 # 創建docker自定義網路
[root@d1 ~]# docker network create -d macvlan --subnet=172.33.1.0/24 --gateway=172.33.1.1 -o parent=ens33 mac1
[root@d2 ~]# docker network create -d macvlan --subnet=172.33.1.0/24 --gateway=172.33.1.1 -o parent=ens33 mac2
 # 檢查自定義網路是否創建成功
[root@d1 ~]# docker network ls
NETWORK ID         NAME            DRIVER            SCOPE
f8a5e7ba5015        bridge             bridge              local
a96c8a04be60        host                host                 local
e179ce74baa4        mac1              macvlan           local
8f8172bcf173        none                null                  local
[root@d2 ~]# docker network ls
NETWORK ID         NAME             DRIVER           SCOPE
68199147d7fe        bridge              bridge              local
eb0d0e219eb8        host                host                 local
9c2b18b8a08a        mac2               macvlan           local
b7ac4a61fcce        none                 null                  local
 #創建并啟用容器
[root@d1 ~]# docker run -itd --name DockerA --ip=172.33.1.11 --network mac1 busybox
00dda3a8691564dce5e062a2c4ea89cb5c9640373102d587eb2c83e122642a67
[root@d1 ~]# docker ps
CONTAINER ID        IMAGE      COMMAND             CREATED             STATUS              PORTS               NAMES
00dda3a86915        busybox             "sh"                4 seconds ago       Up 2 seconds                            DockerA
[root@d2 ~]# docker run -itd --name DockerB --ip=172.33.1.12 --network mac2 busybox
debe59d38ece790d1ffd3d2dc17240a15812b73025fd89b23d9d394f53fa7dc8
[root@d2 ~]# docker ps
CONTAINER ID        IMAGE      COMMAND             CREATED             STATUS              PORTS               NAMES
debe59d38ece        busybox             "sh"                2 seconds ago       Up 2 seconds                            DockerB
 # 驗證不同宿主機上的容器網路連通性
[root@d1 ~]# docker exec -it DockerA sh
/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:AC:21:01:0B
          inet addr:172.33.1.11  Bcast:172.33.1.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:28 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:2544 (2.4 KiB)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
/ # ping 172.33.1.12 -c 3
PING 172.33.1.12 (172.33.1.12): 56 data bytes
64 bytes from 172.33.1.12: seq=0 ttl=64 time=0.405 ms
64 bytes from 172.33.1.12: seq=1 ttl=64 time=0.361 ms
64 bytes from 172.33.1.12: seq=2 ttl=64 time=0.310 ms

--- 172.33.1.12 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.310/0.358/0.405 ms

抓包分析 ICMP 報文

[root@d2 ~]# tcpdump -i ens33 -w macvlan.pcap
tcpdump: listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
^C25 packets captured
26 packets received by filter
0 packets dropped by kernel
[root@d2 ~]# sz macvlan.pcap
??從以上抓包分析中可以看出docker網路環境中,通過macvlan的方式連通兩個不同宿主機上同一個網段的容器時,資料包沒有進行二次封裝轉發的都是原始資料包,這說明使用這種方式更為節能高效,

醞釀醞釀準備寫云計算中的網路虛擬化(二),主要計劃圍繞容器中的各種網路模型來寫,

轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/122574.html

標籤:Linux

上一篇:036.Kubernetes集群網路-K8S網路模型及Linux基礎網路

下一篇:搭建屬于自己的服務器

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • CA和證書

    1、在 CentOS7 中使用 gpg 創建 RSA 非對稱密鑰對 gpg --gen-key #Centos上生成公鑰/密鑰對(存放在家目錄.gnupg/) 2、將 CentOS7 匯出的公鑰,拷貝到 CentOS8 中,在 CentOS8 中使用 CentOS7 的公鑰加密一個檔案 gpg -a ......

    uj5u.com 2020-09-10 00:09:53 more
  • Kubernetes K8S之資源控制器Job和CronJob詳解

    Kubernetes的資源控制器Job和CronJob詳解與示例 ......

    uj5u.com 2020-09-10 00:10:45 more
  • VMware下安裝CentOS

    VMware下安裝CentOS 一、軟硬體準備 1 Centos鏡像準備 1.1 CentOS鏡像下載地址 下載地址 1.2 CentOS鏡像下載程序 點擊下載地址進入如下圖的網站,選擇需要下載的版本,這里選擇的是Centos8,點擊如圖所示。 決定選擇Centos8后,選擇想要的鏡像源進行下載,此 ......

    uj5u.com 2020-09-10 00:12:10 more
  • 如何使用Grep命令查找多個字串

    如何使用Grep 命令查找多個字串 大家好,我是良許! 今天向大家介紹一個非常有用的技巧,那就是使用 grep 命令查找多個字串。 簡單介紹一下,grep 命令可以理解為是一個功能強大的命令列工具,可以用它在一個或多個輸入檔案中搜索與正則運算式相匹配的文本,然后再將每個匹配的文本用標準輸出的格式 ......

    uj5u.com 2020-09-10 00:12:28 more
  • git配置http代理

    git配置http代理 經常遇到克隆 github 慢的問題,這里記錄一下幾種配置 git 代理的方法,解決 clone github 過慢。 目錄 git配置代理 git單獨配置github代理 git配置全域代理 配置終端環境變數 git配置代理 主要使用 git config 命令 git單獨 ......

    uj5u.com 2020-09-10 00:12:33 more
  • Linux npm install 裝包時提示Error EACCES permission denied解

    npm install 裝包時提示Error EACCES permission denied解決辦法 ......

    uj5u.com 2020-09-10 00:12:53 more
  • Centos 7下安裝nginx,使用yum install nginx,提示沒有可用的軟體包

    Centos 7下安裝nginx,使用yum install nginx,提示沒有可用的軟體包。 18 (flaskApi) [root@67 flaskDemo]# yum -y install nginx 19 已加載插件:fastestmirror, langpacks 20 Loading ......

    uj5u.com 2020-09-10 00:13:13 more
  • Linux查看服務器暴力破解ssh IP

    在公網的服務器上經常遇到別人爆破你服務器的22埠,用來挖礦或者干其他嘿嘿嘿的事情~ 這種情況下正確的做法是: 修改默認ssh的22埠 使用設定密鑰登錄或者白名單ip登錄 建議服務器密碼為復雜密碼 創建普通用戶登錄服務器(root權限過大) 建立堡壘機,實作統一管理服務器 統計爆破IP [root ......

    uj5u.com 2020-09-10 00:13:17 more
  • CentOS 7系統常見快捷鍵操作方式

    Linux系統中一些常見的快捷方式,可有效提高操作效率,在某些時刻也能避免操作失誤帶來的問題。 ......

    uj5u.com 2020-09-10 00:13:31 more
  • CentOS 7作業系統目錄結構介紹

    作業系統存在著大量的資料檔案資訊,相應檔案資訊會存在于系統相應目錄中,為了更好的管理資料資訊,會將系統進行一些目錄規劃,不同目錄存放不同的資源。 ......

    uj5u.com 2020-09-10 00:13:35 more
最新发布
  • vim的常用命令

    Vim的6種基本模式 1. 普通模式在普通模式中,用的編輯器命令,比如移動游標,洗掉文本等等。這也是Vim啟動后的默認模式。這正好和許多新用戶期待的操作方式相反(大多數編輯器默認模式為插入模式)。 2. 插入模式在這個模式中,大多數按鍵都會向文本緩沖中插入文本。大多數新用戶希望文本編輯器編輯程序中一 ......

    uj5u.com 2023-04-20 08:43:21 more
  • vim的常用命令

    Vim的6種基本模式 1. 普通模式在普通模式中,用的編輯器命令,比如移動游標,洗掉文本等等。這也是Vim啟動后的默認模式。這正好和許多新用戶期待的操作方式相反(大多數編輯器默認模式為插入模式)。 2. 插入模式在這個模式中,大多數按鍵都會向文本緩沖中插入文本。大多數新用戶希望文本編輯器編輯程序中一 ......

    uj5u.com 2023-04-20 08:42:36 more
  • docker學習

    ###Docker概述 真實專案部署環境可能非常復雜,傳統發布專案一個只需要一個jar包,運行環境需要單獨部署。而通過Docker可將jar包和相關環境(如jdk,redis,Hadoop...)等打包到docker鏡像里,將鏡像發布到Docker倉庫,部署時下載發布的鏡像,直接運行發布的鏡像即可。 ......

    uj5u.com 2023-04-19 09:26:53 more
  • 設定Windows主機的瀏覽器為wls2的默認瀏覽器

    這里以Chrome為例。 1. 準備作業 wsl是可以使用Windows主機上安裝的exe程式,出于安全考慮,默認情況下改功能是無法使用。要使用的話,終端需要以管理員權限啟動。 我這里以Windows Terminal為例,介紹如何默認使用管理員權限打開終端,具體操作如下圖所示: 2. 操作 wsl ......

    uj5u.com 2023-04-19 09:25:49 more
  • docker學習

    ###Docker概述 真實專案部署環境可能非常復雜,傳統發布專案一個只需要一個jar包,運行環境需要單獨部署。而通過Docker可將jar包和相關環境(如jdk,redis,Hadoop...)等打包到docker鏡像里,將鏡像發布到Docker倉庫,部署時下載發布的鏡像,直接運行發布的鏡像即可。 ......

    uj5u.com 2023-04-19 09:19:04 more
  • Linux學習筆記

    IP地址和主機名 IP地址 ifconfig可以用來查詢本機的IP地址,如果不能使用,可以通過install net-tools安裝。 Centos系統下ens33表示主網卡;inet后表示IP地址;lo表示本地回環網卡; 127.0.0.1表示代指本機;0.0.0.0可以用于代指本機,同時在放行設 ......

    uj5u.com 2023-04-18 06:52:01 more
  • 解決linux系統的kdump服務無法啟動的問題

    問題:專案麒麟系統服務器的kdump服務無法啟動,沒有相關日志無法定位問題。 1、查看服務狀態是關閉的,重啟系統也無法啟動 systemctl status kdump 2、修改grub引數,修改“crashkernel”為“512M(有的機器數值太大太小都會導致報錯,建議從128M開始試,或者加個 ......

    uj5u.com 2023-04-12 09:59:50 more
  • 解決linux系統的kdump服務無法啟動的問題

    問題:專案麒麟系統服務器的kdump服務無法啟動,沒有相關日志無法定位問題。 1、查看服務狀態是關閉的,重啟系統也無法啟動 systemctl status kdump 2、修改grub引數,修改“crashkernel”為“512M(有的機器數值太大太小都會導致報錯,建議從128M開始試,或者加個 ......

    uj5u.com 2023-04-12 09:59:01 more
  • 你是不是暴露了?

    作者:袁首京 原創文章,轉載時請保留此宣告,并給出原文連接。 如果您是計算機相關從業人員,那么應該經歷不止一次網路安全專項檢查了,你肯定是收到過資訊系統技術檢測報告,要求你加強風險監測,確保你提供的系統服務堅實可靠了。 沒檢測到問題還好,檢測到問題的話,有些處理起來還是挺麻煩的,尤其是線上正在運行的 ......

    uj5u.com 2023-04-05 16:52:56 more
  • 細節拉滿,80 張圖帶你一步一步推演 slab 記憶體池的設計與實作

    1. 前文回顧 在之前的幾篇記憶體管理系列文章中,筆者帶大家從宏觀角度完整地梳理了一遍 Linux 記憶體分配的整個鏈路,本文的主題依然是記憶體分配,這一次我們會從微觀的角度來探秘一下 Linux 內核中用于零散小記憶體塊分配的記憶體池 —— slab 分配器。 在本小節中,筆者還是按照以往的風格先帶大家簡單 ......

    uj5u.com 2023-04-05 16:44:11 more