From 1112a590fa4e6ca20e4eee49b13dd102164df33f Mon Sep 17 00:00:00 2001
From: Sheogorath <sheogorath@shivering-isles.com>
Date: Sun, 30 Jan 2022 01:37:51 +0100
Subject: [PATCH] feat(firewall): Add firewall configuration

This patch configures calico to help isolating the cluster from the rest
of the world by implementing host firewall rules. This should close
various ports that otherwise would be exposed to the outside world and
posing a risk.

It's important to note, that due to the usage of wireguard there are
some additional ports that must be opened for the whole setup to
function. If ports >40000 on UDP aren't open, the whole network will
die, apparently. At least that's what experimenting with this feature
has indicated.

Reference:
https://projectcalico.docs.tigera.io/security/kubernetes-nodes
---
 .../calico/felix-configuration.yaml           |  2 +-
 .../firewall/controller-config.yaml           |  2 +-
 infrastructure/firewall/ingress-base.yaml     | 40 +++++++++++++++++++
 .../firewall/ingress-control-plane.yaml       | 37 +++++++++++++++++
 infrastructure/firewall/ingress-metallb.yaml  | 28 +++++++++++++
 .../firewall/ingress-monitoring.yaml          | 17 ++++++++
 infrastructure/firewall/ingress-worker.yaml   | 29 ++++++++++++++
 infrastructure/firewall/kustomization.yaml    |  5 +++
 8 files changed, 158 insertions(+), 2 deletions(-)
 create mode 100644 infrastructure/firewall/ingress-base.yaml
 create mode 100644 infrastructure/firewall/ingress-control-plane.yaml
 create mode 100644 infrastructure/firewall/ingress-metallb.yaml
 create mode 100644 infrastructure/firewall/ingress-monitoring.yaml
 create mode 100644 infrastructure/firewall/ingress-worker.yaml

diff --git a/infrastructure/calico/felix-configuration.yaml b/infrastructure/calico/felix-configuration.yaml
index 8b26bdd42..f11f478c8 100644
--- a/infrastructure/calico/felix-configuration.yaml
+++ b/infrastructure/calico/felix-configuration.yaml
@@ -1,4 +1,4 @@
-apiVersion: crd.projectcalico.org/v1
+apiVersion: projectcalico.org/v3
 kind: FelixConfiguration
 metadata:
   name: default
diff --git a/infrastructure/firewall/controller-config.yaml b/infrastructure/firewall/controller-config.yaml
index 5882934a2..5945fdb80 100644
--- a/infrastructure/firewall/controller-config.yaml
+++ b/infrastructure/firewall/controller-config.yaml
@@ -1,4 +1,4 @@
-apiVersion: crd.projectcalico.org/v1
+apiVersion: projectcalico.org/v3
 kind: KubeControllersConfiguration
 metadata:
   annotations:
