241 lines
No EOL
6.8 KiB
Bash
241 lines
No EOL
6.8 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
# ============================================
|
|
# Block file management
|
|
# ============================================
|
|
|
|
# ── Core state queries ─────────────────────
|
|
|
|
function block::file() {
|
|
local name="${1:?name required}"
|
|
ctx::block::path "${name}.block"
|
|
}
|
|
|
|
function block::has_file() {
|
|
local name="${1:?}"
|
|
[[ -f "$(block::file "$name")" ]]
|
|
}
|
|
|
|
function block::has_specific_rules() {
|
|
local name="${1:?}"
|
|
block::has_file "$name" || return 1
|
|
while IFS="|" read -r bname btype target port proto; do
|
|
[[ -z "$btype" ]] && continue
|
|
[[ "$btype" != "full" ]] && return 0
|
|
done < <(block::get_rules "$name")
|
|
return 1
|
|
}
|
|
|
|
function block::is_blocked() {
|
|
local name="${1:?}"
|
|
block::has_file "$name" || return 1
|
|
local result
|
|
result=$(json::block_is_blocked "$(block::file "$name")")
|
|
[[ "$result" == "true" ]]
|
|
}
|
|
|
|
function block::is_blocked_direct() {
|
|
local name="${1:?}"
|
|
block::has_file "$name" || { echo "false"; return 0; }
|
|
json::block_get_direct "$(block::file "$name")"
|
|
}
|
|
|
|
function block::get_groups() {
|
|
local name="${1:?}"
|
|
block::has_file "$name" || return 0
|
|
json::block_get_groups "$(block::file "$name")"
|
|
}
|
|
|
|
function block::get_rules() {
|
|
local name="${1:?}"
|
|
block::has_file "$name" || return 0
|
|
json::block_get_rules "$(block::file "$name")"
|
|
}
|
|
|
|
# ── State mutations ────────────────────────
|
|
|
|
function block::set_direct() {
|
|
local name="${1:?}" client_ip="${2:?}" value="${3:-true}"
|
|
local file
|
|
file=$(block::file "$name")
|
|
json::block_set_direct "$file" "$client_ip" "$value"
|
|
}
|
|
|
|
function block::add_group() {
|
|
local name="${1:?}" client_ip="${2:?}" group="${3:?}"
|
|
local file
|
|
file=$(block::file "$name")
|
|
json::block_add_group "$file" "$client_ip" "$group"
|
|
}
|
|
|
|
function block::remove_group() {
|
|
local name="${1:?}" client_ip="${2:?}" group="${3:?}"
|
|
local file
|
|
file=$(block::file "$name")
|
|
json::block_remove_group "$file" "$client_ip" "$group"
|
|
}
|
|
|
|
function block::add_rule() {
|
|
local name="${1:?}" client_ip="${2:?}"
|
|
local rule_type="${3:?}" rule_name="${4:-}"
|
|
local target="${5:-}" port="${6:-}" proto="${7:-}"
|
|
local file
|
|
file=$(block::file "$name")
|
|
json::block_add_rule "$file" "$client_ip" "$rule_type" \
|
|
"$rule_name" "$target" "$port" "$proto"
|
|
}
|
|
|
|
function block::remove_rule() {
|
|
local name="${1:?}"
|
|
local rule_type="${2:?}" target="${3:-}" port="${4:-}" proto="${5:-}"
|
|
local file
|
|
file=$(block::file "$name")
|
|
json::block_remove_rule "$file" "$rule_type" "$target" "$port" "$proto"
|
|
}
|
|
|
|
function block::remove_file() {
|
|
local name="${1:?}"
|
|
rm -f "$(block::file "$name")"
|
|
}
|
|
|
|
function block::rename() {
|
|
local name="${1:?}" new_name="${2:?}"
|
|
local old_file new_file
|
|
old_file=$(block::file "$name")
|
|
new_file=$(block::file "$new_name")
|
|
[[ -f "$old_file" ]] && mv "$old_file" "$new_file"
|
|
}
|
|
|
|
# ── High level operations ──────────────────
|
|
|
|
function block::apply_full() {
|
|
local name="${1:?}" client_ip="${2:?}"
|
|
|
|
fw::flush_peer "$client_ip"
|
|
fw::block_all "$client_ip" "$name"
|
|
block::add_rule "$name" "$client_ip" "full" "full block"
|
|
|
|
local public_key endpoint
|
|
public_key=$(keys::public "$name") || return 1
|
|
endpoint=$(monitor::endpoint_for_key "$public_key")
|
|
[[ -n "$endpoint" ]] && monitor::watch "$endpoint" "$name"
|
|
peers::remove_from_server "$name"
|
|
peers::reload
|
|
}
|
|
|
|
|
|
function block::restore_peer() {
|
|
local name="${1:?}" client_ip="${2:?}"
|
|
fw::unblock_all "$client_ip"
|
|
fw::flush_peer "$client_ip"
|
|
monitor::unwatch_client "$name"
|
|
if ! peers::exists_in_server "$name"; then
|
|
local public_key
|
|
public_key=$(keys::public "$name") || return 1
|
|
peers::add_to_server "$name" "$public_key" "$client_ip"
|
|
peers::reload
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
function block::restore_rules_for() {
|
|
local name="${1:?}" client_ip="${2:?}"
|
|
while IFS="|" read -r bname btype target port proto; do
|
|
[[ -z "$btype" ]] && continue
|
|
case "$btype" in
|
|
ip) fw::block_ip "$client_ip" "$target" "append" ;;
|
|
port) fw::block_port "$client_ip" "$target" "$port" \
|
|
"${proto:-tcp}" "append" ;;
|
|
subnet) fw::block_subnet "$client_ip" "$target" "append" ;;
|
|
esac
|
|
done < <(block::get_rules "$name")
|
|
}
|
|
|
|
function block::restore_all() {
|
|
while IFS= read -r peer_name; do
|
|
block::has_file "$peer_name" || continue
|
|
local client_ip
|
|
client_ip=$(peers::get_ip "$peer_name")
|
|
[[ -z "$client_ip" ]] && continue
|
|
while IFS="|" read -r bname btype target port proto; do
|
|
[[ -z "$btype" ]] && continue
|
|
case "$btype" in
|
|
full) fw::block_all "$client_ip" "$peer_name" ;;
|
|
ip) fw::block_ip "$client_ip" "$target" ;;
|
|
port) fw::block_port "$client_ip" "$target" "$port" "${proto:-tcp}" ;;
|
|
subnet) fw::block_subnet "$client_ip" "$target" ;;
|
|
esac
|
|
done < <(block::get_rules "$peer_name")
|
|
done < <(peers::all)
|
|
}
|
|
|
|
# ── Display helpers ────────────────────────
|
|
|
|
function block::format_rules() {
|
|
local name="${1:?}"
|
|
block::has_file "$name" || return 0
|
|
|
|
while IFS="|" read -r bname btype target port proto; do
|
|
[[ -z "$btype" ]] && continue
|
|
|
|
local display="" ann=""
|
|
|
|
case "$btype" in
|
|
full)
|
|
display="all traffic"
|
|
;;
|
|
ip)
|
|
display="$target"
|
|
ann=$(net::annotate "$target")
|
|
;;
|
|
port)
|
|
display="${target}:${port}:${proto}"
|
|
ann=$(net::annotate "${target}:${port}:${proto}")
|
|
;;
|
|
subnet)
|
|
display="$target"
|
|
ann=$(net::annotate "${target%%/*}")
|
|
;;
|
|
esac
|
|
|
|
local label="$bname"
|
|
|
|
# If bname wasn't set (equals type default), clear it
|
|
case "$label" in
|
|
full|ip|port|subnet|"") label="" ;;
|
|
esac
|
|
|
|
# Suppress label if it matches annotation
|
|
if [[ -n "$ann" && -n "$label" && \
|
|
("$ann" == "$label" || "$ann" == "${label}:"*) ]]; then
|
|
label=""
|
|
fi
|
|
|
|
# log::debug "label='$label' ann='$ann' match=$([ "$ann" == "$label" ] && echo yes || echo no)"
|
|
|
|
printf " \033[0;31m-\033[0m %-20s \033[0;37m%s%s\033[0m\n" \
|
|
"$display" \
|
|
"${label:+${label} }" \
|
|
"${ann:+→ ${ann}}"
|
|
|
|
done < <(block::get_rules "$name")
|
|
return 0
|
|
}
|
|
|
|
# function block::format_rules() {
|
|
# local name="${1:?}"
|
|
# block::has_file "$name" || return 0
|
|
# while IFS="|" read -r bname btype target port proto; do
|
|
# [[ -z "$btype" ]] && continue
|
|
# local display
|
|
# case "$btype" in
|
|
# full) display="all traffic" ;;
|
|
# ip) display="$target" ;;
|
|
# port) display="${target}:${port}:${proto}" ;;
|
|
# subnet) display="$target" ;;
|
|
# esac
|
|
# local label="${bname:-$btype}"
|
|
# printf " \033[0;31m-\033[0m %-30s \033[0;37m%s\033[0m\n" \
|
|
# "$display" "$label"
|
|
# done < <(block::get_rules "$name")
|
|
# } |