1. 程式人生 > >帶著問題了解Openstack Neutron安全組

帶著問題了解Openstack Neutron安全組

ont 全局 sta 允許 allow top nat ingress env

本文是由最近一個Openstack Neutron安全組的問題所觸發而寫。希望之後借此機會深入探討一下iptables和netfilter相關用法、原理等。
本節先看看網絡問題的解決思路以及Openstack Neutron安全組,之後再開篇細講背後的網絡內核netfilter。

問題簡述

公司系統部同事為業務部門創建lvs服務時,Linux Director與Real Server間無法進行正常的通訊,Real Server是由Hulk平臺創建的openstack虛擬機。
網絡問題排查,按照“確定網絡結構 - 抓包定位 - 分析定位問題 - 糾正網絡部署 - 單元測試 - 完整測試 -(推入生產)- 回歸測試 - 總結回顧”的思路來 就基本搞定了。

確定網絡結構

遇到網絡問題,首先考慮數據包在全流程中drop的位置,所以,首先我們要熟知Openstack Neutron網絡的整個架構。
為了重點講述Openstack Neutron網絡及安全組,我們假設Linux Director和Real Server虛機所在的物理主機之間的網絡可達。如下圖是Openstack Neutron網絡數據面的基本架構。

技術分享圖片 技術分享圖片

看下這個架構圖,首先遇到一個特殊之處,我們暫且花點時間看一下:
br-ethx與br-int是OVS創建的OVS Bridge,qbr-XXX是Linux Bridge,為什麽不把虛機的Tap設備直接掛到OVS Bridge的br-int上,而在br-int和Tap設備間加個Linux Bridge qbr-XXX?

  1. Openstack Neutron需要在宿主機上執行一定的安全策略;
  2. Hulk平臺使用的ovs版本是2.3.1,該版本尚未完全支持安全策略的內核模塊實施部分:netfilter模塊;
  3. 增加一個中間層Linux bridge可以解決網絡策略配置。

Openstack Neutron網絡各設備及配置請參考這裏。

接下來我們進入探索之旅。

抓包定位

在物理機和虛機上抓包:在客戶端發送請求數據包後,分別在ABCDEFG七個點中抓包:

tcpdump -i xxx -nv | grep ipip

其中,在CDEFG 5個點都能抓到數據包,在AB兩點沒有抓到。

分析定位問題

問題出現在BC兩點之間,即Linux bridge與Tap設備之間。Openstack Neutron在這兩點之間利用iptables做安全策略,那麽是如何實現的,為什麽會丟包?反過來想,既然ssh能夠連接上虛機,說明TCP數據包正常,更確信iptables安全策略存在問題。

下面,我們先了解下Openstack Neutron如何實現安全組策略。

Neutron安全組的iptables規則

Neutron L2 Agent承擔使用iptables維護鏈和規則的任務。它為虛機的每塊網卡的tap設備建立 i(進)、o(出)和s(防IP欺騙)鏈和規則,來實現:

1. prepares, updates, removes firewall filters (準備、更新和刪除防火墻過濾器)
2. drops all packets by default (默認丟棄所有包)
3. prevents IP spoofing based on port‘s mac address (compatible with allowed_address_pairs extension) (防IP欺騙)
4. allows incoming DHCP and ICMPv6 RA (允許進入虛機的DHCP包和ICMPV6 RA)
5. blocks outgoing DHCP (禁止出虛機的DHCP包)
6. drops INVALID packets (丟棄無效狀態的包)
7. allows stateful, established connections (允許有狀態的並且已建立的連接,比如允許進來的ICMP的時候,從外面ping虛機時虛機的響應包是可以返回的)
8. converts security group rules to iptables rules (IPv4, IPv6, TCP, UDP, ICMP, ICMPv6) (將用戶配置的規則轉化為iptables規則)
9. multiple TCP/UDP ports per iptables rule using multiport module
支持 IPV4 和 IPV6

來看看Neutron為了實現這些功能添加的iptables鏈:

