> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Demo Cilium Network Policy Part 2

> Hands-on guide to Cilium network policies covering L3 L4 and L7 controls, egress and ingress examples, DNS and HTTP filtering, port and CIDR rules, and clusterwide policies

This guide continues the hands-on exploration of Cilium network policies, focusing on Layer 4 (L4) controls and how they combine with Layer 3 (L3) and Layer 7 (L7) capabilities. Examples use egress rules for clarity, but the syntax and behavior are identical for ingress rules where noted.

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/3_oH8WobznU4DXye/images/Prep-Course-Cilium-Certified-Associate-CCA-Certification/Network-Policy/Demo-Cilium-Network-Policy-Part-2/cilium-network-policy-part-2-demo.jpg?fit=max&auto=format&n=3_oH8WobznU4DXye&q=85&s=eca51e05264bdc8b666f0584af39075c" alt="A presentation slide with the word &#x22;Demo&#x22; on the left. On the right is a teal gradient shape reading &#x22;Cilium Network Policy Part 2&#x22; with a small © KodeKloud notice in the corner." width="1920" height="1080" data-path="images/Prep-Course-Cilium-Certified-Associate-CCA-Certification/Network-Policy/Demo-Cilium-Network-Policy-Part-2/cilium-network-policy-part-2-demo.jpg" />
</Frame>

## L4 egress: restrict by CIDR and port(s)

You can restrict egress by IP ranges (CIDRs) and/or by specific ports or port ranges. Use CIDR restrictions when you want to limit destinations by address space; use `toPorts` for port-based filtering regardless of destination.

Example: allow egress to two specific CIDR ranges, and also allow a broad CIDR but exclude a few subnets/addresses.

```yaml theme={null}
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: l3-policy
  namespace: dev
spec:
  endpointSelector:
    matchLabels:
      app: app1
  egress:
    - toCIDR:
        - 172.16.1.0/24
        - 10.12.1.0/24
    - toCIDRSet:
        - cidr: 10.0.0.0/8
          except:
            - 10.100.0.0/24
            - 10.200.200.11/32
```

To restrict only by ports (L4) and allow those ports to any destination, use `toPorts`:

```yaml theme={null}
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: allow-app1-port80
  namespace: dev
spec:
  endpointSelector:
    matchLabels:
      app: app1
  egress:
    - toPorts:
        - ports:
            - port: "80"
              protocol: TCP
```

This policy permits pods with label `app: app1` to make TCP connections only on port 80 to any IP.

Terminal checks from inside an app1 pod (examples):

```bash theme={null}
# Attempt to reach port 90 -> should fail (connection refused or timeout)
telnet 10.0.2.89 90

# Attempt to reach port 80 -> should succeed (if target accepts TCP)
telnet 10.0.2.89 80
```

### Port ranges

Allow a contiguous port range using `endPort` (inclusive):

```yaml theme={null}
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: allow-app1-port-range
  namespace: dev
spec:
  endpointSelector:
    matchLabels:
      app: app1
  egress:
    - toPorts:
        - ports:
            - port: "80"
              endPort: 100
              protocol: TCP
```

This permits TCP ports 80–100; ports outside that range (e.g., 101) are denied.

## Combine L3 (endpoints/CIDR) with L4 (ports)

For precise allowances, combine `toEndpoints` (L3 pod selectors) or `toCIDR` with `toPorts`. Example: allow app1 to talk to app2 only on TCP port 80.

```yaml theme={null}
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: app1-to-app2-port80
  namespace: dev
spec:
  endpointSelector:
    matchLabels:
      app: app1
  egress:
    - toEndpoints:
        - matchLabels:
            app: app2
      toPorts:
        - ports:
            - port: "80"
              protocol: TCP
```

Behavior summary:

* app1 -> app2 on TCP/80: allowed
* app1 -> app2 on other ports (e.g., 90): blocked
* app1 -> any other pod: blocked (regardless of port)

## L4 with CIDR destinations

You can combine L4 and L3-by-CIDR — for example, permit app1 to contact IPs in a subnet only on a specific port.

```yaml theme={null}
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: app1-to-subnet-port80
  namespace: dev
spec:
  endpointSelector:
    matchLabels:
      app: app1
  egress:
    - toCIDR:
        - 192.168.1.0/24
      toPorts:
        - ports:
            - port: "80"
              protocol: TCP
```

