#!/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 }