mirror of
https://github.com/systemd/systemd.git
synced 2026-11-06 05:17:24 +00:00
imds: warn if net.ipv4.conf.all.rp_filter breaks locked mode
Make that caveat from the previous commit more obvious with a logged warning, and document the workaround (or really, the fix) of disabling `net.ipv4.conf.all.rp_filter` globally. Signed-off-by: Martin Pitt <martin@amutable.com>
This commit is contained in:
1 parent
9d7ae503d9
commit
cec6bc4ea6
4 files changed
+46
-5
No files matched your search
@@ -78,6 +78,16 @@
|
||||
set to <literal>unlocked</literal> (the default) this "prohibit" route is not created, and regular unprivileged
|
||||
processes can directly contact IMDS.</para>
|
||||
|
||||
<para>Some systems set <varname>net.ipv4.conf.all.rp_filter</varname>. With
|
||||
<literal>locked</literal>, IMDS then cannot be reached. <command>systemd-imdsd</command> warns about
|
||||
this when setting up the network. To allow IMDS access, turn it off with a
|
||||
<citerefentry><refentrytitle>sysctl.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
drop-in, e.g. <filename>/etc/sysctl.d/90-imds.conf</filename>:</para>
|
||||
<programlisting>net.ipv4.conf.all.rp_filter = 0</programlisting>
|
||||
|
||||
<para>systemd's <filename>50-default.conf</filename> already turns on reverse path filtering for every
|
||||
individual link, so all other links keep it.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v261"/>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
+17
-1
@@ -47,6 +47,7 @@
|
||||
#include "socket-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "sysctl-util.h"
|
||||
#include "time-util.h"
|
||||
#include "tmpfile-util.h"
|
||||
#include "utf8.h"
|
||||
@@ -1637,6 +1638,19 @@ static int imds_configured(int level) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void warn_rp_filter_all(void) {
|
||||
int r, v;
|
||||
|
||||
/* The kernel applies the maximum of the link's and the "all" setting, so turning off reverse path
|
||||
* filtering on the link does not help if "all" turns it on. */
|
||||
r = sysctl_read_ip_property_int(AF_INET, "all", "rp_filter", &v);
|
||||
if (r < 0)
|
||||
return (void) log_debug_errno(r, "Failed to read net.ipv4.conf.all.rp_filter, ignoring: %m");
|
||||
if (v != 0)
|
||||
log_warning("net.ipv4.conf.all.rp_filter=%i turns on IPv4 reverse path filtering on all links, "
|
||||
"which drops IMDS replies in locked mode. Set it to 0 to allow IMDS access.", v);
|
||||
}
|
||||
|
||||
static int setup_network(void) {
|
||||
int r;
|
||||
|
||||
@@ -1691,9 +1705,11 @@ static int setup_network(void) {
|
||||
/* IMDS's replies to imdsd carry no firewall mark. Reverse path filtering would check their source
|
||||
* address against the main table, find the prohibit route below, and drop them. IPv6 has no
|
||||
* reverse path filter. */
|
||||
if (arg_network_mode != IMDS_NETWORK_UNLOCKED && in4_addr_is_set(&arg_address_ipv4))
|
||||
if (arg_network_mode != IMDS_NETWORK_UNLOCKED && in4_addr_is_set(&arg_address_ipv4)) {
|
||||
fputs("# Reverse path filtering would drop IMDS's replies due to the prohibit route\n"
|
||||
"IPv4ReversePathFilter=no\n", f);
|
||||
warn_rp_filter_all();
|
||||
}
|
||||
|
||||
fputs("\n"
|
||||
"[DHCP]\n"
|
||||
|
||||
@@ -25,6 +25,10 @@ at_exit() {
|
||||
rmdir /run/systemd/system/systemd-imdsd@.service.d
|
||||
# cached negative entries would short-circuit the /flaky retry on a rerun
|
||||
rm -rf /run/systemd/imds/cache/veth-imds
|
||||
if [[ -v RP_FILTER_ALL ]]; then
|
||||
rm -f /run/sysctl.d/90-imds.conf
|
||||
sysctl -w net.ipv4.conf.all.rp_filter="$RP_FILTER_ALL"
|
||||
fi
|
||||
rm -rf "$WORK_DIR"
|
||||
}
|
||||
|
||||
@@ -168,11 +172,12 @@ ip -n imds addr add 169.254.169.254/32 dev veth-imds-peer
|
||||
IMDSD_LOCKED=("${IMDSD[@]}" --data-url=http://169.254.169.254:8088 --address-ipv4=169.254.169.254)
|
||||
|
||||
# Unlocked mode has no prohibit route, and keeps reverse path filtering
|
||||
SYSTEMD_PROC_CMDLINE=systemd.imds.network=unlocked "${IMDSD[@]}" --address-ipv4=169.254.169.254 --setup-network
|
||||
SYSTEMD_PROC_CMDLINE=systemd.imds.network=unlocked "${IMDSD[@]}" --address-ipv4=169.254.169.254 --setup-network 2>&1 | tee "$WORK_DIR/setup-network-unlocked.log"
|
||||
cat /run/systemd/network/85-imds-early.network
|
||||
(! grep -F -e "Type=prohibit" -e "IPv4ReversePathFilter=" /run/systemd/network/85-imds-early.network >/dev/null)
|
||||
(! grep -F "net.ipv4.conf.all.rp_filter" "$WORK_DIR/setup-network-unlocked.log" >/dev/null)
|
||||
|
||||
SYSTEMD_PROC_CMDLINE=systemd.imds.network=locked "${IMDSD_LOCKED[@]}" --setup-network
|
||||
SYSTEMD_PROC_CMDLINE=systemd.imds.network=locked "${IMDSD_LOCKED[@]}" --setup-network 2>&1 | tee "$WORK_DIR/setup-network.log"
|
||||
cat /run/systemd/network/85-imds-early.network
|
||||
grep -Fx "Type=prohibit" /run/systemd/network/85-imds-early.network >/dev/null
|
||||
grep -Fx "IPv4ReversePathFilter=no" /run/systemd/network/85-imds-early.network >/dev/null
|
||||
@@ -204,15 +209,25 @@ assert_eq "$(sysctl -n net.ipv4.conf.veth-imds.rp_filter)" 0
|
||||
# applies the maximum of that and net.ipv4.conf.all.rp_filter, which some distributions turn on (e.g.
|
||||
# Ubuntu). Then the reverse path filter still drops the replies.
|
||||
if [[ "$(sysctl -n net.ipv4.conf.all.rp_filter)" == 0 ]]; then
|
||||
(! grep -F "net.ipv4.conf.all.rp_filter" "$WORK_DIR/setup-network.log" >/dev/null)
|
||||
assert_eq "$("${IMDSD_LOCKED[@]}" --interface=veth-imds /hostname)" "piff"
|
||||
else
|
||||
echo "WARNING: net.ipv4.conf.all.rp_filter is on, imdsd cannot reach IMDS in locked mode"
|
||||
grep -F "net.ipv4.conf.all.rp_filter=" "$WORK_DIR/setup-network.log" >/dev/null
|
||||
# Do not wait for imdsd's overall 40s timeout (too annoying); instead, check that reverse path
|
||||
# filtering drops the replies
|
||||
rp_filter_drops() { nstat -asz TcpExtIPReversePathFilter | awk '/IPReversePathFilter/ { print $2 }'; }
|
||||
DROPS="$(rp_filter_drops)"
|
||||
assert_rc 124 timeout 5 "${IMDSD_LOCKED[@]}" --interface=veth-imds /hostname
|
||||
(( "$(rp_filter_drops)" > DROPS ))
|
||||
|
||||
# The documented workaround. Only apply this file: all sysctl.d files would also reset the link's
|
||||
# setting, which networkd configures after them during boot.
|
||||
RP_FILTER_ALL="$(sysctl -n net.ipv4.conf.all.rp_filter)"
|
||||
mkdir -p /run/sysctl.d
|
||||
echo "net.ipv4.conf.all.rp_filter = 0" >/run/sysctl.d/90-imds.conf
|
||||
/usr/lib/systemd/systemd-sysctl /run/sysctl.d/90-imds.conf
|
||||
sysctl net.ipv4.conf.all.rp_filter net.ipv4.conf.veth-imds.rp_filter
|
||||
assert_eq "$("${IMDSD_LOCKED[@]}" --interface=veth-imds /hostname)" "piff"
|
||||
fi
|
||||
|
||||
# Everybody else gets blocked
|
||||
|
||||
@@ -15,7 +15,7 @@ Before=network-pre.target
|
||||
Wants=network-pre.target
|
||||
Conflicts=shutdown.target initrd-switch-root.target
|
||||
Before=shutdown.target initrd-switch-root.target
|
||||
After=sys-devices-virtual-dmi-id.device
|
||||
After=sys-devices-virtual-dmi-id.device systemd-sysctl.service
|
||||
|
||||
[Service]
|
||||
ExecStart={{LIBEXECDIR}}/systemd-imdsd --setup-network
|
||||
|
||||
Reference in new issue
Block a user