This allows TCP port 80 traffic from app1 to addresses in 192.168.1.0/24 only.

<Callout icon="lightbulb" color="#1CB2FE">
  Egress policies are deny-by-default: when you add egress rules, Cilium blocks anything not explicitly allowed. Common control-plane traffic (for example DNS) will be blocked unless you permit it.
</Callout>

## DNS gets blocked by default — add an explicit rule

Because egress is deny-by-default, restrictive egress policies often break DNS resolution inside pods. You must explicitly allow DNS to the cluster’s DNS service (typically CoreDNS) on port 53.

Example symptom after applying a restrictive policy:

```text theme={null}
;; communications error to 10.96.0.10#53: timed out
```

Steps to allow DNS for app1:

1. Find CoreDNS pod labels:

```bash theme={null}
kubectl get pod -n kube-system --show-labels | grep -i coredns
```

2. Create a namespaced policy that permits egress from app1 to the CoreDNS pods on port 53. DNS often uses UDP/TCP, so `protocol: ANY` is acceptable:

```yaml theme={null}
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: allow-dns-for-app1
  namespace: dev
spec:
  endpointSelector:
    matchLabels:
      app: app1
  egress:
    - toEndpoints:
        - matchLabels:
            k8s.io.kubernetes.pod.namespace: kube-system
            k8s-app: kube-dns
      toPorts:
        - ports:
            - port: "53"
              protocol: ANY
```

After applying the rule, DNS queries from app1 should succeed:

```text theme={null}
Server:  10.96.0.10
Address: 10.96.0.10#53

Non-authoritative answer:
Name:    google.com
Address: 142.250.176.206
```

<Callout icon="warning" color="#FF6B6B">
  If you forget to allow DNS, many higher-level application behaviors will fail (package downloads, image pulls inside pods, service discovery, etc.). Always include DNS allowances when applying restrictive egress policies.
</Callout>

## L7: DNS filtering (match names / patterns)

Cilium's L7 rules can match DNS queries by name or pattern. Use `rules.dns` to allow only specific domain names to be resolved.

Example: allow only \*.google.com and yahoo.com queries from app1 to CoreDNS:

```yaml theme={null}
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: dns-l7-restrict
  namespace: dev
spec:
  endpointSelector:
    matchLabels:
      app: app1
  egress:
    - toEndpoints:
        - matchLabels:
            k8s.io.kubernetes.pod.namespace: kube-system
            k8s-app: kube-dns
      toPorts:
        - ports:
            - port: "53"
              protocol: ANY
      rules:
        dns:
          - matchPattern: "*.google.com"
          - matchName: "yahoo.com"
```

Result:

* Queries for \*.google.com and yahoo.com: allowed
* Queries for other domains (e.g., amazon.com): refused/blocked

Example from app1 after applying policy:

```text theme={null}
# Allowed
nslookup google.com

# Refused
nslookup amazon.com
;; communications error to 10.96.0.10#53: timed out
```

## L7: HTTP filtering (method, path, headers, host)

Cilium can perform HTTP-aware L7 filtering. You can allow or deny requests based on HTTP method, path, headers, and host. The following policy lets only GET /auth requests from app1 to app2 on port 80.

```yaml theme={null}
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: app1-to-app2-http-get-auth
  namespace: dev
spec:
  endpointSelector:
    matchLabels:
      app: app2
  ingress:
    - fromEndpoints:
        - matchLabels:
            app: app1
      toPorts:
        - ports:
            - port: "80"
              protocol: TCP
          rules:
            http:
              - method: "GET"
                path: /auth
```

Test plan:

* Start packet capture or application logs on app2 to observe incoming requests.
* From app1:
  * curl http\://\<app2-ip>/auth  => allowed
  * curl http\://\<app2-ip>/products => blocked by L7 policy

Note: If app2 has no HTTP server running, you may see connection refused. Policy enforcement can still be verified by checking whether requests are accepted or dropped at the network policy layer.

## Ingress from other pods and external entities

Ingress policies follow the same selector patterns. Example: allow ingress to app1 only from pods labeled `app: app2`:

```yaml theme={null}
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: app1-ingress-from-app2
  namespace: dev
spec:
  endpointSelector:
    matchLabels:
      app: app1
  ingress:
    - fromEndpoints:
        - matchLabels:
            app: app2
```

