github.com/cilium/cilium@v1.16.2/images/runtime/iptables-wrapper-installer.sh (about)

     1  #!/bin/sh
     2  # shellcheck disable=SC2166
     3  
     4  # This script is copied from upstream with below link
     5  # https://github.com/kubernetes-sigs/iptables-wrappers/blob/e139a115350974aac8a82ec4b815d2845f86997e/iptables-wrapper-installer.sh
     6  # Copyright 2020 The Kubernetes Authors.
     7  #
     8  # Licensed under the Apache License, Version 2.0 (the "License");
     9  # you may not use this file except in compliance with the License.
    10  # You may obtain a copy of the License at
    11  #
    12  #     http://www.apache.org/licenses/LICENSE-2.0
    13  #
    14  # Unless required by applicable law or agreed to in writing, software
    15  # distributed under the License is distributed on an "AS IS" BASIS,
    16  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    17  # See the License for the specific language governing permissions and
    18  # limitations under the License.
    19  
    20  # Usage:
    21  #
    22  #   iptables-wrapper-installer.sh [--no-sanity-check]
    23  #
    24  # Installs a wrapper iptables script in a container that will figure out
    25  # whether iptables-legacy or iptables-nft is in use on the host and then
    26  # replaces itself with the correct underlying iptables version.
    27  #
    28  # Unless "--no-sanity-check" is passed, it will first verify that the
    29  # container already contains a suitable version of iptables.
    30  
    31  # NOTE: This can only use POSIX /bin/sh features; the build container
    32  # might not contain bash.
    33  
    34  set -eu
    35  
    36  # Find iptables binary location
    37  if [ -d /usr/sbin -a -e /usr/sbin/iptables ]; then
    38      sbin="/usr/sbin"
    39  elif [ -d /sbin -a -e /sbin/iptables ]; then
    40      sbin="/sbin"
    41  else
    42      echo "ERROR: iptables is not present in either /usr/sbin or /sbin" 1>&2
    43      exit 1
    44  fi
    45  
    46  # Determine how the system selects between iptables-legacy and iptables-nft
    47  if [ -x /usr/sbin/alternatives ]; then
    48      # Fedora/SUSE style alternatives
    49      altstyle="fedora"
    50  elif [ -x /usr/sbin/update-alternatives ]; then
    51      # Debian style alternatives
    52      altstyle="debian"
    53  else
    54      # No alternatives system
    55      altstyle="none"
    56  fi
    57  
    58  if [ "${1:-}" != "--no-sanity-check" ]; then
    59      # Ensure dependencies are installed
    60      if ! version=$("${sbin}/iptables-nft" --version 2> /dev/null); then
    61          echo "ERROR: iptables-nft is not installed" 1>&2
    62          exit 1
    63      fi
    64      if ! "${sbin}/iptables-legacy" --version > /dev/null 2>&1; then
    65          echo "ERROR: iptables-legacy is not installed" 1>&2
    66          exit 1
    67      fi
    68  
    69      case "${version}" in
    70      *v1.8.[0123]\ *)
    71          echo "ERROR: iptables 1.8.0 - 1.8.3 have compatibility bugs." 1>&2
    72          echo "       Upgrade to 1.8.4 or newer." 1>&2
    73          exit 1
    74          ;;
    75      *)
    76          # 1.8.4+ are OK
    77          ;;
    78      esac
    79  fi
    80  
    81  # Start creating the wrapper...
    82  rm -f "${sbin}/iptables-wrapper"
    83  cat > "${sbin}/iptables-wrapper" <<EOF
    84  #!/bin/sh
    85  
    86  # Copyright 2020 The Kubernetes Authors.
    87  #
    88  # Licensed under the Apache License, Version 2.0 (the "License");
    89  # you may not use this file except in compliance with the License.
    90  # You may obtain a copy of the License at
    91  #
    92  #     http://www.apache.org/licenses/LICENSE-2.0
    93  #
    94  # Unless required by applicable law or agreed to in writing, software
    95  # distributed under the License is distributed on an "AS IS" BASIS,
    96  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    97  # See the License for the specific language governing permissions and
    98  # limitations under the License.
    99  
   100  # NOTE: This can only use POSIX /bin/sh features; the container image
   101  # might not contain bash.
   102  
   103  # This is a Cilium variant of the original Kubernetes iptablejs-wrapper
   104  # the change is to follow Kube-proxy instead of Kubelet. This fixes
   105  # issues where kube-proxy and kubelet iptables versions are not in
   106  # sync and we observed kube-proxy incorrectly using different ipt/nft
   107  # configuration from kubelet.
   108  
   109  set -eu
   110  
   111  # In kubernetes 1.17 and later, kubelet will have created at least
   112  # one chain in the "mangle" table (either "KUBE-IPTABLES-HINT" or
   113  # "KUBE-KUBELET-CANARY"), we expect kubeproxy will follow similar
   114  # pattern so we check that first, against iptables-nft, because we
   115  # can check that more efficiently and it's more common these days.
   116  nft_kubeproxy_rules=\$( (iptables-nft-save -t mangle || true; ip6tables-nft-save -t mangle || true) 2>/dev/null | grep -E '^:(KUBE-IPTABLES-HINT|KUBE-PROXY-CANARY)' | wc -l)
   117  if [ "\${nft_kubeproxy_rules}" -ne 0 ]; then
   118      mode=nft
   119  else
   120      # Next lets check for a kubeproxy canary in iptables indicating
   121      # kube-proxy is using ipt.
   122      legacy_kubeproxy_rules=\$( (iptables-legacy-save || true; ip6tables-legacy-save || true) 2>/dev/null | grep -E '^:(KUBE-IPTABLES-HINT|KUBE-PROXY-CANARY)' | wc -l)
   123      if [ "\${legacy_kubeproxy_rules}" -ne 0 ]; then
   124          mode=legacy
   125      else
   126  	# If we did not find a kube proxy canary either we started before
   127  	# kube-proxy or it doesn't exist so lets use ipwrapper standard
   128  	# logic to follow kubelet.
   129          nft_kubelet_rules=\$( (iptables-nft-save -t mangle || true; ip6tables-nft-save -t mangle || true) 2>/dev/null | grep -E '^:KUBE-KUBELET-CANARY' | wc -l)
   130          if [ "\${nft_kubeproxy_rules}" -ne 0 ]; then
   131  		mode = nft
   132  	else
   133      	    # Check for kubernetes 1.17-or-later with iptables-legacy. We
   134      	    # can't pass "-t mangle" to iptables-legacy-save because it would
   135      	    # cause the kernel to create that table if it didn't already
   136      	    # exist, which we don't want. So we have to grab all the rules
   137      	    legacy_kubelet_rules=\$( (iptables-legacy-save || true; ip6tables-legacy-save || true) 2>/dev/null | grep -E '^:KUBE-KUBELET-CANARY' | wc -l)
   138      	    if [ "\${legacy_kubelet_rules}" -ne 0 ]; then
   139      	        mode=legacy
   140      	    else
   141      	        # With older kubernetes releases there may not be any _specific_
   142      	        # rules we can look for, but we assume that some non-containerized process
   143      	        # (possibly kubelet) will have created _some_ iptables rules.
   144      	        num_legacy_lines=\$( (iptables-legacy-save || true; ip6tables-legacy-save || true) 2>/dev/null | grep '^-' | wc -l)
   145  	        num_nft_lines=\$( (iptables-nft-save || true; ip6tables-nft-save || true) 2>/dev/null | grep '^-' | wc -l)
   146                  if [ "\${num_legacy_lines}" -gt "\${num_nft_lines}" ]; then
   147              	    mode=legacy
   148                  else
   149              	    mode=nft
   150  	        fi
   151              fi
   152  	fi
   153      fi
   154  fi
   155  
   156  EOF
   157  
   158  # Write out the appropriate alternatives-selection commands
   159  case "${altstyle}" in
   160      fedora)
   161  cat >> "${sbin}/iptables-wrapper" <<EOF
   162  # Update links to point to the selected binaries
   163  alternatives --set iptables "/usr/sbin/iptables-\${mode}" > /dev/null || failed=1
   164  EOF
   165      ;;
   166  
   167      debian)
   168  cat >> "${sbin}/iptables-wrapper" <<EOF
   169  # Update links to point to the selected binaries
   170  update-alternatives --set iptables "/usr/sbin/iptables-\${mode}" > /dev/null || failed=1
   171  update-alternatives --set ip6tables "/usr/sbin/ip6tables-\${mode}" > /dev/null || failed=1
   172  EOF
   173      ;;
   174  
   175      *)
   176  cat >> "${sbin}/iptables-wrapper" <<EOF
   177  # Update links to point to the selected binaries
   178  for cmd in iptables iptables-save iptables-restore ip6tables ip6tables-save ip6tables-restore; do
   179      rm -f "${sbin}/\${cmd}"
   180      ln -s "${sbin}/xtables-\${mode}-multi" "${sbin}/\${cmd}"
   181  done 2>/dev/null || failed=1
   182  EOF
   183      ;;
   184  esac
   185  
   186  # Write out the post-alternatives-selection error checking and final wrap-up
   187  cat >> "${sbin}/iptables-wrapper" <<EOF
   188  if [ "\${failed:-0}" = 1 ]; then
   189      echo "Unable to redirect iptables binaries. (Are you running in an unprivileged pod?)" 1>&2
   190      # fake it, though this will probably also fail if they aren't root
   191      exec "${sbin}/xtables-\${mode}-multi" "\$0" "\$@"
   192  fi
   193  
   194  # Now re-exec the original command with the newly-selected alternative
   195  exec "\$0" "\$@"
   196  EOF
   197  chmod +x "${sbin}/iptables-wrapper"
   198  
   199  # Now back in the installer script, point the iptables binaries at our
   200  # wrapper
   201  case "${altstyle}" in
   202      fedora)
   203  	alternatives \
   204              --install /usr/sbin/iptables iptables /usr/sbin/iptables-wrapper 100 \
   205              --slave /usr/sbin/iptables-restore iptables-restore /usr/sbin/iptables-wrapper \
   206              --slave /usr/sbin/iptables-save iptables-save /usr/sbin/iptables-wrapper \
   207              --slave /usr/sbin/ip6tables iptables /usr/sbin/iptables-wrapper \
   208              --slave /usr/sbin/ip6tables-restore iptables-restore /usr/sbin/iptables-wrapper \
   209              --slave /usr/sbin/ip6tables-save iptables-save /usr/sbin/iptables-wrapper
   210  	;;
   211  
   212      debian)
   213  	update-alternatives \
   214              --install /usr/sbin/iptables iptables /usr/sbin/iptables-wrapper 100 \
   215              --slave /usr/sbin/iptables-restore iptables-restore /usr/sbin/iptables-wrapper \
   216              --slave /usr/sbin/iptables-save iptables-save /usr/sbin/iptables-wrapper
   217  	update-alternatives \
   218              --install /usr/sbin/ip6tables ip6tables /usr/sbin/iptables-wrapper 100 \
   219              --slave /usr/sbin/ip6tables-restore ip6tables-restore /usr/sbin/iptables-wrapper \
   220              --slave /usr/sbin/ip6tables-save ip6tables-save /usr/sbin/iptables-wrapper
   221  	;;
   222  
   223      *)
   224  	for cmd in iptables iptables-save iptables-restore ip6tables ip6tables-save ip6tables-restore; do
   225              rm -f "${sbin}/${cmd}"
   226              ln -s "${sbin}/iptables-wrapper" "${sbin}/${cmd}"
   227  	done
   228  	;;
   229  esac
   230  
   231  # Cleanup
   232  rm -f "$0"