Skip to main content
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.
A presentation slide with the word "Demo" on the left. On the right is a teal gradient shape reading "Cilium Network Policy Part 2" with a small © KodeKloud notice in the corner.

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.
To restrict only by ports (L4) and allow those ports to any destination, use toPorts:
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):

Port ranges

Allow a contiguous port range using endPort (inclusive):
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.
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.
This allows TCP port 80 traffic from app1 to addresses in 192.168.1.0/24 only.
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.

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:
Steps to allow DNS for app1:
  1. Find CoreDNS pod labels:
  1. 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:
After applying the rule, DNS queries from app1 should succeed:
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.

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:
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:

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.
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:
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:
Example NodePort service exposing app1 on 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:
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

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.
For advanced tactics like entities, additional L7 rules, HTTP header or host matching, consult the Cilium policy documentation above.

Watch Video

Practice Lab