[cilium] Host 방화벽 설정해보기

cilium을 사용하면 HostFirewall도 설정이 가능합니다. 이번 글에서는 Hostfirewall을 테스트해보도록 하겠습니다. 

 

테스트 환경 구성하기

cilium 설치하기

가장 기본적으로 구성한다면 아래와 같이 구성할 수 있습니다. devices는 cilium이 구성될 인터페이스를 지정하면 됩니다. 지정하지 않을 경우 자동으로 선택되게 됩니다. 

helm install cilium cilium/cilium --version 1.18.1 \
  --namespace kube-system \
  --set hostFirewall.enabled=true \
  --set devices='{ethX,ethY}'

 

자동으로 선택되게 하였을 경우 어떤 인터페이스가 선택되었는지 확인하고자 한다면 다음의 명령어로 확인이 가능합니다. 

kubectl exec -n kube-system ds/cilium -- cilium-dbg status | grep 'Host firewall'

 

이제 Cilium이 관리하는 노드들은 네트워크 정책을 적용할 준비가 되었습니다.

 

노드에 라벨 부착

특정 노드에서만 동작하는 규칙을 적용해보기 위해 라벨도 적용해보겠습니다. 

kubectl label node kind-worker node-access=ssh

 

 

호스트 엔드포인트에 정책 감사 모드(Publicy Audit Mode) 활성화

호스트 정책은 노드에서 발생하는 다양한 연결에 대해 접근 제어를 시행합니다.

그러다보니 잘못된 설정으로 인해 클러스터에 필요한 연결마저 끊어질 수 있습니다. 이를 막기 위해 감사모드를 사용해서 영향도를 검증하도록 합니다. 감사모드를 사용중에는 네트워크 정책이 실제로 적용되지는 않기 때문에 운영환경에서는 사용하는 것을 권장하지 않는다고 합니다. 

 

다음 명령으로 특정 노드의 호스트 엔드포인트에 대해 정책 감사 모드를 활성화하고 상태를 확인합니다.

먼저 활성화할 호스트의 아이디를 확인합니다. 활성화할 호스트의 cilium-agent에서 endpoint list를 확인했을 때 identity가 1번인 엔드포인트가 host의 정보입니다. 그러므로 확인하고자 하는 노드에 떠있는 cilium-agent 파드의 이름을 확인합니다. 

kubectl get pods -n kube-system --field-selector spec.nodeName=kind-worker

 

이제 해당 cilium-agent에 들어가서 endpoint list 값을 확인해봅니다. 위에서 설정했던 노드의 라벨도 잘 보이는 것을 알 수 있습니다. 그리고 이 Host의 아이디가 2488이라는 것도 확인이 됩니다. 

kubectl exec -it -n kube-system cilium-qlfpn -- cilium endpoint list

 

이제 이 노드에 감사모드가 활성화 되어있는지 확인해보겠습니다. 

kubectl exec -it -n kube-system cilium-qlfpn --  cilium-dbg endpoint config 2488 | grep PolicyAuditMode

 

활성화가 되어있지 않은 것을 확인했으니 이젠 아래의 명령어로 감사모드를 활성화 합니다. 

kubectl exec -it -n kube-system cilium-qlfpn --  cilium-dbg endpoint config 2488 PolicyAuditMode=Enabled

 

다시 확인해보면 활성화가 되어있는 것을 알 수 있습니다. 

 

호스트 네트워크 정책 적용

호스트 정책은 노드 셀렉터(Node Selector) 로 노드 라벨을 매칭하여 정책이 적용될 노드를 확인합니다. 이 정책들은 호스트 네임스페이스(HostNetwork 파드 포함)에만 적용됩니다. 그리고 HostNetwork 파드가 아닌 일반 파드 간 통신이나 파드와 클러스터 외부 간 통신에는 적용되지 않습니다(단, 호스트 네트워킹 파드는 예외적으로 적용).

 

지금 부터 테스트해볼 설정은 클러스터 외부에서 들어오는 통신 중 TCP/22(SSH)와 ICMP 에코 요청(ping)만 허용하는 설정입니다.

그 중에서 node-access=ssh 라벨이 있는 모든 노드에 적용되며 반대로 클러스터에서 호스트로 나가는 통신은 모두 허용합니다.

cat << EOF | kubectl apply -f -
apiVersion: "cilium.io/v2"
kind: CiliumClusterwideNetworkPolicy
metadata:
  name: "demo-host-policy"
spec:
  description: ""
  nodeSelector:
    matchLabels:
      node-access: ssh
  ingress:
  - fromEntities:
    - cluster
  - toPorts:
    - ports:
      - port: "22"
        protocol: TCP
  - icmps:
    - fields:
      - type: EchoRequest
        family: IPv4
EOF

 

호스트는 cilium-dbg endpoint list 명령 출력에서 reserved:host 라벨을 가진 특수 엔드포인트로 표시됩니다. 아래 명령으로 호스트 정책 상태를 점검할 수 있습니다. 인그레스 트래픽은 감사모드이지만 Disabled되어있고 egress는 비활성화 되어있습니다. 

 

환경에 맞게 호스트 정책 조정

위에서 감사모드를 설정했기 때문에 실제로 트래픽이 끊기거나 하지는 않습니다. 하지만 cilium-dbg monitor에 action audit으로 보고됩니다. 이 데이터를 통해 미리 끊길 수 있는 정보를 확인가능합니다.

 

ssh 통신이 되는지 확인하기 위해 sshd 활성화 여부를 확인합니다. 테스트를 위해 2202포트로 오픈을 해두었습니다. 

 

클라이언트로 접근할 컨테이너도 하나 생성합니다.

docker run -d --rm --name client --cap-add=NET_ADMIN --network kind nicolaka/netshoot tail -f /dev/null

 

이제 실제로 노드에 ssh 연결을 시도해보며 로그를 확인해보겠습니다. 

kubectl exec -it -n kube-system cilium-qlfpn --  cilium-dbg monitor -t policy-verdict --related-to 2488

 

2202번 포트로 접근하려고 하는것이 잘 보입니다. 그리고 action audit으로 감시 로그가 남은것을 볼 수 있습니다. 

 

그리고 실제로 접근도 정상적으로 잘 되는 것을 볼 수 있습니다.

 

정책 감사 모드 비활성화

이번엔 감사모드를 꺼서 실제로 통신이 안되는지 확인해보겠습니다. 

kubectl exec -it -n kube-system cilium-qlfpn --  cilium-dbg endpoint config 2488 PolicyAuditMode=Disabled

 

이제 인그레스 호스트 정책이 적용된 것을 확인할 수 있습니다.

 

이제 호스트 정책에서 명시적으로 허용하지 않은 통신은 바로 드롭됩니다.

kubectl exec -it -n kube-system cilium-qlfpn --  cilium-dbg monitor -t policy-verdict --related-to 2488

 

사전에 연결되어있던 통신까지도 끊기는 것을 확인했습니다. 

 

정상 통신 확인

ssh 포트를 22번으로 변경한 뒤 확인해보면 정상적으로 잘 연결되는 것을 확인할 수. 있습니다.