Skip to main content

The --make-iptables-util-chains Argument Is Set To True

More Info:​

When makeIPTablesUtilChains is true, the kubelet manages the iptables utility chains needed for correct pod networking and traffic filtering on the node.

Risk Level​

Medium

Address​

Security

Compliance Standards​

  • CIS EKS

Triage and Remediation​

Remediation​

Manual Steps
  1. On every worker node, open the kubelet config file and set makeIPTablesUtilChains to true:

    sudo mkdir -p /etc/kubernetes/kubelet
    sudo sed -i '/makeIPTablesUtilChains/d' /var/lib/kubelet/config.yaml
    echo 'makeIPTablesUtilChains: true' | sudo tee -a /var/lib/kubelet/config.yaml

    If your environment instead uses /etc/kubernetes/kubelet/kubelet-config.json, edit that file:

    sudo sed -i '/makeIPTablesUtilChains/d' /etc/kubernetes/kubelet/kubelet-config.json
    sudo sed -i 's/^{/{\n "makeIPTablesUtilChains": true,/' /etc/kubernetes/kubelet/kubelet-config.json
  2. On every worker node, ensure the systemd drop-in does not override this setting:

    if [ -f /etc/systemd/system/kubelet.service.d/10-kubelet-args.conf ]; then
    sudo sed -i 's/--make-iptables-util-chains[=:][^[:space:]]*//g' /etc/systemd/system/kubelet.service.d/10-kubelet-args.conf
    fi
  3. On every worker node, reload systemd and restart kubelet (this restarts the kubelet and may briefly disrupt workloads on that node):

    sudo systemctl daemon-reload
    sudo systemctl restart kubelet.service
    sudo systemctl status kubelet -l
  4. From any machine with kubectl access, optionally verify the live kubelet config via the configz endpoint for a given worker node:

    kubectl proxy --port=8001 &
    export HOSTNAME_PORT=localhost:8001
    export NODE_NAME=<worker-node-name>
    curl -sSL "http://${HOSTNAME_PORT}/api/v1/nodes/${NODE_NAME}/proxy/configz" | grep -i makeIPTablesUtilChains
  5. On every worker node, confirm the running kubelet process is not passing a conflicting --make-iptables-util-chains flag:

    /bin/ps -fC kubelet

    Ensure the command line either omits --make-iptables-util-chains (so the config file value is used) or, if present, has it set to true.

Using kubectl

kubectl cannot modify the kubelet’s host-level configuration or process flags, including makeIPTablesUtilChains. This finding must be remediated directly on each worker node by editing the kubelet config and/or systemd unit files as described in the Manual Steps section.

Automation
#!/usr/bin/env bash
#
# Fix CISEKS 3.2.6: Ensure that the --make-iptables-util-chains argument is set to true
#
# Run on: every worker node (with root privileges)
# Safe to re-run: yes

set -euo pipefail

KUBELET_CONF_JSON="/etc/kubernetes/kubelet/kubelet-config.json"
KUBELET_DROPIN="/etc/systemd/system/kubelet.service.d/10-kubelet-args.conf"

echo "[INFO] Ensuring kubelet manages iptables utility chains (makeIPTablesUtilChains: true)"

#-------------------------------------------------------------------------------
# Helper: ensure string is present and not contradicted in systemd drop-in
#-------------------------------------------------------------------------------
ensure_no_make_iptables_flag_in_dropin() {
local f="$1"
if [[ ! -f "$f" ]]; then
echo "[INFO] Systemd drop-in $f not found; nothing to clean."
return 0
fi

if grep -q -- "--make-iptables-util-chains" "$f"; then
echo "[INFO] Removing --make-iptables-util-chains from $f to avoid overriding kubelet config."

cp -a "$f" "${f}.bak.$(date +%Y%m%d%H%M%S)"

# Remove any occurrences of the flag in the file
# Handles both '--make-iptables-util-chains=true' and '--make-iptables-util-chains:false' variants
sed -i 's/\s*--make-iptables-util-chains[=:]\(true\|false\)//g' "$f"

echo "[INFO] Cleaned $f. Backup saved as ${f}.bak.*"
else
echo "[INFO] No --make-iptables-util-chains flag found in $f; leaving as-is."
fi
}

