Skip to content

Commit 21c5290

Browse files
aaurenmrueg
authored andcommitted
feat(iptables): add upstream wrapper script
1 parent 295c862 commit 21c5290

File tree

2 files changed

+232
-0
lines changed

2 files changed

+232
-0
lines changed

Dockerfile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,17 @@ COPY build/image-assets/vimrc /root/.vimrc
2121
COPY build/image-assets/motd-kube-router.sh /etc/motd-kube-router.sh
2222
COPY kube-router gobgp /usr/local/bin/
2323

24+
# Use iptables-wrappers so that correct version of iptables-legacy or iptables-nft gets used. Alpine contains both, but
25+
# which version is used should be based on the host system as well as where rules that may have been added before
26+
# kube-router are being placed. For more information see: https://github.com/kubernetes-sigs/iptables-wrappers
27+
COPY build/image-assets/iptables-wrapper-installer.sh /
28+
# This is necessary because of the bug reported here: https://github.com/flannel-io/flannel/pull/1340/files
29+
# Basically even under QEMU emulation, it still doesn't have an ARM kernel in-play which means that calls to
30+
# iptables-nft will fail in the build process. The sanity check here only makes sure that we are not using
31+
# iptables-1.8.0-1.8.2. For now we'll manage that on our own.
32+
RUN /iptables-wrapper-installer.sh --no-sanity-check
33+
34+
2435
# Since alpine image doesn't contain /etc/nsswitch.conf, the hosts in /etc/hosts (e.g. localhost)
2536
# cannot be used. So manually add /etc/nsswitch.conf to work around this issue.
2637
RUN echo "hosts: files dns" > /etc/nsswitch.conf
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
#!/bin/sh
2+
3+
# Copyright 2020 The Kubernetes Authors.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
# Usage:
18+
#
19+
# iptables-wrapper-installer.sh [--no-sanity-check]
20+
#
21+
# Installs a wrapper iptables script in a container that will figure out
22+
# whether iptables-legacy or iptables-nft is in use on the host and then
23+
# replaces itself with the correct underlying iptables version.
24+
#
25+
# Unless "--no-sanity-check" is passed, it will first verify that the
26+
# container already contains a suitable version of iptables.
27+
28+
# NOTE: This can only use POSIX /bin/sh features; the build container
29+
# might not contain bash.
30+
31+
# This script was taken verbatum from upstream on 4/8/2021:
32+
# https://github.com/kubernetes-sigs/iptables-wrappers/blob/master/iptables-wrapper-installer.sh
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.[012]\ *)
71+
echo "ERROR: iptables 1.8.0 - 1.8.2 have compatibility bugs." 1>&2
72+
echo " Upgrade to 1.8.3 or newer." 1>&2
73+
exit 1
74+
;;
75+
*v1.8.3\ *)
76+
# 1.8.3 mostly works but can get stuck in an infinite loop if the nft
77+
# kernel modules are unavailable
78+
need_timeout=1
79+
;;
80+
*)
81+
# 1.8.4+ are OK
82+
;;
83+
esac
84+
fi
85+
86+
# Start creating the wrapper...
87+
rm -f "${sbin}/iptables-wrapper"
88+
cat > "${sbin}/iptables-wrapper" <<EOF
89+
#!/bin/sh
90+
91+
# Copyright 2020 The Kubernetes Authors.
92+
#
93+
# Licensed under the Apache License, Version 2.0 (the "License");
94+
# you may not use this file except in compliance with the License.
95+
# You may obtain a copy of the License at
96+
#
97+
# http://www.apache.org/licenses/LICENSE-2.0
98+
#
99+
# Unless required by applicable law or agreed to in writing, software
100+
# distributed under the License is distributed on an "AS IS" BASIS,
101+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
102+
# See the License for the specific language governing permissions and
103+
# limitations under the License.
104+
105+
# NOTE: This can only use POSIX /bin/sh features; the container image
106+
# might not contain bash.
107+
108+
set -eu
109+
110+
# Detect whether the base system is using iptables-legacy or
111+
# iptables-nft. This assumes that some non-containerized process (eg
112+
# kubelet) has already created some iptables rules.
113+
EOF
114+
115+
if [ "${need_timeout:-0}" = 0 ]; then
116+
# Write out the simpler version of legacy-vs-nft detection
117+
cat >> "${sbin}/iptables-wrapper" <<EOF
118+
num_legacy_lines=\$( (iptables-legacy-save || true; ip6tables-legacy-save || true) 2>/dev/null | grep '^-' | wc -l)
119+
num_nft_lines=\$( (iptables-nft-save || true; ip6tables-nft-save || true) 2>/dev/null | grep '^-' | wc -l)
120+
if [ "\${num_legacy_lines}" -ge "\${num_nft_lines}" ]; then
121+
mode=legacy
122+
else
123+
mode=nft
124+
fi
125+
EOF
126+
else
127+
# Write out the version of legacy-vs-nft detection with an nft timeout
128+
cat >> "${sbin}/iptables-wrapper" <<EOF
129+
# The iptables-nft binary in this image can get stuck in an infinite
130+
# loop if nft is not available so we need to wrap a timeout around it
131+
# (and to avoid that, we don't even bother calling iptables-nft if it
132+
# looks like iptables-legacy is going to win).
133+
num_legacy_lines=\$( (iptables-legacy-save || true; ip6tables-legacy-save || true) 2>/dev/null | grep '^-' | wc -l)
134+
if [ "\${num_legacy_lines}" -ge 10 ]; then
135+
mode=legacy
136+
else
137+
num_nft_lines=\$( (timeout 5 sh -c "iptables-nft-save; ip6tables-nft-save" || true) 2>/dev/null | grep '^-' | wc -l)
138+
if [ "\${num_legacy_lines}" -ge "\${num_nft_lines}" ]; then
139+
mode=legacy
140+
else
141+
mode=nft
142+
fi
143+
fi
144+
EOF
145+
fi
146+
147+
# Write out the appropriate alternatives-selection commands
148+
case "${altstyle}" in
149+
fedora)
150+
cat >> "${sbin}/iptables-wrapper" <<EOF
151+
# Update links to point to the selected binaries
152+
alternatives --set iptables "/usr/sbin/iptables-\${mode}" > /dev/null || failed=1
153+
EOF
154+
;;
155+
156+
debian)
157+
cat >> "${sbin}/iptables-wrapper" <<EOF
158+
# Update links to point to the selected binaries
159+
update-alternatives --set iptables "/usr/sbin/iptables-\${mode}" > /dev/null || failed=1
160+
update-alternatives --set ip6tables "/usr/sbin/ip6tables-\${mode}" > /dev/null || failed=1
161+
EOF
162+
;;
163+
164+
*)
165+
cat >> "${sbin}/iptables-wrapper" <<EOF
166+
# Update links to point to the selected binaries
167+
for cmd in iptables iptables-save iptables-restore ip6tables ip6tables-save ip6tables-restore; do
168+
rm -f "${sbin}/\${cmd}"
169+
ln -s "${sbin}/xtables-\${mode}-multi" "${sbin}/\${cmd}"
170+
done 2>/dev/null || failed=1
171+
EOF
172+
;;
173+
esac
174+
175+
# Write out the post-alternatives-selection error checking and final wrap-up
176+
cat >> "${sbin}/iptables-wrapper" <<EOF
177+
if [ "\${failed:-0}" = 1 ]; then
178+
echo "Unable to redirect iptables binaries. (Are you running in an unprivileged pod?)" 1>&2
179+
# fake it, though this will probably also fail if they aren't root
180+
exec "${sbin}/xtables-\${mode}-multi" "\$0" "\$@"
181+
fi
182+
183+
# Now re-exec the original command with the newly-selected alternative
184+
exec "\$0" "\$@"
185+
EOF
186+
chmod +x "${sbin}/iptables-wrapper"
187+
188+
# Now back in the installer script, point the iptables binaries at our
189+
# wrapper
190+
case "${altstyle}" in
191+
fedora)
192+
alternatives \
193+
--install /usr/sbin/iptables iptables /usr/sbin/iptables-wrapper 100 \
194+
--slave /usr/sbin/iptables-restore iptables-restore /usr/sbin/iptables-wrapper \
195+
--slave /usr/sbin/iptables-save iptables-save /usr/sbin/iptables-wrapper \
196+
--slave /usr/sbin/ip6tables iptables /usr/sbin/iptables-wrapper \
197+
--slave /usr/sbin/ip6tables-restore iptables-restore /usr/sbin/iptables-wrapper \
198+
--slave /usr/sbin/ip6tables-save iptables-save /usr/sbin/iptables-wrapper
199+
;;
200+
201+
debian)
202+
update-alternatives \
203+
--install /usr/sbin/iptables iptables /usr/sbin/iptables-wrapper 100 \
204+
--slave /usr/sbin/iptables-restore iptables-restore /usr/sbin/iptables-wrapper \
205+
--slave /usr/sbin/iptables-save iptables-save /usr/sbin/iptables-wrapper
206+
update-alternatives \
207+
--install /usr/sbin/ip6tables ip6tables /usr/sbin/iptables-wrapper 100 \
208+
--slave /usr/sbin/ip6tables-restore ip6tables-restore /usr/sbin/iptables-wrapper \
209+
--slave /usr/sbin/ip6tables-save ip6tables-save /usr/sbin/iptables-wrapper
210+
;;
211+
212+
*)
213+
for cmd in iptables iptables-save iptables-restore ip6tables ip6tables-save ip6tables-restore; do
214+
rm -f "${sbin}/${cmd}"
215+
ln -s "${sbin}/iptables-wrapper" "${sbin}/${cmd}"
216+
done
217+
;;
218+
esac
219+
220+
# Cleanup
221+
rm -f "$0"

0 commit comments

Comments
 (0)