TL;DR: kube-restrict-ip allows you to restrict access to specified TCP ports of the Kubernetes nodes to defined set of IP addresses. Configuration for
kube-restrict-ip is provided via a ConfigMap and it can be reconfigured in a live cluster by creating or editing this
Okay, let's imagine we have a Kubernetes cluster and deployed NGINX Ingress Controller. Its deployment descriptor specified use of
hostNetwork: true for a great reason: this way NGINX running in a pod can directly see the network interfaces of the host machine where the pod was started. But the side effect of such setup is any service running in a pod will be directly accessible by the outside world, for example Prometheus metrics service running on port 10254.
Surely, we could manually add iptables rules for any node we need to restrict access to these ports, but it isn't in any way match Kubernetes ideology of the dynamic environment where nodes and pods can be created and destroyed at any moment. So, it will be great if these iptables rules will be also created automatically. And here we come to the
kube-restrict-ip is a little utility written in Go that creates an iptables chain containing matching rules for user-specified IP addresses (hosts and CIDR ranges), and a rule in INPUT chain that routes requests bound to restricted ports to rules chain. All unmatched IPs will be rejected.
The simplest way to apply these restrictions to all nodes in a Kubernetes cluster is launch the
kube-restrict-ip utility as a DaemonSet.
kube-restrict-ip repo includes an example kube-restrict-ip.yaml file that can be used to launch the kube-restrict-ip as a DaemonSet:
kubectl create -f kube-restrict-ip.yaml
kube-restrict-ip container will wait for a config file mounted to
/etc/kube-restrict-ip/config.yaml mount point. This file can be provided via a
ConfigMap, so it can be reconfigured in a live cluster by creating or editing this
kube-restrict-ip repo includes an example config file that could be used to create the
ConfigMap in your cluster:
kubectl create configmap kube-restrict-ip --from-file=config.yaml --namespace=kube-system
Please note that the
ConfigMap in the same namespace as the DaemonSet Pods, and named the
kube-restrict-ip to match the DaemonSet spec. This is necessary for the
ConfigMap to appear in the Pods' filesystems.
Let's look into example
restrictedPorts: A list restricted TCP ports (required).
allowedNetworks: A list allowed hosts and networks in CIDR notation (required). Please don't forget to add all internal networks here (docker, flannel, etc).
checkInterval: The interval to check config for updates (optional, default 60s). The syntax is any format accepted by Go's time.ParseDuration function. Please note that
ConfigMapupdates are propagated in the Kubernetes cluster with some delay which by my observations is about a minute, so setting
checkIntervalto values less of several tens seconds makes little sense.
There is another option not included in the example above:
ipChain: iptables chain name (optional, default "KUBE-RESTRICT-IP"). You could use it for specifying alternate rules chain name in case of multiple
kube-restrict-iprunning in a cluster.
After applying this config file to
kube-restrict-ip, the next iptables rules will be created at the Kubernetes node:
# iptables --list
Chain INPUT (policy ACCEPT)
target prot opt source destination
KUBE-RESTRICT-IP tcp -- 0.0.0.0/0 0.0.0.0/0 multiport dports 9100,10254 /* kube-restrict-ip */
Chain KUBE-RESTRICT-IP (1 references)
target prot opt source destination
RETURN all -- localhost anywhere
RETURN all -- 10.244.0.0/16 anywhere
RETURN all -- 172.17.0.0/16 anywhere
REJECT all -- anywhere anywhere reject-with icmp-port-unreachable
kube-restrict-ip is an utility focused in providing a simple way to restrict access to the services in a Kubernetes cluster. You could use it to limit access to ports exposed by pods with
hostNetwork: true, like Prometheus metrics services, and modify these restrictions on the fly using a Kubernetes