feat: modularize project structure with new helper libraries, centralized configuration, and reverse proxy management

This commit is contained in:
houseassassin
2026-04-24 16:45:26 +03:00
parent 0115fd63e7
commit b844bc4e0e
10 changed files with 1404 additions and 66 deletions
Executable
+182
View File
@@ -0,0 +1,182 @@
#!/bin/bash
# Common functions library for Proxy-Core
# Version: 2.1.1
# Author: houseassassin
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
CYAN='\033[0;36m'
GRAY='\033[0;90m'
NC='\033[0m'
# Logging functions
log() {
echo -e "${GREEN}[INFO]${NC} $1"
}
warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
error() {
echo -e "${RED}[ERROR]${NC} $1"
}
success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
# Validation functions
validate_port() {
local port=$1
if ! [[ "$port" =~ ^[0-9]+$ ]] || [ "$port" -lt 1 ] || [ "$port" -gt 65535 ]; then
error "Неверный порт: $port (должен быть 1-65535)"
return 1
fi
return 0
}
validate_name() {
local name=$1
if [ -z "$name" ]; then
error "Имя не может быть пустым"
return 1
fi
if ! [[ "$name" =~ ^[a-zA-Z0-9_-]+$ ]]; then
error "Неверное имя: $name (только буквы, цифры, _ и -)"
return 1
fi
return 0
}
check_port_available() {
local port=$1
if ss -ltun | awk '{print $4}' | grep -q ":$port\$"; then
error "Порт $port уже используется"
return 1
fi
return 0
}
validate_ip() {
local ip=$1
if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
return 0
else
error "Неверный IP адрес: $ip"
return 1
fi
}
# Network utilities
get_server_ip() {
curl -s -4 ifconfig.me || curl -s -4 api.ipify.org || curl -s -4 ipinfo.io/ip
}
get_random_port() {
local MIN=${1:-3000}
local MAX=${2:-6999}
while :; do
PORT=$(shuf -i "$MIN-$MAX" -n 1)
if check_port_available "$PORT"; then
echo "$PORT"
return
fi
done
}
# System checks
check_root() {
if [[ $EUID -ne 0 ]]; then
error "Этот скрипт должен быть запущен с правами root"
exit 1
fi
}
detect_os() {
if [ -f /etc/os-release ]; then
. /etc/os-release
OS=$ID
VER=$VERSION_ID
else
error "Не удалось определить операционную систему"
exit 1
fi
}
# Spinner animation
spinner() {
local pid=$1
local text=$2
local spinstr='⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏'
while kill -0 "$pid" 2>/dev/null; do
for (( i=0; i<${#spinstr}; i++ )); do
printf "\r${GREEN}[%s]${NC} %s" "${spinstr:$i:1}" "$text"
sleep 0.1
done
done
printf "\r\033[K"
}
# Confirmation prompt
confirm() {
local prompt="${1:-Продолжить?}"
local default="${2:-n}"
if [ "$default" = "y" ]; then
read -p "$prompt (Y/n): " response
response=${response:-y}
else
read -p "$prompt (y/N): " response
response=${response:-n}
fi
[[ "$response" =~ ^[Yy]$ ]]
}
# Generate random password
generate_password() {
local length=${1:-16}
openssl rand -base64 $length | tr -d "=+/" | cut -c1-$length
}
# Check if command exists
command_exists() {
command -v "$1" >/dev/null 2>&1
}
# Check if service is running
service_running() {
systemctl is-active --quiet "$1"
}
# Wait for service to start
wait_for_service() {
local service=$1
local timeout=${2:-30}
local counter=0
while [ $counter -lt $timeout ]; do
if service_running "$service"; then
return 0
fi
sleep 1
((counter++))
done
return 1
}
# Export all functions
export -f log warn error success
export -f validate_port validate_name check_port_available validate_ip
export -f get_server_ip get_random_port
export -f check_root detect_os spinner confirm
export -f generate_password command_exists service_running wait_for_service
Executable
+56
View File
@@ -0,0 +1,56 @@
#!/bin/bash
# Logging library for Proxy-Core
# Version: 2.1.1
# Author: houseassassin
LOGDIR="/var/log/proxy-core"
mkdir -p "$LOGDIR" 2>/dev/null
# Source common for colors
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/common.sh" 2>/dev/null || true
log_to_file() {
local level=$1
local message=$2
local script=$(basename "${BASH_SOURCE[2]}" 2>/dev/null || echo "unknown")
local logfile="${LOGDIR}/$(date +%Y-%m-%d).log"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$script] [$level] $message" >> "$logfile" 2>/dev/null
}
log() {
echo -e "${GREEN}[INFO]${NC} $1"
log_to_file "INFO" "$1"
}
error() {
echo -e "${RED}[ERROR]${NC} $1"
log_to_file "ERROR" "$1"
}
warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
log_to_file "WARN" "$1"
}
success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
log_to_file "SUCCESS" "$1"
}
debug() {
if [ "${DEBUG:-0}" = "1" ]; then
echo -e "${GRAY}[DEBUG]${NC} $1"
log_to_file "DEBUG" "$1"
fi
}
# Rotate logs older than 30 days
rotate_logs() {
find "$LOGDIR" -name "*.log" -mtime +30 -delete 2>/dev/null
}
# Export functions
export -f log_to_file log error warn success debug rotate_logs
+193
View File
@@ -0,0 +1,193 @@
#!/bin/bash
# WireGuard common functions library
# Version: 2.1.1
# Author: houseassassin
# Source common library
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/common.sh"
WG_DIR="${WG_DIR:-/etc/wireguard}"
WG_CONF="$WG_DIR/wg0.conf"
# Get next available IP for WireGuard client
get_next_wg_ip() {
if [ ! -f "$WG_CONF" ]; then
echo "10.0.0.2"
return
fi
LAST_IP=$(grep "AllowedIPs" "$WG_CONF" | grep -oE "10\.0\.0\.[0-9]+" | sort -t . -k 4 -n | tail -1)
if [ -z "$LAST_IP" ]; then
echo "10.0.0.2"
else
LAST_NUM=$(echo $LAST_IP | cut -d. -f4)
NEXT_NUM=$((LAST_NUM + 1))
echo "10.0.0.$NEXT_NUM"
fi
}
# Add WireGuard client
add_wireguard_client() {
local client_name=$1
if [ -z "$client_name" ]; then
read -p "Введите имя клиента: " client_name
fi
if ! validate_name "$client_name"; then
return 1
fi
local CLIENT_DIR="$WG_DIR/clients/$client_name"
if [ -d "$CLIENT_DIR" ]; then
error "Клиент $client_name уже существует"
return 1
fi
mkdir -p "$CLIENT_DIR"
cd "$CLIENT_DIR"
# Generate keys
wg genkey | tee private.key | wg pubkey > public.key
chmod 600 private.key
CLIENT_PRIVATE_KEY=$(cat private.key)
CLIENT_PUBLIC_KEY=$(cat public.key)
SERVER_PUBLIC_KEY=$(cat $WG_DIR/server_public.key)
SERVER_IP=$(get_server_ip)
SERVER_PORT=$(grep ListenPort $WG_CONF | awk '{print $3}')
CLIENT_IP=$(get_next_wg_ip)
# Add peer to server config
cat >> $WG_CONF <<EOF
[Peer]
# $client_name
PublicKey = $CLIENT_PUBLIC_KEY
AllowedIPs = $CLIENT_IP/32
EOF
# Create client config
cat > client.conf <<EOF
[Interface]
PrivateKey = $CLIENT_PRIVATE_KEY
Address = $CLIENT_IP/24
DNS = 8.8.8.8, 1.1.1.1
[Peer]
PublicKey = $SERVER_PUBLIC_KEY
Endpoint = $SERVER_IP:$SERVER_PORT
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25
EOF
systemctl restart wg-quick@wg0
success "Клиент $client_name создан"
log "IP адрес: $CLIENT_IP"
log "Конфигурация: $CLIENT_DIR/client.conf"
echo ""
log "QR-код для мобильных устройств:"
if command_exists qrencode; then
qrencode -t ansiutf8 < client.conf
else
warn "qrencode не установлен, QR-код недоступен"
fi
echo ""
log "Конфигурация клиента:"
cat client.conf
}
# List WireGuard clients
list_wireguard_clients() {
log "Список клиентов WireGuard:"
echo ""
if [ ! -d "$WG_DIR/clients" ]; then
warn "Клиенты не найдены"
return
fi
for client in $WG_DIR/clients/*; do
if [ -d "$client" ]; then
CLIENT_NAME=$(basename "$client")
CLIENT_IP=$(grep -A 2 "# $CLIENT_NAME" $WG_CONF | grep AllowedIPs | awk '{print $3}' | cut -d/ -f1)
echo -e "${GREEN}${NC} $CLIENT_NAME ${BLUE}($CLIENT_IP)${NC}"
fi
done
}
# Remove WireGuard client
remove_wireguard_client() {
local client_name=$1
if [ -z "$client_name" ]; then
read -p "Введите имя клиента для удаления: " client_name
fi
if ! validate_name "$client_name"; then
return 1
fi
local CLIENT_DIR="$WG_DIR/clients/$client_name"
if [ ! -d "$CLIENT_DIR" ]; then
error "Клиент $client_name не найден"
return 1
fi
if ! confirm "Удалить клиента $client_name?"; then
log "Отменено"
return 0
fi
sed -i "/# $client_name/,+2d" $WG_CONF
rm -rf "$CLIENT_DIR"
systemctl restart wg-quick@wg0
success "Клиент $client_name удален"
}
# Show WireGuard client QR code
show_wireguard_qr() {
local client_name=$1
if [ -z "$client_name" ]; then
read -p "Введите имя клиента: " client_name
fi
if ! validate_name "$client_name"; then
return 1
fi
local CLIENT_DIR="$WG_DIR/clients/$client_name"
if [ ! -d "$CLIENT_DIR" ]; then
error "Клиент $client_name не найден"
return 1
fi
echo ""
log "Конфигурация клиента $client_name:"
cat "$CLIENT_DIR/client.conf"
echo ""
log "QR-код:"
if command_exists qrencode; then
qrencode -t ansiutf8 < "$CLIENT_DIR/client.conf"
else
error "qrencode не установлен"
return 1
fi
}
# Export functions
export -f get_next_wg_ip add_wireguard_client list_wireguard_clients
export -f remove_wireguard_client show_wireguard_qr