From 4645eb10f0b9887a6b416d2a8c2f0bf708b56a37 Mon Sep 17 00:00:00 2001 From: Jack Yu Date: Thu, 30 Apr 2026 15:08:41 +0800 Subject: [PATCH 1/2] docs: update network requirement Signed-off-by: Jack Yu --- docs/install/requirements.md | 142 +++++++++++++++++++++++++++-------- 1 file changed, 110 insertions(+), 32 deletions(-) diff --git a/docs/install/requirements.md b/docs/install/requirements.md index 513283f991..77fda9353c 100644 --- a/docs/install/requirements.md +++ b/docs/install/requirements.md @@ -60,38 +60,116 @@ Harvester nodes have the following network requirements for installation. Harvester nodes require the following port connections or inbound rules. Typically, all outbound traffic is allowed. -| Protocol | Port | Source | Description | -|:----------|:---------------------------|:-----------------------------------------|:----------------------------------------| -| TCP | 2379 | Harvester management nodes | Etcd client port | -| TCP | 2381 | Harvester management nodes | Etcd metrics collection | -| TCP | 2380 | Harvester management nodes | Etcd peer port | -| TCP | 2382 | Harvester management nodes | Etcd client port (HTTP only) | -| TCP | 10010 | Harvester management and compute nodes | Containerd | -| TCP | 6443 | Harvester management nodes | Kubernetes API | -| TCP | 9345 | Harvester management nodes | Kubernetes API | -| TCP | 10252 | Harvester management nodes | Kube-controller-manager health checks | -| TCP | 10257 | Harvester management nodes | Kube-controller-manager secure port | -| TCP | 10251 | Harvester management nodes | Kube-scheduler health checks | -| TCP | 10259 | Harvester management nodes | Kube-scheduler secure port | -| TCP | 10250 | Harvester management and compute nodes | Kubelet | -| TCP | 10256 | Harvester management and compute nodes | Kube-proxy health checks | -| TCP | 10258 | Harvester management nodes | cloud-controller-manager | -| TCP | 10260 | Harvester management nodes | cloud-controller-manager | -| TCP | 9091 | Harvester management and compute nodes | Canal calico-node felix | -| TCP | 9099 | Harvester management and compute nodes | Canal CNI health checks | -| UDP | 8472 | Harvester management and compute nodes | Canal CNI with VxLAN | -| TCP | 2112 | Harvester management nodes | Kube-vip | -| TCP | 6444 | Harvester management and compute nodes | RKE2 agent | -| TCP | 10246/10247/10248/10249 | Harvester management and compute nodes | Nginx worker process | -| TCP | 8181 | Harvester management and compute nodes | Nginx-ingress-controller | -| TCP | 8444 | Harvester management and compute nodes | Nginx-ingress-controller | -| TCP | 10245 | Harvester management and compute nodes | Nginx-ingress-controller | -| TCP | 80 | Harvester management and compute nodes | Nginx | -| TCP | 9796 | Harvester management and compute nodes | Node-exporter | -| TCP | 30000-32767 | Harvester management and compute nodes | NodePort port range | -| TCP | 22 | Harvester management and compute nodes | sshd | -| UDP | 68 | Harvester management and compute nodes | NetworkManager | -| TCP | 3260 | Harvester management and compute nodes | iscsid | +Ports that bind only to `127.0.0.1` are accessible from localhost only and do not require inbound firewall rules; they are included here for completeness. + +#### Control-plane Node + +| Protocol | Port | Bind Address | Source | Description | +|:---------|:-----|:-------------|:-------|:------------| +| TCP | 22 | `0.0.0.0` | All | SSH | +| TCP | 80 | `0.0.0.0` | All | Harvester UI HTTP (nginx proxy) | +| TCP | 443 | `0.0.0.0` | All | Harvester UI HTTPS (nginx proxy) | +| TCP | 2112 | `0.0.0.0` | All | kube-vip Prometheus metrics | +| TCP | 2379 | `127.0.0.1`, node IP | Harvester management nodes | etcd client port | +| TCP | 2380 | `127.0.0.1`, node IP | Harvester management nodes | etcd peer port | +| TCP | 2381 | `127.0.0.1` only | localhost | etcd metrics/health | +| TCP | 2382 | `127.0.0.1` only | localhost | etcd learner client (HTTP) | +| TCP | 6443 | `0.0.0.0` | All | Kubernetes API server | +| TCP | 9091 | `0.0.0.0` | All | calico-node metrics (Prometheus) | +| TCP | 9099 | `127.0.0.1` only | localhost | Canal/CNI health check | +| TCP | 9345 | `0.0.0.0` | Harvester nodes | RKE2 supervisor API | +| TCP | 9796 | `0.0.0.0` | All | Prometheus node-exporter | +| TCP | 10010 | `127.0.0.1` only | localhost | containerd gRPC | +| TCP | 10248 | `127.0.0.1` only | localhost | kubelet healthz | +| TCP | 10249 | `127.0.0.1` only | localhost | kube-proxy metrics | +| TCP | 10250 | `0.0.0.0` | Kubernetes components | kubelet API | +| TCP | 10256 | `127.0.0.1` only | localhost | kube-proxy health | +| TCP | 10257 | `127.0.0.1` only | localhost | kube-controller-manager | +| TCP | 10258 | `127.0.0.1` only | localhost | cloud-controller-manager | +| TCP | 10259 | `127.0.0.1` only | localhost | kube-scheduler | +| TCP | 30000-32767 | `0.0.0.0` | All | NodePort services (TCP) | +| UDP | 8472 | `0.0.0.0` | Harvester nodes | VXLAN (Flannel/Canal) | +| UDP | 30000-32767 | `0.0.0.0` | All | NodePort services (UDP) | + +#### Worker Node + +| Protocol | Port | Bind Address | Source | Description | +|:---------|:-----|:-------------|:-------|:------------| +| TCP | 22 | `0.0.0.0` | All | SSH | +| TCP | 80 | `0.0.0.0` | All | Harvester UI HTTP (nginx proxy) | +| TCP | 443 | `0.0.0.0` | All | Harvester UI HTTPS (nginx proxy) | +| TCP | 6443 | `127.0.0.1`, `[::1]` | localhost | Kubernetes API server (RKE2 agent proxy) | +| TCP | 6444 | `127.0.0.1`, `[::1]` | localhost | RKE2 agent API proxy | +| TCP | 9091 | `0.0.0.0` | All | calico-node metrics (Prometheus) | +| TCP | 9099 | `127.0.0.1` only | localhost | Canal/CNI health check | +| TCP | 9796 | `0.0.0.0` | All | Prometheus node-exporter | +| TCP | 10010 | `127.0.0.1` only | localhost | containerd gRPC | +| TCP | 10248 | `127.0.0.1` only | localhost | kubelet healthz | +| TCP | 10249 | `127.0.0.1` only | localhost | kube-proxy metrics | +| TCP | 10250 | `0.0.0.0` | Kubernetes components | kubelet API | +| TCP | 10256 | `127.0.0.1` only | localhost | kube-proxy health | +| TCP | 30000-32767 | `0.0.0.0` | All | NodePort services (TCP) | +| UDP | 8472 | `0.0.0.0` | Harvester nodes | VXLAN (Flannel/Canal) | +| UDP | 30000-32767 | `0.0.0.0` | All | NodePort services (UDP) | + +#### Witness Node + +| Protocol | Port | Bind Address | Source | Description | +|:---------|:-----|:-------------|:-------|:------------| +| TCP | 22 | `0.0.0.0` | All | SSH | +| TCP | 2379 | `127.0.0.1`, node IP | Harvester management nodes | etcd client port | +| TCP | 2380 | `127.0.0.1`, node IP | Harvester management nodes | etcd peer port | +| TCP | 2381 | `127.0.0.1` only | localhost | etcd metrics/health | +| TCP | 2382 | `127.0.0.1` only | localhost | etcd learner client (HTTP) | +| TCP | 6443 | `127.0.0.1` only | localhost | Kubernetes API server (RKE2 agent proxy) | +| TCP | 6444 | `127.0.0.1` only | localhost | RKE2 agent API proxy | +| TCP | 9091 | `0.0.0.0` | All | calico-node metrics (Prometheus) | +| TCP | 9099 | `127.0.0.1` only | localhost | Canal/CNI health check | +| TCP | 9345 | `0.0.0.0` | Harvester nodes | RKE2 supervisor API | +| TCP | 9796 | `0.0.0.0` | All | Prometheus node-exporter | +| TCP | 10010 | `127.0.0.1` only | localhost | containerd gRPC | +| TCP | 10248 | `127.0.0.1` only | localhost | kubelet healthz | +| TCP | 10249 | `127.0.0.1` only | localhost | kube-proxy metrics | +| TCP | 10250 | `0.0.0.0` | Kubernetes components | kubelet API | +| TCP | 10256 | `127.0.0.1` only | localhost | kube-proxy health | +| TCP | 10258 | `127.0.0.1` only | localhost | cloud-controller-manager | +| UDP | 8472 | `0.0.0.0` | Harvester nodes | VXLAN (Flannel/Canal) | + +### Port Requirements for Addons + +The following tables list the additional ports opened by optional Harvester addons on each node role, compared to the baseline with no addons enabled. + +#### kubeovn-operator (Experimental) + +**Control-plane Node** + +| Protocol | Port | Bind Address | Source | Description | +|:---------|:-----|:-------------|:-------|:------------| +| TCP | 6641 | node IP | Harvester nodes | OVN Northbound DB | +| TCP | 6642 | node IP | Harvester nodes | OVN Southbound DB | +| TCP | 6643 | node IP | Harvester nodes | OVN JSON-RPC | +| TCP | 6644 | node IP | Harvester nodes | OVN JSON-RPC | +| TCP | 10660 | node IP | Harvester nodes | kube-ovn-controller metrics | +| TCP | 10665 | node IP | Harvester nodes | kube-ovn-daemon metrics/API | +| UDP | 4789 | `0.0.0.0` | Harvester nodes | VXLAN tunnel (Kube-OVN overlay) | + +**Worker Node** + +| Protocol | Port | Bind Address | Source | Description | +|:---------|:-----|:-------------|:-------|:------------| +| TCP | 8080 | node IP | Harvester nodes | kube-ovn-webhook HTTP | +| TCP | 8443 | `0.0.0.0` | All | kube-ovn-webhook HTTPS | +| TCP | 10660 | node IP | Harvester nodes | kube-ovn-controller metrics | +| TCP | 10665 | node IP | Harvester nodes | kube-ovn-daemon metrics/API | +| UDP | 4789 | `0.0.0.0` | Harvester nodes | VXLAN tunnel (Kube-OVN overlay) | + +**Witness Node** + +| Protocol | Port | Bind Address | Source | Description | +|:---------|:-----|:-------------|:-------|:------------| +| TCP | 10665 | node IP | Harvester nodes | kube-ovn-daemon metrics/API | +| UDP | 4789 | `0.0.0.0` | Harvester nodes | VXLAN tunnel (Kube-OVN overlay) | + ### Port Requirements for Integrating Harvester with Rancher From 9f07310346167545c0f3c3fa36ce62613eb0ef0a Mon Sep 17 00:00:00 2001 From: Jack Yu Date: Thu, 30 Apr 2026 17:56:17 +0800 Subject: [PATCH 2/2] docs: add host network security Signed-off-by: Jack Yu --- docs/install/requirements.md | 2 +- docs/networking/host-network-security.md | 358 +++++++++++++++++++++++ 2 files changed, 359 insertions(+), 1 deletion(-) create mode 100644 docs/networking/host-network-security.md diff --git a/docs/install/requirements.md b/docs/install/requirements.md index 77fda9353c..6c0d0bf10d 100644 --- a/docs/install/requirements.md +++ b/docs/install/requirements.md @@ -149,7 +149,7 @@ The following tables list the additional ports opened by optional Harvester addo | TCP | 6642 | node IP | Harvester nodes | OVN Southbound DB | | TCP | 6643 | node IP | Harvester nodes | OVN JSON-RPC | | TCP | 6644 | node IP | Harvester nodes | OVN JSON-RPC | -| TCP | 10660 | node IP | Harvester nodes | kube-ovn-controller metrics | +| TCP | 10661 | node IP | Harvester nodes | kube-ovn-monitor | | TCP | 10665 | node IP | Harvester nodes | kube-ovn-daemon metrics/API | | UDP | 4789 | `0.0.0.0` | Harvester nodes | VXLAN tunnel (Kube-OVN overlay) | diff --git a/docs/networking/host-network-security.md b/docs/networking/host-network-security.md new file mode 100644 index 0000000000..ca147b8621 --- /dev/null +++ b/docs/networking/host-network-security.md @@ -0,0 +1,358 @@ +--- +sidebar_position: 11 +sidebar_label: Host Network Security +title: "Host Network Security" +keywords: +- Harvester +- networking +- host +- security +--- + + + + + +By default, Harvester nodes do not filter inbound traffic, so any host which can reach the management network can connect to any open port. To reduce the attack surface, you can apply iptables rules to restrict inbound traffic to only the ports required for cluster operation. + +For the full list of required ports per node role, see [Network Requirements](../install/requirements.md#network-requirements). + +## Applying iptables Rules + +The examples below use a custom iptables chain (`HARVESTER_INPUT`) attached to the `INPUT` hook on the management bridge ([mgmt-br](./clusternetwork.md#cluster-network-details)). The rule set follows this structure: + +1. **Established connections** — Allow return traffic from connections already tracked by conntrack. +2. **Protocol rules** — Allow ICMP, DHCP, and other protocol-level traffic. +3. **Service-specific ACCEPT rules** — Allow traffic to ports required by the node role. +4. **LOG + DROP** — Log and drop everything else. + +```sh +# Create the custom chain and attach it to the INPUT hook +iptables -N HARVESTER_INPUT +iptables -A INPUT -i mgmt-br -j HARVESTER_INPUT + +iptables -A HARVESTER_INPUT -m conntrack --ctstate ESTABLISHED,RELATED \ + -m comment --comment "Accept return traffic from established connections" -j ACCEPT +iptables -A HARVESTER_INPUT -p icmp \ + -m comment --comment "ICMP" -j ACCEPT +iptables -A HARVESTER_INPUT -s 10.52.0.0/16 \ + -m comment --comment "Allow pod network return traffic" -j ACCEPT + +# ... role-specific ACCEPT rules ... + +iptables -A HARVESTER_INPUT -m limit --limit 10/min \ + -m comment --comment "Rate-limit logging of dropped packets" \ + -j LOG --log-prefix HARVESTER_DROP_ --log-level 4 +iptables -A HARVESTER_INPUT -m comment --comment "Drop all other traffic" -j DROP +``` + +If you apply these commands manually, use `iptables -L INPUT -v -n --line-numbers` to verify that `HARVESTER_INPUT` appears as **the last entry** in the `INPUT` chain: + +``` +harvester1:/home/rancher # iptables -L INPUT -v -n --line-numbers +# Warning: iptables-legacy tables present, use iptables-legacy to see them +Chain INPUT (policy ACCEPT xxx packets, xxxx bytes) +num pkts bytes target prot opt in out source destination +1 301K 140M cali-INPUT all -- * * 0.0.0.0/0 0.0.0.0/0 /* cali:Cz_u1IQiXIMmKD4c */ +2 0 0 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 match-set ovn40services dst +3 0 0 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 match-set ovn40services src +4 0 0 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 match-set ovn40subnets dst +5 0 0 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 match-set ovn40subnets src +6 0 0 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:6081 +7 300K 535M KUBE-PROXY-FIREWALL all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate NEW /* kubernetes load balancer firewall */ +8 2391K 1748M KUBE-NODEPORTS all -- * * 0.0.0.0/0 0.0.0.0/0 /* kubernetes health check service ports */ +9 300K 535M KUBE-EXTERNAL-SERVICES all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate NEW /* kubernetes externally-visible service portals */ +10 2421K 1796M KUBE-FIREWALL all -- * * 0.0.0.0/0 0.0.0.0/0 +11 49274 19M HARVESTER_INPUT all -- mgmt-br * 0.0.0.0/0 0.0.0.0/0 +``` + +:::warning + +The pod CIDR `10.52.0.0/16` is the default for Harvester. Replace it with the actual CIDR of your cluster if it differs. This rule reduces false positives from pod-to-node return traffic and is safe to omit if not needed. + +::: + +## Debugging and Verification + +### Monitoring INPUT Traffic + +Run the following command to list all rules in `HARVESTER_INPUT` with packet and byte counters. This is useful for verifying which rules are being hit and understanding traffic patterns on the node. + +```sh +iptables -L HARVESTER_INPUT -v -n --line-numbers +``` + +### Monitoring Dropped Packets + +The LOG rule records packets that do not match any ACCEPT rule. To monitor in real time: + +```sh +journalctl -k -f | grep HARVESTER_DROP + +# from the last 5 minutes: +journalctl -k --since "5 minutes ago" | grep HARVESTER_DROP +``` + +Key fields in a log entry: + +| Field | Description | +|:------|:------------| +| `IN=mgmt-br` | Packet arrived on the management bridge | +| `SRC` / `DST` | Source and destination IP addresses | +| `PROTO` | Protocol (TCP or UDP) | +| `SPT` / `DPT` | Source / destination port — use `DPT` to identify a missing rule | + +### False Positives + +After applying rules to a running node, some log entries may appear briefly and then stop. These are **false positives** caused by conntrack state loss — return traffic from connections established before the rules were applied no longer matches the `ESTABLISHED,RELATED` state and hits the DROP rule. They are harmless and self-heal as connections are re-established. + +A false positive has these characteristics: +- TCP flags are `ACK`, `ACK PSH`, or `ACK FIN` (not `SYN`). +- `SPT` is a known service port (e.g., `6443`, `9345`, `10250`). +- `DPT` is a high ephemeral port (above 1024). +- Log entries stop within a few minutes. + +**Example:** + +``` +Apr 22 10:00:01 harvester3 kernel: HARVESTER_DROP_IN=mgmt-br OUT= MAC=... SRC=192.168.122.61 DST=192.168.122.63 LEN=52 PROTO=TCP SPT=9345 DPT=46002 WINDOW=521 RES=0x00 ACK FIN URGP=0 +``` + +`SPT=9345` (RKE2 supervisor API), `DPT=46002` (ephemeral), `ACK FIN` — connection teardown, not a new blocked connection. This is a false positive. + +If log entries **persist** with `SYN` flags or an unrecognized `DPT`, a required port is likely missing — add the corresponding ACCEPT rule. + +## Persisting Rules with CloudInit CRD + +The iptables rules are lost on reboot. Use the [CloudInit CRD](../advanced/cloudinitcrd.md) to re-apply them at boot time. + +The `boot` stage runs before the node is fully operational, ensuring rules are in place from the start and avoiding conntrack state loss. + +The cleanup commands at the beginning prevent duplicate chain entries on subsequent reboots. + +```yaml +apiVersion: node.harvesterhci.io/v1beta1 +kind: CloudInit +metadata: + name: iptables-control-plane +spec: + matchSelector: + node-role.kubernetes.io/control-plane: "true" + node-role.kubernetes.io/etcd: "true" + filename: 91-iptables-control-plane + contents: | + stages: + boot: + - name: "Apply iptables rules for control-plane node" + commands: + # Clean up any existing chain from a previous boot + - iptables -D INPUT -i mgmt-br -j HARVESTER_INPUT 2>/dev/null || true + - iptables -F HARVESTER_INPUT 2>/dev/null || true + - iptables -X HARVESTER_INPUT 2>/dev/null || true + # Create the chain and attach it + - iptables -N HARVESTER_INPUT + - iptables -A INPUT -i mgmt-br -j HARVESTER_INPUT + # Allow established connections and ICMP + - iptables -A HARVESTER_INPUT -m conntrack --ctstate ESTABLISHED,RELATED -m comment --comment "Accept return traffic from established connections" -j ACCEPT + - iptables -A HARVESTER_INPUT -p icmp -m comment --comment "ICMP" -j ACCEPT + - iptables -A HARVESTER_INPUT -s 10.52.0.0/16 -m comment --comment "Allow pod network return traffic" -j ACCEPT + # ... role-specific ACCEPT rules ... + # Log and drop everything else + - iptables -A HARVESTER_INPUT -m limit --limit 10/min -m comment --comment "Rate-limit logging of dropped packets" -j LOG --log-prefix HARVESTER_DROP_ --log-level 4 + - iptables -A HARVESTER_INPUT -m comment --comment "Drop all other traffic" -j DROP + paused: false +``` + +:::warning + +After creating or updating a `CloudInit` resource, nodes must be **rebooted** for the changes to take effect. To apply rules immediately without rebooting, run the commands manually via SSH. + +::: + +### Remove the iptables Rules + +1. Delete the `CloudInit` resource. +2. Run the following commands to remove the chain from the running system: + +```sh +iptables -D INPUT -i mgmt-br -j HARVESTER_INPUT 2>/dev/null || true +iptables -F HARVESTER_INPUT 2>/dev/null || true +iptables -X HARVESTER_INPUT 2>/dev/null || true +``` + +## Role-Specific CloudInit Resources + +Create a separate `CloudInit` resource for each node role present in your cluster. If you have not explicitly assigned a role in the Harvester configuration, the node defaults to control-plane and you can apply the control-plane example below. + +:::warning + +Ensure that the `spec.matchSelector` of each `CloudInit` resource is **mutually exclusive**. A node that matches more than one iptables-related `CloudInit` will have the chain created multiple times, resulting in duplicate rules and unpredictable behavior. Verify that no other iptables `CloudInit` resources in your cluster have overlapping selectors before applying these examples. + +::: + +:::note + +The following examples include ports for the **kubeovn-operator** and **rancher-monitoring** addons. Remove the corresponding rules if you don't want. See [Port Requirements for Addons](../install/requirements.md#port-requirements-for-addons) for details. + +::: + +### Control-Plane Node + +```yaml +apiVersion: node.harvesterhci.io/v1beta1 +kind: CloudInit +metadata: + name: iptables-control-plane +spec: + matchSelector: + node-role.kubernetes.io/control-plane: "true" + node-role.kubernetes.io/etcd: "true" + filename: 91-iptables-control-plane + contents: | + stages: + boot: + - name: "Apply iptables rules for control-plane node" + commands: + - iptables -D INPUT -i mgmt-br -j HARVESTER_INPUT 2>/dev/null || true + - iptables -F HARVESTER_INPUT 2>/dev/null || true + - iptables -X HARVESTER_INPUT 2>/dev/null || true + - iptables -N HARVESTER_INPUT + - iptables -A INPUT -i mgmt-br -j HARVESTER_INPUT + - iptables -A HARVESTER_INPUT -m conntrack --ctstate ESTABLISHED,RELATED -m comment --comment "Accept return traffic from established connections" -j ACCEPT + - iptables -A HARVESTER_INPUT -p icmp -m comment --comment "ICMP (ping, MTU discovery, etc.)" -j ACCEPT + - iptables -A HARVESTER_INPUT -s 10.52.0.0/16 -m comment --comment "Allow pod network return traffic" -j ACCEPT + - iptables -A HARVESTER_INPUT -p udp --sport 67 --dport 68 -m comment --comment "DHCP server reply" -j ACCEPT + - iptables -A HARVESTER_INPUT -p udp --sport 68 --dport 67 -m comment --comment "DHCP client request" -j ACCEPT + - iptables -A HARVESTER_INPUT -p tcp --dport 22 -m comment --comment "SSH" -j ACCEPT + - iptables -A HARVESTER_INPUT -p tcp --dport 80 -m comment --comment "Harvester UI HTTP" -j ACCEPT + - iptables -A HARVESTER_INPUT -p tcp --dport 443 -m comment --comment "Harvester UI HTTPS" -j ACCEPT + - iptables -A HARVESTER_INPUT -p tcp --dport 2112 -m comment --comment "kube-vip Prometheus metrics" -j ACCEPT + - iptables -A HARVESTER_INPUT -p tcp --dport 2379:2380 -m comment --comment "etcd client/peer" -j ACCEPT + - iptables -A HARVESTER_INPUT -p tcp --dport 6443 -m comment --comment "Kubernetes API server" -j ACCEPT + - iptables -A HARVESTER_INPUT -p tcp --dport 9091 -m comment --comment "calico-node metrics (Prometheus)" -j ACCEPT + - iptables -A HARVESTER_INPUT -p tcp --dport 9345 -m comment --comment "RKE2 supervisor API" -j ACCEPT + - iptables -A HARVESTER_INPUT -p tcp --dport 9796 -m comment --comment "Prometheus node-exporter metrics (rancher-monitoring)" -j ACCEPT + - iptables -A HARVESTER_INPUT -p tcp --dport 10250 -m comment --comment "kubelet API" -j ACCEPT + - iptables -A HARVESTER_INPUT -p tcp --dport 30000:32767 -m comment --comment "NodePort TCP range" -j ACCEPT + - iptables -A HARVESTER_INPUT -p udp --dport 30000:32767 -m comment --comment "NodePort UDP range" -j ACCEPT + - iptables -A HARVESTER_INPUT -p udp --dport 8472 -m comment --comment "VXLAN (Flannel/Canal)" -j ACCEPT + - iptables -A HARVESTER_INPUT -p tcp --dport 8080 -m comment --comment "kube-ovn-webhook HTTP (kubeovn-operator)" -j ACCEPT + - iptables -A HARVESTER_INPUT -p tcp --dport 8443 -m comment --comment "kube-ovn-webhook HTTPS (kubeovn-operator)" -j ACCEPT + - iptables -A HARVESTER_INPUT -p tcp --dport 6641:6644 -m comment --comment "OVN NB/SB DB and JSON-RPC (kubeovn-operator)" -j ACCEPT + - iptables -A HARVESTER_INPUT -p tcp --dport 10661 -m comment --comment "kube-ovn-monitor metrics (kubeovn-operator)" -j ACCEPT + - iptables -A HARVESTER_INPUT -p tcp --dport 10665 -m comment --comment "kube-ovn-daemon (kubeovn-operator)" -j ACCEPT + - iptables -A HARVESTER_INPUT -p udp --dport 4789 -m comment --comment "VXLAN (Kube-OVN, kubeovn-operator)" -j ACCEPT + - iptables -A HARVESTER_INPUT -m limit --limit 10/min -m comment --comment "Rate-limit logging of dropped packets" -j LOG --log-prefix HARVESTER_DROP_ --log-level 4 + - iptables -A HARVESTER_INPUT -m comment --comment "Drop all other traffic" -j DROP + paused: false +``` + +### Worker Node + +```yaml +apiVersion: node.harvesterhci.io/v1beta1 +kind: CloudInit +metadata: + name: iptables-worker +spec: + matchSelector: + node-role.harvesterhci.io/worker: "true" + filename: 91-iptables-worker + contents: | + stages: + boot: + - name: "Apply iptables rules for worker node" + commands: + - iptables -D INPUT -i mgmt-br -j HARVESTER_INPUT 2>/dev/null || true + - iptables -F HARVESTER_INPUT 2>/dev/null || true + - iptables -X HARVESTER_INPUT 2>/dev/null || true + - iptables -N HARVESTER_INPUT + - iptables -A INPUT -i mgmt-br -j HARVESTER_INPUT + - iptables -A HARVESTER_INPUT -m conntrack --ctstate ESTABLISHED,RELATED -m comment --comment "Accept return traffic from established connections" -j ACCEPT + - iptables -A HARVESTER_INPUT -p icmp -m comment --comment "ICMP (ping, MTU discovery, etc.)" -j ACCEPT + - iptables -A HARVESTER_INPUT -s 10.52.0.0/16 -m comment --comment "Allow pod network return traffic" -j ACCEPT + - iptables -A HARVESTER_INPUT -p udp --sport 67 --dport 68 -m comment --comment "DHCP server reply" -j ACCEPT + - iptables -A HARVESTER_INPUT -p udp --sport 68 --dport 67 -m comment --comment "DHCP client request" -j ACCEPT + - iptables -A HARVESTER_INPUT -p tcp --dport 22 -m comment --comment "SSH" -j ACCEPT + - iptables -A HARVESTER_INPUT -p tcp --dport 80 -m comment --comment "Harvester UI HTTP" -j ACCEPT + - iptables -A HARVESTER_INPUT -p tcp --dport 443 -m comment --comment "Harvester UI HTTPS" -j ACCEPT + - iptables -A HARVESTER_INPUT -p tcp --dport 9091 -m comment --comment "calico-node metrics (Prometheus)" -j ACCEPT + - iptables -A HARVESTER_INPUT -p tcp --dport 9796 -m comment --comment "Prometheus node-exporter metrics (rancher-monitoring)" -j ACCEPT + - iptables -A HARVESTER_INPUT -p tcp --dport 10250 -m comment --comment "kubelet API" -j ACCEPT + - iptables -A HARVESTER_INPUT -p tcp --dport 30000:32767 -m comment --comment "NodePort TCP range" -j ACCEPT + - iptables -A HARVESTER_INPUT -p udp --dport 30000:32767 -m comment --comment "NodePort UDP range" -j ACCEPT + - iptables -A HARVESTER_INPUT -p udp --dport 8472 -m comment --comment "VXLAN (Flannel/Canal)" -j ACCEPT + - iptables -A HARVESTER_INPUT -p tcp --dport 8080 -m comment --comment "kube-ovn-webhook HTTP (kubeovn-operator)" -j ACCEPT + - iptables -A HARVESTER_INPUT -p tcp --dport 8443 -m comment --comment "kube-ovn-webhook HTTPS (kubeovn-operator)" -j ACCEPT + - iptables -A HARVESTER_INPUT -p tcp --dport 10660 -m comment --comment "kube-ovn-controller (kubeovn-operator)" -j ACCEPT + - iptables -A HARVESTER_INPUT -p tcp --dport 10665 -m comment --comment "kube-ovn-daemon (kubeovn-operator)" -j ACCEPT + - iptables -A HARVESTER_INPUT -p udp --dport 4789 -m comment --comment "VXLAN (Kube-OVN, kubeovn-operator)" -j ACCEPT + - iptables -A HARVESTER_INPUT -m limit --limit 10/min -m comment --comment "Rate-limit logging of dropped packets" -j LOG --log-prefix HARVESTER_DROP_ --log-level 4 + - iptables -A HARVESTER_INPUT -m comment --comment "Drop all other traffic" -j DROP + paused: false +``` + +### Witness Node + +```yaml +apiVersion: node.harvesterhci.io/v1beta1 +kind: CloudInit +metadata: + name: iptables-witness +spec: + matchSelector: + node-role.harvesterhci.io/witness: "true" + filename: 91-iptables-witness + contents: | + stages: + boot: + - name: "Apply iptables rules for witness node" + commands: + - iptables -D INPUT -i mgmt-br -j HARVESTER_INPUT 2>/dev/null || true + - iptables -F HARVESTER_INPUT 2>/dev/null || true + - iptables -X HARVESTER_INPUT 2>/dev/null || true + - iptables -N HARVESTER_INPUT + - iptables -A INPUT -i mgmt-br -j HARVESTER_INPUT + - iptables -A HARVESTER_INPUT -m conntrack --ctstate ESTABLISHED,RELATED -m comment --comment "Accept return traffic from established connections" -j ACCEPT + - iptables -A HARVESTER_INPUT -p icmp -m comment --comment "ICMP (ping, MTU discovery, etc.)" -j ACCEPT + - iptables -A HARVESTER_INPUT -s 10.52.0.0/16 -m comment --comment "Allow pod network return traffic" -j ACCEPT + - iptables -A HARVESTER_INPUT -p udp --sport 67 --dport 68 -m comment --comment "DHCP server reply" -j ACCEPT + - iptables -A HARVESTER_INPUT -p udp --sport 68 --dport 67 -m comment --comment "DHCP client request" -j ACCEPT + - iptables -A HARVESTER_INPUT -p tcp --dport 22 -m comment --comment "SSH" -j ACCEPT + - iptables -A HARVESTER_INPUT -p tcp --dport 2379:2380 -m comment --comment "etcd client/peer" -j ACCEPT + - iptables -A HARVESTER_INPUT -p tcp --dport 9091 -m comment --comment "calico-node metrics (Prometheus)" -j ACCEPT + - iptables -A HARVESTER_INPUT -p tcp --dport 9345 -m comment --comment "RKE2 supervisor API" -j ACCEPT + - iptables -A HARVESTER_INPUT -p tcp --dport 9796 -m comment --comment "Prometheus node-exporter metrics (rancher-monitoring)" -j ACCEPT + - iptables -A HARVESTER_INPUT -p tcp --dport 10250 -m comment --comment "kubelet API" -j ACCEPT + - iptables -A HARVESTER_INPUT -p udp --dport 8472 -m comment --comment "VXLAN (Flannel/Canal)" -j ACCEPT + - iptables -A HARVESTER_INPUT -p tcp --dport 10665 -m comment --comment "kube-ovn-daemon (kubeovn-operator)" -j ACCEPT + - iptables -A HARVESTER_INPUT -p udp --dport 4789 -m comment --comment "VXLAN (Kube-OVN, kubeovn-operator)" -j ACCEPT + - iptables -A HARVESTER_INPUT -m limit --limit 10/min -m comment --comment "Rate-limit logging of dropped packets" -j LOG --log-prefix HARVESTER_DROP_ --log-level 4 + - iptables -A HARVESTER_INPUT -m comment --comment "Drop all other traffic" -j DROP + paused: false +``` + +## Upgrade + +### False Positives During Upgrade + +During an upgrade, Harvester restarts multiple components. Each restart clears conntrack state for the affected connections, causing return traffic to hit the DROP rule temporarily — the same false positive mechanism described in [False Positives](#false-positives), but repeating throughout the upgrade. + +You might see entries like these: + +``` +May 05 04:40:28 harvester1 kernel: HARVESTER_DROP_IN=mgmt-br ... SRC=192.168.122.62 DST=192.168.122.61 ... PROTO=TCP SPT=10250 DPT=56266 ... ACK RST URGP=0 +May 05 04:43:35 harvester2 kernel: HARVESTER_DROP_IN=mgmt-br ... SRC=192.168.122.61 DST=192.168.122.62 ... PROTO=TCP SPT=6443 DPT=43707 ... ACK URGP=0 +``` + +Both entries are false positives: +- `SPT=10250 ACK RST` — kubelet restarted and reset an existing connection; the RST packet no longer has a conntrack state. +- `SPT=6443 ACK` — the API server restarted; return traffic from pre-restart connections lost conntrack state. + +These entries may persist for the duration of the upgrade and stop once all components have stabilized. This is expected behavior and does not indicate missing rules. + +If entries with `SYN` flags or unrecognized `DPT` values **persist after the upgrade completes**, a rule may be missing. + +### Network Issues During Upgrade + +If you still encounter network issues during the upgrade, refer to [Remove the iptables Rules](#remove-the-iptables-rules) to remove the chain before upgrading, and re-apply it after the upgrade completes. \ No newline at end of file