[root@w-openstack32 ~]# iptables -S | grep neutron
-N neutron-filter-top
-N neutron-openvswi-FORWARD             #neutorn定義的FORWARD鏈
-N neutron-openvswi-INPUT               #Neutron定義的INPUT鏈
-N neutron-openvswi-OUTPUT              #Neutron定義的OUTPUT鏈 
-N neutron-openvswi-ibddxxxxc-b         #處理進入該虛機的網絡包
-N neutron-openvswi-local
-N neutron-openvswi-obddxxxxc-b         #處理出該虛機的網絡包
-N neutron-openvswi-sbddxxxxc-b         #處理出該虛機的網絡包的防IP欺騙
-N neutron-openvswi-sg-chain    
-N neutron-openvswi-sg-fallback
-A INPUT -j neutron-openvswi-INPUT      #將INPUT鏈轉到neutron的INPUT鏈
-A FORWARD -j neutron-filter-top
-A FORWARD -j neutron-openvswi-FORWARD  #將FORWARD鏈轉到neutorn的forward鏈
-A OUTPUT -j neutron-filter-top
-A OUTPUT -j neutron-openvswi-OUTPUT    #將OUTPUT鏈轉到neutron的output鏈
-A neutron-filter-top -j neutron-openvswi-local

這些鏈之間的關系:
技術分享圖片

當前由於iptables主要做控制qbr橋在虛機和br-int之間轉發的網絡幀,Bridge代碼應該是用filter表的FORWARD鏈來處理這些網絡幀。

下面我們逐步跟蹤FORWARD鏈,來找到neutron-openvswi-ixxxxx鏈定位這個問題。

鏈跟蹤,定位位置

首先,查看FORWARD鏈:

[root@w-openstack32 ~]# iptables -nxvL FORWARD
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
    pkts      bytes target     prot opt in     out     source               destination
46935472750 20715430397978 neutron-filter-top  all  --  *      *       0.0.0.0/0            0.0.0.0/0
46935472750 20715430397978 neutron-openvswi-FORWARD  all  --  *      *       0.0.0.0/0            0.0.0.0/0

往下走,跟蹤neutron-openvswi-FORWARD鏈:

[root@w-openstack32 ~]# iptables -nxvL neutron-openvswi-FORWARD
Chain neutron-openvswi-FORWARD (1 references)
    pkts      bytes target     prot opt in     out     source               destination
46934035761 20714724813160 neutron-openvswi-scope  all  --  *      *       0.0.0.0/0            0.0.0.0/0
459609600 121602465610 neutron-openvswi-sg-chain  all  --  *      *       0.0.0.0/0            0.0.0.0/0            PHYSDEV match --physdev-out tapbddxxxxc-bd --physdev-is-bridged /* Direct traffic from the VM interface to the security group chain. */
418512415 87324679449 neutron-openvswi-sg-chain  all  --  *      *       0.0.0.0/0            0.0.0.0/0            PHYSDEV match --physdev-in tapbddxxxxc-bd --physdev-is-bridged /* Direct traffic from the VM interface to the security group chain. */

繼續往下走,跟蹤neutron-openvswi-sg-chain鏈:

[root@w-openstack32 ~]# iptables -nxvL neutron-openvswi-sg-chain
Chain neutron-openvswi-sg-chain (10 references)
    pkts      bytes target     prot opt in     out     source               destination
459619285 121606141606 neutron-openvswi-ibddxxxxc-b  all  --  *      *       0.0.0.0/0            0.0.0.0/0            PHYSDEV match --physdev-out tapbddxxxxc-bd --physdev-is-bridged /* Jump to the VM specific chain. */
418522179 87328347603 neutron-openvswi-obddxxxxc-b  all  --  *      *       0.0.0.0/0            0.0.0.0/0            PHYSDEV match --physdev-in tapbddxxxxc-bd --physdev-is-bridged /* Jump to the VM specific chain. */
46927558621 20715211464005 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0

往下走,跟蹤進入neutron-openvswi-ibddxxxxc-b鏈:

[root@w-openstack32 ~]# iptables -nxvL neutron-openvswi-ibddxxxxc-b
Chain neutron-openvswi-ibddxxxxc-b (1 references)
    pkts      bytes target     prot opt in     out     source               destination
428583997 119531816501 RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED /* Direct packets associated with a known session to the RETURN chain. */
       0        0 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0            state INVALID /* Drop packets that appear related to an existing connection (e.g. TCP ACK/FIN) but do not have an entry in conntrack. */
 1937647 124006974 neutron-openvswi-sg-fallback  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* Send unmatched traffic to the fallback chain. */

最後看下,如果以上規則都不匹配,做的動作:

