wren-linux / tools / test-ping.sh
#!/bin/bash
# Checks that this laptop doesn't answer pings (data/sysctl-hardening.conf):
# the file's ICMP settings are loaded into a network namespace of its own
# (unshare -rn, no sudo), where 127.0.0.1 and ::1 must stop answering. Without
# ping or user namespaces, only the file itself is checked.
# Run by test.sh, or: bash tools/test-ping.sh
# shellcheck disable=SC2016 # the sh -c and eval lines expand their own variables
HERE=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)
CONF=$HERE/data/sysctl-hardening.conf
fails=0
check() { # DESCRIPTION CONDITION-COMMAND...
local what=$1
shift
if "$@" >/dev/null 2>&1; then printf ' ok %s\n' "$what"; else printf ' FAIL %s\n' "$what"; fails=$((fails + 1)); fi
}
check "pings over IPv4 go unanswered" grep -qxE 'net\.ipv4\.icmp_echo_ignore_all *= *1' "$CONF"
check "pings over IPv6 go unanswered" grep -qxE 'net\.ipv6\.icmp\.echo_ignore_all *= *1' "$CONF"
if ! command -v ping >/dev/null || ! unshare -rn true 2>/dev/null; then
printf ' ok skipped: no ping, or no user namespaces here, for the real check\n'
exit $((fails > 0))
fi
# In the namespace: does loopback answer before, and after the file's ICMP
# settings? Prints one word per ping.
out=$(unshare -rn sh -c '
ip link set lo up
ping -c1 -W1 127.0.0.1 >/dev/null 2>&1 && echo v4-before
grep -E "^net\.ipv[46]\.icmp" "$1" | while read -r key _ value; do
echo "$value" > "/proc/sys/$(echo "$key" | tr . /)"
done
ping -c1 -W1 127.0.0.1 >/dev/null 2>&1 && echo v4-after
ping -6 -c1 -W1 ::1 >/dev/null 2>&1 && echo v6-after
exit 0' sh "$CONF" 2>&1)
check "a ping is answered without the settings (the check can see one)" grep -qx v4-before <<<"$out"
check "with the settings, 127.0.0.1 doesn't answer a ping" eval '! grep -qx v4-after <<<"$out"'
check "with the settings, ::1 doesn't answer a ping" eval '! grep -qx v6-after <<<"$out"'
exit $((fails > 0))