#-------------------------------------------------------------------------------
# Method 1: Kubelet config file (preferred, per remediation)
#-------------------------------------------------------------------------------
configure_kubelet_config_file() {
local f="$1"

if [[ ! -f "$f" ]]; then
echo "[WARN] $f does not exist; skipping Method 1 remediation."
return 1
fi

cp -a "$f" "${f}.bak.$(date +%Y%m%d%H%M%S)"

if command -v jq >/dev/null 2>&1; then
echo "[INFO] Using jq to set makeIPTablesUtilChains: true in $f"
tmp="$(mktemp)"
jq '.makeIPTablesUtilChains = true' "$f" > "$tmp"
mv "$tmp" "$f"
else
echo "[INFO] jq not available; updating $f with sed/awk."

# If key exists, set it to true; otherwise insert it near the top-level keys.
if grep -q '"makeIPTablesUtilChains"' "$f"; then
sed -i 's/"makeIPTablesUtilChains"[[:space:]]*:[[:space:]]*[^,]*/"makeIPTablesUtilChains": true/' "$f"
else
# Insert after first '{' (simple but safe for standard kubelet-config.json)
tmp="$(mktemp)"
awk '
BEGIN{inserted=0}
{
print $0
if (!inserted && $0 ~ /{/) {
print " \"makeIPTablesUtilChains\": true,"
inserted=1
}
}
' "$f" > "$tmp"
mv "$tmp" "$f"
fi
fi

echo "[INFO] Updated $f to ensure makeIPTablesUtilChains: true"
return 0
}

#-------------------------------------------------------------------------------
# Method 2 fallback: systemd executable argument if no kubelet-config.json
#-------------------------------------------------------------------------------
configure_kubelet_service_args() {
local f="$1"

if [[ ! -f "$f" ]]; then
echo "[WARN] $f not found; cannot apply Method 2 remediation."
return 1
fi

cp -a "$f" "${f}.bak.$(date +%Y%m%d%H%M%S)"

# Ensure we have an Environment line defining KUBELET_ARGS or similar.
if ! grep -q "KUBELET_ARGS" "$f"; then
echo "[WARN] No KUBELET_ARGS variable found in $f; manual review needed."
return 1
fi

# Remove any existing make-iptables flag and append correct one once.
sed -i 's/\s*--make-iptables-util-chains[=:]\(true\|false\)//g' "$f"

if grep -q -- "--make-iptables-util-chains" "$f"; then
echo "[INFO] --make-iptables-util-chains already present in $f"
else
echo "[INFO] Adding --make-iptables-util-chains=true to KUBELET_ARGS in $f"
sed -i 's/^\(Environment=.*KUBELET_ARGS="\)\(.*\)"/\1\2 --make-iptables-util-chains=true"/' "$f"
fi

return 0
}

#-------------------------------------------------------------------------------
# Apply remediation
#-------------------------------------------------------------------------------
method_used="none"

if configure_kubelet_config_file "$KUBELET_CONF_JSON"; then
method_used="configfile"
ensure_no_make_iptables_flag_in_dropin "$KUBELET_DROPIN"
else
echo "[INFO] Falling back to Method 2 (systemd executable args)."
if configure_kubelet_service_args "$KUBELET_DROPIN"; then
method_used="serviceargs"
else
echo "[ERROR] Could not apply remediation via config file or service args. Manual intervention required."
exit 1
fi
fi

#-------------------------------------------------------------------------------
# Restart kubelet to apply changes
#-------------------------------------------------------------------------------
echo "[INFO] Reloading systemd and restarting kubelet (this will restart the kubelet on this node)."
systemctl daemon-reload
systemctl restart kubelet.service

# Optional: brief wait to ensure process is up
sleep 5

echo "[INFO] Checking kubelet status:"
systemctl status kubelet -l --no-pager || true

#-------------------------------------------------------------------------------
# Verification (adapted from audit command)
#-------------------------------------------------------------------------------
echo "[INFO] Verifying kubelet process flags for --make-iptables-util-chains=true"

/bin/ps -fC kubelet || {
echo "[ERROR] kubelet process not found after restart."
exit 1
}

if /bin/ps -o args= -C kubelet | grep -q -- "--make-iptables-util-chains=true"; then
echo "[PASS] kubelet is running with --make-iptables-util-chains=true"
else
echo "[WARN] kubelet is not showing --make-iptables-util-chains=true as an explicit flag."
echo " If Method 1 (config file) was used, this is expected; kubelet reads it from $KUBELET_CONF_JSON."
echo " Additional verification via configz endpoint is recommended:"
echo " kubectl proxy --port=8001 &"
echo " export HOSTNAME_PORT=localhost:8001"
echo " export NODE_NAME=<this-node-name-from-kubectl-get-nodes>"
echo " curl -sSL \"http://${HOSTNAME_PORT}/api/v1/nodes/\${NODE_NAME}/proxy/configz\" | grep -i makeIPTablesUtilChains"
fi

echo "[INFO] Remediation script completed on this node (method used: $method_used)"