[root@w-openstack32 ~]# iptables -nxvL neutron-openvswi-sg-fallback
Chain neutron-openvswi-sg-fallback (10 references)
    pkts      bytes target     prot opt in     out     source               destination
 9841017 629783588 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* Default drop rule for unmatched traffic. */

Openstack Neutron安全組白名單機制

Openstack Neutron安全組使用白名單機制,此時網絡的訪問能力 = 用戶自定義的規則允許的能力。如果這些規則都不匹配,沒看錯,是drop掉該數據包。

可以通過上邊的iptables命令看到,安全組沒有放開IPIP協議的規則,所以數據包沒進到虛機中。

控制節點上再確認下安全組策略,的確沒有IPIP協議規則。

[root@w-openstack01 ~]# neutron security-group-list
+--------------------------------------+---------+------------------------------------------------+
| id                                   | name    | security_group_rules                           |
+--------------------------------------+---------+------------------------------------------------+
| 15b463bf-f232-489e-90b2-c08699454b29 | default |                                                |
+--------------------------------------+---------+------------------------------------------------+

確認IPIP協議號

查看kernel源碼中頭文件include/uapi/linux/in.h,可以看到IPIP協議號是4;

/* Standard well-defined IP protocols.  */
enum {
  IPPROTO_IP = 0,   /* Dummy protocol for TCP   */
  IPPROTO_ICMP = 1,   /* Internet Control Message Protocol  */
  IPPROTO_IGMP = 2,   /* Internet Group Management Protocol */
  IPPROTO_IPIP = 4,   /* IPIP tunnels (older KA9Q tunnels use 94) */
  IPPROTO_TCP = 6,    /* Transmission Control Protocol  */
  IPPROTO_EGP = 8,    /* Exterior Gateway Protocol    */
  IPPROTO_PUP = 12,   /* PUP protocol       */
  IPPROTO_UDP = 17,   /* User Datagram Protocol   */
  IPPROTO_IDP = 22,   /* XNS IDP protocol     */
  IPPROTO_DCCP = 33,    /* Datagram Congestion Control Protocol */
  IPPROTO_RSVP = 46,    /* RSVP protocol      */
  IPPROTO_GRE = 47,   /* Cisco GRE tunnels (rfc 1701,1702)  */
...

加入規則,糾正網絡

在Openstack Neutron安全組dashboard上加入規則:

技術分享圖片

在控制節點上看到規則已經生成:

[root@w-openstack01 ~]# neutron security-group-list
+--------------------------------------+---------+------------------------------------------------+
| id                                   | name    | security_group_rules                           |
+--------------------------------------+---------+------------------------------------------------+
| 15b463bf-f232-489e-90b2-c08699454b29 | default | ingress, IPv4, 4, remote_ip_prefix: 0.0.0.0/0 |
+--------------------------------------+---------+------------------------------------------------+

單元測試

再去虛機抓包,客戶端發包通信接收到應答包,並且在虛機上抓到IPIP數據包。同時用命令行查看iptables,已有數據包匹配並執行(prot為4的pkts不為0)。

[root@w-openstack32 ~]# iptables -nxvL neutron-openvswi-ibddxxxxc-b
Chain neutron-openvswi-ibddxxxxc-b (1 references)
    pkts      bytes target     prot opt in     out     source               destination
428583997 119531816501 RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED /* Direct packets associated with a known session to the RETURN chain. */
   12266  7040888 RETURN     4    --  *      *       0.0.0.0/0            0.0.0.0/0
       0        0 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0            state INVALID /* Drop packets that appear related to an existing connection (e.g. TCP ACK/FIN) but do not have an entry in conntrack. */
 1937647 124006974 neutron-openvswi-sg-fallback  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* Send unmatched traffic to the fallback chain. */

在虛機上抓包,沒有看到其他類型數據包進入:

tcpdump -i any \(not icmp\) and \(not udp\) and \(not tcp\) and \(not arp\)

推入生產,回歸測試

經驗證,和測試環境效果一致,done。

總結

通過問題的探索,我們了解Openstack Neutron的安全組策略相關知識了,也對Neutron網絡數據面的網絡拓撲架構有了基本的認識。之後,我會結合源碼展開談談iptables模式匹配與執行,以及iptables的高級用法和原理,以及部分netfilter的原理。

帶著問題了解Openstack Neutron安全組