Protect hosts and VMs
Big picture
Use Calico network policy to restrict traffic to/from hosts and VMs.
Value
Restricting traffic between hosts and the outside world is not unique to Calico; many solutions provide this capability. However, the advantage of using Calico to protect the host is you can use the same Calico policy configuration as workloads. You only need to learn one tool. Write a cluster-wide policy, and it is immediately applied to every host.
Concepts
Hosts and workloads
In the context of Calico configuration, a workload is a containerized compute instance running in Kubernetes. A host is a computer or virtual machine (VM) that acts as a node in a Kubernetes cluster or that runs application workloads outside of Kubernetes. Calico is unique in that it can enforce network policy and provide visibility in a consistent way for both workloads and hosts, even if those hosts are on-premises servers or VMs running in the public clou.
Host endpoints
Each host has one or more network interfaces that it uses to communicate externally. You can use Calico network policy to secure these interfaces (called host endpoints). Calico host endpoints can have labels, and they work the same as labels on workload endpoints. The network policy rules can apply to both workload and host endpoints using label selectors.
Failsafe rules
It is easy to inadvertently cut all host connectivity because of nonexistent or misconfigured network policy. To avoid this, Calico provides failsafe rules with default/configurable ports that are open on all host endpoints.
Default behavior of workload to host traffic
By default, Calico blocks all connections from a workload to its local host. You can control whether connections from a workload endpoint to its local host are dropped, returned, or accepted using a simple parameter.
Calico allows all connections from processes running on the host to guest workloads on the host. This allows host processes to run health checks and debug guest workloads.
Default behavior of external traffic to/from host
If a host endpoint is added and network policy is not in place, the Calico default is to deny traffic to/from that endpoint (except for traffic allowed by failsafe rules). For host endpoints, Calico blocks traffic only to/from interfaces that it’s been explicitly told about in network policy. Traffic to/from other interfaces is ignored.
Other host protection
In terms of design consistency in Calico, you may wonder about the following use cases.
Does Calico protect a local host from workloads?
Yes. DefaultEndpointToHostAction controls whether or not workloads can access their local host.
Does Calico protect a workload from the host it is running on?
No. Calico allows connections the host makes to the workloads running on that host. Some orchestrators like Kubernetes depend on this connectivity for health checking the workload. Moreover, processes running on the local host are often privileged enough to override local Calico policy. Be very cautious with the processes that you allow to run in the host's root network namespace.
Before you begin...
If you are already running Calico for Kubernetes, you are good to go. If you want to install Calico on a non-cluster machine for host protection only, see Non-cluster hosts.
How to
- Avoid accidentally cutting all host connectivity
- Use policy to restrict host traffic
- Control default behavior of workload endpoint to host traffic
Avoid accidentally cutting all host connectivity
To avoid inadvertently cutting all host connectivity because of nonexistent or misconfigured network policy, Calico uses failsafe rules that open specific ports and CIDRs on all host endpoints.
Review the following table to determine if the defaults work for your implementation. If not, change the default ports using the parameters, FailsafeInboundHostPorts and FailsafeOutboundHostPorts in Configuring Felix.
Port | Protocol | CIDR | Direction | Purpose |
---|---|---|---|---|
22 | TCP | 0.0.0.0/0 | Inbound | SSH access |
53 | UDP | 0.0.0.0/0 | Outbound | DNS queries |
67 | UDP | 0.0.0.0/0 | Outbound | DHCP access |
68 | UDP | 0.0.0.0/0 | Inbound | DHCP access |
179 | TCP | 0.0.0.0/0 | Inbound & Outbound | BGP access (Calico networking) |
2379 | TCP | 0.0.0.0/0 | Inbound & Outbound | etcd access |
2380 | TCP | 0.0.0.0/0 | Inbound & Outbound | etcd access |
6443 | TCP | 0.0.0.0/0 | Inbound & Outbound | Kubernetes API server access |
6666 | TCP | 0.0.0.0/0 | Inbound & Outbound | etcd self-hosted service access |
6667 | TCP | 0.0.0.0/0 | Inbound & Outbound | etcd self-hosted service access |
Use policy to restrict host traffic
Step 1: Create policy to restrict host traffic
Although failsafe rules provide protection from removing all connectivity to a host, you should create a GlobalNetworkPolicy policy that restricts host traffic.
In the following example, we use a GlobalNetworkPolicy that applies to all worker nodes (defined by a label). Ingress SSH access is allowed from a defined "management" subnet.
Ingress traffic is also allowed for ICMP, and on TCP port 10250 (default kubelet port). Egress traffic is allowed to etcd on a particular IP, and UDP on port 53 and 67 for DNS and DHCP.
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: k8s-worker
spec:
selector: "role == 'k8s-worker'"
order: 0
ingress:
- action: Allow
protocol: TCP
source:
nets:
- '<your management CIDR>'
destination:
ports: [22]
- action: Allow
protocol: ICMP
- action: Allow
protocol: TCP
destination:
ports: [10250]
egress:
- action: Allow
protocol: TCP
destination:
nets:
- '<your etcd IP>/32'
ports: [2379]
- action: Allow
protocol: UDP
destination:
ports: [53, 67]
Step 2: Create host endpoints
For each host point that you want to secure with policy, you must create a HostEndpoint object. To do that, you need the name of the Calico node on the host that owns the interface; in most cases, it is the same as the hostname of the host.
In the following example, we create a HostEndpoint for the host named my-host with the interface named eth0, with IP 10.0.0.1. Note that the value for node: must match the hostname used on the Calico node object.
When the HostEndpoint is created, traffic to or from the interface is dropped unless policy is in place.
apiVersion: projectcalico.org/v3
kind: HostEndpoint
metadata:
name: my-host-eth0
labels:
role: k8s-worker
environment: production
spec:
interfaceName: eth0
node: my-host
expectedIPs: ['10.0.0.1']
Control default behavior of workload endpoint to host traffic
The default Calico behavior blocks all connections from workloads to their local host (after traffic passes any egress policy applied to the workload). You can change this behavior using the DefaultEndpointToHostAction parameter in Felix configuration.
This parameter works at the IP table level, where you can specify packet behavior to Drop (default), Accept, or Return.
To change this parameter for all hosts, edit the FelixConfiguration object named “default.”
-
Get a copy of the object to edit.
calicoctl get felixconfiguration default --export -o yaml > default-felix-config.yaml
-
Open the file in a text editor and add the parameter, defaultEndpointToHostAction. For example:
apiVersion: projectcalico.org/v3
kind: FelixConfiguration
metadata:
name: default
spec:
ipipEnabled: true
logSeverityScreen: Info
reportingInterval: 0s
defaultEndpointToHostAction: Accept -
Update the FelixConfiguration on the cluster.
calicoctl apply -f default-felix-config.yaml