k8s egress network policy not working for dns

Viewed 932

I have added this NetworkPolicy to block all egress but allow DNS.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all-egress
  namespace: {{ $namespace }}
spec:
  podSelector: {}
  egress:
  - to:
    - namespaceSelector:
        matchLabels:
          networking/namespace: kube-system
      podSelector:
        matchLabels:
          k8s-app: kube-dns
    ports:
    - protocol: TCP
      port: 53
    - protocol: UDP
      port: 53
  policyTypes:
  - Egress

However, I'm getting this error with a service that this rule applies to: Could not lookup srv records on _origintunneld._tcp.argotunnel.com: lookup _origintunneld._tcp.argotunnel.com on 10.2.0.10:53: read udp 10.32.1.179:40784->10.2.0.10:53: i/o timeout

This IP (10.2.0.10) belongs to the kube-dns service, which has a pod with the k8s-app=kube-dns label and is in the kube-system namespace with the label networking/namespace=kube-system.

If I remove the pod selector and namespace selector then the egress policy works and I do not get the error

This works but is not secure as it isn't restricted to the kube-dns pod:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all-egress
  namespace: {{ $namespace }}
spec:
  podSelector: {}
  egress:
  - to:
    ports:
    - protocol: TCP
      port: 53
    - protocol: UDP
      port: 53
  policyTypes:
  - Egress

kube-system namespace yaml: kubectl get namespace kube-system -o yaml

apiVersion: v1
kind: Namespace
metadata:
  creationTimestamp: "2020-07-30T22:08:25Z"
  labels:
    networking/namespace: kube-system
  name: kube-system
  resourceVersion: "4084751"
  selfLink: /api/v1/namespaces/kube-system
  uid: b93e68b0-7899-4f39-a3b8-e0e12e4008ee
spec:
  finalizers:
  - kubernetes
status:
  phase: Active
2 Answers

Current policy does not explicitly allow traffic to Kubernetes DNS. As a result, DNS queries from pods in {{ $namespace }} will be dropped, unless allowed by other rules.

Creating an allow egress rule to k8s DNS should resolve your issue.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all-egress
  namespace: {{ $namespace }}
spec:
  podSelector: {}
  policyTypes:
    - Egress
  egress:
    - to:
        - namespaceSelector:
            matchLabels:
              networking/namespace: kube-system
          podSelector:
            matchLabels:
              k8s-app: kube-dns
      ports:
        - port: 53
          protocol: TCP
        - port: 53
          protocol: UDP
    - to:
        - namespaceSelector: {}
          podSelector:
            matchLabels:
              k8s-app: kube-dns
      ports:
        - port: 53
          protocol: UDP

I've encountered the same issue. For me it was because NodeLocal DNSCache was enabled on my cluster.

Related