Calico ネットワーク・ポリシーを使用したクラシック・クラスター上のトラフィックの制御
Calico ポリシーを使用して、特定の IP アドレスとのネットワーク・トラフィックを許可する方法を説明します。
以下のステップは、クラシック・ロード・バランサーを使用するクラシック・クラスターを対象としていることに注意してください。
デフォルトで、Kubernetes の NodePort、LoadBalancer、Ingress の各サービスは、パブリックとプライベートのすべてのクラスター・ネットワーク・インターフェースでアプリを使用可能にします。 デフォルトの allow-node-port-dnat
Calico ポリシーでは、NodePort、ネットワーク・ロード・バランサー (NLB)、Ingress アプリケーション・ロード・バランサー (ALB) の各サービスから、それらのサービスが公開しているアプリ・ポッドへの着信トラフィックが許可されます。
Kubernetes は宛先ネットワーク・アドレス変換 (DNAT) を使用してサービス要求を正しいポッドに転送します。
ただし、セキュリティー上の理由から、特定のソース IP アドレスからのネットワーク・サービスへのトラフィックのみを許可する必要がある場合があります。 Calico 事前DNATポリシー を使用して、特定のIPアドレスからのトラフィックまたは特定のIPアドレスへのトラフィックを許可またはブロックすることができます。 Pre-DNAT ポリシーは、Kubernetes がポッドにトラフィックを転送するために通常の DNAT を使用する前に適用されるため、指定されたトラフィックがアプリに到達することを防止します。 Calico Pre-DNAT ポリシーを作成する場合、ソース IP アドレスを許可またはブロックに入れるかどうかを選択します。 ほとんどのシナリオでは、特定のトラフィックを許可すると、既知の許可されたソース IP アドレスからのトラフィックを除き、すべてのトラフィックがブロックされるため、最もセキュアな構成が得られます。特定のトラフィックを拒否するのは通常、少数の IP アドレスからの攻撃を防ぐなどのシナリオでのみ役立ちます。
このシナリオでは、PR 会社のネットワーク管理者の役割を担って、アプリへの何らかの異常なトラフィックを見つけます。 このチュートリアルのレッスンでは、サンプル Web サーバー・アプリを作成し、ネットワーク・ロード・バランサー (NLB) サービスを使用してアプリを公開し、Calico ポリシーの許可リストとブロックリストの両方を使用して、不要で異常なトラフィックからアプリを保護します。
目標
- 上位の Pre-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 サーバーでは、クライアントからクラスターへの接続に関するデータが表示され、PR 会社のクラスターへのアクセスをテストできます。 次に、ネットワーク・ロード・バランサー (NLB) 1.0 サービスを作成して、アプリを公開します。 NLB 1.0 サービスにより、NLB サービス IP アドレスとワーカー・ノードのノード・ポートの両方でアプリが使用可能になります。
レッスン1の終わりには、パブリックノードポートとパブリックNLBによって、ウェブサーバーアプリがインターネットに公開されます。
-
サンプル Web サーバー・アプリをデプロイします。 接続が Web サーバー・アプリに対して行われると、アプリは接続で受信した HTTP ヘッダーを使用して応答します。
kubectl apply -f https://raw.githubusercontent.com/IBM-Cloud/kube-samples/master/deploy-apps-clusters/webserver.yaml
-
Web サーバー・アプリ・ポッドの 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
出力例
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
-
メモ用のテキスト・ファイルを作成して、NLB IP をそのテキスト・ファイルにコピーします。 このメモは、後のレッスンで値を迅速に取り出すために役立ちます。
-
NLB の外部 IP にパブリック・アクセスできることを確認します。
curl --connect-timeout 10 <loadbalancer_IP>:80
以下の出力例では、NLB によってパブリック NLB IP アドレス
169.1.1.1
でアプリが公開されたことを確認できます。webserver-855556f688-76rkp
アプリ・ポッドが curl 要求を受け取りました。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
です。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
-
クラシック・クラスターの場合は、ワーカー・ノードの「Public IP」のアドレスを取得します。 VPC クラスターの場合は、代わりに「 Private IP」のアドレスを取得します。
ibmcloud ks worker ls --cluster <cluster_name>
出力例
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.32_1513* kube-dal10-cr18e61e63c6e94b658596ca93d087eed9-w2 169.xx.xxx.xxx 10.176.48.79 u3c.2x4.encrypted normal Ready dal10 1.32_1513* kube-dal10-cr18e61e63c6e94b658596ca93d087eed9-w3 169.xx.xxx.xxx 10.176.48.78 u3c.2x4.encrypted normal Ready dal10 1.32_1513*
-
後のレッスンで使用するために、ワーカー・ノードのパブリック IP とノード・ポートをメモのテキストにコピーします。
-
ノード・ポートを使用してワーカー・ノードのパブリック IP アドレスにアクセスできることを確認します。 注: VPC クラスター内のワーカー・ノードはパブリック IP アドレスを持たないため、NodePort を介してアプリにアクセスできるのは、VPN 接続などを介してプライベート VPC ネットワークに接続している場合のみです。 その後で、ワーカー・ノードのプライベート IP アドレスと NodePort (
<worker_private_IP>:<NodePort>
) を使用できます。curl --connect-timeout 10 <worker_IP>:<NodePort>
以下の出力例では、アプリへの要求がワーカー・ノードのプライベート IP アドレス
10.1.1.1
とノード・ポート31024
を介して受信されたことを確認できます。 アプリ・ポッドwebserver-855556f688-xd849
が curl 要求を受信しました。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 ポリシーを作成して適用します。
すべてのノード・ポートへの着信トラフィックをブロックする
PR 会社のクラスターを保護するには、アプリを公開している NLB サービスとノード・ポートの両方へのパブリック・アクセスをブロックする必要があります。 まず、ノード・ポートへのアクセスをブロックします。
レッスン2の最後では、ウェブサーバーアプリはパブリックNLBによってのみインターネットに公開されている。
-
テキスト・エディターで、
deny-nodeports.yaml
という上位の Pre-DNAT ポリシーを作成し、すべてのソース IP からのノード・ポートへの着信 TCP および UDP トラフィックを拒否します。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:
calicoctl apply -f filepath/deny-nodeports.yaml --config=filepath/calicoctl.cfg
出力例
Successfully applied 1 'GlobalNetworkPolicy' resource(s)
-
-
メモの値を使用して、ワーカー・ノードのパブリック IP アドレスおよびノード・ポートにパブリック・アクセスできないことを確認します。
curl --connect-timeout 10 <worker_IP>:<NodePort>
作成した Calico ポリシーによってノード・ポートへのトラフィックがブロックされるため、接続がタイムアウトになります。
curl: (28) Connection timed out after 10016 milliseconds
-
前のレッスンで作成した LoadBalancer の externalTrafficPolicy を
Cluster
からLocal
に変更します。Local
は、次のステップで LoadBalancer の外部 IP に対して curl を実行するときに、システムのソース IP が保持されるようにします。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 です。 それ以外の場合、プロキシーまたは VPN を介してインターネットに接続している場合は、プロキシーまたは VPN がシステムの実際の IP アドレスを不明瞭にしている可能性があります。 いずれの場合も、NLB はシステムのソース IP アドレスをクライアント IP アドレスとして認識します。 -
後のレッスンで使用するために、システムのソース IP アドレス (前のステップの出力では
client_address=1.1.1.1
) をメモにコピーします。
うまくできました。 この時点で、アプリはパブリック NLB ポートからのみパブリック・インターネットに公開されています。 パブリック・ノード・ポートへのトラフィックはブロックされています。 不要なトラフィックからクラスターが部分的にロックされました。
次に、特定のソース IP のみからのトラフィックを許可するための Calico ポリシーを作成して適用します。
特定の IP からの NLB への着信トラフィックを許可する
独自のコンピューター IP アドレスのみを許可することによって、PR 会社のクラスターへのトラフィックを完全にロックして、アクセスをテストします。
最初に、ノード・ポートに加えて、アプリを公開している NLB へのすべての着信トラフィックをブロックする必要があります。 その後、システムの IP アドレスを許可に入れるポリシーを作成できます。 レッスン 3 の終了時には、パブリックのノード・ポートおよび NLB へのすべてのトラフィックがブロックされ、許可したシステム IP からのトラフィックだけが許可されます。
-
テキスト・エディターで、
deny-lb-port-80.yaml
という上位の Pre-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:
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 アドレスに置き換えます。 システム 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:
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 アドレスのみにアクセスを制限するようなテスト目的の場合によく機能します。 ただし、PR 会社のアプリは広く公開される必要のあるものです。 少数の IP アドレスで見られる異常なトラフィックを除き、すべてのトラフィックが許可される必要があります。 拒否リストは、少数の IP アドレスからの攻撃を防ぐのに役立つため、このようなシナリオで有用です。
このレッスンでは、所有するシステムのソース IP アドレスからのトラフィックをブロックします。 レッスン 4 の終了時に、パブリック・ノード・ポートへのすべてのトラフィックがブロックされ、パブリック NLB へのすべてのトラフィックが許可されます。 特定のシステムの IP から NLB へのトラフィックのみがブロックされます。
-
前のレッスンで作成した許可リスト・ポリシーをクリーンアップします。
- Linux:
calicoctl delete GlobalNetworkPolicy deny-lb-port-80
calicoctl delete GlobalNetworkPolicy allowlist
- Windows および OS X:
calicoctl delete GlobalNetworkPolicy deny-lb-port-80 --config=filepath/calicoctl.cfg
calicoctl delete GlobalNetworkPolicy allowlist --config=filepath/calicoctl.cfg
すべてのソース IP からの NLB IP アドレスとポートへの着信 TCP および UDP トラフィックが再度許可されます。
- Linux:
-
システムのソース IP アドレスから NLB の IP アドレスおよびポートへのすべての着信 TCP および UDP トラフィックを拒否するには、テキスト・エディターで
blocklist.yaml
という下位の pre-DNAT ポリシーを作成します。 メモの値を使用して、<loadbalancer_IP>
を NLB のパブリック IP アドレスに、<client_address>
をシステムのソース IP のパブリック 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:
calicoctl apply -f filepath/blocklist.yaml --config=filepath/calicoctl.cfg
システムの IP アドレスがブロックされました。
-
-
メモの値を使用し、システムの IP がブロックされるため、NLB IP にアクセスできないことをシステムから確認します。
curl --connect-timeout 10 <loadbalancer_IP>:80
この時点で、パブリック・ノード・ポートへのすべてのトラフィックがブロックされ、パブリック NLB へのすべてのトラフィックが許可されます。 特定のシステムの IP から NLB へのトラフィックのみがブロックされます。
おつかれさまでした。 Calico Pre-DNAT ポリシーを使用してソース IP をブロックすることにより、アプリへのトラフィックを正常に制御しました。
特定の IP からの NLB へのブロックされたトラフィックをログに記録する
前のレッスンでは、システム IP から NLB へのトラフィックをブロックしました。 このレッスンでは、拒否されたトラフィック要求をログに記録する方法を学習します。
このシナリオでは、あなたが勤務するPR会社が、ネットワークポリシーの1つで継続的に拒否されている異常なトラフィックについて、ログ記録を設定することを望んでいます。 潜在的なセキュリティー脅威をモニターするには、NLB IP で試行されたアクションがブロックリスト・ポリシーで拒否されるたびに記録するようにロギングをセットアップします。
-
Calico NetworkPolicy
log-denied-packets
を作成します。 このログ・ポリシーでは、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:
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:
calicoctl delete GlobalNetworkPolicy blocklist --config=filepath/calicoctl.cfg
- Linux:
- ログ・ポリシーをクリーンアップします。
- Linux:
calicoctl delete GlobalNetworkPolicy log-denied-packets
- Windows および OS X:
calicoctl delete GlobalNetworkPolicy log-denied-packets --config=filepath/calicoctl.cfg
- Linux:
次のステップ
- ネットワーク・ポリシーによるトラフィックの制御をお読みください。
- クラスターとの間のトラフィックを制御する Calico ネットワーク・ポリシーの例については、 Calico チュートリアルを参照してください。