feat: Реализована веб-панель управления и интеграция Sing-box для настройки VPN.
This commit is contained in:
@@ -15,14 +15,18 @@ services:
|
|||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: docker/Dockerfile.singbox
|
dockerfile: docker/Dockerfile.singbox
|
||||||
args:
|
|
||||||
VLESS_URL: ${VLESS_URL-}
|
|
||||||
|
|
||||||
# HOST MODE — контейнер использует сеть хоста напрямую
|
# HOST MODE — контейнер использует сеть хоста напрямую
|
||||||
# Это решает проблему UDP ASSOCIATE для SOCKS5
|
# Это решает проблему UDP ASSOCIATE для SOCKS5
|
||||||
# ВАЖНО: работает только на Linux, не на Windows/macOS!
|
# ВАЖНО: работает только на Linux, не на Windows/macOS!
|
||||||
network_mode: host
|
network_mode: host
|
||||||
|
|
||||||
|
environment:
|
||||||
|
# Порт веб-интерфейса (по умолчанию 3456)
|
||||||
|
- PORT=${PORT:-3456}
|
||||||
|
# Порт прокси HTTP/SOCKS5 (по умолчанию 8080)
|
||||||
|
- PROXY_PORT=${PROXY_PORT:-8080}
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
- ./data:/app/data
|
- ./data:/app/data
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -33,6 +37,5 @@ services:
|
|||||||
|
|
||||||
# Порты при network_mode: host не нужно пробрасывать,
|
# Порты при network_mode: host не нужно пробрасывать,
|
||||||
# они автоматически доступны на хосте:
|
# они автоматически доступны на хосте:
|
||||||
# - 8082: HTTP/SOCKS прокси (TCP)
|
# - 3456: Веб-интерфейс (PORT)
|
||||||
# - 1080: SOCKS5 прокси (TCP + UDP)
|
# - 8080: SOCKS5/HTTP прокси (PROXY_PORT)
|
||||||
# - 3456: Веб-интерфейс
|
|
||||||
|
|||||||
@@ -5,13 +5,14 @@ services:
|
|||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: docker/Dockerfile.singbox
|
dockerfile: docker/Dockerfile.singbox
|
||||||
args:
|
|
||||||
# Передайте URL через переменную окружения VLESS_URL при сборке:
|
|
||||||
# export VLESS_URL="vless://..."
|
|
||||||
VLESS_URL: ${VLESS_URL-}
|
|
||||||
ports:
|
ports:
|
||||||
- "8082:8082"
|
# Веб-интерфейс (можно переопределить: PORT=9090 docker compose up)
|
||||||
- "3456:3456"
|
- "${PORT:-3456}:${PORT:-3456}"
|
||||||
|
# Прокси HTTP/SOCKS5 (можно переопределить: PROXY_PORT=8082 docker compose up)
|
||||||
|
- "${PROXY_PORT:-8080}:${PROXY_PORT:-8080}"
|
||||||
|
environment:
|
||||||
|
- PORT=${PORT:-3456}
|
||||||
|
- PROXY_PORT=${PROXY_PORT:-8080}
|
||||||
volumes:
|
volumes:
|
||||||
- ./data:/app/data
|
- ./data:/app/data
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -19,5 +20,3 @@ services:
|
|||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
memory: 256m
|
memory: 256m
|
||||||
# Для Docker Desktop лимит также можно задать через mem_limit (устаревшее поле, но работает вне swarm)
|
|
||||||
# mem_limit: 256m
|
|
||||||
|
|||||||
@@ -21,5 +21,8 @@ COPY --chown=suser:suser web/ /app/web/
|
|||||||
# Исправляем окончания строк (важно для Windows пользователей) и даем права на запуск
|
# Исправляем окончания строк (важно для Windows пользователей) и даем права на запуск
|
||||||
RUN dos2unix /app/*.sh && chmod +x /app/entrypoint.sh
|
RUN dos2unix /app/*.sh && chmod +x /app/entrypoint.sh
|
||||||
|
|
||||||
EXPOSE 8082 9090 3456
|
# Порты по умолчанию (можно переопределить через ENV)
|
||||||
|
# PORT - веб-интерфейс, PROXY_PORT - прокси
|
||||||
|
EXPOSE 3456 8080 9090
|
||||||
|
|
||||||
ENTRYPOINT ["/app/entrypoint.sh"]
|
ENTRYPOINT ["/app/entrypoint.sh"]
|
||||||
@@ -4,6 +4,10 @@ set -e
|
|||||||
CONFIG_FILE="/app/data/client.json"
|
CONFIG_FILE="/app/data/client.json"
|
||||||
SINGBOX_PID=""
|
SINGBOX_PID=""
|
||||||
|
|
||||||
|
# Порты из ENV (по умолчанию: 3456 для веба, 8080 для прокси)
|
||||||
|
PORT="${PORT:-3456}"
|
||||||
|
PROXY_PORT="${PROXY_PORT:-8080}"
|
||||||
|
|
||||||
# Ensure data directory exists
|
# Ensure data directory exists
|
||||||
mkdir -p /app/data
|
mkdir -p /app/data
|
||||||
|
|
||||||
@@ -14,7 +18,7 @@ start_singbox() {
|
|||||||
SINGBOX_PID=$!
|
SINGBOX_PID=$!
|
||||||
echo "$(date): sing-box started with PID $SINGBOX_PID"
|
echo "$(date): sing-box started with PID $SINGBOX_PID"
|
||||||
else
|
else
|
||||||
echo "$(date): Config file not found. Use web UI at :3456 to apply config."
|
echo "$(date): Config file not found. Use web UI at :$PORT to apply config."
|
||||||
SINGBOX_PID=""
|
SINGBOX_PID=""
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
@@ -35,9 +39,9 @@ restart_singbox() {
|
|||||||
|
|
||||||
start_singbox
|
start_singbox
|
||||||
|
|
||||||
# Start Web UI Server
|
# Start Web UI Server with configurable port
|
||||||
echo "$(date): Starting Web UI on port 3456..."
|
echo "$(date): Starting Web UI on port $PORT..."
|
||||||
python3 /app/web/server.py &
|
PORT=$PORT PROXY_PORT=$PROXY_PORT python3 /app/web/server.py &
|
||||||
WEBUI_PID=$!
|
WEBUI_PID=$!
|
||||||
|
|
||||||
# HTTP Control Server (Simple Netcat loop)
|
# HTTP Control Server (Simple Netcat loop)
|
||||||
|
|||||||
@@ -270,7 +270,7 @@
|
|||||||
class="max-w-[1400px] mx-auto px-6 flex justify-between items-center text-[9px] uppercase tracking-[0.2em] opacity-40 text-[#00ff41]">
|
class="max-w-[1400px] mx-auto px-6 flex justify-between items-center text-[9px] uppercase tracking-[0.2em] opacity-40 text-[#00ff41]">
|
||||||
<div class="flex gap-6">
|
<div class="flex gap-6">
|
||||||
<span>Core: 4.1.0-Release</span>
|
<span>Core: 4.1.0-Release</span>
|
||||||
<span>Proxy: HTTP/8082</span>
|
<span>Proxy: HTTP/8080</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="hidden md:flex gap-6">
|
<div class="hidden md:flex gap-6">
|
||||||
<span>AES-256-GCM</span>
|
<span>AES-256-GCM</span>
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ import time
|
|||||||
from urllib.parse import parse_qs, unquote
|
from urllib.parse import parse_qs, unquote
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
PORT = 3456
|
PORT = int(os.environ.get("PORT", 3456))
|
||||||
|
PROXY_PORT = int(os.environ.get("PROXY_PORT", 8080))
|
||||||
APP_NAME = "VPN-Proxy-Control by Dokril"
|
APP_NAME = "VPN-Proxy-Control by Dokril"
|
||||||
APP_DIR = Path(__file__).parent
|
APP_DIR = Path(__file__).parent
|
||||||
BASE_DIR = APP_DIR.parent
|
BASE_DIR = APP_DIR.parent
|
||||||
@@ -86,7 +87,7 @@ def measure_tcp_latency(host: str, port: int, timeout: float = 2.0) -> int:
|
|||||||
|
|
||||||
def measure_proxy_performance(enable_speed_test: bool = False) -> dict:
|
def measure_proxy_performance(enable_speed_test: bool = False) -> dict:
|
||||||
"""Measure proxy latency, speed and public IP via local proxy"""
|
"""Measure proxy latency, speed and public IP via local proxy"""
|
||||||
proxy_url = "http://127.0.0.1:8082"
|
proxy_url = f"http://127.0.0.1:{PROXY_PORT}"
|
||||||
proxies = {"http": proxy_url, "https": proxy_url}
|
proxies = {"http": proxy_url, "https": proxy_url}
|
||||||
|
|
||||||
# 1. Measure Latency (Ping)
|
# 1. Measure Latency (Ping)
|
||||||
@@ -264,7 +265,7 @@ def generate_vless_config(vless_params: dict) -> dict:
|
|||||||
"sniff": True,
|
"sniff": True,
|
||||||
"users": [],
|
"users": [],
|
||||||
"listen": "0.0.0.0",
|
"listen": "0.0.0.0",
|
||||||
"listen_port": 8082,
|
"listen_port": PROXY_PORT,
|
||||||
"set_system_proxy": False
|
"set_system_proxy": False
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -633,7 +634,7 @@ class ProxyControlHandler(http.server.BaseHTTPRequestHandler):
|
|||||||
"sniff": True,
|
"sniff": True,
|
||||||
"users": [],
|
"users": [],
|
||||||
"listen": "0.0.0.0",
|
"listen": "0.0.0.0",
|
||||||
"listen_port": 8082,
|
"listen_port": PROXY_PORT,
|
||||||
"set_system_proxy": False
|
"set_system_proxy": False
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user