Files
Linux_post_install/bin/pos-system-firewall
T
2026-07-28 10:28:11 -04:00

285 lines
8.8 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'
if [[ $EUID -ne 0 ]]; then
echo "ERROR: Please run as root (sudo)."
echo "Usage: sudo pos system firewall"
exit 1
fi
HISTORY=()
DRY_RUN=0
if [[ "${1:-}" == "--dry-run" ]]; then
DRY_RUN=1
fi
log() { echo "[+] $*"; }
warn() { echo "[!] $*"; }
err() { echo "ERROR: $*" >&2; exit 1; }
run_cmd() {
local -a cmd=("$@")
printf "\n>>> %s\n" "${cmd[*]}"
read -rp "Execute this command? [y/N]: " confirm
if [[ "$confirm" =~ ^[Yy]$ ]]; then
if [[ "$DRY_RUN" -eq 1 ]]; then
echo "(dry-run) skipping execution"
else
"${cmd[@]}"
fi
HISTORY+=("${cmd[*]}")
else
echo "Cancelled."
fi
}
build_ufw_cmd() {
local action="$1"
local direction="$2"
local proto="$3"
local from="$4"
local to="$5"
local port="$6"
local onif="$7"
local logmode="$8"
local comment="$9"
local insert_pos="${10:-}"
local suffix="${11:-}"
local -a cmd=(ufw)
if [[ -n "$insert_pos" ]]; then
if [[ "$insert_pos" == "prepend" ]]; then
cmd+=(prepend)
else
cmd+=(insert "$insert_pos")
fi
fi
cmd+=("$action")
[[ -n "$direction" ]] && cmd+=("$direction")
[[ -n "$onif" ]] && cmd+=(on "$onif")
[[ -n "$proto" ]] && cmd+=(proto "$proto")
[[ -n "$from" ]] && cmd+=(from "$from")
cmd+=(to "$to")
[[ -n "$port" ]] && cmd+=(port "$port")
[[ -n "$logmode" ]] && cmd+=("$logmode")
if [[ -n "$comment" ]]; then
local safe="${comment// /_}"
cmd+=(comment "$safe")
fi
[[ "$suffix" == "v6" ]] && cmd+=(v6)
run_cmd "${cmd[@]}"
}
prompt_ipver() {
local ver
read -rp "IP version (4 / 6 / both): " ver
echo "$ver"
}
apply_for_versions() {
local action="$1" direction="$2" proto="$3" from="$4" to="$5"
local port="$6" onif="$7" logmode="$8" comment="$9"
local insert_pos="${10:-}"
local ipver
ipver=$(prompt_ipver)
case "$ipver" in
4) build_ufw_cmd "$action" "$direction" "$proto" "$from" "$to" "$port" "$onif" "$logmode" "$comment" "$insert_pos" "" ;;
6) build_ufw_cmd "$action" "$direction" "$proto" "$from" "$to" "$port" "$onif" "$logmode" "$comment" "$insert_pos" "v6" ;;
both)
build_ufw_cmd "$action" "$direction" "$proto" "$from" "$to" "$port" "$onif" "$logmode" "$comment" "$insert_pos" ""
build_ufw_cmd "$action" "$direction" "$proto" "$from" "$to" "$port" "$onif" "$logmode" "$comment" "$insert_pos" "v6"
;;
*) echo "Invalid choice. Choose 4, 6 or both." ;;
esac
}
add_rule() {
echo
echo "Choose rule type:"
echo "1) Port/service (eg: port 8080 or 'ssh')"
echo "2) IP-based (from X to Y)"
echo "3) Directional port rule (in/out to any port ...)"
read -rp "Choice: " rtype
case "$rtype" in
1)
read -rp "Action (allow/deny/reject/limit) [allow]: " action
action=${action:-allow}
read -rp "Enter port number or service name (eg 'ssh' or '8080'): " port_or_svc
if [[ "$port_or_svc" =~ ^[0-9]+$ ]]; then
read -rp "Protocol (tcp/udp/any) [tcp]: " proto
proto=${proto:-tcp}
[[ "$proto" == "any" ]] && proto=""
read -rp "Interface (leave empty for any): " onif
read -rp "Log? (none/log/log-all) [none]: " logmode
[[ "$logmode" == "none" ]] && logmode=""
read -rp "Comment (optional): " comment
apply_for_versions "$action" "" "$proto" "" "any" "$port_or_svc" "$onif" "$logmode" "$comment"
else
read -rp "IP version (4 / 6 / both) [4]: " ipver
ipver=${ipver:-4}
case "$ipver" in
4) run_cmd ufw "$action" "$port_or_svc" ;;
6) run_cmd ufw "$action" "$port_or_svc" v6 ;;
both) run_cmd ufw "$action" "$port_or_svc"
run_cmd ufw "$action" "$port_or_svc" v6 ;;
*) echo "invalid ipver" ;;
esac
fi
;;
2)
read -rp "Action (allow/deny/reject) [deny]: " action
action=${action:-deny}
read -rp "From address/CIDR (eg 192.168.1.5 or 10.0.0.0/24): " from
read -rp "To address (leave empty for 'any') [any]: " to
to=${to:-any}
read -rp "Direction (in/out) [in]: " direction
direction=${direction:-in}
read -rp "Port (leave empty if not applicable): " port
read -rp "Protocol (tcp/udp/any) [any]: " proto
[[ "$proto" == "any" ]] && proto=""
read -rp "Interface (leave empty for any): " onif
read -rp "Log? (none/log/log-all) [none]: " logmode
[[ "$logmode" == "none" ]] && logmode=""
read -rp "Comment (optional): " comment
apply_for_versions "$action" "$direction" "$proto" "$from" "$to" "$port" "$onif" "$logmode" "$comment"
;;
3)
read -rp "Action (allow/deny/reject/limit) [allow]: " action
action=${action:-allow}
read -rp "Direction (in/out) [in]: " direction
direction=${direction:-in}
read -rp "Port number: " port
read -rp "Protocol (tcp/udp/any) [tcp]: " proto
[[ "$proto" == "any" ]] && proto=""
read -rp "On interface (leave empty for any): " onif
read -rp "From address (optional): " from
from=${from:-}
read -rp "To address [any]: " to
to=${to:-any}
read -rp "Log? (none/log/log-all) [none]: " logmode
[[ "$logmode" == "none" ]] && logmode=""
read -rp "Comment (optional): " comment
read -rp "Insert position (number/prepend/empty): " insert_pos
apply_for_versions "$action" "$direction" "$proto" "$from" "$to" "$port" "$onif" "$logmode" "$comment" "$insert_pos"
;;
*) echo "Unknown choice." ;;
esac
}
delete_rule() {
echo
echo "Delete rule by:"
echo "1) rule number (use 'ufw status numbered' to see numbers)"
echo "2) rule text (eg: 'allow 22/tcp')"
read -rp "Choice: " dch
case "$dch" in
1)
ufw status numbered
read -rp "Number to delete: " num
run_cmd ufw delete "$num"
;;
2)
read -rp "Exact rule text to delete (eg: deny 80/tcp): " ruletext
run_cmd ufw delete $ruletext
;;
*) echo "Unknown choice." ;;
esac
}
show_status() {
echo
echo "1) Simple status"
echo "2) Verbose status"
echo "3) Numbered status (useful for delete)"
read -rp "Choice: " sc
case "$sc" in
1) run_cmd ufw status ;;
2) run_cmd ufw status verbose ;;
3) run_cmd ufw status numbered ;;
*) echo "Unknown choice." ;;
esac
}
while true; do
cat <<'MENU'
==============================
UFW POWER — human friendly
==============================
1) Add rule (port/service/ip/directional)
2) Delete rule (by number or text)
3) Show status (simple / verbose / numbered)
4) Enable UFW
5) Disable UFW
6) Reset UFW (delete all rules)
7) Set default policy (incoming/outgoing)
8) Show executed commands history (so far)
0) Exit
------------------------------
MENU
read -rp "Choose: " opt
case "$opt" in
1) add_rule ;;
2) delete_rule ;;
3) show_status ;;
4) run_cmd ufw enable ;;
5) run_cmd ufw disable ;;
6)
echo "WARNING: ufw reset will disable and remove all rules."
read -rp "Type 'RESET' to confirm: " c
[[ "$c" == "RESET" ]] && run_cmd ufw reset || echo "Reset aborted."
;;
7)
read -rp "Default incoming policy (allow/deny/reject) [deny]: " defin
defin=${defin:-deny}
read -rp "Default outgoing policy (allow/deny/reject) [allow]: " defout
defout=${defout:-allow}
run_cmd ufw default "$defin" incoming
run_cmd ufw default "$defout" outgoing
;;
8)
echo
echo "Executed commands so far:"
echo
if [[ "${#HISTORY[@]}" -eq 0 ]]; then
echo "(none yet)"
else
for c in "${HISTORY[@]}"; do echo " - $c"; done
fi
;;
0)
echo
echo "Final executed commands summary:"
if [[ "${#HISTORY[@]}" -eq 0 ]]; then
echo "(no commands executed)"
else
for c in "${HISTORY[@]}"; do echo " - $c"; done
fi
echo "Goodbye — firewall remains watchful."
exit 0
;;
*) echo "Unknown option." ;;
esac
echo
read -rp "Press Enter to continue..."
clear
done