使用 Calico 網路原則來控制「標準」叢集上的資料流量
瞭解如何使用 Calico 政策,以允許來自特定IP位址及發送至特定IP位址的網路流量。
請注意,下列步驟適用於具有 Classic LoadBalancers 的 Classic 群集。
依預設,Kubernetes NodePort、LoadBalancer 及 Ingress 服務可讓您的應用程式能夠在所有公用及專用叢集網路介面上使用。 allow-node-port-dnat 預設 Calico 原則允許從 NodePort、網路負載平衡器 (NLB) 及 Ingress 應用程式負載平衡器 (ALB) 服務送入那些服務所公開之應用程式 Pod 的資料流量。 Kubernetes 會使用目的地網址轉譯 (DNAT) 將服務要求轉遞至正確的
Pod。
不過,基於安全理由,您可能需要只允許從特定來源 IP 位址到網路服務的資料流量。 您可以使用 Calico 的「Pre-DNAT」政策,來允許或封鎖來自或發往特定 IP 位址的流量。 DNAT 前原則可防止指定的資料流量到達您的應用程式,因為在 Kubernetes 使用一般 DNAT 將資料流量轉遞至 Pod 之前,已套用這些原則。 建立「Calico」的 Pre-DNAT 政策時,您需選擇要允許還是封鎖來源 IP 位址。 對於大部分實務範例,容許特定資料流量會提供最安全的配置,因為除了來自已知允許來源 IP 位址的資料流量之外,所有資料流量都會被封鎖。拒絕特定資料流量通常只有在防止來自一小組 IP 位址的攻擊之類的情況下才有用。
在此情境中,您扮演的是公關公司的網路管理者角色,且您會發現一些不尋常的資料流量正在攻擊您的應用程式。 本教學中的課程將引導您逐步建立一個範例 Web 伺服器應用程式,透過網路負載平衡 (NLB) 服務將該應用程式對外公開,並利用「允許清單」和「阻擋清單」Calico 政策,保護該應用程式免受不必要的異常流量侵擾。
目標
- 學習藉由建立高階 DNAT 前原則,以封鎖送入所有節點埠的所有資料流量。
- 學習如何透過建立一個低位元 Pre-DNAT 政策,允許特定的來源 IP 位址存取 NLB 的公開 IP 位址和埠號。 低階原則會置換高階原則。
- 學習透過建立低位元 Pre-DNAT 政策,來封鎖特定來源 IP 位址存取 NLB 的公網 IP 和埠號。
適用對象
本指導教學的適用對象是想要管理送至應用程式之網路資料流量的軟體開發人員及網路管理者。
必要條件
- 建立具有至少 3 個工作者節點的標準叢集。 單一工作者節點叢集沒有完成本指導教學所需的資源。 本指導教學無法使用於 VPC 叢集。
- 請登入您的帳戶。 適用的話,請將適當的資源群組設為目標。 設定叢集的環境定義。
- 安裝並配置 Calico CLI。
- 確保您具有用於 IBM Cloud 的下列 IBM Cloud Kubernetes Service IAM 存取原則:
部署應用程式並透過 NLB 使其對外開放
第一課告訴您如何從多個 IP 位址及埠公開您的應用程式,以及公用資料流量是從哪裡進入您的叢集。
開始部署要在整個指導教學中使用的 Web 伺服器應用程式範例。 echoserver Web 伺服器顯示有關從用戶端與叢集建立的連線的資料,並且您可以測試對公關公司叢集的存取。 然後,藉由建立網路負載平衡器 (NLB) 1.0 服務來公開應用程式。 NLB 1.0 服務可讓您的應用程式透過 NLB 服務 IP 位址及工作者節點的節點埠來使用。
在第 1 課結束時,Web 伺服器應用程式透過公共節點連接埠和公共 NLB 暴露在網路上。
-
部署 Web 伺服器應用程式範例。 與 Web 伺服器應用程式建立連線時,應用程式會以其在連線中收到的 HTTP 標頭回應。
kubectl apply -f https://raw.githubusercontent.com/IBM-Cloud/kube-samples/master/deploy-apps-clusters/webserver.yaml -
驗證 Web 伺服器應用程式 Pod 的 STATUS 為
Running。kubectl get pods -o wide輸出範例
NAME READY STATUS RESTARTS AGE IP NODE webserver-855556f688-6dbsn 1/1 Running 0 1m 172.30.xxx.xxx 10.176.48.78 webserver-855556f688-76rkp 1/1 Running 0 1m 172.30.xxx.xxx 10.176.48.78 webserver-855556f688-xd849 1/1 Running 0 1m 172.30.xxx.xxx 10.176.48.78 -
若要在公用網際網路上公開應用程式,請在文字編輯器中建立一個稱為
webserver-lb.yaml的 NLB 1.0 服務配置檔。apiVersion: v1 kind: Service metadata: labels: run: webserver name: webserver-lb spec: type: LoadBalancer selector: run: webserver ports: - name: webserver-port protocol: TCP port: 8080 targetPort: 8080 # Optional. By default, the `targetPort` is set to match the `port` value unless specified otherwise. -
部署 NLB。
kubectl apply -f filepath/webserver-lb.yaml -
驗證是否可以從您的電腦公開存取由 NLB 公開的應用程式。
- 取得 NLB 的公用 EXTERNAL-IP 位址。
kubectl get svc -o wide ``` 輸出範例 ```sh {: screen} NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR webserver-lb 172.21.xxx.xxx 169.xx.xxx.xxx 80:31024/TCP 2m run=webserver ``` 2. 建立提要文字檔,並將 NLB IP 複製到文字檔。 提要將協助您在稍後的課程中更快速地使用這些值。 3. 驗證您可公開存取 NLB 的外部 IP。 ```sh {: pre} curl --connect-timeout 10 <loadbalancer_IP>:80 ``` 下列輸出範例確認 NLB 會在 `169.1.1.1` 公用 NLB IP 位址上公開您的應用程式。 `webserver-855556f688-76rkp` 應用程式 pod 接收到了此 curl 請求。 ```sh {: screen} Hostname: webserver-855556f688-76rkp Pod Information: -no pod information available- Server values: server_version=nginx: 1.13.3 - lua: 10008 Request Information: client_address=10.176.XX.XX method=GET real path=/ query= request_version=1.1 request_scheme=http request_uri=http://169.1.1.1:8080/ Request Headers: accept=*/* host=169.1.1.1 user-agent=curl/7.54.0 Request Body: -no body in request- ``` -
驗證是否可以從您的電腦公開存取由節點埠公開的應用程式。 NLB 服務可讓您的應用程式透過 NLB 服務 IP 位址及工作者節點的節點埠來使用。
- 取得 NLB 指派給工作者節點的節點埠。 節點埠位於 30000 到 32767 範圍內。
kubectl get svc -o wide ``` 在下列輸出範例中,節點埠為 `31024`: ```sh {: screen} NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR webserver-lb 172.21.xxx.xxx 169.xx.xxx.xxx 80:31024/TCP 2m run=webserver ``` 2. 對於經典叢集,請取得工作節點的**公共 IP** 位址。 若為 VPC 叢集,請改為取得 **專用 IP** 位址。 ```sh {: pre} ibmcloud ks worker ls --cluster <cluster_name> ``` 輸出範例 ```sh {: screen} ID Public IP Private IP Machine Type State Status Zone Version kube-dal10-cr18e61e63c6e94b658596ca93d087eed9-w1 169.xx.xxx.xxx 10.176.48.67 u3c.2x4.encrypted normal Ready dal10 1.36_1513* kube-dal10-cr18e61e63c6e94b658596ca93d087eed9-w2 169.xx.xxx.xxx 10.176.48.79 u3c.2x4.encrypted normal Ready dal10 1.36_1513* kube-dal10-cr18e61e63c6e94b658596ca93d087eed9-w3 169.xx.xxx.xxx 10.176.48.78 u3c.2x4.encrypted normal Ready dal10 1.36_1513* ``` 3. 將工作者節點及節點埠的公用 IP 複製到您的文字提要,以在稍後課程中使用。 4. 驗證您可以透過節點埠存取工作者節點的公用 IP 位址。 **附註**: 因為 VPC 叢集裡的工作者節點沒有公用 IP 位址,所以僅當您連接至專用 VPC 網路 (例如透過 VPN 連線) 時,才能透過 NodePort 存取應用程式。 然後,您可以使用工作節點的私有IP位址和NodePort:`<worker_private_IP>:<NodePort>`。 ```sh {: pre} curl --connect-timeout 10 <worker_IP>:<NodePort> ``` 下列輸出範例確認,是透過工作者節點的專用 IP 位址 `10.1.1.1` 及 `31024` 節點埠,對您的應用程式提出要求。 `webserver-855556f688-xd849` 應用程式 Pod 收到 Curl 要求: ```sh {: screen} Hostname: webserver-855556f688-xd849 Pod Information: -no pod information available- Server values: server_version=nginx: 1.13.3 - lua: 10008 Request Information: client_address=1.1.1.1 method=GET real path=/ query= request_version=1.1 request_scheme=http request_uri=http://10.1.1.1:8080/ Request Headers: accept=*/* host=10.1.1.1:31024 user-agent=curl/7.60.0 Request Body: -no body in request- ```
此時,會從多個 IP 位址及埠公開您的應用程式。 其中大部分 IP 都在叢集的內部,而且只能透過專用網路存取。 只有公用節點埠及公用 NLB 埠,才會在公用網際網路公開。
接下來,您可以開始建立並套用 Calico 原則來封鎖公用資料流量。
封鎖所有傳入至所有節點埠的流量
若要保護公關公司的叢集,您必須封鎖對公開您應用程式之 NLB 服務及節點埠兩者的公開存取。 首先,封鎖對節點埠的存取。
在第 2 課結束時,Web 伺服器應用程式僅透過公共 NLB 暴露在網路上。
-
在文字編輯器中,建立一個稱為
deny-nodeports.yaml的高階 DNAT 前原則,來拒絕將 TCP 及 UDP 資料流量從任何來源 IP 送入所有節點埠。apiVersion: projectcalico.org/v3 kind: GlobalNetworkPolicy metadata: name: deny-nodeports spec: applyOnForward: true preDNAT: true ingress: - action: Deny destination: ports: - 30000:32767 protocol: TCP source: {} - action: Deny destination: ports: - 30000:32767 protocol: UDP source: {} selector: ibm.role=='worker_public' order: 1100 types: - Ingress -
套用原則。
- Linux:
calicoctl apply -f filepath/deny-nodeports.yaml ``` - Windows 及 OS X: ```sh {: pre} calicoctl apply -f filepath/deny-nodeports.yaml --config=filepath/calicoctl.cfg ``` 輸出範例 ```sh {: screen} Successfully applied 1 'GlobalNetworkPolicy' resource(s) -
使用來自提要的值,驗證您無法公開存取工作者節點公用 IP 位址及節點埠。
curl --connect-timeout 10 <worker_IP>:<NodePort>連線逾時,因為您建立的 Calico 原則封鎖資料流量送入節點埠。
curl: (28) Connection timed out after 10016 milliseconds -
改變externalTrafficPolicy的LoadBalancer您在上一課中創建的
Cluster到Local。Local確保當您捲曲外部 IP 時保留系統的來源 IPLoadBalancer在下一步中。kubectl patch svc webserver-lb -p '{"spec":{"externalTrafficPolicy":"Local"}}' -
使用來自提要的值,驗證您仍然可公開存取 NLB 外部 IP 位址。
curl --connect-timeout 10 <loadbalancer_IP>:80輸出範例
Hostname: webserver-855556f688-76rkp Pod Information: -no pod information available- Server values: server_version=nginx: 1.13.3 - lua: 10008 Request Information: client_address=1.1.1.1 method=GET real path=/ query= request_version=1.1 request_scheme=http request_uri=http://<loadbalancer_IP>:8080/ Request Headers: accept=*/* host=<loadbalancer_IP> user-agent=curl/7.54.0 Request Body: -no body in request-例如,在輸出的
Request Information區段中,來源 IP 位址為client_address=1.1.1.1。 來源 IP 位址是您要用來執行 Curl 之系統的公用 IP。 否則,如果您是透過 Proxy 或 VPN 連接至網際網路,則 Proxy 或 VPN 可能會遮蔽系統的實際 IP 位址。 在任一情況下,NLB 會將您系統的來源 IP 位址看成用戶端 IP 位址。 -
將您系統的來源 IP 位址(前一個步驟輸出中的
client_address=1.1.1.1)複製到您的提要,以在稍後課桯中使用。
太好了! 此時,只會從公用 NLB 埠,在公用網際網路上公開您的應用程式。 送入公用節點埠的資料流量會遭到封鎖。 已局部鎖定叢集以阻止不想要的資料流量。
接著,您可以建立並套用「Calico」政策,僅允許來自特定來源 IP 的流量。
允許來自特定 IP 的傳入流量進入 NLB
您現在決定完全封鎖通往公關公司叢集的流量,並僅允許您自己電腦的 IP 位址存取,藉此進行測試。
首先,除了節點埠之外,您還必須封鎖送入公開應用程式之 NLB 的所有資料流量。 接著,您可以建立一項允許系統 IP 位址的政策。 在第 3 課結束時,所有傳往公共節點埠和 NLB 的流量均被封鎖,僅允許來自您已允許的系統 IP 的流量。
-
在文字編輯器中,建立一個稱為
deny-lb-port-80.yaml的高階 DNAT 前原則,來拒絕從任何來源 IP 送入 NLB IP 位址及埠的所有 TCP 及 UDP 資料流量。 請將<loadbalancer_IP>替換為您參考手冊中列出的 NLB 公網 IP 位址。apiVersion: projectcalico.org/v3 kind: GlobalNetworkPolicy metadata: name: deny-lb-port-80 spec: applyOnForward: true preDNAT: true ingress: - action: Deny destination: nets: - <loadbalancer_IP>/32 ports: - 80 protocol: TCP source: {} - action: Deny destination: nets: - <loadbalancer_IP>/32 ports: - 80 protocol: UDP source: {} selector: ibm.role=='worker_public' order: 800 types: - Ingress -
套用原則。
- Linux:
calicoctl apply -f filepath/deny-lb-port-80.yaml ``` - Windows 及 OS X: ```sh {: pre} calicoctl apply -f filepath/deny-lb-port-80.yaml --config=filepath/calicoctl.cfg ``` -
使用來自提要的值,驗證您現在無法存取公用 NLB IP 位址。 連線逾時,因為您建立的 Calico 原則封鎖送入 NLB 的資料流量。
curl --connect-timeout 10 <loadbalancer_IP>:80 -
在文字編輯器中,建立一個名為「
allowlist.yaml」的低優先級 Pre-DNAT 政策,以允許來自您系統 IP 至 NLB IP 位址及埠的流量。 請根據您的參考表中的數值,將<loadbalancer_IP>替換為 NLB 的公開 IP 位址,並將<client_address>替換為您系統的來源 IP 位址。 如果記不住系統 IP,可以執行curl ifconfig.co。apiVersion: projectcalico.org/v3 kind: GlobalNetworkPolicy metadata: name: allowlist spec: applyOnForward: true preDNAT: true ingress: - action: Allow destination: nets: - <loadbalancer_IP>/32 ports: - 80 protocol: TCP source: nets: - <client_address>/32 selector: ibm.role=='worker_public' order: 500 types: - Ingress -
套用原則。
- Linux:
calicoctl apply -f filepath/allowlist.yaml ``` - Windows 及 OS X: ```sh {: pre} calicoctl apply -f filepath/allowlist.yaml --config=filepath/calicoctl.cfg ``` 您的系統 IP 位址現已獲准存取。 -
使用來自提要的值,驗證您現在可以存取公用 NLB IP 位址。
curl --connect-timeout 10 <loadbalancer_IP>:80 -
如果您可以存取另一個具有不同 IP 位址的系統,請嘗試從該系統存取 NLB。
curl --connect-timeout 10 <loadbalancer_IP>:80由於該系統的 IP 位址未獲准,因此連線超時。
此時,所有送入公用節點埠及 NLB 的資料流量都會遭到封鎖。 僅允許來自您允許的系統 IP 的流量。
拒絕從特定 IP 送入 NLB 的資料流量
在上節課中,您封鎖了所有流量,並僅允許少數幾個 IP 位址存取。 當您想要限制只存取少數受管理的來源 IP 位址時,該情境適用於測試目的。 不過,公關公司具有需要大眾可以廣泛使用的應用程式。 您需要確定允許所有資料流量,但您從少數 IP 位址看到的不尋常資料流量除外。 在這種情況下,阻擋清單非常有用,因為它能協助您防止來自一小群 IP 位址的攻擊。
在本課程中,封鎖來自您自己系統的來源 IP 位址的資料流量。 在第 4 課結束時,將封鎖流至公用節點埠的所有資料流量,但允許流至公用 NLB 的所有資料流量。 僅會封鎖來自您特定系統 IP 至 NLB 的流量。
-
請整理上一堂課所建立的允許清單政策。
- Linux:
calicoctl delete GlobalNetworkPolicy deny-lb-port-80 ``` ```sh {: pre} calicoctl delete GlobalNetworkPolicy allowlist ``` - Windows 及 OS X: ```sh {: pre} calicoctl delete GlobalNetworkPolicy deny-lb-port-80 --config=filepath/calicoctl.cfg ``` ```sh {: pre} calicoctl delete GlobalNetworkPolicy allowlist --config=filepath/calicoctl.cfg ``` 現在,再次允許從任何來源 IP 送入 NLB IP 位址及埠的所有 TCP 及 UDP 資料流量。 -
若要封鎖所有從您系統的來源 IP 位址發送至 NLB IP 位址及埠號的 TCP 與 UDP 傳入流量,請在文字編輯器中建立一個名為「
blocklist.yaml」的低階預先 DNAT 政策。 請根據您的參考表中的數值,將<loadbalancer_IP>替換為 NLB 的公開 IP 位址,並將<client_address>替換為您系統的來源 IP 位址。apiVersion: projectcalico.org/v3 kind: GlobalNetworkPolicy metadata: name: blocklist spec: applyOnForward: true preDNAT: true ingress: - action: Deny destination: nets: - <loadbalancer_IP>/32 ports: - 80 protocol: TCP source: nets: - <client_address>/32 - action: Deny destination: nets: - <loadbalancer_IP>/32 ports: - 80 protocol: UDP source: nets: - <client_address>/32 selector: ibm.role=='worker_public' order: 500 types: - Ingress -
套用原則。
- Linux:
calicoctl apply -f filepath/blocklist.yaml ``` - Windows 及 OS X: ```sh {: pre} calicoctl apply -f filepath/blocklist.yaml --config=filepath/calicoctl.cfg ``` 您的系統 IP 位址現已被封鎖。 -
請使用您的參考表中的數值,透過您的系統確認您無法存取 NLB IP,因為您的系統 IP 已被封鎖。
curl --connect-timeout 10 <loadbalancer_IP>:80此時,會封鎖所有送入公用節點埠的資料流量,而且允許所有送入公用 NLB 的資料流量。 僅會封鎖來自您特定系統 IP 至 NLB 的流量。
做得好! 您已成功透過使用 Calico 的「Pre-DNAT」政策來封鎖來源 IP 位址,從而有效管控流入您應用程式的流量。
記載從特定 IP 到 NLB 的已封鎖資料流量
在上節課程中,您已封鎖從系統 IP 至 NLB 的流量。 在本課程中,您可以學習如何記載拒絕的資料流量要求。
在此範例情境中,您任職的公關公司希望您針對任何持續被網路政策之一拒絕的異常流量,建立日誌追蹤路徑。 為了監控潛在的安全威脅,您應設定日誌記錄功能,以記錄每次阻擋清單政策拒絕針對 NLB IP 的操作嘗試時的情況。
-
建立名為
log-denied-packets的 Calico NetworkPolicy。 此日誌政策使用與「blocklist」政策相同的选择器,該選擇器會將此政策新增至「Calico」Iptables 規則鏈中。 透過使用較低的序號(例如300),您可以確保此規則會在「封鎖清單」政策之前,被加入到 Iptables 規則鏈中。 來自您 IP 的封包會在嘗試與「blocklist」政策規則進行比對並遭拒絕之前,先由本政策進行記錄。apiVersion: projectcalico.org/v3 kind: GlobalNetworkPolicy metadata: name: log-denied-packets spec: applyOnForward: true preDNAT: true ingress: - action: Log destination: nets: - <loadbalancer_IP>/32 ports: - 80 protocol: TCP source: nets: - <client_address>/32 - action: Log destination: nets: - <loadbalancer_IP>/32 ports: - 80 protocol: UDP source: nets: - <client_address>/32 selector: ibm.role=='worker_public' order: 300 types: - Ingress -
套用原則。
- Linux:
calicoctl apply -f /log-denied-packets.yaml ``` - Windows 及 OS X: ```sh calicoctl apply -f /log-denied-packets.yaml --config=<filepath>/calicoctl.cfg ``` -
將要求從系統 IP 傳送至 NLB IP,以產生日誌項目。 在拒絕這些要求封包之前,會先行記載。
curl --connect-timeout 10 <loadbalancer_IP>:80 -
檢查寫入
/var/log/syslog路徑的日誌項目。 日誌項目會與下列內容類似。Sep 5 14:34:40 <worker_hostname> kernel: [158271.044316] calico-packet: IN=eth1 OUT= MAC=08:00:27:d5:4e:57:0a:00:27:00:00:00:08:00 SRC=192.XXX.XX.X DST=192.XXX.XX.XX LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=52866 DF PROTO=TCP SPT=42962 DPT=22 WINDOW=29200 RES=0x00 SYN URGP=0
太好了! 您設定了記錄功能,以便更輕鬆地監控遭阻擋的流量。
若要清理阻擋清單和日誌政策:
- 整理黑名單政策。
- Linux:
calicoctl delete GlobalNetworkPolicy blocklist ``` - Windows 及 OS X: ```sh {: pre} calicoctl delete GlobalNetworkPolicy blocklist --config=filepath/calicoctl.cfg ``` - 清除日誌原則。
- Linux:
calicoctl delete GlobalNetworkPolicy log-denied-packets ``` - Windows 及 OS X: ```sh {: pre} calicoctl delete GlobalNetworkPolicy log-denied-packets --config=filepath/calicoctl.cfg ```
下一步為何?
- 深入閱讀使用網路原則控制資料流量。
- 如需更多範例 Calico 網路原則,可控制進出叢集的資料流量,您可以查看 Calico 指導教學。