SDN控制器之OVN實驗五:配置OVN網路安全功能(ACL)
概覽
基於我之前的文章中的相關內容,本文通過使用OVN訪問控制列表(ACL)來實現基本的網路安全功能。
OVN訪問控制列表和地址集介紹
OVN中的ACL規則儲存於北向資料庫的ACL表中,並且可以使用ovn-nbctl的acl命令進行配置。目前,ACL只能應用於邏輯交換機,但是未來將支援應用到邏輯路由器。
在出站和入站方向都支援使用ACL:
-
入站:從工作負載(from-lport)進入邏輯埠
-
出站:從邏輯端口出去到工作負載(to-lport)。
此外,為每個ACL分配一個優先順序,以確定它們的匹配順序,最高優先順序首先被匹配。另外ACL可以被賦予相同的優先順序。 然而,在兩個具有相同優先順序並且都匹配同一個分組的ACL的情況下,將僅匹配一個ACL。確切地說,哪一個ACL最終將被匹配是不確定的,你不能真正地確定哪個規則將應用於給定的情況。所以我建議:在大多數情況下儘量使用不同的優先順序。
ACL中的匹配規則基於OVS中的流語法,對於具有程式設計背景的人都會覺得很熟悉。該語法在ovn-sb手冊頁的“Logical_Flow表”部分中進行了說明。它值得一讀,特別是介紹“!=”匹配規則的那部分內容。
另外值得強調的一點是,您不能在具有type = router的埠上建立ACL匹配規則。為了減少ACL表中的條目數量,可以使用定義相同型別地址組的地址集。例如,一組IPv4地址/網路,一組MAC地址或一組IPv6地址可以放置在一個可命名的地址集內。為了減少ACL表中的條目數,可以使用定義相同型別地址組的地址集。 例如,一組IPv4地址/網路,一組MAC地址或一組IPv6地址可以放置在命名地址集內。 然後地址集可以被ACL的match子句內的“name”引用(以$ name的形式)。
下面舉個例子:
#允許來自交換機“ls1”上埠“ls1-vm1”的所有ip流量,同時允許相關回包通過 ovn-nbctl acl-add ls1 from-lport 1000 "inport == \"ls1-vm1\" && ip" allow-related
# 允許 ssh 到 ls1-vm1 ovn-nbctl acl-add ls1 to-lport 999 "outport == \"ls1-vm1\" && tcp.dst == 22" allow-related
# 阻止所有到ls1-vm1的IPv4/IPv6流量 ovn-nbctl acl-add ls1 to-lport 998 "outport == \"ls1-vm1\" && ip" drop |
注意“allow-related”的使用。 它的作用是這樣:它允許反向相關的流量(例如,響應,fragements等)通過。 在第二條規則中,為了允許從伺服器回來的SSH響應流量通過,我就使用了 allow-related 。
我們再來看看地址集。 如前文所述,地址集是相同型別的地址組。 使用ovn-nbctl北向資料庫命令建立地址集,然後在ACL中呼叫地址集。 這裡有幾個建立地址集的例子:
ovn-nbctl create Address_Set name=wwwServers addresses=172.16.1.2,172.16.1.3 ovn-nbctl create Address_Set name=www6Servers addresses=\"fd00::1\",\"fd00::2\" ovn-nbctl create Address_Set name=macs addresses=\"02:00:00:00:00:01\",\"02:00:00:00:00:02\" |
注意使用帶有包含‘:’字元的地址集的雙引號。 如果你在命令中不使用雙引號,將會報錯。
實驗環境
我們在實驗室環境中使用ACL進行實驗。詳細的環境介紹和搭建,請參考我之前的文章。
物理網路環境:
OVN邏輯網路環境:
實驗一
第一步,我們將通過為每個伺服器建立一個靜態NAT規則來允許從外部訪問DMZ中的伺服器。
在ubuntu1上執行:
#為vm1建立snat-dnat規則並應用於edge1 ovn-nbctl -- --id=@nat create nat type="dnat_and_snat" logical_ip=172.16.255.130 \ external_ip=10.127.0.250 -- add logical_router edge1 nat @nat
#為vm2建立snat-dnat規則並應用於edge1 ovn-nbctl -- --id=@nat create nat type="dnat_and_snat" logical_ip=172.16.255.131 \ external_ip=10.127.0.251 -- add logical_router edge1 nat @nat |
從 ubuntu1 ping snat-dnat 的外部IP:
root@ubuntu1:~# ping 10.127.0.250 PING 10.127.0.250 (10.127.0.250) 56(84) bytes of data. 64 bytes from 10.127.0.250: icmp_seq=1 ttl=62 time=2.57 ms 64 bytes from 10.127.0.250: icmp_seq=2 ttl=62 time=1.23 ms 64 bytes from 10.127.0.250: icmp_seq=3 ttl=62 time=0.388 ms
root@ubuntu1:~# ping 10.127.0.251 PING 10.127.0.251 (10.127.0.251) 56(84) bytes of data. 64 bytes from 10.127.0.251: icmp_seq=1 ttl=62 time=3.15 ms 64 bytes from 10.127.0.251: icmp_seq=2 ttl=62 time=1.52 ms 64 bytes from 10.127.0.251: icmp_seq=3 ttl=62 time=0.475 ms |
第二步:檢查虛擬機器可以使用正確的IP連線到外部世界
root@ubuntu2:~# ip netns exec vm1 ping 10.127.0.130 PING 10.127.0.130 (10.127.0.130) 56(84) bytes of data. 64 bytes from 10.127.0.130: icmp_seq=1 ttl=62 time=3.05 ms
root@ubuntu3:~# ip netns exec vm2 ping 10.127.0.130 PING 10.127.0.130 (10.127.0.130) 56(84) bytes of data. 64 bytes from 10.127.0.130: icmp_seq=1 ttl=62 time=1.87 ms
root@ubuntu1:~# tcpdump -i br-eth1 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on br-eth1, link-type EN10MB (Ethernet), capture size 262144bytes 17:51:01.055258 IP 10.127.0.250 > 10.127.0.130: ICMP echo request, id4565, seq 12, length 64 17:51:01.055320 IP 10.127.0.130 > 10.127.0.250: ICMP echo reply, id 4565, seq 12, length 64
17:51:56.378089 IP 10.127.0.251 > 10.127.0.130: ICMP echo request, id4301, seq 6, length 64 17:51:56.378160 IP 10.127.0.130 > 10.127.0.251: ICMP echo reply, id 4301, seq 6, length 64 |
現在,我們可以從ubuntu1上的tcpdump的輸出結果看到虛擬機器正在使用正確的NAT地址。
第三步:應用一些安全策略。 首先,我們將完全鎖定DMZ。
#新增預設ACL策略(對不匹配任何轉發規則的流量進行丟棄) ovn-nbctl acl-add dmz to-lport 900 "outport == \"dmz-vm1\" && ip" drop ovn-nbctl acl-add dmz to-lport 900 "outport == \"dmz-vm2\" && ip" drop |
在ubuntu1上驗證網路已經不通:
root@ubuntu1:~# ping 10.127.0.250 PING 10.127.0.250 (10.127.0.250) 56(84) bytes of data. ^C --- 10.127.0.250 ping statistics --- 2 packets transmitted, 0 received, 100% packet loss, time 1007ms
root@ubuntu1:~# ping 10.127.0.251 PING 10.127.0.251 (10.127.0.251) 56(84) bytes of data. ^C --- 10.127.0.251 ping statistics --- 2 packets transmitted, 0 received, 100% packet loss, time 1007ms |
DMZ伺服器現在無法從外部訪問,但這時候從DMZ內部ping 外界網路也不通了:
root@ubuntu2:~# ip netns exec vm1 ping 10.127.0.130 PING 10.127.0.130 (10.127.0.130) 56(84) bytes of data. ^C --- 10.127.0.130 ping statistics --- 2 packets transmitted, 0 received, 100% packet loss, time 1008ms
root@ubuntu3:~# ip netns exec vm2 ping 10.127.0.130 PING 10.127.0.130 (10.127.0.130) 56(84) bytes of data. ^C --- 10.127.0.130 ping statistics --- 2 packets transmitted, 0 received, 100% packet loss, time 1008ms |
我們來解決這個問題:
#允許所有ip流量和相關連接回包通過 ovn-nbctl acl-add dmz from-lport 1000 "inport == \"dmz-vm1\" && ip" allow-related ovn-nbctl acl-add dmz from-lport 1000 "inport == \"dmz-vm2\" && ip" allow-related |
驗證:
root@ubuntu2:~# ip netns exec vm1 ping 10.127.0.130 PING 10.127.0.130 (10.127.0.130) 56(84) bytes of data. 64 bytes from 10.127.0.130: icmp_seq=1 ttl=62 time=4.16 ms 64 bytes from 10.127.0.130: icmp_seq=2 ttl=62 time=3.07 ms
root@ubuntu3:~# ip netns exec vm2 ping 10.127.0.130 PING 10.127.0.130 (10.127.0.130) 56(84) bytes of data. 64 bytes from 10.127.0.130: icmp_seq=1 ttl=62 time=3.59 ms 64 bytes from 10.127.0.130: icmp_seq=2 ttl=62 time=2.30 ms |
允許到DMZ伺服器的入站HTTPS (tcp 443埠)流量:
#允許到DMZ伺服器的入站HTTPS (tcp 443埠)和回包流量: ovn-nbctl acl-add dmz to-lport 1000 "outport == \"dmz-vm1\" && tcp.dst == 443" allow-related ovn-nbctl acl-add dmz to-lport 1000 "outport == \"dmz-vm2\" && tcp.dst == 443" allow-related |
驗證: 首先需要監聽tcp 443 埠。我喜歡使用ncat。 它實際上是nmap軟體包的一部分。所以第一步是在所有3個Ubuntu主機上安裝它:
apt-get -y install nmap |
現在我們可以在443埠執行一個監聽程序。程序將在連線結束時終止,但是你可以使用-k引數來持續執行它。
在ubuntu2:
ip netns exec vm1 ncat -l -p 443 |
在 ubuntu3:
ip netns exec vm2 ncat -l -p 443 |
並在ubuntu1的檢查連通性。 如果連線成功,它將保持開啟狀態,直到您終止它。 如果沒有,那麼它應該在1秒後超時
root@ubuntu1:~# ncat -w 1 10.127.0.250 443 ^C
root@ubuntu1:~# ncat -w 1 10.127.0.251 443 ^C |
策略生效了! 我們加固了“inside”伺服器的安全性。
實驗二
接下來的操作會使它更加安全:阻止所有出站訪問,並且只允許從dmz訪問tcp 3306。 我們將配置一個地址集來表示DMZ內的一些地址。 注意在“acl-add”命令中使用了單引號。 我們實際上是通過地址集名稱來引用它,字首是一個'$'字元。 因為我們不希望bash將其解釋為一個變數,所以我們使用了單引號。
# 為dmz伺服器建立一個地址集。 使用/31掩碼 ovn-nbctl create Address_Set name=dmz addresses=\"172.16.255.130/31\"
# 允許源IP為dmz地址集內的IP地址,且目標埠為3306 ovn-nbctl acl-add inside to-lport 1000 'outport == "inside-vm3" && ip4.src == $dmz && tcp.dst == 3306' allow-related ovn-nbctl acl-add inside to-lport 1000 'outport == "inside-vm4" && ip4.src == $dmz && tcp.dst == 3306' allow-related
# 新增預設ACL策略(對不匹配任何轉發規則的流量進行丟棄) ovn-nbctl acl-add inside to-lport 900 "outport == \"inside-vm3\" && ip" drop ovn-nbctl acl-add inside to-lport 900 "outport == \"inside-vm4\" && ip" drop |
我們將再次使用ncat監聽我們的VM,但這次是在vm3 /vm4上進行
在 ubuntu2:
ip netns exec vm3 ncat -l -p 3306 |
在 ubuntu3:
ip netns exec vm4 ncat -l -p 3306 |
驗證 dmz到 inside的網路連通性:
root@ubuntu2:~# ip netns exec vm1 ncat -w 1 172.16.255.195 3306 ^C
root@ubuntu3:~# ip netns exec vm2 ncat -w 1 172.16.255.194 3306 ^C |
貌似生效了。 最後再來確認vm3 /vm4彼此隔離的:
root@ubuntu2:~# ip netns exec vm3 ncat -w 1 172.16.255.195 3306 Ncat: Connection timed out.
root@ubuntu3:~# ip netns exec vm4 ncat -w 1 172.16.255.194 3306 Ncat: Connection timed out. |
vm3 /vm4確認是彼此隔離的,上面的ACL策略的確生效了。實驗成功!
清理環境
刪除ACL和地址集。
在 ubuntu1:
ovn-nbctl acl-del dmz ovn-nbctl acl-del inside ovn-nbctl destroy Address_Set dmz |
結語
傳統防火牆是在路徑中的第三層裝置上實現的,例如路由器或專用防火牆裝置。而在OVN在邏輯交換機上應用策略可能看起來就很奇怪了。然而這種方法的優點在於,它通過在邏輯埠級別實施安全性,建立了一種以東西(east-west )方式使工作負載更安全的簡單方法。這種安全方法已經被稱為“微分段”(又譯作“微分割”),因為它允許管理員以非常精細的方式應用安全策略。傳統網路設計(認為web-tier / db-tier)中存在的大多數層級是由於網路安全性以前只能在位於層之間的某個中央裝置上完成。微分段方法的本質是:允許將網路設計扁平化到靠一個邏輯交換機來實現一切:安全策略和網路佈局。
在下一篇文章中,我將介紹用於容器網路的OVN模型。
原文:https://blog.csdn.net/zhengmx100/article/details/75431393?utm_source=blogxgwz1