134 lines
4.9 KiB
Bash
134 lines
4.9 KiB
Bash
#!/bin/bash
|
|
# Turns the contest restrictions off and on, for maintenance. Root only, so
|
|
# it is used through sudo from the administrator account (icpc).
|
|
#
|
|
# sudo contest-restrictions status
|
|
# sudo contest-restrictions report [SINCE] (refused attempts, default: today)
|
|
# sudo contest-restrictions off [all|firewall|usb|network]
|
|
# sudo contest-restrictions on [all|firewall|usb|network]
|
|
#
|
|
# firewall firewall, web proxy, DNS filter (/disable_firewall.sh, /enable_firewall.sh)
|
|
# usb USBGuard, USB disks and phones for the team account
|
|
# network network settings (Wi-Fi, hotspot, ...) for the team account
|
|
#
|
|
# "off" stays in effect after a reboot, until "on".
|
|
set -u
|
|
DISABLED=/etc/contest-restrictions/disabled
|
|
USB_FILES="/etc/polkit-1/rules.d/10-acpc-no-removable-media.rules /etc/udev/rules.d/72-acpc-no-phone-access.rules"
|
|
NETWORK_FILES="/etc/polkit-1/rules.d/10-acpc-no-network-changes.rules"
|
|
|
|
usage() {
|
|
sed -n '2,14p' "$0" | sed 's/^# \{0,1\}//'
|
|
exit 2
|
|
}
|
|
|
|
[ "$(id -u)" -eq 0 ] || { echo "Run it with sudo, from the administrator account." >&2; exit 1; }
|
|
mkdir -p "$DISABLED"
|
|
chmod 700 /etc/contest-restrictions
|
|
|
|
# Moves rule files out of the way (off) or back (on)
|
|
move_rules() {
|
|
action=$1
|
|
shift
|
|
for f in "$@"; do
|
|
if [ "$action" = off ] && [ -f "$f" ]; then
|
|
mv "$f" "$DISABLED/"
|
|
elif [ "$action" = on ] && [ -f "$DISABLED/$(basename "$f")" ]; then
|
|
mv "$DISABLED/$(basename "$f")" "$f"
|
|
fi
|
|
done
|
|
}
|
|
|
|
firewall() {
|
|
if [ "$1" = off ]; then
|
|
/disable_firewall.sh
|
|
else
|
|
/enable_firewall.sh
|
|
/refresh_rules.sh
|
|
fi
|
|
}
|
|
|
|
usb() {
|
|
if [ "$1" = off ]; then
|
|
systemctl disable --now usbguard.service
|
|
# USBGuard leaves the controllers refusing new devices when it stops
|
|
for f in /sys/bus/usb/devices/usb*/authorized_default; do
|
|
[ -e "$f" ] && echo 1 > "$f"
|
|
done
|
|
move_rules off $USB_FILES
|
|
udevadm control --reload
|
|
echo "USB devices allowed (unplug and plug again a device refused before)."
|
|
echo "USB disks and phones can be used from the team account."
|
|
else
|
|
# Removable media mounted while the restriction was off
|
|
findmnt -rno TARGET | grep '^/run/media/' | while read -r m; do
|
|
umount "$m" && echo "Unmounted $m"
|
|
done
|
|
move_rules on $USB_FILES
|
|
udevadm control --reload
|
|
systemctl enable --now usbguard.service
|
|
echo "USB restrictions on. The devices plugged in right now stay allowed until they are unplugged."
|
|
fi
|
|
}
|
|
|
|
network() {
|
|
if [ "$1" = off ]; then
|
|
move_rules off $NETWORK_FILES
|
|
echo "The team account can change the network settings."
|
|
else
|
|
move_rules on $NETWORK_FILES
|
|
echo "Network settings restricted to the administrators."
|
|
fi
|
|
}
|
|
|
|
state() {
|
|
if [ "$1" = yes ]; then echo "on"; else echo "OFF"; fi
|
|
}
|
|
|
|
status() {
|
|
fw=no; systemctl is-active --quiet firewall.service && fw=yes
|
|
us=no; systemctl is-active --quiet usbguard.service && [ -f /etc/polkit-1/rules.d/10-acpc-no-removable-media.rules ] && us=yes
|
|
nw=no; [ -f /etc/polkit-1/rules.d/10-acpc-no-network-changes.rules ] && nw=yes
|
|
echo "firewall $(state $fw)"
|
|
echo "usb $(state $us)"
|
|
echo "network $(state $nw)"
|
|
}
|
|
|
|
# What the machine refused: web sites, DNS names, USB devices
|
|
report() {
|
|
since=${1:-today}
|
|
echo "== Web sites refused by the proxy (since $since)"
|
|
journalctl -t contest_proxy --since "$since" --no-pager -o cat 2>/dev/null \
|
|
| awk '$3 != "200" || $4 == "-" {print $2}' | sort | uniq -c | sort -rn | head -40
|
|
echo
|
|
echo "== DNS names refused by the filter"
|
|
# Names that Firefox, VS Code, the IDEs and Kattis pages look up on their
|
|
# own in the background
|
|
background='(^|\.)(mozilla\.(com|org|net)|firefox-portal-detection\.com|googleapis\.com|gvt1\.com|microsoft\.com|vscode-cdn\.net|vscode-unpkg\.net|exp-tas\.com|openh264\.org|ipv4only\.arpa|sentry\.io|cloudflare-dns\.com|jetbrains\.com|ubuntu\.com|canonical\.com|snapcraft\.io)$'
|
|
names=$(journalctl -u contest-dns --since "$since" --no-pager -o cat 2>/dev/null \
|
|
| sed -n 's/^config \(.*\) is NXDOMAIN$/\1/p')
|
|
printf '%s\n' "$names" | grep -v -E "$background" | grep . | sort | uniq -c | sort -rn | head -40
|
|
echo " ($(printf '%s\n' "$names" | grep -c -E "$background") lookups by Firefox, VS Code and the IDEs in the background, not listed)"
|
|
echo
|
|
echo "== USB devices rejected"
|
|
journalctl -u usbguard --since "$since" --no-pager -o short 2>/dev/null \
|
|
| grep "target.new='reject'" \
|
|
| sed -E 's/^([A-Za-z]+ +[0-9]+ [0-9:]+).* name "([^"]*)".*/\1 \2/' | tail -20
|
|
}
|
|
|
|
case "${1:-}" in
|
|
status) status ;;
|
|
report) report "${2:-today}" ;;
|
|
on|off)
|
|
what=${2:-all}
|
|
case "$what" in
|
|
all) firewall "$1"; usb "$1"; network "$1" ;;
|
|
firewall|usb|network) "$what" "$1" ;;
|
|
*) usage ;;
|
|
esac
|
|
echo
|
|
status
|
|
;;
|
|
*) usage ;;
|
|
esac
|