fix: stabilize installer flows, managers, and terminal output

This commit is contained in:
houseassassin
2026-05-17 14:46:56 +03:00
parent 6dc1afcb2a
commit 1c183496ca
9 changed files with 605 additions and 148 deletions
+1 -1
View File
@@ -53,7 +53,7 @@
### Одна команда (рекомендуется) ### Одна команда (рекомендуется)
```bash ```bash
bash <(curl -Ls https://raw.githubusercontent.com/houseassassin/proxy-core/main/install.sh) sudo bash <(curl -Ls https://raw.githubusercontent.com/houseassassin/proxy-core/main/install.sh)
``` ```
### Альтернативный метод ### Альтернативный метод
+1 -1
View File
@@ -27,7 +27,7 @@ show_gradient_banner() {
echo -e "${CYAN}${CYAN} ██║ ██║ ██║╚██████╔╝██╔╝ ██╗ ██║ ╚██████╗╚██████╔╝ ${CYAN}${NC}" echo -e "${CYAN}${CYAN} ██║ ██║ ██║╚██████╔╝██╔╝ ██╗ ██║ ╚██████╗╚██████╔╝ ${CYAN}${NC}"
echo -e "${CYAN}${CYAN} ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ${CYAN}${NC}" echo -e "${CYAN}${CYAN} ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ${CYAN}${NC}"
echo -e "${CYAN}║ ║${NC}" echo -e "${CYAN}║ ║${NC}"
echo -e "${CYAN}${WHITE} 🚀 Advanced VPN & Proxy Panel Auto-Installer 🚀 ${CYAN}${NC}" echo -e "${CYAN}${WHITE} Advanced VPN & Proxy Panel Auto-Installer ${CYAN}${NC}"
echo -e "${CYAN}╚═══════════════════════════════════════════════════════════════════════╝${NC}" echo -e "${CYAN}╚═══════════════════════════════════════════════════════════════════════╝${NC}"
echo "" echo ""
echo -e " ${GREEN}┌─────────────────────────────────────────────────────────────────┐${NC}" echo -e " ${GREEN}┌─────────────────────────────────────────────────────────────────┐${NC}"
+332 -95
View File
@@ -14,6 +14,13 @@ set -euo pipefail
SCRIPT_VERSION="2.1.1" SCRIPT_VERSION="2.1.1"
PROJECT_DIR="/opt/proxy-core" PROJECT_DIR="/opt/proxy-core"
LANG_FILE="${PROJECT_DIR}/.selected_language" LANG_FILE="${PROJECT_DIR}/.selected_language"
REPO_ARCHIVE_URL="https://github.com/houseassassin/proxy-core/archive/refs/heads/main.tar.gz"
THREEXUI_INSTALL_URL="https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh"
WG_PORT_MIN=51820
WG_PORT_MAX=51900
HYSTERIA_PORT_MIN=36712
HYSTERIA_PORT_MAX=36800
MTPROXY_PORT_DEFAULT=8443
# Colors and styles # Colors and styles
RED='\033[0;31m' RED='\033[0;31m'
@@ -39,29 +46,64 @@ BG_BLUE='\033[44m'
BG_MAGENTA='\033[45m' BG_MAGENTA='\033[45m'
BG_CYAN='\033[46m' BG_CYAN='\033[46m'
# Create project directory first USE_UNICODE=1
mkdir -p "$PROJECT_DIR" if ! locale charmap 2>/dev/null | grep -qi "utf-8"; then
USE_UNICODE=0
fi
if [ ! -t 1 ] || [ "${TERM:-}" = "dumb" ] || [ "${NO_COLOR:-}" = "1" ]; then
RED=""
GREEN=""
YELLOW=""
BLUE=""
MAGENTA=""
CYAN=""
GRAY=""
WHITE=""
NC=""
BOLD=""
DIM=""
UNDERLINE=""
BLINK=""
BG_RED=""
BG_GREEN=""
BG_BLUE=""
BG_MAGENTA=""
BG_CYAN=""
fi
if [ "$USE_UNICODE" -eq 1 ]; then
SYM_INFO=""
SYM_WARN="⚠"
SYM_ERR="✗"
SYM_OK="✓"
else
SYM_INFO="i"
SYM_WARN="!"
SYM_ERR="x"
SYM_OK="+"
fi
# Logging # Logging
LOGFILE="${PROJECT_DIR}/installer.log" LOGFILE="/tmp/proxy-core-installer.log"
log() { log() {
echo -e " ${CYAN}${NC} ${WHITE}$1${NC}" echo -e " ${CYAN}${SYM_INFO}${NC} ${WHITE}$1${NC}"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [INFO] $1" >> "$LOGFILE" 2>/dev/null echo "[$(date '+%Y-%m-%d %H:%M:%S')] [INFO] $1" >> "$LOGFILE" 2>/dev/null
} }
warn() { warn() {
echo -e " ${YELLOW}${NC} ${YELLOW}$1${NC}" echo -e " ${YELLOW}${SYM_WARN}${NC} ${YELLOW}$1${NC}"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [WARN] $1" >> "$LOGFILE" 2>/dev/null echo "[$(date '+%Y-%m-%d %H:%M:%S')] [WARN] $1" >> "$LOGFILE" 2>/dev/null
} }
error() { error() {
echo -e " ${RED}${NC} ${RED}$1${NC}" echo -e " ${RED}${SYM_ERR}${NC} ${RED}$1${NC}"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] $1" >> "$LOGFILE" 2>/dev/null echo "[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] $1" >> "$LOGFILE" 2>/dev/null
} }
success() { success() {
echo -e " ${GREEN}${NC} ${GREEN}$1${NC}" echo -e " ${GREEN}${SYM_OK}${NC} ${GREEN}$1${NC}"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [SUCCESS] $1" >> "$LOGFILE" 2>/dev/null echo "[$(date '+%Y-%m-%d %H:%M:%S')] [SUCCESS] $1" >> "$LOGFILE" 2>/dev/null
} }
@@ -69,7 +111,10 @@ success() {
spinner() { spinner() {
local pid=$1 local pid=$1
local text=$2 local text=$2
local frames=("" "" "" "⠸" "⠼" "⠴" "⠦" "⠧" "⠇" "⠏") local frames=("|" "/" "-" "\\")
if [ "$USE_UNICODE" -eq 1 ]; then
frames=("⠋" "⠙" "⠹" "⠸" "⠼" "⠴" "⠦" "⠧" "⠇" "⠏")
fi
while kill -0 "$pid" 2>/dev/null; do while kill -0 "$pid" 2>/dev/null; do
for frame in "${frames[@]}"; do for frame in "${frames[@]}"; do
@@ -77,52 +122,9 @@ spinner() {
sleep 0.1 sleep 0.1
done done
done done
printf "\r ${GREEN}${NC} ${WHITE}%s${NC}\n" "$text" printf "\r ${GREEN}${SYM_OK}${NC} ${WHITE}%s${NC}\n" "$text"
} }
# Language support
declare -A LANG_EN=(
[MENU_TITLE]="VPN Panel Installer"
[MENU_INSTALL]="Install Panel"
[MENU_MANAGE]="Manage Services"
[MENU_BACKUP]="Backup & Restore"
[MENU_UPDATE]="Update Components"
[MENU_UNINSTALL]="Uninstall"
[MENU_EXIT]="Exit"
[SELECT_PANEL]="Select panel to install"
[WIREGUARD]="WireGuard VPN"
[3XUI]="3x-ui Panel"
[REMNAWAVE]="Remnawave Panel"
[HYSTERIA2]="Hysteria2 Proxy"
[MTPROXY]="MTProxy (Telegram)"
[SELECT_REVERSE_PROXY]="Select Reverse Proxy"
[NGINX]="Nginx"
[CADDY]="Caddy"
[SELFSTEAL]="Install Selfsteal Template"
[ALL]="Install All"
)
declare -A LANG_RU=(
[MENU_TITLE]="Установщик VPN панелей"
[MENU_INSTALL]="Установить панель"
[MENU_MANAGE]="Управление сервисами"
[MENU_BACKUP]="Резервное копирование"
[MENU_UPDATE]="Обновить компоненты"
[MENU_UNINSTALL]="Удалить"
[MENU_EXIT]="Выход"
[SELECT_PANEL]="Выберите панель для установки"
[WIREGUARD]="WireGuard VPN"
[3XUI]="Панель 3x-ui"
[REMNAWAVE]="Панель Remnawave"
[HYSTERIA2]="Прокси Hysteria2"
[MTPROXY]="MTProxy (Telegram)"
[SELECT_REVERSE_PROXY]="Выберите Reverse Proxy"
[NGINX]="Nginx"
[CADDY]="Caddy"
[SELFSTEAL]="Установить Selfsteal шаблон"
[ALL]="Установить всё"
)
MENU_LANG="en" MENU_LANG="en"
load_language() { load_language() {
@@ -139,14 +141,22 @@ save_language() {
L() { L() {
local key="$1" local key="$1"
local var_name="LANG_${MENU_LANG^^}_${key}" case "$MENU_LANG:$key" in
echo "${!var_name:-$key}" "ru:SELECT_REVERSE_PROXY") echo "Выберите Reverse Proxy" ;;
"ru:NGINX") echo "Nginx" ;;
"ru:CADDY") echo "Caddy" ;;
"en:SELECT_REVERSE_PROXY") echo "Select Reverse Proxy" ;;
"en:NGINX") echo "Nginx" ;;
"en:CADDY") echo "Caddy" ;;
*) echo "$key" ;;
esac
} }
# System checks # System checks
check_root() { check_root() {
if [[ $EUID -ne 0 ]]; then if [[ $EUID -ne 0 ]]; then
error "Этот скрипт должен быть запущен с правами root" error "Этот скрипт должен быть запущен с правами root"
exit 1
fi fi
} }
@@ -157,10 +167,112 @@ detect_os() {
VER=$VERSION_ID VER=$VERSION_ID
else else
error "Не удалось определить операционную систему" error "Не удалось определить операционную систему"
exit 1
fi fi
log "Обнаружена ОС: $OS $VER" log "Обнаружена ОС: $OS $VER"
} }
reload_firewall() {
if command -v firewall-cmd >/dev/null 2>&1; then
firewall-cmd --reload >/dev/null 2>&1 || true
fi
}
open_firewall_port() {
local port=$1
local protocol=$2
if command -v ufw >/dev/null 2>&1; then
ufw allow "${port}/${protocol}" >/dev/null 2>&1 || true
return 0
fi
if command -v firewall-cmd >/dev/null 2>&1; then
firewall-cmd --permanent --add-port="${port}/${protocol}" >/dev/null 2>&1 || true
reload_firewall
fi
}
run_remote_script() {
local url=$1
local tmp_script
tmp_script="$(mktemp /tmp/proxy-core-remote.XXXXXX.sh)"
curl -fsSL "$url" -o "$tmp_script"
chmod 700 "$tmp_script"
bash "$tmp_script"
rm -f "$tmp_script"
}
ensure_project_files() {
mkdir -p "$PROJECT_DIR"
LOGFILE="${PROJECT_DIR}/installer.log"
local need_bootstrap=0
local required_files=(
"manage.sh"
"wg-manager.sh"
"update.sh"
"mtproxy-manager.sh"
"reverse-proxy-manager.sh"
"banner.sh"
)
for file in "${required_files[@]}"; do
if [ ! -f "$PROJECT_DIR/$file" ]; then
need_bootstrap=1
break
fi
done
if [ "$need_bootstrap" -eq 0 ] && [ -d "$PROJECT_DIR/lib" ] && [ -d "$PROJECT_DIR/config" ]; then
return 0
fi
local script_dir
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
if [ -f "$script_dir/manage.sh" ] && [ -d "$script_dir/lib" ] && [ -d "$script_dir/config" ]; then
cp -f "$script_dir/"*.sh "$PROJECT_DIR/" 2>/dev/null || true
cp -rf "$script_dir/lib" "$PROJECT_DIR/"
cp -rf "$script_dir/config" "$PROJECT_DIR/"
chmod +x "$PROJECT_DIR/"*.sh 2>/dev/null || true
return 0
fi
log "Загружаем файлы проекта в $PROJECT_DIR..."
local archive
archive="$(mktemp /tmp/proxy-core-src.XXXXXX.tar.gz)"
curl -fsSL "$REPO_ARCHIVE_URL" -o "$archive"
tar -xzf "$archive" --strip-components=1 -C "$PROJECT_DIR"
rm -f "$archive"
chmod +x "$PROJECT_DIR/"*.sh 2>/dev/null || true
}
run_project_script() {
local script_name=$1
if [ -f "$PROJECT_DIR/$script_name" ]; then
bash "$PROJECT_DIR/$script_name"
else
error "$script_name не найден в $PROJECT_DIR"
return 1
fi
}
load_defaults() {
local defaults_path=""
local script_dir
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
if [ -f "$PROJECT_DIR/config/defaults.conf" ]; then
defaults_path="$PROJECT_DIR/config/defaults.conf"
elif [ -f "$script_dir/config/defaults.conf" ]; then
defaults_path="$script_dir/config/defaults.conf"
fi
if [ -n "$defaults_path" ]; then
source "$defaults_path"
log "Загружены настройки по умолчанию: $defaults_path"
fi
}
check_memory() { check_memory() {
local mem_mb=$(free -m | grep Mem: | awk '{print $2}') local mem_mb=$(free -m | grep Mem: | awk '{print $2}')
if [ $mem_mb -lt 2000 ]; then if [ $mem_mb -lt 2000 ]; then
@@ -203,9 +315,11 @@ install_docker() {
fi fi
log "Установка Docker..." log "Установка Docker..."
curl -fsSL https://get.docker.com -o /tmp/get-docker.sh local docker_installer
sh /tmp/get-docker.sh docker_installer="$(mktemp /tmp/get-docker.XXXXXX.sh)"
rm /tmp/get-docker.sh curl -fsSL https://get.docker.com -o "$docker_installer"
sh "$docker_installer"
rm -f "$docker_installer"
systemctl enable docker systemctl enable docker
systemctl start docker systemctl start docker
@@ -249,6 +363,14 @@ install_packages() {
ufw --force enable >/dev/null 2>&1 ufw --force enable >/dev/null 2>&1
fi fi
if command -v firewall-cmd >/dev/null 2>&1; then
systemctl enable firewalld >/dev/null 2>&1 || true
systemctl start firewalld >/dev/null 2>&1 || true
firewall-cmd --permanent --add-service=ssh >/dev/null 2>&1 || true
firewall-cmd --permanent --add-service=https >/dev/null 2>&1 || true
reload_firewall
fi
success "Системные пакеты установлены" success "Системные пакеты установлены"
} }
@@ -273,7 +395,7 @@ install_wireguard() {
SERVER_PRIVATE_KEY=$(cat server_private.key) SERVER_PRIVATE_KEY=$(cat server_private.key)
SERVER_PUBLIC_KEY=$(cat server_public.key) SERVER_PUBLIC_KEY=$(cat server_public.key)
SERVER_IP=$(get_server_ip) SERVER_IP=$(get_server_ip)
WG_PORT=$(get_random_port 51820 51900) WG_PORT=$(get_random_port "$WG_PORT_MIN" "$WG_PORT_MAX")
cat > /etc/wireguard/wg0.conf <<EOF cat > /etc/wireguard/wg0.conf <<EOF
[Interface] [Interface]
@@ -290,7 +412,7 @@ EOF
systemctl enable wg-quick@wg0 systemctl enable wg-quick@wg0
systemctl start wg-quick@wg0 systemctl start wg-quick@wg0
ufw allow $WG_PORT/udp 2>/dev/null || firewall-cmd --permanent --add-port=$WG_PORT/udp 2>/dev/null open_firewall_port "$WG_PORT" "udp"
success "WireGuard установлен на порту $WG_PORT" success "WireGuard установлен на порту $WG_PORT"
@@ -303,7 +425,7 @@ EOF
# 3x-ui installation # 3x-ui installation
install_3xui() { install_3xui() {
log "Установка 3x-ui..." log "Установка 3x-ui..."
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) run_remote_script "$THREEXUI_INSTALL_URL"
success "3x-ui установлен" success "3x-ui установлен"
} }
@@ -339,8 +461,8 @@ EOF
success "Remnawave установлен" success "Remnawave установлен"
echo "" echo ""
log "Админ логин: admin" echo -e " ${CYAN}${SYM_INFO}${NC} ${WHITE}Админ логин: admin${NC}"
log "Админ пароль: $ADMIN_PASSWORD" echo -e " ${CYAN}${SYM_INFO}${NC} ${WHITE}Админ пароль: ${ADMIN_PASSWORD}${NC}"
warn "Сохраните эти данные!" warn "Сохраните эти данные!"
} }
@@ -349,14 +471,16 @@ install_hysteria2() {
log "Установка Hysteria2..." log "Установка Hysteria2..."
HYSTERIA_VERSION=$(curl -s https://api.github.com/repos/apernet/hysteria/releases/latest | grep tag_name | cut -d '"' -f 4) HYSTERIA_VERSION=$(curl -s https://api.github.com/repos/apernet/hysteria/releases/latest | grep tag_name | cut -d '"' -f 4)
wget -O /tmp/hysteria "https://github.com/apernet/hysteria/releases/download/${HYSTERIA_VERSION}/hysteria-linux-amd64" local hysteria_bin
chmod +x /tmp/hysteria hysteria_bin="$(mktemp /tmp/hysteria.XXXXXX)"
mv /tmp/hysteria /usr/local/bin/hysteria wget -O "$hysteria_bin" "https://github.com/apernet/hysteria/releases/download/${HYSTERIA_VERSION}/hysteria-linux-amd64"
chmod +x "$hysteria_bin"
mv "$hysteria_bin" /usr/local/bin/hysteria
mkdir -p /etc/hysteria mkdir -p /etc/hysteria
HYSTERIA_PASSWORD=$(openssl rand -base64 32) HYSTERIA_PASSWORD=$(openssl rand -base64 32)
HYSTERIA_PORT=$(get_random_port 36712 36800) HYSTERIA_PORT=$(get_random_port "$HYSTERIA_PORT_MIN" "$HYSTERIA_PORT_MAX")
cat > /etc/hysteria/config.yaml <<EOF cat > /etc/hysteria/config.yaml <<EOF
listen: :$HYSTERIA_PORT listen: :$HYSTERIA_PORT
@@ -397,12 +521,12 @@ EOF
systemctl enable hysteria-server systemctl enable hysteria-server
systemctl start hysteria-server systemctl start hysteria-server
ufw allow $HYSTERIA_PORT/udp 2>/dev/null || firewall-cmd --permanent --add-port=$HYSTERIA_PORT/udp 2>/dev/null open_firewall_port "$HYSTERIA_PORT" "udp"
success "Hysteria2 установлен" success "Hysteria2 установлен"
echo "" echo ""
log "Порт: $HYSTERIA_PORT" log "Порт: $HYSTERIA_PORT"
log "Пароль: $HYSTERIA_PASSWORD" echo -e " ${CYAN}${SYM_INFO}${NC} ${WHITE}Пароль: ${HYSTERIA_PASSWORD}${NC}"
warn "Сохраните эти данные!" warn "Сохраните эти данные!"
} }
@@ -433,8 +557,12 @@ install_mtproxy() {
SECRET=$(head -c 16 /dev/urandom | xxd -ps) SECRET=$(head -c 16 /dev/urandom | xxd -ps)
read -p "Введите порт для MTProxy (по умолчанию 8443): " MTPROXY_PORT read -p "Введите порт для MTProxy (по умолчанию ${MTPROXY_PORT_DEFAULT}): " MTPROXY_PORT
MTPROXY_PORT=${MTPROXY_PORT:-8443} MTPROXY_PORT=${MTPROXY_PORT:-$MTPROXY_PORT_DEFAULT}
if ! [[ "$MTPROXY_PORT" =~ ^[0-9]+$ ]] || [ "$MTPROXY_PORT" -lt 1 ] || [ "$MTPROXY_PORT" -gt 65535 ]; then
error "Неверный порт: $MTPROXY_PORT"
return 1
fi
cat > /etc/systemd/system/mtproxy.service <<EOF cat > /etc/systemd/system/mtproxy.service <<EOF
[Unit] [Unit]
@@ -455,7 +583,7 @@ EOF
systemctl enable mtproxy systemctl enable mtproxy
systemctl start mtproxy systemctl start mtproxy
ufw allow $MTPROXY_PORT/tcp 2>/dev/null || firewall-cmd --permanent --add-port=$MTPROXY_PORT/tcp 2>/dev/null open_firewall_port "$MTPROXY_PORT" "tcp"
cat > /opt/MTProxy/.config <<EOF cat > /opt/MTProxy/.config <<EOF
MTPROXY_PORT=$MTPROXY_PORT MTPROXY_PORT=$MTPROXY_PORT
@@ -658,63 +786,158 @@ EOF
success "Selfsteal шаблон установлен" success "Selfsteal шаблон установлен"
} }
backup_configs() {
local backup_dir="/root/proxy-core-backup-$(date +%Y%m%d-%H%M%S)"
mkdir -p "$backup_dir"
[ -d "/etc/wireguard" ] && cp -r /etc/wireguard "$backup_dir/"
[ -d "/etc/hysteria" ] && cp -r /etc/hysteria "$backup_dir/"
[ -d "/opt/MTProxy" ] && cp -r /opt/MTProxy/.config "$backup_dir/mtproxy.config" 2>/dev/null || true
[ -f "/etc/systemd/system/mtproxy.service" ] && cp /etc/systemd/system/mtproxy.service "$backup_dir/"
[ -f "/etc/systemd/system/hysteria-server.service" ] && cp /etc/systemd/system/hysteria-server.service "$backup_dir/"
[ -d "/opt/remnawave" ] && cp -r /opt/remnawave "$backup_dir/remnawave" 2>/dev/null || true
success "Резервная копия создана: $backup_dir"
}
uninstall_panels_menu() {
echo ""
echo -e "${YELLOW}Выберите компонент для удаления:${NC}"
echo "1) WireGuard"
echo "2) 3x-ui"
echo "3) Remnawave"
echo "4) Hysteria2"
echo "5) MTProxy"
echo "6) Удалить всё"
echo "0) Назад"
echo ""
read -p "Ваш выбор: " uninstall_choice
case $uninstall_choice in
1)
systemctl disable --now wg-quick@wg0 >/dev/null 2>&1 || true
rm -rf /etc/wireguard
success "WireGuard удален"
;;
2)
if command -v x-ui >/dev/null 2>&1; then
x-ui uninstall || warn "Не удалось выполнить x-ui uninstall, проверьте вручную"
else
warn "x-ui не найден, возможно уже удален"
fi
;;
3)
if [ -d "/opt/remnawave" ]; then
cd /opt/remnawave
docker compose down >/dev/null 2>&1 || true
cd /opt
rm -rf /opt/remnawave
success "Remnawave удален"
else
warn "Remnawave не найден"
fi
;;
4)
systemctl disable --now hysteria-server >/dev/null 2>&1 || true
rm -f /etc/systemd/system/hysteria-server.service
systemctl daemon-reload
rm -rf /etc/hysteria
rm -f /usr/local/bin/hysteria
success "Hysteria2 удален"
;;
5)
local mtproxy_port=""
if [ -f "/opt/MTProxy/.config" ]; then
mtproxy_port="$(grep '^MTPROXY_PORT=' /opt/MTProxy/.config | cut -d= -f2)"
fi
systemctl disable --now mtproxy >/dev/null 2>&1 || true
rm -f /etc/systemd/system/mtproxy.service
systemctl daemon-reload
rm -rf /opt/MTProxy
if [ -n "$mtproxy_port" ] && command -v ufw >/dev/null 2>&1; then
ufw delete allow "${mtproxy_port}/tcp" >/dev/null 2>&1 || true
fi
success "MTProxy удален"
;;
6)
systemctl disable --now wg-quick@wg0 >/dev/null 2>&1 || true
systemctl disable --now hysteria-server >/dev/null 2>&1 || true
systemctl disable --now mtproxy >/dev/null 2>&1 || true
rm -f /etc/systemd/system/hysteria-server.service /etc/systemd/system/mtproxy.service
systemctl daemon-reload
rm -rf /etc/wireguard /etc/hysteria /opt/MTProxy /opt/remnawave
if command -v x-ui >/dev/null 2>&1; then
x-ui uninstall >/dev/null 2>&1 || true
fi
success "Основные компоненты удалены"
;;
0)
return 0
;;
*)
warn "Неверный выбор"
return 1
;;
esac
}
# Main menu # Main menu
show_main_menu() { show_main_menu() {
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Source banner # Source banner
if [ -f "$SCRIPT_DIR/banner.sh" ]; then if [ "$USE_UNICODE" -eq 1 ] && [ -f "$SCRIPT_DIR/banner.sh" ]; then
source "$SCRIPT_DIR/banner.sh" source "$SCRIPT_DIR/banner.sh"
show_gradient_banner show_gradient_banner
else else
clear clear
echo -e "${MAGENTA}╔════════════════════════════════════════╗${NC}" echo -e "${MAGENTA}╔════════════════════════════════════════╗${NC}"
echo -e "${MAGENTA} 🚀 Proxy-Core Installer ║${NC}" echo -e "${MAGENTA}║ Proxy-Core Installer ${NC}"
echo -e "${MAGENTA}║ Version: ${SCRIPT_VERSION}${NC}" echo -e "${MAGENTA}║ Version: ${SCRIPT_VERSION}${NC}"
echo -e "${MAGENTA}╚════════════════════════════════════════╝${NC}" echo -e "${MAGENTA}╚════════════════════════════════════════╝${NC}"
echo "" echo ""
fi fi
echo -e " ${CYAN}╔═══════════════════════════════════════════════════════════════╗${NC}" echo -e " ${CYAN}╔═══════════════════════════════════════════════════════════════╗${NC}"
echo -e " ${CYAN}${NC} ${WHITE}📦 УСТАНОВКА${NC} ${CYAN}${NC}" echo -e " ${CYAN}${NC} ${WHITE}УСТАНОВКА${NC} ${CYAN}${NC}"
echo -e " ${CYAN}╚═══════════════════════════════════════════════════════════════╝${NC}" echo -e " ${CYAN}╚═══════════════════════════════════════════════════════════════╝${NC}"
echo "" echo ""
echo -e " ${YELLOW}1.${NC} 🔧 ${WHITE}Установить панель${NC}" echo -e " ${YELLOW}1.${NC} ${WHITE}Установить панель${NC}"
echo -e " ${GRAY}WireGuard, 3x-ui, Remnawave, Hysteria2, MTProxy${NC}" echo -e " ${GRAY}WireGuard, 3x-ui, Remnawave, Hysteria2, MTProxy${NC}"
echo "" echo ""
echo -e " ${CYAN}╔═══════════════════════════════════════════════════════════════╗${NC}" echo -e " ${CYAN}╔═══════════════════════════════════════════════════════════════╗${NC}"
echo -e " ${CYAN}${NC} ${WHITE}⚙️ УПРАВЛЕНИЕ${NC} ${CYAN}${NC}" echo -e " ${CYAN}${NC} ${WHITE}УПРАВЛЕНИЕ${NC} ${CYAN}${NC}"
echo -e " ${CYAN}╚═══════════════════════════════════════════════════════════════╝${NC}" echo -e " ${CYAN}╚═══════════════════════════════════════════════════════════════╝${NC}"
echo "" echo ""
echo -e " ${YELLOW}2.${NC} 🎮 ${WHITE}Управление сервисами${NC}" echo -e " ${YELLOW}2.${NC} ${WHITE}Управление сервисами${NC}"
echo -e " ${GRAY}Запуск, остановка, перезапуск панелей${NC}" echo -e " ${GRAY}Запуск, остановка, перезапуск панелей${NC}"
echo "" echo ""
echo -e " ${YELLOW}3.${NC} 💾 ${WHITE}Резервное копирование${NC}" echo -e " ${YELLOW}3.${NC} ${WHITE}Резервное копирование${NC}"
echo -e " ${GRAY}Создание и восстановление бэкапов${NC}" echo -e " ${GRAY}Создание и восстановление бэкапов${NC}"
echo "" echo ""
echo -e " ${YELLOW}4.${NC} 🔄 ${WHITE}Обновить компоненты${NC}" echo -e " ${YELLOW}4.${NC} ${WHITE}Обновить компоненты${NC}"
echo -e " ${GRAY}Обновление установленных панелей${NC}" echo -e " ${GRAY}Обновление установленных панелей${NC}"
echo "" echo ""
echo -e " ${CYAN}╔═══════════════════════════════════════════════════════════════╗${NC}" echo -e " ${CYAN}╔═══════════════════════════════════════════════════════════════╗${NC}"
echo -e " ${CYAN}${NC} ${WHITE}🌐 ДОПОЛНИТЕЛЬНО${NC} ${CYAN}${NC}" echo -e " ${CYAN}${NC} ${WHITE}ДОПОЛНИТЕЛЬНО${NC} ${CYAN}${NC}"
echo -e " ${CYAN}╚═══════════════════════════════════════════════════════════════╝${NC}" echo -e " ${CYAN}╚═══════════════════════════════════════════════════════════════╝${NC}"
echo "" echo ""
echo -e " ${YELLOW}5.${NC} 🗑️ ${WHITE}Удалить панель${NC}" echo -e " ${YELLOW}5.${NC} ${WHITE}Удалить панель${NC}"
echo -e " ${GRAY}Полное удаление установленных компонентов${NC}" echo -e " ${GRAY}Полное удаление установленных компонентов${NC}"
echo "" echo ""
echo -e " ${YELLOW}6.${NC} 🎭 ${WHITE}Установить Selfsteal${NC}" echo -e " ${YELLOW}6.${NC} ${WHITE}Установить Selfsteal${NC}"
echo -e " ${GRAY}Маскировка трафика под обычный сайт${NC}" echo -e " ${GRAY}Маскировка трафика под обычный сайт${NC}"
echo "" echo ""
echo -e " ${YELLOW}7.${NC} 🌐 ${WHITE}Настроить Reverse Proxy${NC}" echo -e " ${YELLOW}7.${NC} ${WHITE}Настроить Reverse Proxy${NC}"
echo -e " ${GRAY}Nginx, Caddy, HAProxy - установка и настройка${NC}" echo -e " ${GRAY}Nginx, Caddy, HAProxy - установка и настройка${NC}"
echo "" echo ""
echo -e " ${GRAY}─────────────────────────────────────────────────────────────────${NC}" echo -e " ${GRAY}─────────────────────────────────────────────────────────────────${NC}"
echo "" echo ""
echo -e " ${YELLOW}9.${NC} 🌍 ${WHITE}Сменить язык / Change language${NC}" echo -e " ${YELLOW}9.${NC} ${WHITE}Сменить язык / Change language${NC}"
echo -e " ${YELLOW}0.${NC} 🚪 ${WHITE}Выход / Exit${NC}" echo -e " ${YELLOW}0.${NC} ${WHITE}Выход / Exit${NC}"
echo "" echo ""
echo -e " ${GRAY}─────────────────────────────────────────────────────────────────${NC}" echo -e " ${GRAY}─────────────────────────────────────────────────────────────────${NC}"
echo "" echo ""
@@ -724,39 +947,39 @@ show_install_menu() {
clear clear
echo "" echo ""
echo -e " ${GREEN}╔═══════════════════════════════════════════════════════════════╗${NC}" echo -e " ${GREEN}╔═══════════════════════════════════════════════════════════════╗${NC}"
echo -e " ${GREEN}${NC} ${WHITE}📦 Выберите панель для установки${NC} ${GREEN}${NC}" echo -e " ${GREEN}${NC} ${WHITE}Выберите панель для установки${NC} ${GREEN}${NC}"
echo -e " ${GREEN}╚═══════════════════════════════════════════════════════════════╝${NC}" echo -e " ${GREEN}╚═══════════════════════════════════════════════════════════════╝${NC}"
echo "" echo ""
echo -e " ${YELLOW}1.${NC} 🔐 ${WHITE}WireGuard VPN${NC}" echo -e " ${YELLOW}1.${NC} ${WHITE}WireGuard VPN${NC}"
echo -e " ${GRAY}Современный, быстрый и безопасный VPN${NC}" echo -e " ${GRAY}Современный, быстрый и безопасный VPN${NC}"
echo "" echo ""
echo -e " ${YELLOW}2.${NC} 🌐 ${WHITE}3x-ui Panel${NC}" echo -e " ${YELLOW}2.${NC} ${WHITE}3x-ui Panel${NC}"
echo -e " ${GRAY}VLESS, VMess, Trojan, Shadowsocks${NC}" echo -e " ${GRAY}VLESS, VMess, Trojan, Shadowsocks${NC}"
echo "" echo ""
echo -e " ${YELLOW}3.${NC} 🐳 ${WHITE}Remnawave Panel${NC}" echo -e " ${YELLOW}3.${NC} ${WHITE}Remnawave Panel${NC}"
echo -e " ${GRAY}Современная панель с Docker${NC}" echo -e " ${GRAY}Современная панель с Docker${NC}"
echo "" echo ""
echo -e " ${YELLOW}4.${NC} ${WHITE}Hysteria2 Proxy${NC}" echo -e " ${YELLOW}4.${NC} ${WHITE}Hysteria2 Proxy${NC}"
echo -e " ${GRAY}Высокоскоростной прокси с маскировкой${NC}" echo -e " ${GRAY}Высокоскоростной прокси с маскировкой${NC}"
echo "" echo ""
echo -e " ${YELLOW}5.${NC} 📱 ${WHITE}MTProxy (Telegram)${NC}" echo -e " ${YELLOW}5.${NC} ${WHITE}MTProxy (Telegram)${NC}"
echo -e " ${GRAY}Официальный прокси для Telegram${NC}" echo -e " ${GRAY}Официальный прокси для Telegram${NC}"
echo "" echo ""
echo -e " ${GRAY}─────────────────────────────────────────────────────────────────${NC}" echo -e " ${GRAY}─────────────────────────────────────────────────────────────────${NC}"
echo "" echo ""
echo -e " ${YELLOW}6.${NC} 🚀 ${WHITE}Установить всё${NC}" echo -e " ${YELLOW}6.${NC} ${WHITE}Установить всё${NC}"
echo -e " ${GRAY}Последовательная установка всех панелей${NC}" echo -e " ${GRAY}Последовательная установка всех панелей${NC}"
echo "" echo ""
echo -e " ${YELLOW}0.${NC} ⬅️ ${WHITE}Назад / Back${NC}" echo -e " ${YELLOW}0.${NC} ${WHITE}Назад / Back${NC}"
echo "" echo ""
} }
main() { main() {
check_root check_root
ensure_project_files
load_defaults
detect_os detect_os
check_memory check_memory
mkdir -p "$PROJECT_DIR"
load_language load_language
while true; do while true; do
@@ -813,6 +1036,20 @@ main() {
read -p "Нажмите Enter / Press Enter..." read -p "Нажмите Enter / Press Enter..."
fi fi
;; ;;
2)
run_project_script "manage.sh"
;;
3)
backup_configs
read -p "Нажмите Enter / Press Enter..."
;;
4)
run_project_script "update.sh"
;;
5)
uninstall_panels_menu
read -p "Нажмите Enter / Press Enter..."
;;
7) 7)
# Запуск Reverse Proxy Manager # Запуск Reverse Proxy Manager
if [ -f "$PROJECT_DIR/reverse-proxy-manager.sh" ]; then if [ -f "$PROJECT_DIR/reverse-proxy-manager.sh" ]; then
+14 -2
View File
@@ -23,8 +23,12 @@ get_next_wg_ip() {
if [ -z "$LAST_IP" ]; then if [ -z "$LAST_IP" ]; then
echo "10.0.0.2" echo "10.0.0.2"
else else
LAST_NUM=$(echo $LAST_IP | cut -d. -f4) LAST_NUM=$(echo "$LAST_IP" | cut -d. -f4)
NEXT_NUM=$((LAST_NUM + 1)) NEXT_NUM=$((LAST_NUM + 1))
if [ "$NEXT_NUM" -gt 254 ]; then
error "Пул адресов WireGuard исчерпан (10.0.0.2-10.0.0.254)"
return 1
fi
echo "10.0.0.$NEXT_NUM" echo "10.0.0.$NEXT_NUM"
fi fi
} }
@@ -147,7 +151,15 @@ remove_wireguard_client() {
return 0 return 0
fi fi
sed -i "/# $client_name/,+2d" $WG_CONF local tmp_conf
tmp_conf="$(mktemp)"
awk -v marker="# ${client_name}" '
BEGIN {skip=0}
$0 == marker {skip=1; next}
skip && /^\[Peer\]/ {skip=0}
!skip {print}
' "$WG_CONF" > "$tmp_conf"
mv "$tmp_conf" "$WG_CONF"
rm -rf "$CLIENT_DIR" rm -rf "$CLIENT_DIR"
systemctl restart wg-quick@wg0 systemctl restart wg-quick@wg0
+61 -5
View File
@@ -19,6 +19,38 @@ warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
error() { echo -e "${RED}[ERROR]${NC} $1"; } error() { echo -e "${RED}[ERROR]${NC} $1"; }
success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; } success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
get_server_ip() {
curl -s -4 ifconfig.me || curl -s -4 api.ipify.org || curl -s -4 ipinfo.io/ip
}
validate_client_name() {
local client_name=$1
[[ "$client_name" =~ ^[a-zA-Z0-9_-]+$ ]]
}
remove_wg_peer_block() {
local client_name=$1
local tmp_conf
tmp_conf="$(mktemp)"
awk -v marker="# ${client_name}" '
BEGIN {skip=0}
$0 == marker {skip=1; next}
skip && /^\[Peer\]/ {skip=0}
!skip {print}
' /etc/wireguard/wg0.conf > "$tmp_conf"
mv "$tmp_conf" /etc/wireguard/wg0.conf
}
run_remote_script() {
local url=$1
local tmp_script
tmp_script="$(mktemp /tmp/proxy-core-remote.XXXXXX.sh)"
curl -fsSL "$url" -o "$tmp_script"
chmod 700 "$tmp_script"
bash "$tmp_script"
rm -f "$tmp_script"
}
# WireGuard Management # WireGuard Management
manage_wireguard() { manage_wireguard() {
if ! systemctl is-active --quiet wg-quick@wg0; then if ! systemctl is-active --quiet wg-quick@wg0; then
@@ -84,6 +116,10 @@ add_wireguard_client() {
error "Имя не может быть пустым" error "Имя не может быть пустым"
return 1 return 1
fi fi
if ! validate_client_name "$CLIENT_NAME"; then
error "Неверное имя: только буквы, цифры, _ и -"
return 1
fi
CLIENT_DIR="/etc/wireguard/clients/$CLIENT_NAME" CLIENT_DIR="/etc/wireguard/clients/$CLIENT_NAME"
@@ -102,7 +138,7 @@ add_wireguard_client() {
CLIENT_PRIVATE_KEY=$(cat private.key) CLIENT_PRIVATE_KEY=$(cat private.key)
CLIENT_PUBLIC_KEY=$(cat public.key) CLIENT_PUBLIC_KEY=$(cat public.key)
SERVER_PUBLIC_KEY=$(cat /etc/wireguard/server_public.key) SERVER_PUBLIC_KEY=$(cat /etc/wireguard/server_public.key)
SERVER_IP=$(curl -s ifconfig.me) SERVER_IP=$(get_server_ip)
SERVER_PORT=$(grep ListenPort /etc/wireguard/wg0.conf | awk '{print $3}') SERVER_PORT=$(grep ListenPort /etc/wireguard/wg0.conf | awk '{print $3}')
# Get next available IP # Get next available IP
@@ -112,6 +148,10 @@ add_wireguard_client() {
else else
LAST_NUM=$(echo $LAST_IP | cut -d. -f4) LAST_NUM=$(echo $LAST_IP | cut -d. -f4)
NEXT_NUM=$((LAST_NUM + 1)) NEXT_NUM=$((LAST_NUM + 1))
if [ "$NEXT_NUM" -gt 254 ]; then
error "Пул адресов WireGuard исчерпан (10.0.0.2-10.0.0.254)"
return 1
fi
CLIENT_IP="10.0.0.$NEXT_NUM" CLIENT_IP="10.0.0.$NEXT_NUM"
fi fi
@@ -146,7 +186,11 @@ EOF
echo "" echo ""
log "QR-код для мобильных устройств:" log "QR-код для мобильных устройств:"
qrencode -t ansiutf8 < client.conf if command -v qrencode >/dev/null 2>&1; then
qrencode -t ansiutf8 < client.conf
else
warn "qrencode не установлен, пропускаем QR-код"
fi
echo "" echo ""
read -p "Нажмите Enter..." read -p "Нажмите Enter..."
@@ -182,6 +226,10 @@ remove_wireguard_client() {
error "Имя не может быть пустым" error "Имя не может быть пустым"
return 1 return 1
fi fi
if ! validate_client_name "$CLIENT_NAME"; then
error "Неверное имя: только буквы, цифры, _ и -"
return 1
fi
CLIENT_DIR="/etc/wireguard/clients/$CLIENT_NAME" CLIENT_DIR="/etc/wireguard/clients/$CLIENT_NAME"
@@ -190,7 +238,7 @@ remove_wireguard_client() {
return 1 return 1
fi fi
sed -i "/# $CLIENT_NAME/,+2d" /etc/wireguard/wg0.conf remove_wg_peer_block "$CLIENT_NAME"
rm -rf "$CLIENT_DIR" rm -rf "$CLIENT_DIR"
systemctl restart wg-quick@wg0 systemctl restart wg-quick@wg0
@@ -206,6 +254,10 @@ show_wireguard_qr() {
error "Имя не может быть пустым" error "Имя не может быть пустым"
return 1 return 1
fi fi
if ! validate_client_name "$CLIENT_NAME"; then
error "Неверное имя: только буквы, цифры, _ и -"
return 1
fi
CLIENT_DIR="/etc/wireguard/clients/$CLIENT_NAME" CLIENT_DIR="/etc/wireguard/clients/$CLIENT_NAME"
@@ -220,7 +272,11 @@ show_wireguard_qr() {
echo "" echo ""
log "QR-код:" log "QR-код:"
qrencode -t ansiutf8 < "$CLIENT_DIR/client.conf" if command -v qrencode >/dev/null 2>&1; then
qrencode -t ansiutf8 < "$CLIENT_DIR/client.conf"
else
warn "qrencode не установлен, пропускаем QR-код"
fi
echo "" echo ""
read -p "Нажмите Enter..." read -p "Нажмите Enter..."
@@ -274,7 +330,7 @@ manage_3xui() {
x-ui log x-ui log
;; ;;
6) 6)
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) run_remote_script "https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh"
success "3x-ui обновлен" success "3x-ui обновлен"
sleep 2 sleep 2
;; ;;
+59 -6
View File
@@ -3,10 +3,13 @@
# MTProxy Manager # MTProxy Manager
# Author: houseassassin # Author: houseassassin
set -euo pipefail
RED='\033[0;31m' RED='\033[0;31m'
GREEN='\033[0;32m' GREEN='\033[0;32m'
YELLOW='\033[1;33m' YELLOW='\033[1;33m'
BLUE='\033[0;34m' BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m' NC='\033[0m'
log() { echo -e "${GREEN}[INFO]${NC} $1"; } log() { echo -e "${GREEN}[INFO]${NC} $1"; }
@@ -16,6 +19,18 @@ success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
MTPROXY_DIR="/opt/MTProxy" MTPROXY_DIR="/opt/MTProxy"
get_server_ip() {
curl -s -4 ifconfig.me || curl -s -4 api.ipify.org || curl -s -4 ipinfo.io/ip
}
validate_port() {
local port=$1
if ! [[ "$port" =~ ^[0-9]+$ ]] || [ "$port" -lt 1 ] || [ "$port" -gt 65535 ]; then
return 1
fi
return 0
}
check_installed() { check_installed() {
if [ ! -d "$MTPROXY_DIR" ]; then if [ ! -d "$MTPROXY_DIR" ]; then
error "MTProxy не установлен" error "MTProxy не установлен"
@@ -30,7 +45,7 @@ get_connection_link() {
fi fi
source "$MTPROXY_DIR/.config" source "$MTPROXY_DIR/.config"
SERVER_IP=$(curl -s ifconfig.me) SERVER_IP=$(get_server_ip)
echo "" echo ""
log "Ссылка для подключения:" log "Ссылка для подключения:"
@@ -60,12 +75,29 @@ regenerate_secret() {
return 0 return 0
fi fi
source "$MTPROXY_DIR/.config"
NEW_SECRET=$(head -c 16 /dev/urandom | xxd -ps) NEW_SECRET=$(head -c 16 /dev/urandom | xxd -ps)
# Обновляем конфигурацию # Обновляем конфигурацию
sed -i "s/SECRET=.*/SECRET=$NEW_SECRET/" "$MTPROXY_DIR/.config" sed -i "s/SECRET=.*/SECRET=$NEW_SECRET/" "$MTPROXY_DIR/.config"
cat > /etc/systemd/system/mtproxy.service <<EOF
[Unit]
Description=MTProxy Telegram Proxy
After=network.target
[Service]
Type=simple
WorkingDirectory=$MTPROXY_DIR
ExecStart=$MTPROXY_DIR/objs/bin/mtproto-proxy -u nobody -p $MTPROXY_PORT -H $MTPROXY_PORT -S $NEW_SECRET --aes-pwd proxy-secret proxy-multi.conf -M 1
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
# Перезапускаем сервис # Перезапускаем сервис
systemctl daemon-reload
systemctl restart mtproxy systemctl restart mtproxy
success "Новый секрет сгенерирован: $NEW_SECRET" success "Новый секрет сгенерирован: $NEW_SECRET"
@@ -81,6 +113,10 @@ change_port() {
error "Порт не может быть пустым" error "Порт не может быть пустым"
return 1 return 1
fi fi
if ! validate_port "$NEW_PORT"; then
error "Неверный порт: $NEW_PORT"
return 1
fi
# Проверяем, что порт свободен # Проверяем, что порт свободен
if ss -ltun | grep -q ":$NEW_PORT "; then if ss -ltun | grep -q ":$NEW_PORT "; then
@@ -88,6 +124,9 @@ change_port() {
return 1 return 1
fi fi
source "$MTPROXY_DIR/.config"
local old_port="$MTPROXY_PORT"
# Обновляем конфигурацию # Обновляем конфигурацию
sed -i "s/MTPROXY_PORT=.*/MTPROXY_PORT=$NEW_PORT/" "$MTPROXY_DIR/.config" sed -i "s/MTPROXY_PORT=.*/MTPROXY_PORT=$NEW_PORT/" "$MTPROXY_DIR/.config"
@@ -113,8 +152,14 @@ EOF
systemctl restart mtproxy systemctl restart mtproxy
# Обновляем firewall # Обновляем firewall
ufw delete allow $MTPROXY_PORT/tcp 2>/dev/null if command -v ufw >/dev/null 2>&1; then
ufw allow $NEW_PORT/tcp 2>/dev/null ufw delete allow $old_port/tcp 2>/dev/null || true
ufw allow $NEW_PORT/tcp 2>/dev/null || true
elif command -v firewall-cmd >/dev/null 2>&1; then
firewall-cmd --permanent --remove-port="${old_port}/tcp" >/dev/null 2>&1 || true
firewall-cmd --permanent --add-port="${NEW_PORT}/tcp" >/dev/null 2>&1 || true
firewall-cmd --reload >/dev/null 2>&1 || true
fi
success "Порт изменен на $NEW_PORT" success "Порт изменен на $NEW_PORT"
get_connection_link get_connection_link
@@ -156,7 +201,7 @@ show_stats() {
# Количество подключений # Количество подключений
echo "" echo ""
log "Активные подключения:" log "Активные подключения:"
ss -tn | grep -c ":$(source $MTPROXY_DIR/.config && echo $MTPROXY_PORT) " || echo "0" ss -tn | grep -c ":$MTPROXY_PORT " || echo "0"
echo "" echo ""
} }
@@ -183,6 +228,9 @@ uninstall_mtproxy() {
return 0 return 0
fi fi
source "$MTPROXY_DIR/.config" 2>/dev/null || true
local mtproxy_port="${MTPROXY_PORT:-}"
# Остановка и удаление сервиса # Остановка и удаление сервиса
systemctl stop mtproxy systemctl stop mtproxy
systemctl disable mtproxy systemctl disable mtproxy
@@ -193,8 +241,12 @@ uninstall_mtproxy() {
rm -rf "$MTPROXY_DIR" rm -rf "$MTPROXY_DIR"
# Удаление правила firewall # Удаление правила firewall
source "$MTPROXY_DIR/.config" 2>/dev/null if [ -n "$mtproxy_port" ] && command -v ufw >/dev/null 2>&1; then
ufw delete allow $MTPROXY_PORT/tcp 2>/dev/null ufw delete allow $mtproxy_port/tcp 2>/dev/null || true
elif [ -n "$mtproxy_port" ] && command -v firewall-cmd >/dev/null 2>&1; then
firewall-cmd --permanent --remove-port="${mtproxy_port}/tcp" >/dev/null 2>&1 || true
firewall-cmd --reload >/dev/null 2>&1 || true
fi
success "MTProxy удален" success "MTProxy удален"
exit 0 exit 0
@@ -270,3 +322,4 @@ if [[ $EUID -ne 0 ]]; then
fi fi
main_menu main_menu
source "$MTPROXY_DIR/.config"
+68 -25
View File
@@ -17,6 +17,7 @@ YELLOW='\033[1;33m'
BLUE='\033[0;34m' BLUE='\033[0;34m'
MAGENTA='\033[0;35m' MAGENTA='\033[0;35m'
CYAN='\033[0;36m' CYAN='\033[0;36m'
WHITE='\033[1;37m'
NC='\033[0m' NC='\033[0m'
# Configuration # Configuration
@@ -115,6 +116,49 @@ configure_nginx_3xui() {
read -p "Введите домен (например, vpn.example.com): " DOMAIN read -p "Введите домен (например, vpn.example.com): " DOMAIN
read -p "Введите порт 3x-ui (по умолчанию 2053): " XRAY_PORT read -p "Введите порт 3x-ui (по умолчанию 2053): " XRAY_PORT
XRAY_PORT=${XRAY_PORT:-2053} XRAY_PORT=${XRAY_PORT:-2053}
if ! [[ "$XRAY_PORT" =~ ^[0-9]+$ ]] || [ "$XRAY_PORT" -lt 1 ] || [ "$XRAY_PORT" -gt 65535 ]; then
error "Неверный порт: $XRAY_PORT"
return 1
fi
cat > "$NGINX_DIR/sites-available/3xui" <<EOF
server {
listen 80;
listen [::]:80;
server_name $DOMAIN;
location /.well-known/acme-challenge/ {
root /var/www/html;
}
location / {
return 301 https://\$server_name\$request_uri;
}
}
server {
listen 443;
listen [::]:443;
server_name $DOMAIN;
location / {
proxy_pass http://127.0.0.1:$XRAY_PORT;
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
}
}
EOF
ln -sf "$NGINX_DIR/sites-available/3xui" "$NGINX_DIR/sites-enabled/"
nginx -t
log "Получение SSL сертификата..."
certbot certonly --nginx -d $DOMAIN --non-interactive --agree-tos --email admin@$DOMAIN
cat > "$NGINX_DIR/sites-available/3xui" <<EOF cat > "$NGINX_DIR/sites-available/3xui" <<EOF
server { server {
@@ -155,11 +199,6 @@ server {
} }
EOF EOF
ln -sf "$NGINX_DIR/sites-available/3xui" "$NGINX_DIR/sites-enabled/"
log "Получение SSL сертификата..."
certbot certonly --nginx -d $DOMAIN --non-interactive --agree-tos --email admin@$DOMAIN
nginx -t && systemctl reload nginx nginx -t && systemctl reload nginx
success "Nginx настроен для 3x-ui на домене $DOMAIN" success "Nginx настроен для 3x-ui на домене $DOMAIN"
@@ -201,6 +240,10 @@ configure_haproxy_loadbalancer() {
log "Настройка HAProxy для балансировки нагрузки..." log "Настройка HAProxy для балансировки нагрузки..."
read -p "Введите количество backend серверов: " BACKEND_COUNT read -p "Введите количество backend серверов: " BACKEND_COUNT
if ! [[ "$BACKEND_COUNT" =~ ^[0-9]+$ ]] || [ "$BACKEND_COUNT" -lt 1 ]; then
error "Введите число больше 0"
return 1
fi
echo "" echo ""
log "Введите IP адреса backend серверов:" log "Введите IP адреса backend серверов:"
@@ -306,12 +349,12 @@ show_tips() {
clear clear
echo "" echo ""
echo -e "${MAGENTA}╔════════════════════════════════════════════════════════════════════╗${NC}" echo -e "${MAGENTA}╔════════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${MAGENTA}${NC} ${WHITE}💡 Подсказки по настройке Reverse Proxy${NC} ${MAGENTA}${NC}" echo -e "${MAGENTA}${NC} ${WHITE}Подсказки по настройке Reverse Proxy${NC} ${MAGENTA}${NC}"
echo -e "${MAGENTA}╚════════════════════════════════════════════════════════════════════╝${NC}" echo -e "${MAGENTA}╚════════════════════════════════════════════════════════════════════╝${NC}"
echo "" echo ""
echo -e " ${CYAN}╔═══════════════════════════════════════════════════════════════╗${NC}" echo -e " ${CYAN}╔═══════════════════════════════════════════════════════════════╗${NC}"
echo -e " ${CYAN}${NC} ${WHITE}🔧 Nginx${NC} ${CYAN}${NC}" echo -e " ${CYAN}${NC} ${WHITE}Nginx${NC} ${CYAN}${NC}"
echo -e " ${CYAN}╚═══════════════════════════════════════════════════════════════╝${NC}" echo -e " ${CYAN}╚═══════════════════════════════════════════════════════════════╝${NC}"
echo -e " ${GREEN}${NC} Лучший выбор для высоких нагрузок" echo -e " ${GREEN}${NC} Лучший выбор для высоких нагрузок"
echo -e " ${GREEN}${NC} Отличное кэширование и обработка статики" echo -e " ${GREEN}${NC} Отличное кэширование и обработка статики"
@@ -320,7 +363,7 @@ show_tips() {
echo "" echo ""
echo -e " ${CYAN}╔═══════════════════════════════════════════════════════════════╗${NC}" echo -e " ${CYAN}╔═══════════════════════════════════════════════════════════════╗${NC}"
echo -e " ${CYAN}${NC} ${WHITE}🚀 Caddy${NC} ${CYAN}${NC}" echo -e " ${CYAN}${NC} ${WHITE}Caddy${NC} ${CYAN}${NC}"
echo -e " ${CYAN}╚═══════════════════════════════════════════════════════════════╝${NC}" echo -e " ${CYAN}╚═══════════════════════════════════════════════════════════════╝${NC}"
echo -e " ${GREEN}${NC} Автоматический SSL из коробки" echo -e " ${GREEN}${NC} Автоматический SSL из коробки"
echo -e " ${GREEN}${NC} Простая конфигурация" echo -e " ${GREEN}${NC} Простая конфигурация"
@@ -329,7 +372,7 @@ show_tips() {
echo "" echo ""
echo -e " ${CYAN}╔═══════════════════════════════════════════════════════════════╗${NC}" echo -e " ${CYAN}╔═══════════════════════════════════════════════════════════════╗${NC}"
echo -e " ${CYAN}${NC} ${WHITE}⚖️ HAProxy${NC} ${CYAN}${NC}" echo -e " ${CYAN}${NC} ${WHITE}HAProxy${NC} ${CYAN}${NC}"
echo -e " ${CYAN}╚═══════════════════════════════════════════════════════════════╝${NC}" echo -e " ${CYAN}╚═══════════════════════════════════════════════════════════════╝${NC}"
echo -e " ${GREEN}${NC} Лучший для балансировки нагрузки" echo -e " ${GREEN}${NC} Лучший для балансировки нагрузки"
echo -e " ${GREEN}${NC} TCP и HTTP режимы" echo -e " ${GREEN}${NC} TCP и HTTP режимы"
@@ -338,7 +381,7 @@ show_tips() {
echo "" echo ""
echo -e " ${CYAN}╔═══════════════════════════════════════════════════════════════╗${NC}" echo -e " ${CYAN}╔═══════════════════════════════════════════════════════════════╗${NC}"
echo -e " ${CYAN}${NC} ${WHITE}🔄 Гибридные решения${NC} ${CYAN}${NC}" echo -e " ${CYAN}${NC} ${WHITE}Гибридные решения${NC} ${CYAN}${NC}"
echo -e " ${CYAN}╚═══════════════════════════════════════════════════════════════╝${NC}" echo -e " ${CYAN}╚═══════════════════════════════════════════════════════════════╝${NC}"
echo -e " ${BLUE}${NC} Nginx + Caddy: статика + автоSSL" echo -e " ${BLUE}${NC} Nginx + Caddy: статика + автоSSL"
echo -e " ${BLUE}${NC} HAProxy + Nginx: балансировка + кэш" echo -e " ${BLUE}${NC} HAProxy + Nginx: балансировка + кэш"
@@ -346,7 +389,7 @@ show_tips() {
echo "" echo ""
echo -e " ${YELLOW}╔═══════════════════════════════════════════════════════════════╗${NC}" echo -e " ${YELLOW}╔═══════════════════════════════════════════════════════════════╗${NC}"
echo -e " ${YELLOW}${NC} ${WHITE}📋 Рекомендации${NC} ${YELLOW}${NC}" echo -e " ${YELLOW}${NC} ${WHITE}Рекомендации${NC} ${YELLOW}${NC}"
echo -e " ${YELLOW}╚═══════════════════════════════════════════════════════════════╝${NC}" echo -e " ${YELLOW}╚═══════════════════════════════════════════════════════════════╝${NC}"
echo -e " ${WHITE}1.${NC} Для простых VPN панелей: ${GREEN}Caddy${NC}" echo -e " ${WHITE}1.${NC} Для простых VPN панелей: ${GREEN}Caddy${NC}"
echo -e " ${WHITE}2.${NC} Для высоких нагрузок: ${GREEN}Nginx${NC}" echo -e " ${WHITE}2.${NC} Для высоких нагрузок: ${GREEN}Nginx${NC}"
@@ -364,7 +407,7 @@ show_main_menu() {
clear clear
echo "" echo ""
echo -e "${CYAN}╔═══════════════════════════════════════════════════════════════════════╗${NC}" echo -e "${CYAN}╔═══════════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${CYAN}${MAGENTA} 🌐 REVERSE PROXY MANAGER ${CYAN}${NC}" echo -e "${CYAN}${MAGENTA} REVERSE PROXY MANAGER ${CYAN}${NC}"
echo -e "${CYAN}${BLUE} Nginx • Caddy • HAProxy ${CYAN}${NC}" echo -e "${CYAN}${BLUE} Nginx • Caddy • HAProxy ${CYAN}${NC}"
echo -e "${CYAN}╚═══════════════════════════════════════════════════════════════════════╝${NC}" echo -e "${CYAN}╚═══════════════════════════════════════════════════════════════════════╝${NC}"
echo "" echo ""
@@ -378,50 +421,50 @@ show_main_menu() {
echo "" echo ""
echo -e " ${CYAN}╔═══════════════════════════════════════════════════════════════╗${NC}" echo -e " ${CYAN}╔═══════════════════════════════════════════════════════════════╗${NC}"
echo -e " ${CYAN}${NC} ${WHITE}📦 УСТАНОВКА${NC} ${CYAN}${NC}" echo -e " ${CYAN}${NC} ${WHITE}УСТАНОВКА${NC} ${CYAN}${NC}"
echo -e " ${CYAN}╚═══════════════════════════════════════════════════════════════╝${NC}" echo -e " ${CYAN}╚═══════════════════════════════════════════════════════════════╝${NC}"
echo "" echo ""
echo -e " ${YELLOW}1.${NC} 🔧 ${WHITE}Установить Nginx${NC}" echo -e " ${YELLOW}1.${NC} ${WHITE}Установить Nginx${NC}"
echo -e " ${GRAY}Высокая производительность и кэширование${NC}" echo -e " ${GRAY}Высокая производительность и кэширование${NC}"
echo "" echo ""
echo -e " ${YELLOW}2.${NC} 🚀 ${WHITE}Установить Caddy${NC}" echo -e " ${YELLOW}2.${NC} ${WHITE}Установить Caddy${NC}"
echo -e " ${GRAY}Автоматический SSL из коробки${NC}" echo -e " ${GRAY}Автоматический SSL из коробки${NC}"
echo "" echo ""
echo -e " ${YELLOW}3.${NC} ⚖️ ${WHITE}Установить HAProxy${NC}" echo -e " ${YELLOW}3.${NC} ${WHITE}Установить HAProxy${NC}"
echo -e " ${GRAY}Балансировка нагрузки${NC}" echo -e " ${GRAY}Балансировка нагрузки${NC}"
echo "" echo ""
echo -e " ${CYAN}╔═══════════════════════════════════════════════════════════════╗${NC}" echo -e " ${CYAN}╔═══════════════════════════════════════════════════════════════╗${NC}"
echo -e " ${CYAN}${NC} ${WHITE}⚙️ НАСТРОЙКА${NC} ${CYAN}${NC}" echo -e " ${CYAN}${NC} ${WHITE}НАСТРОЙКА${NC} ${CYAN}${NC}"
echo -e " ${CYAN}╚═══════════════════════════════════════════════════════════════╝${NC}" echo -e " ${CYAN}╚═══════════════════════════════════════════════════════════════╝${NC}"
echo "" echo ""
echo -e " ${YELLOW}4.${NC} 🌐 ${WHITE}Настроить Nginx для 3x-ui${NC}" echo -e " ${YELLOW}4.${NC} ${WHITE}Настроить Nginx для 3x-ui${NC}"
echo -e " ${GRAY}Автоматическая настройка с SSL${NC}" echo -e " ${GRAY}Автоматическая настройка с SSL${NC}"
echo "" echo ""
echo -e " ${YELLOW}5.${NC} 🔐 ${WHITE}Настроить Caddy для 3x-ui${NC}" echo -e " ${YELLOW}5.${NC} ${WHITE}Настроить Caddy для 3x-ui${NC}"
echo -e " ${GRAY}Автоматический HTTPS${NC}" echo -e " ${GRAY}Автоматический HTTPS${NC}"
echo "" echo ""
echo -e " ${YELLOW}6.${NC} ⚖️ ${WHITE}Настроить HAProxy (балансировка)${NC}" echo -e " ${YELLOW}6.${NC} ${WHITE}Настроить HAProxy (балансировка)${NC}"
echo -e " ${GRAY}Распределение нагрузки между серверами${NC}" echo -e " ${GRAY}Распределение нагрузки между серверами${NC}"
echo "" echo ""
echo -e " ${YELLOW}7.${NC} 🔄 ${WHITE}Настроить Nginx + Caddy (гибрид)${NC}" echo -e " ${YELLOW}7.${NC} ${WHITE}Настроить Nginx + Caddy (гибрид)${NC}"
echo -e " ${GRAY}Статика + автоматический SSL${NC}" echo -e " ${GRAY}Статика + автоматический SSL${NC}"
echo "" echo ""
echo -e " ${CYAN}╔═══════════════════════════════════════════════════════════════╗${NC}" echo -e " ${CYAN}╔═══════════════════════════════════════════════════════════════╗${NC}"
echo -e " ${CYAN}${NC} ${WHITE}ИНФОРМАЦИЯ${NC} ${CYAN}${NC}" echo -e " ${CYAN}${NC} ${WHITE}ИНФОРМАЦИЯ${NC} ${CYAN}${NC}"
echo -e " ${CYAN}╚═══════════════════════════════════════════════════════════════╝${NC}" echo -e " ${CYAN}╚═══════════════════════════════════════════════════════════════╝${NC}"
echo "" echo ""
echo -e " ${YELLOW}8.${NC} 💡 ${WHITE}Показать подсказки${NC}" echo -e " ${YELLOW}8.${NC} ${WHITE}Показать подсказки${NC}"
echo -e " ${GRAY}Рекомендации по выбору${NC}" echo -e " ${GRAY}Рекомендации по выбору${NC}"
echo "" echo ""
echo -e " ${YELLOW}9.${NC} 📊 ${WHITE}Статус сервисов${NC}" echo -e " ${YELLOW}9.${NC} ${WHITE}Статус сервисов${NC}"
echo -e " ${GRAY}Проверка работы установленных proxy${NC}" echo -e " ${GRAY}Проверка работы установленных proxy${NC}"
echo "" echo ""
echo -e " ${GRAY}─────────────────────────────────────────────────────────────────${NC}" echo -e " ${GRAY}─────────────────────────────────────────────────────────────────${NC}"
echo "" echo ""
echo -e " ${YELLOW}0.${NC} 🚪 ${WHITE}Выход${NC}" echo -e " ${YELLOW}0.${NC} ${WHITE}Выход${NC}"
echo "" echo ""
echo -e " ${GRAY}─────────────────────────────────────────────────────────────────${NC}" echo -e " ${GRAY}─────────────────────────────────────────────────────────────────${NC}"
echo "" echo ""
+12 -2
View File
@@ -5,7 +5,7 @@
# Author: houseassassin # Author: houseassassin
# GitHub: https://github.com/houseassassin/proxy-core # GitHub: https://github.com/houseassassin/proxy-core
set -e set -euo pipefail
GREEN='\033[0;32m' GREEN='\033[0;32m'
RED='\033[0;31m' RED='\033[0;31m'
@@ -19,6 +19,16 @@ print_error() {
echo -e "${RED}[ERROR]${NC} $1" echo -e "${RED}[ERROR]${NC} $1"
} }
run_remote_script() {
local url=$1
local tmp_script
tmp_script="$(mktemp /tmp/proxy-core-remote.XXXXXX.sh)"
curl -fsSL "$url" -o "$tmp_script"
chmod 700 "$tmp_script"
bash "$tmp_script"
rm -f "$tmp_script"
}
check_root() { check_root() {
if [[ $EUID -ne 0 ]]; then if [[ $EUID -ne 0 ]]; then
print_error "Требуются права root" print_error "Требуются права root"
@@ -28,7 +38,7 @@ check_root() {
update_3xui() { update_3xui() {
print_msg "Обновление 3x-ui..." print_msg "Обновление 3x-ui..."
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) run_remote_script "https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh"
print_msg "3x-ui обновлен" print_msg "3x-ui обновлен"
} }
+57 -11
View File
@@ -5,7 +5,7 @@
# Author: houseassassin # Author: houseassassin
# GitHub: https://github.com/houseassassin/proxy-core # GitHub: https://github.com/houseassassin/proxy-core
set -e set -euo pipefail
RED='\033[0;31m' RED='\033[0;31m'
GREEN='\033[0;32m' GREEN='\033[0;32m'
@@ -30,6 +30,28 @@ check_root() {
fi fi
} }
validate_client_name() {
local client_name=$1
[[ "$client_name" =~ ^[a-zA-Z0-9_-]+$ ]]
}
get_server_ip() {
curl -s -4 ifconfig.me || curl -s -4 api.ipify.org || curl -s -4 ipinfo.io/ip
}
remove_peer_block() {
local client_name=$1
local tmp_conf
tmp_conf="$(mktemp)"
awk -v marker="# ${client_name}" '
BEGIN {skip=0}
$0 == marker {skip=1; next}
skip && /^\[Peer\]/ {skip=0}
!skip {print}
' "$WG_CONF" > "$tmp_conf"
mv "$tmp_conf" "$WG_CONF"
}
get_next_ip() { get_next_ip() {
if [ ! -f "$WG_CONF" ]; then if [ ! -f "$WG_CONF" ]; then
echo "10.0.0.2" echo "10.0.0.2"
@@ -41,8 +63,12 @@ get_next_ip() {
if [ -z "$LAST_IP" ]; then if [ -z "$LAST_IP" ]; then
echo "10.0.0.2" echo "10.0.0.2"
else else
LAST_NUM=$(echo $LAST_IP | cut -d. -f4) LAST_NUM=$(echo "$LAST_IP" | cut -d. -f4)
NEXT_NUM=$((LAST_NUM + 1)) NEXT_NUM=$((LAST_NUM + 1))
if [ "$NEXT_NUM" -gt 254 ]; then
print_error "Пул адресов WireGuard исчерпан (10.0.0.2-10.0.0.254)"
return 1
fi
echo "10.0.0.$NEXT_NUM" echo "10.0.0.$NEXT_NUM"
fi fi
} }
@@ -54,6 +80,10 @@ add_client() {
print_error "Имя клиента не может быть пустым" print_error "Имя клиента не может быть пустым"
exit 1 exit 1
fi fi
if ! validate_client_name "$CLIENT_NAME"; then
print_error "Неверное имя: только буквы, цифры, _ и -"
exit 1
fi
CLIENT_DIR="$WG_DIR/clients/$CLIENT_NAME" CLIENT_DIR="$WG_DIR/clients/$CLIENT_NAME"
@@ -70,12 +100,12 @@ add_client() {
CLIENT_PRIVATE_KEY=$(cat private.key) CLIENT_PRIVATE_KEY=$(cat private.key)
CLIENT_PUBLIC_KEY=$(cat public.key) CLIENT_PUBLIC_KEY=$(cat public.key)
SERVER_PUBLIC_KEY=$(cat $WG_DIR/server_public.key) SERVER_PUBLIC_KEY=$(cat "$WG_DIR/server_public.key")
SERVER_IP=$(curl -s ifconfig.me) SERVER_IP=$(get_server_ip)
SERVER_PORT=$(grep ListenPort $WG_CONF | awk '{print $3}') SERVER_PORT=$(grep ListenPort "$WG_CONF" | awk '{print $3}')
CLIENT_IP=$(get_next_ip) CLIENT_IP=$(get_next_ip)
cat >> $WG_CONF <<EOF cat >> "$WG_CONF" <<EOF
[Peer] [Peer]
# $CLIENT_NAME # $CLIENT_NAME
@@ -104,7 +134,11 @@ EOF
echo "" echo ""
print_msg "QR-код для мобильных устройств:" print_msg "QR-код для мобильных устройств:"
qrencode -t ansiutf8 < client.conf if command -v qrencode >/dev/null 2>&1; then
qrencode -t ansiutf8 < client.conf
else
print_error "qrencode не установлен, пропускаем QR-код"
fi
echo "" echo ""
print_msg "Конфигурация клиента:" print_msg "Конфигурация клиента:"
@@ -120,10 +154,10 @@ list_clients() {
return return
fi fi
for client in $WG_DIR/clients/*; do for client in "$WG_DIR"/clients/*; do
if [ -d "$client" ]; then if [ -d "$client" ]; then
CLIENT_NAME=$(basename "$client") CLIENT_NAME=$(basename "$client")
CLIENT_IP=$(grep -A 2 "# $CLIENT_NAME" $WG_CONF | grep AllowedIPs | awk '{print $3}' | cut -d/ -f1) CLIENT_IP=$(grep -A 2 "# $CLIENT_NAME" "$WG_CONF" | grep AllowedIPs | awk '{print $3}' | cut -d/ -f1)
echo "- $CLIENT_NAME ($CLIENT_IP)" echo "- $CLIENT_NAME ($CLIENT_IP)"
fi fi
done done
@@ -136,6 +170,10 @@ remove_client() {
print_error "Имя клиента не может быть пустым" print_error "Имя клиента не может быть пустым"
exit 1 exit 1
fi fi
if ! validate_client_name "$CLIENT_NAME"; then
print_error "Неверное имя: только буквы, цифры, _ и -"
exit 1
fi
CLIENT_DIR="$WG_DIR/clients/$CLIENT_NAME" CLIENT_DIR="$WG_DIR/clients/$CLIENT_NAME"
@@ -144,7 +182,7 @@ remove_client() {
exit 1 exit 1
fi fi
sed -i "/# $CLIENT_NAME/,+2d" $WG_CONF remove_peer_block "$CLIENT_NAME"
rm -rf "$CLIENT_DIR" rm -rf "$CLIENT_DIR"
systemctl restart wg-quick@wg0 systemctl restart wg-quick@wg0
@@ -159,6 +197,10 @@ show_client() {
print_error "Имя клиента не может быть пустым" print_error "Имя клиента не может быть пустым"
exit 1 exit 1
fi fi
if ! validate_client_name "$CLIENT_NAME"; then
print_error "Неверное имя: только буквы, цифры, _ и -"
exit 1
fi
CLIENT_DIR="$WG_DIR/clients/$CLIENT_NAME" CLIENT_DIR="$WG_DIR/clients/$CLIENT_NAME"
@@ -172,7 +214,11 @@ show_client() {
echo "" echo ""
print_msg "QR-код:" print_msg "QR-код:"
qrencode -t ansiutf8 < "$CLIENT_DIR/client.conf" if command -v qrencode >/dev/null 2>&1; then
qrencode -t ansiutf8 < "$CLIENT_DIR/client.conf"
else
print_error "qrencode не установлен, пропускаем QR-код"
fi
} }
show_menu() { show_menu() {