102 lines
2.9 KiB
Bash
102 lines
2.9 KiB
Bash
#!/usr/bin/env bash
|
|
# Shared helpers: ipdeny ru.zone -> HAProxy src -f allowlist (bash, no pip).
|
|
# Логика из Answer.and.other.shit/scripts/mikrotik-ru-ipdeny/mikrotik_ru_ipdeny_lib.sh
|
|
set -Eeuo pipefail
|
|
|
|
DEFAULT_ZONE_URL="${IPDENY_ZONE_URL:-https://www.ipdeny.com/ipblocks/data/countries/ru.zone}"
|
|
DEFAULT_MIN_LINES="${HAPROXY_MIN_ENTRIES:-8000}"
|
|
|
|
die() {
|
|
echo "error: $*" >&2
|
|
exit 1
|
|
}
|
|
|
|
fetch_zone() {
|
|
local url=$1
|
|
local dest=$2
|
|
curl -fsSL --max-time 120 -A "haproxy-ru-ipdeny/1.0" "$url" -o "$dest"
|
|
}
|
|
|
|
count_subnets_in_zone() {
|
|
local zone_file=$1
|
|
local count=0
|
|
local line
|
|
while IFS= read -r line || [[ -n $line ]]; do
|
|
line="${line//$'\r'/}"
|
|
line="${line#"${line%%[![:space:]]*}"}"
|
|
line="${line%"${line##*[![:space:]]}"}"
|
|
[[ -z $line || $line == \#* ]] && continue
|
|
[[ $line != */* ]] && continue
|
|
count=$((count + 1))
|
|
done <"$zone_file"
|
|
printf '%s' "$count"
|
|
}
|
|
|
|
write_zone_allowlist() {
|
|
local zone_file=$1
|
|
local output_path=$2
|
|
|
|
{
|
|
while IFS= read -r line || [[ -n $line ]]; do
|
|
line="${line//$'\r'/}"
|
|
line="${line#"${line%%[![:space:]]*}"}"
|
|
line="${line%"${line##*[![:space:]]}"}"
|
|
[[ -z $line || $line == \#* ]] && continue
|
|
[[ $line != */* ]] && continue
|
|
printf '%s\n' "$line"
|
|
done <"$zone_file"
|
|
} >"$output_path"
|
|
}
|
|
|
|
append_static_allowlist() {
|
|
local static_file=$1
|
|
local output_path=$2
|
|
|
|
[[ -f $static_file ]] || return 0
|
|
while IFS= read -r line || [[ -n $line ]]; do
|
|
line="${line//$'\r'/}"
|
|
line="${line#"${line%%[![:space:]]*}"}"
|
|
line="${line%"${line##*[![:space:]]}"}"
|
|
[[ -z $line || $line == \#* ]] && continue
|
|
printf '%s\n' "$line"
|
|
done <"$static_file" >>"$output_path"
|
|
}
|
|
|
|
generate_allowlist_bundle() {
|
|
local zone_url=${1:-$DEFAULT_ZONE_URL}
|
|
local output_path=${2:-}
|
|
local static_file=${3:-}
|
|
local min_lines=${4:-$DEFAULT_MIN_LINES}
|
|
|
|
[[ -n $output_path ]] || die "output path required"
|
|
|
|
local tmp_zone merged
|
|
tmp_zone=$(mktemp)
|
|
merged=$(mktemp)
|
|
trap "rm -f '${tmp_zone}' '${merged}'" RETURN
|
|
|
|
fetch_zone "$zone_url" "$tmp_zone"
|
|
|
|
local zone_entries
|
|
zone_entries=$(count_subnets_in_zone "$tmp_zone")
|
|
if [[ $zone_entries -lt $min_lines ]]; then
|
|
die "too few subnets: ${zone_entries} (expected at least ${min_lines})"
|
|
fi
|
|
|
|
write_zone_allowlist "$tmp_zone" "$merged"
|
|
append_static_allowlist "$static_file" "$merged"
|
|
sort -u "$merged" >"$output_path"
|
|
|
|
local total_entries bytes
|
|
total_entries=$(wc -l <"$output_path" | tr -d '[:space:]')
|
|
bytes=$(wc -c <"$output_path" | tr -d '[:space:]')
|
|
|
|
rm -f "$tmp_zone" "$merged"
|
|
trap - RETURN
|
|
|
|
GENERATED_ZONE_ENTRIES=$zone_entries
|
|
GENERATED_ENTRIES=$total_entries
|
|
GENERATED_BYTES=$bytes
|
|
GENERATED_OUTPUT=$output_path
|
|
}
|