diff --git a/infrastructure/firewall/ingress-base.yaml b/infrastructure/firewall/ingress-base.yaml
new file mode 100644
index 000000000..2811c071e
--- /dev/null
+++ b/infrastructure/firewall/ingress-base.yaml
@@ -0,0 +1,40 @@
+---
+apiVersion: projectcalico.org/v3
+kind: GlobalNetworkPolicy
+metadata:
+  name: ingress-k8s-base
+spec:
+  selector: has(node-role.kubernetes.io/control-plane) || has(node-role.kubernetes.io/worker)
+  ingress:
+  # Allow ICMP from everywhere
+  - action: Allow
+    protocol: ICMP
+  # Allow SSH from everywhere
+  - action: Allow
+    protocol: TCP
+    destination:
+      ports:
+      - 22
+  # Allow DHCP from everywhere
+  - action: Allow
+    protocol: UDP
+    destination:
+      ports:
+        - 68
+  # Allow bird and typha for calico from all cluster nodes
+  - action: Allow
+    protocol: TCP
+    source:
+      selector: has(node-role.kubernetes.io/control-plane) || has(node-role.kubernetes.io/worker)
+    destination:
+      ports:
+        - 179
+        - 5473
+  - action: Allow
+    protocol: UDP
+    source:
+      selector: has(node-role.kubernetes.io/control-plane) || has(node-role.kubernetes.io/worker)
+    destination:
+      ports:
+        - 4789
+        - 40000:65534
diff --git a/infrastructure/firewall/ingress-control-plane.yaml b/infrastructure/firewall/ingress-control-plane.yaml
new file mode 100644
index 000000000..a85e572d6
--- /dev/null
+++ b/infrastructure/firewall/ingress-control-plane.yaml
@@ -0,0 +1,37 @@
+---
+apiVersion: projectcalico.org/v3
+kind: GlobalNetworkPolicy
+metadata:
+  name: ingress-k8s-control-plane
+spec:
+  selector: has(node-role.kubernetes.io/control-plane)
+  # Control plane ports
+  # https://kubernetes.io/docs/reference/ports-and-protocols/
+  ingress:
+  # Allow localhost access
+  - action: Allow
+    destination:
+      nets:
+      - 127.0.0.0/8
+  # Allow Kube API access from everywhere
+  - action: Allow
+    protocol: TCP
+    destination:
+      ports:
+      - 6443
+  # Allow Kubelet and etcd access from control-plane nodes
+  - action: Allow
+    protocol: TCP
+    source:
+      selector: has(node-role.kubernetes.io/control-plane)
+    destination:
+      ports:
+      - 2379
+      - 2380
+      - 10250
+  # Allow NodePorts
+  - action: Allow
+    protocol: TCP
+    destination:
+      ports:
+        - 30000:32767
diff --git a/infrastructure/firewall/ingress-metallb.yaml b/infrastructure/firewall/ingress-metallb.yaml
new file mode 100644
index 000000000..e0f4cde2a
--- /dev/null
+++ b/infrastructure/firewall/ingress-metallb.yaml
@@ -0,0 +1,28 @@
+---
+apiVersion: projectcalico.org/v3
+kind: GlobalNetworkPolicy
+metadata:
+  name: ingress-k8s-metallb
+spec:
+  selector: has(node-role.kubernetes.io/control-plane) || has(node-role.kubernetes.io/worker)
+  ingress:
+  # Allow access for metallb speaker
+  - action: Allow
+    protocol: TCP
+    source:
+      selector: has(node-role.kubernetes.io/control-plane) || has(node-role.kubernetes.io/worker)
+    destination:
+      ports:
+      # metallb-membership port
+      - 7946
+      # metallb-metrics port
+      - 7472
+  # Allow access for metallb speaker
+  - action: Allow
+    protocol: UDP
+    source:
+      selector: has(node-role.kubernetes.io/control-plane) || has(node-role.kubernetes.io/worker)
+    destination:
+      ports:
+      # metallb-membership port
+      - 7946
diff --git a/infrastructure/firewall/ingress-monitoring.yaml b/infrastructure/firewall/ingress-monitoring.yaml
new file mode 100644
index 000000000..d4ec12b6e
--- /dev/null
+++ b/infrastructure/firewall/ingress-monitoring.yaml
@@ -0,0 +1,17 @@
+---
+apiVersion: projectcalico.org/v3
+kind: GlobalNetworkPolicy
+metadata:
+  name: ingress-k8s-monitoring
+spec:
+  selector: has(node-role.kubernetes.io/control-plane) || has(node-role.kubernetes.io/worker)
+  ingress:
+  # Allow access for metallb speaker
+  - action: Allow
+    protocol: TCP
+    source:
+      selector: has(node-role.kubernetes.io/control-plane) || has(node-role.kubernetes.io/worker)
+    destination:
+      ports:
+      # node-exporter
+      - 9100
diff --git a/infrastructure/firewall/ingress-worker.yaml b/infrastructure/firewall/ingress-worker.yaml
new file mode 100644
index 000000000..7387d3d1c
--- /dev/null
+++ b/infrastructure/firewall/ingress-worker.yaml
@@ -0,0 +1,29 @@
+---
+apiVersion: projectcalico.org/v3
+kind: GlobalNetworkPolicy
+metadata:
+  name: ingress-k8s-worker
+spec:
+  selector: has(node-role.kubernetes.io/worker)
+  # Control plane ports
+  # https://kubernetes.io/docs/reference/ports-and-protocols/
+  ingress:
+  # Allow localhost access
+  - action: Allow
+    destination:
+      nets:
+      - 127.0.0.0/8
+  # Allow kublet access from control-plane nodes
+  - action: Allow
+    protocol: TCP
+    source:
+      selector: has(node-role.kubernetes.io/control-plane)
+    destination:
+      ports:
+      - 10250
+  # Allow NodePorts
+  - action: Allow
+    protocol: TCP
+    destination:
+      ports:
+        - 30000:32767
diff --git a/infrastructure/firewall/kustomization.yaml b/infrastructure/firewall/kustomization.yaml
index 0d33fe9d2..865d3c487 100644
--- a/infrastructure/firewall/kustomization.yaml
+++ b/infrastructure/firewall/kustomization.yaml
@@ -3,3 +3,8 @@ kind: Kustomization
 namespace: default
 resources:
   - controller-config.yaml
+  - ingress-base.yaml
+  - ingress-control-plane.yaml
+  - ingress-worker.yaml
+  - ingress-metallb.yaml
+  - ingress-monitoring.yaml
-- 
GitLab