#!/usr/bin/env bash # # bt-access - network access controls for ButtonTask. # # Usage: # bt-access status # bt-access icmp # bt-access ssh # bt-access ssh-port set -euo pipefail err() { echo "bt-access: $*" >&2; exit 1; } SSH_DROPIN="/etc/ssh/sshd_config.d/99-buttontask.conf" SYSCTL_DROPIN="/etc/sysctl.d/99-buttontask-access.conf" valid_port() { [[ "${1:-}" =~ ^[0-9]{1,5}$ ]] && [ "$1" -ge 1 ] && [ "$1" -le 65535 ] } ssh_unit() { if systemctl list-unit-files ssh.service &>/dev/null; then echo ssh.service elif systemctl list-unit-files sshd.service &>/dev/null; then echo sshd.service else echo ssh.service fi } ssh_port() { local port if command -v sshd >/dev/null 2>&1; then port="$(sshd -T 2>/dev/null | awk '$1 == "port" {print $2; exit}')" if valid_port "${port:-}"; then echo "$port" return 0 fi fi port="$(awk 'tolower($1) == "port" {print $2; found=1} END {if (!found) print 22}' \ /etc/ssh/sshd_config "$SSH_DROPIN" 2>/dev/null | tail -n1)" valid_port "${port:-}" && echo "$port" || echo 22 } write_icmp() { local state="$1" value case "$state" in on) value=0 ;; off) value=1 ;; *) err "icmp expects on or off" ;; esac printf 'net.ipv4.icmp_echo_ignore_all=%s\n' "$value" > "$SYSCTL_DROPIN" sysctl -w "net.ipv4.icmp_echo_ignore_all=$value" >/dev/null } write_ssh_port() { local port="$1" valid_port "$port" || err "invalid ssh port" install -d -m 0755 "$(dirname "$SSH_DROPIN")" printf 'Port %s\n' "$port" > "$SSH_DROPIN" systemctl restart "$(ssh_unit)" >/dev/null 2>&1 || true } set_ssh() { local state="$1" unit unit="$(ssh_unit)" case "$state" in on) systemctl enable "$unit" >/dev/null 2>&1 || update-rc.d ssh defaults >/dev/null 2>&1 || true systemctl start "$unit" >/dev/null 2>&1 || service ssh start >/dev/null 2>&1 || true ;; off) systemctl stop "$unit" >/dev/null 2>&1 || service ssh stop >/dev/null 2>&1 || true systemctl disable "$unit" >/dev/null 2>&1 || update-rc.d -f ssh remove >/dev/null 2>&1 || true ;; *) err "ssh expects on or off" ;; esac } status() { local icmp ssh_state port unit icmp="$(sysctl -n net.ipv4.icmp_echo_ignore_all 2>/dev/null || echo 0)" unit="$(ssh_unit)" if systemctl is-active --quiet "$unit"; then ssh_state=on else ssh_state=off fi port="$(ssh_port)" printf '{"icmp":"%s","ssh":"%s","sshPort":%s}\n' \ "$([ "$icmp" = "1" ] && echo off || echo on)" \ "$ssh_state" \ "$port" } case "${1:-}" in status) status ;; icmp) [ "$#" -eq 2 ] || err "usage: bt-access icmp "; write_icmp "$2"; status ;; ssh) [ "$#" -eq 2 ] || err "usage: bt-access ssh "; set_ssh "$2"; status ;; ssh-port) [ "$#" -eq 2 ] || err "usage: bt-access ssh-port "; write_ssh_port "$2"; status ;; *) err "usage: bt-access {status|icmp |ssh |ssh-port }" ;; esac