#!/bin/sh set -e CLIENT_NAME="" OBF_PORT=1080 REDSOCKS_PORT=12345 SOCKS5_LOGIN="" SOCKS5_PASSWORD="" SERVER_IP="" LAN_DEVICE="" REMOVE=0 REDSOCKS_CONF="/etc/redsocks.conf" NFT_FILE="/etc/nftables.d/30-phobos-socks5.nft" REDSOCKS_INIT="/etc/init.d/phobos-redsocks" log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" } error() { echo "[ERROR] $*" >&2 log "ERROR: $*" } usage() { cat </dev/null 2>&1 || missing="$missing $cmd" done if [ ! -x /usr/sbin/redsocks ] && ! command -v redsocks >/dev/null 2>&1; then missing="$missing redsocks" fi if [ -n "$missing" ]; then error "Missing required utilities:$missing" return 1 fi return 0 } detect_lan_device() { if [ -n "$LAN_DEVICE" ]; then return 0 fi LAN_DEVICE=$(uci -q get network.lan.device 2>/dev/null) [ -n "$LAN_DEVICE" ] || LAN_DEVICE="br-lan" } redsocks_bin() { if [ -x /usr/sbin/redsocks ]; then echo /usr/sbin/redsocks else command -v redsocks 2>/dev/null || echo /usr/sbin/redsocks fi } stop_redsocks() { [ -x "$REDSOCKS_INIT" ] && "$REDSOCKS_INIT" stop >/dev/null 2>&1 || true if [ -x /etc/init.d/redsocks ]; then /etc/init.d/redsocks stop >/dev/null 2>&1 || true /etc/init.d/redsocks disable >/dev/null 2>&1 || true fi [ -f /var/run/redsocks.pid ] && kill "$(cat /var/run/redsocks.pid)" 2>/dev/null || true pkill -f "$(redsocks_bin)" 2>/dev/null || true rm -f /var/run/redsocks.pid 2>/dev/null || true sleep 1 } create_redsocks_init() { log "Создание procd-сервиса ${REDSOCKS_INIT}..." cat > "$REDSOCKS_INIT" </dev/null | grep -qE "[:.]${port}[[:space:]]" && return 0 { command -v ss >/dev/null 2>&1 && ss -ltn 2>/dev/null | grep -qE "[:.]${port}[[:space:]]"; } } remove_config() { log "Удаление конфигурации SOCKS5 (redsocks + nft redirect)..." if [ -x "$REDSOCKS_INIT" ]; then "$REDSOCKS_INIT" disable >/dev/null 2>&1 || true fi stop_redsocks rm -f "$REDSOCKS_INIT" 2>/dev/null || true rm -f "$NFT_FILE" 2>/dev/null || true rm -f "$REDSOCKS_CONF" 2>/dev/null || true nft delete chain inet fw4 phobos_socks5_dstnat 2>/dev/null || true nft delete chain inet fw4 phobos_socks5_input 2>/dev/null || true fw4 reload >/dev/null 2>&1 || /etc/init.d/firewall reload >/dev/null 2>&1 || true log "Конфигурация SOCKS5 удалена" } write_redsocks_conf() { log "Запись ${REDSOCKS_CONF} (upstream 127.0.0.1:${OBF_PORT})..." cat > "$REDSOCKS_CONF" </dev/null | awk '/^Address[ :]/{print $NF}' | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' | grep -v '^127\.' | head -1) fi if echo "$ip" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$'; then SERVER_EXCLUDE=", ${ip}" fi } write_nft_redirect() { log "Запись nft-редиректа ${NFT_FILE} (LAN ${LAN_DEVICE} TCP → :${REDSOCKS_PORT})..." resolve_server_exclude mkdir -p /etc/nftables.d cat > "$NFT_FILE" </dev/null 2>&1 || true "$REDSOCKS_INIT" restart >/dev/null 2>&1 || "$REDSOCKS_INIT" start >/dev/null 2>&1 || true fw4 reload >/dev/null 2>&1 || /etc/init.d/firewall reload >/dev/null 2>&1 || true } verify() { log "Проверка настройки SOCKS5..." local ok=1 if port_listening "${REDSOCKS_PORT}"; then log "redsocks слушает :${REDSOCKS_PORT} ✓" else error "redsocks не слушает :${REDSOCKS_PORT}" ok=0 fi if nft list chain inet fw4 phobos_socks5_dstnat >/dev/null 2>&1; then log "nft redirect-правило активно ✓" else error "nft redirect-правило не найдено" ok=0 fi if port_listening "${OBF_PORT}"; then log "обфускатор слушает 127.0.0.1:${OBF_PORT} ✓" else log "ВНИМАНИЕ: не удалось подтвердить обфускатор на :${OBF_PORT} (проверьте init обфускатора)" fi [ "$ok" -eq 1 ] } main() { parse_args "$@" if [ "$REMOVE" -eq 1 ]; then remove_config exit 0 fi if ! check_dependencies; then exit 1 fi detect_lan_device log "=== Phobos SOCKS5 OpenWRT Configuration ===" log "Клиент: ${CLIENT_NAME} · LAN: ${LAN_DEVICE} · redsocks :${REDSOCKS_PORT} → obf :${OBF_PORT}" stop_redsocks write_redsocks_conf create_redsocks_init write_nft_redirect start_services sleep 2 if verify; then log "" log "SOCKS5 успешно настроен на OpenWRT" log "TCP-трафик из LAN (${LAN_DEVICE}) прозрачно идёт через SOCKS5 → сервер" log "" exit 0 else error "Не удалось подтвердить настройку SOCKS5" exit 1 fi } main "$@"