#!/bin/bash # Вызывается из socat EXEC; в окружении есть SOCAT_PEERADDR. set -uo pipefail STATUS_FILE="${STATUS_FILE:-/var/www/cfb/status.html}" ALLOW="${STATUS_HTTP_ALLOW_IPS:-}" ip_to_int() { local a b c d IFS=. read -r a b c d <<<"$1" [[ -n "$d" ]] || return 1 echo $(((a << 24) | (b << 16) | (c << 8) | d)) } ipv4_in_cidr() { local ip="$1" cidr="$2" base masklen ipn basen mask [[ "$cidr" =~ ^([0-9]{1,3}(\.[0-9]{1,3}){3})/([0-9]{1,2})$ ]] || return 1 base="${BASH_REMATCH[1]}" masklen="${BASH_REMATCH[3]}" (( masklen >= 0 && masklen <= 32 )) || return 1 (( masklen == 0 )) && return 0 ipn=$(ip_to_int "$ip") || return 1 basen=$(ip_to_int "$base") || return 1 (( masklen == 32 )) && { [[ "$ip" == "$base" ]]; return; } mask=$(( (0xFFFFFFFF << (32 - masklen)) & 0xFFFFFFFF )) (( (ipn & mask) == (basen & mask) )) } extract_peer_ip() { local raw="${SOCAT_PEERADDR:-}" [[ -n "$raw" ]] || { echo ""; return 1; } if [[ "$raw" == \[*\]* ]]; then local inner="${raw#\[}" echo "${inner%%\]*}" return 0 fi if [[ "$raw" =~ ^[0-9]{1,3}(\.[0-9]{1,3}){3}:[0-9]+$ ]]; then echo "${raw%:*}" return 0 fi echo "$raw" } allowed_ip() { local peer="$1" entry trimmed [[ -n "$peer" ]] || return 1 IFS=',' read -ra _entries <<<"$ALLOW" for entry in "${_entries[@]}"; do trimmed="${entry#"${entry%%[![:space:]]*}"}" trimmed="${trimmed%"${trimmed##*[![:space:]]}"}" [[ -n "$trimmed" ]] || continue if [[ "$trimmed" == */* ]]; then if [[ "$peer" =~ ^[0-9]{1,3}(\.[0-9]{1,3}){3}$ ]]; then ipv4_in_cidr "$peer" "$trimmed" && return 0 fi continue fi [[ "$peer" == "$trimmed" ]] && return 0 done return 1 } # Считать минимальный HTTP-запрос while IFS= read -r line; do line="${line%$'\r'}" [[ -z "$line" ]] && break done peer_ip=$(extract_peer_ip) hdr_ok=$'HTTP/1.0 200 OK\r\nContent-Type: text/html; charset=utf-8\r\nConnection: close\r\n\r\n' hdr_denied=$'HTTP/1.0 403 Forbidden\r\nContent-Type: text/plain; charset=utf-8\r\nConnection: close\r\n\r\nForbidden\r\n' if [[ -z "${ALLOW// }" ]]; then # только loopback — на всякий случай if [[ "$peer_ip" != "127.0.0.1" && "$peer_ip" != "::1" ]]; then printf '%b' "$hdr_denied" exit 0 fi else if ! allowed_ip "$peer_ip"; then printf '%b' "$hdr_denied" exit 0 fi fi printf '%b' "$hdr_ok" if [[ -r "$STATUS_FILE" ]]; then cat "$STATUS_FILE" else printf '%s\n' '

status pending

' fi