If you expose a pod with a NodePort or similar, external traffic is treated as an entity outside the cluster. Use `fromEntities` to allow traffic from those external sources:

```yaml theme={null}
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: allow-nodeport-world
  namespace: dev
spec:
  endpointSelector:
    matchLabels:
      app: app1
  ingress:
    - fromEntities:
        - world
```

Example NodePort service exposing app1 on nodePort 30007:

```yaml theme={null}
apiVersion: v1
kind: Service
metadata:
  name: my-service
  namespace: dev
spec:
  type: NodePort
  selector:
    app: app1
  ports:
    - port: 80
      targetPort: 80
      nodePort: 30007
```

If your cluster has a restrictive ingress policy, external curl to \<nodeIP>:30007 will be blocked unless you permit `fromEntities: ["world"]` (or another appropriate ingress allowance).

## Cilium Cluster-wide Network Policies (CCNP)

A CiliumClusterwideNetworkPolicy (CCNP) applies across all namespaces. Use a CCNP when you want the same policy to affect pods in every namespace — for example, to allow DNS cluster-wide.

Example: allow all pods cluster-wide to query CoreDNS on port 53:

```yaml theme={null}
apiVersion: "cilium.io/v2"
kind: CiliumClusterwideNetworkPolicy
metadata:
  name: allow-dns-clusterwide
spec:
  endpointSelector: {}   # matches all pods in all namespaces
  egress:
    - toEndpoints:
        - matchLabels:
            k8s.io.kubernetes.pod.namespace: kube-system
            k8s-app: kube-dns
      toPorts:
        - ports:
            - port: "53"
              protocol: ANY
```

Notes:

* A namespaced CiliumNetworkPolicy applies only to pods in that namespace. A CCNP applies cluster-wide.
* To include or exclude specific namespaces in endpoint selectors, use the `k8s.io.kubernetes.pod.namespace` label in `fromEndpoints`/`toEndpoints`.

## Quick reference: L3 vs L4 vs L7

| Layer            | What it controls                   | Cilium fields                        | Common use cases                               |
| ---------------- | ---------------------------------- | ------------------------------------ | ---------------------------------------------- |
| L3 (Network)     | Destination IPs / pods             | `toCIDR`, `toCIDRSet`, `toEndpoints` | Restrict to specific pods or subnets           |
| L4 (Transport)   | Ports and protocols                | `toPorts`, `port`, `endPort`         | Allow only specific TCP/UDP ports or ranges    |
| L7 (Application) | Protocol methods, paths, DNS names | `rules: { http:, dns: }`             | HTTP method/path filtering, DNS name filtering |

## Summary

* Use `toPorts` for L4 port-based restrictions and `toCIDR`/`toEndpoints` for L3 (IP/pod) restrictions.
* Combine L3 + L4 to express fine-grained policies (e.g., app1 → app2 on TCP/80).
* Cilium policies are deny-by-default for egress; always explicitly allow control-plane traffic such as DNS.
* Cilium supports L7 policies (DNS, HTTP, etc.) for application-aware controls.
* Use CiliumClusterwideNetworkPolicy to apply consistent rules cluster-wide.

## Links and references

* Cilium Network Policy documentation: [https://docs.cilium.io/en/stable/policy/](https://docs.cilium.io/en/stable/policy/)
* Kubernetes DNS (CoreDNS) overview: [https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/)
* Kubernetes Services: [https://kubernetes.io/docs/concepts/services-networking/service/](https://kubernetes.io/docs/concepts/services-networking/service/)

For advanced tactics like entities, additional L7 rules, HTTP header or host matching, consult the Cilium policy documentation above.

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/cilium-certified-associate-cca/module/bf652c52-bb30-4bcc-9d18-c703f7b3e88a/lesson/09fd7ca2-c277-4ef1-b77c-3616cbc9d2c0" />

  <Card title="Practice Lab" icon="flask-conical" cta="Learn more" href="https://learn.kodekloud.com/user/courses/cilium-certified-associate-cca/module/bf652c52-bb30-4bcc-9d18-c703f7b3e88a/lesson/0e692f32-82dd-433b-a0dd-8ff541c33f67" />
</CardGroup>
