25
changelog
25
changelog
@ -1,19 +1,18 @@
|
|||||||
# [1.16.0] - 2025-08-19
|
# [1.17.0] - 2025-08-24
|
||||||
|
|
||||||
#### ✨ New Features
|
|
||||||
|
|
||||||
* 📊 **Dashboard Redesign**
|
#### ⚡ Authentication
|
||||||
|
|
||||||
* Modernized UI with detailed server stats
|
* 🚀 **Implemented Go HTTP Auth Server** for **maximum performance**
|
||||||
* 🖥️ **Server API Enhancements**
|
* ⚡ Removed old command-based auth system
|
||||||
|
|
||||||
* Added uptime and traffic-since-reboot metrics
|
#### 👥 User Management
|
||||||
* ⚡ **System Monitor Optimization**
|
|
||||||
|
|
||||||
* Improved performance with async I/O
|
* ✨ **Bulk User Creation** added across:
|
||||||
* Accurate traffic tracking since reboot
|
|
||||||
|
|
||||||
#### 🐛 Fixes
|
* 🖥️ **Frontend UI**
|
||||||
|
* 📡 **API Endpoint**
|
||||||
* 🔧 Correctly count **actual device connections** instead of unique users
|
* 💻 **CLI Command**
|
||||||
* 🔥 Fixed subscription blocked page to display the right user data
|
* 📜 **Automation Script**
|
||||||
|
* 🔍 New **Online User Filter & Sort** on the Users page
|
||||||
|
* 🐛 Fixed: underscores now supported in usernames
|
||||||
@ -13,8 +13,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"auth": {
|
"auth": {
|
||||||
"type": "command",
|
"type": "http",
|
||||||
"command": "/etc/hysteria/core/scripts/hysteria2/user.sh"
|
"http": {
|
||||||
|
"url": "http://127.0.0.1:28262/auth"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"quic": {
|
"quic": {
|
||||||
"initStreamReceiveWindow": 8388608,
|
"initStreamReceiveWindow": 8388608,
|
||||||
|
|||||||
139
core/scripts/auth/user_auth.go
Normal file
139
core/scripts/auth/user_auth.go
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/subtle"
|
||||||
|
"encoding/json"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
listenAddr = "127.0.0.1:28262"
|
||||||
|
usersFile = "/etc/hysteria/users.json"
|
||||||
|
cacheTTL = 5 * time.Second
|
||||||
|
)
|
||||||
|
|
||||||
|
type User struct {
|
||||||
|
Password string `json:"password"`
|
||||||
|
MaxDownloadBytes int64 `json:"max_download_bytes"`
|
||||||
|
ExpirationDays int `json:"expiration_days"`
|
||||||
|
AccountCreationDate string `json:"account_creation_date"`
|
||||||
|
Blocked bool `json:"blocked"`
|
||||||
|
UploadBytes int64 `json:"upload_bytes"`
|
||||||
|
DownloadBytes int64 `json:"download_bytes"`
|
||||||
|
UnlimitedUser bool `json:"unlimited_user"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type httpAuthRequest struct {
|
||||||
|
Addr string `json:"addr"`
|
||||||
|
Auth string `json:"auth"`
|
||||||
|
Tx uint64 `json:"tx"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type httpAuthResponse struct {
|
||||||
|
OK bool `json:"ok"`
|
||||||
|
ID string `json:"id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
userCache map[string]User
|
||||||
|
cacheMutex = &sync.RWMutex{}
|
||||||
|
)
|
||||||
|
|
||||||
|
func loadUsersToCache() {
|
||||||
|
data, err := os.ReadFile(usersFile)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var users map[string]User
|
||||||
|
if err := json.Unmarshal(data, &users); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cacheMutex.Lock()
|
||||||
|
userCache = users
|
||||||
|
cacheMutex.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func authHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Method != http.MethodPost {
|
||||||
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var req httpAuthRequest
|
||||||
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||||
|
http.Error(w, "Invalid request", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
username, password, ok := strings.Cut(req.Auth, ":")
|
||||||
|
if !ok {
|
||||||
|
json.NewEncoder(w).Encode(httpAuthResponse{OK: false})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cacheMutex.RLock()
|
||||||
|
user, ok := userCache[username]
|
||||||
|
cacheMutex.RUnlock()
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
json.NewEncoder(w).Encode(httpAuthResponse{OK: false})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if user.Blocked {
|
||||||
|
json.NewEncoder(w).Encode(httpAuthResponse{OK: false})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if subtle.ConstantTimeCompare([]byte(user.Password), []byte(password)) != 1 {
|
||||||
|
time.Sleep(5 * time.Second) // Slow down brute-force attacks
|
||||||
|
json.NewEncoder(w).Encode(httpAuthResponse{OK: false})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if user.UnlimitedUser {
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
json.NewEncoder(w).Encode(httpAuthResponse{OK: true, ID: username})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if user.ExpirationDays > 0 {
|
||||||
|
creationDate, err := time.Parse("2006-01-02", user.AccountCreationDate)
|
||||||
|
if err == nil && time.Now().After(creationDate.AddDate(0, 0, user.ExpirationDays)) {
|
||||||
|
json.NewEncoder(w).Encode(httpAuthResponse{OK: false})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if user.MaxDownloadBytes > 0 && (user.DownloadBytes+user.UploadBytes) >= user.MaxDownloadBytes {
|
||||||
|
json.NewEncoder(w).Encode(httpAuthResponse{OK: false})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
json.NewEncoder(w).Encode(httpAuthResponse{OK: true, ID: username})
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
log.SetOutput(io.Discard)
|
||||||
|
loadUsersToCache()
|
||||||
|
|
||||||
|
ticker := time.NewTicker(cacheTTL)
|
||||||
|
go func() {
|
||||||
|
for range ticker.C {
|
||||||
|
loadUsersToCache()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
http.HandleFunc("/auth", authHandler)
|
||||||
|
if err := http.ListenAndServe(listenAddr, nil); err != nil {
|
||||||
|
log.SetOutput(os.Stderr)
|
||||||
|
log.Fatalf("Failed to start server: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
74
core/scripts/hysteria2/auth_server.py
Normal file
74
core/scripts/hysteria2/auth_server.py
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
import json
|
||||||
|
import os
|
||||||
|
import asyncio
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
from aiohttp import web
|
||||||
|
import aiofiles
|
||||||
|
from init_paths import *
|
||||||
|
from paths import *
|
||||||
|
|
||||||
|
users_data = {}
|
||||||
|
users_lock = asyncio.Lock()
|
||||||
|
|
||||||
|
async def load_users(app):
|
||||||
|
global users_data
|
||||||
|
async with users_lock:
|
||||||
|
if os.path.exists(USERS_FILE):
|
||||||
|
try:
|
||||||
|
async with aiofiles.open(USERS_FILE, 'r') as f:
|
||||||
|
content = await f.read()
|
||||||
|
users_data = json.loads(content)
|
||||||
|
except (IOError, json.JSONDecodeError):
|
||||||
|
users_data = {}
|
||||||
|
else:
|
||||||
|
users_data = {}
|
||||||
|
app['users_data'] = users_data
|
||||||
|
|
||||||
|
async def authenticate(request):
|
||||||
|
global users_data
|
||||||
|
try:
|
||||||
|
data = await request.json()
|
||||||
|
auth_str = data.get("auth")
|
||||||
|
if not auth_str:
|
||||||
|
return web.json_response({"ok": False, "msg": "Auth field missing"}, status=400)
|
||||||
|
|
||||||
|
username, password = auth_str.split(":", 1)
|
||||||
|
except (json.JSONDecodeError, ValueError, TypeError):
|
||||||
|
return web.json_response({"ok": False, "msg": "Invalid request format"}, status=400)
|
||||||
|
|
||||||
|
async with users_lock:
|
||||||
|
user = users_data.get(username)
|
||||||
|
|
||||||
|
if not user:
|
||||||
|
return web.json_response({"ok": False, "msg": "User not found"}, status=401)
|
||||||
|
|
||||||
|
if user.get("blocked", False):
|
||||||
|
return web.json_response({"ok": False, "msg": "User is blocked"}, status=401)
|
||||||
|
|
||||||
|
if user.get("password") != password:
|
||||||
|
return web.json_response({"ok": False, "msg": "Invalid password"}, status=401)
|
||||||
|
|
||||||
|
expiration_days = user.get("expiration_days", 0)
|
||||||
|
if expiration_days > 0:
|
||||||
|
creation_date_str = user.get("account_creation_date")
|
||||||
|
if creation_date_str:
|
||||||
|
creation_date = datetime.strptime(creation_date_str, "%Y-%m-%d")
|
||||||
|
expiration_date = creation_date + timedelta(days=expiration_days)
|
||||||
|
if datetime.now() >= expiration_date:
|
||||||
|
return web.json_response({"ok": False, "msg": "Account expired"}, status=401)
|
||||||
|
|
||||||
|
max_bytes = user.get("max_download_bytes", 0)
|
||||||
|
if max_bytes > 0:
|
||||||
|
current_up = user.get("upload_bytes", 0)
|
||||||
|
current_down = user.get("download_bytes", 0)
|
||||||
|
if (current_up + current_down) >= max_bytes:
|
||||||
|
return web.json_response({"ok": False, "msg": "Data limit exceeded"}, status=401)
|
||||||
|
|
||||||
|
return web.json_response({"ok": True, "id": username})
|
||||||
|
|
||||||
|
app = web.Application()
|
||||||
|
app.router.add_post("/auth", authenticate)
|
||||||
|
app.on_startup.append(load_users)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
web.run_app(app, host="127.0.0.1", port=28262)
|
||||||
@ -5,6 +5,29 @@ source /etc/hysteria/core/scripts/utils.sh
|
|||||||
source /etc/hysteria/core/scripts/scheduler.sh
|
source /etc/hysteria/core/scripts/scheduler.sh
|
||||||
define_colors
|
define_colors
|
||||||
|
|
||||||
|
compile_auth_binary() {
|
||||||
|
echo "Compiling authentication binary..."
|
||||||
|
local auth_dir="/etc/hysteria/core/scripts/auth"
|
||||||
|
|
||||||
|
if [ -f "$auth_dir/user_auth.go" ]; then
|
||||||
|
(
|
||||||
|
cd "$auth_dir" || exit 1
|
||||||
|
go mod init hysteria-auth >/dev/null 2>&1
|
||||||
|
go mod tidy >/dev/null 2>&1
|
||||||
|
if go build -o user_auth .; then
|
||||||
|
chmod +x user_auth
|
||||||
|
echo "Authentication binary compiled successfully."
|
||||||
|
else
|
||||||
|
echo -e "${red}Error:${NC} Failed to compile the authentication binary."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
)
|
||||||
|
else
|
||||||
|
echo -e "${red}Error:${NC} Go source file not found at $auth_dir/user_auth.go"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
install_hysteria() {
|
install_hysteria() {
|
||||||
local port=$1
|
local port=$1
|
||||||
|
|
||||||
@ -13,6 +36,8 @@ install_hysteria() {
|
|||||||
|
|
||||||
mkdir -p /etc/hysteria && cd /etc/hysteria/
|
mkdir -p /etc/hysteria && cd /etc/hysteria/
|
||||||
|
|
||||||
|
compile_auth_binary
|
||||||
|
|
||||||
echo "Generating CA key and certificate..."
|
echo "Generating CA key and certificate..."
|
||||||
openssl ecparam -genkey -name prime256v1 -out ca.key >/dev/null 2>&1
|
openssl ecparam -genkey -name prime256v1 -out ca.key >/dev/null 2>&1
|
||||||
openssl req -new -x509 -days 36500 -key ca.key -out ca.crt -subj "/CN=$sni" >/dev/null 2>&1
|
openssl req -new -x509 -days 36500 -key ca.key -out ca.crt -subj "/CN=$sni" >/dev/null 2>&1
|
||||||
@ -80,9 +105,20 @@ install_hysteria() {
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
chmod +x /etc/hysteria/core/scripts/hysteria2/user.sh
|
|
||||||
chmod +x /etc/hysteria/core/scripts/hysteria2/kick.py
|
chmod +x /etc/hysteria/core/scripts/hysteria2/kick.py
|
||||||
|
|
||||||
|
if ! check_auth_server_service; then
|
||||||
|
echo "Setting up Hysteria auth server..."
|
||||||
|
setup_hysteria_auth_server
|
||||||
|
fi
|
||||||
|
|
||||||
|
if systemctl is-active --quiet hysteria-auth.service; then
|
||||||
|
echo -e "${cyan}Hysteria auth server${NC} has been successfully started."
|
||||||
|
else
|
||||||
|
echo -e "${red}Error:${NC} hysteria-auth.service is not active."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
if ! check_scheduler_service; then
|
if ! check_scheduler_service; then
|
||||||
setup_hysteria_scheduler
|
setup_hysteria_scheduler
|
||||||
fi
|
fi
|
||||||
|
|||||||
@ -27,10 +27,7 @@ EOF
|
|||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
systemctl enable hysteria-scheduler.service
|
systemctl enable hysteria-scheduler.service
|
||||||
systemctl start hysteria-scheduler.service
|
systemctl start hysteria-scheduler.service
|
||||||
# wait 2
|
|
||||||
(crontab -l | grep -v "hysteria2_venv.*traffic-status" | grep -v "hysteria2_venv.*backup-hysteria") | crontab -
|
(crontab -l | grep -v "hysteria2_venv.*traffic-status" | grep -v "hysteria2_venv.*backup-hysteria") | crontab -
|
||||||
|
|
||||||
# return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
check_scheduler_service() {
|
check_scheduler_service() {
|
||||||
@ -40,3 +37,38 @@ check_scheduler_service() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setup_hysteria_auth_server() {
|
||||||
|
# chmod +x /etc/hysteria/core/scripts/auth/user_auth
|
||||||
|
|
||||||
|
cat > /etc/systemd/system/hysteria-auth.service << 'EOF'
|
||||||
|
[Unit]
|
||||||
|
Description=Hysteria Auth Server
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=root
|
||||||
|
ExecStart=/etc/hysteria/core/scripts/auth/user_auth
|
||||||
|
Restart=always
|
||||||
|
RestartSec=5
|
||||||
|
StandardOutput=journal
|
||||||
|
StandardError=journal
|
||||||
|
SyslogIdentifier=hysteria-Auth
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable hysteria-auth.service
|
||||||
|
systemctl start hysteria-auth.service
|
||||||
|
}
|
||||||
|
|
||||||
|
check_auth_server_service() {
|
||||||
|
if systemctl is-active --quiet hysteria-auth.service; then
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
@ -3,6 +3,7 @@
|
|||||||
declare -a services=(
|
declare -a services=(
|
||||||
"hysteria-server.service"
|
"hysteria-server.service"
|
||||||
"hysteria-scheduler.service"
|
"hysteria-scheduler.service"
|
||||||
|
"hysteria-auth.service"
|
||||||
"hysteria-webpanel.service"
|
"hysteria-webpanel.service"
|
||||||
"hysteria-caddy.service"
|
"hysteria-caddy.service"
|
||||||
"hysteria-telegram-bot.service"
|
"hysteria-telegram-bot.service"
|
||||||
@ -22,8 +23,6 @@ for service in "${services[@]}"; do
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
# Remove trailing comma and close JSON properly
|
|
||||||
status_json="${status_json%,}}"
|
status_json="${status_json%,}}"
|
||||||
|
|
||||||
# Format output as valid JSON
|
|
||||||
echo "$status_json" | jq -M .
|
echo "$status_json" | jq -M .
|
||||||
|
|||||||
@ -76,7 +76,7 @@ check_os_version() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
install_packages() {
|
install_packages() {
|
||||||
local REQUIRED_PACKAGES=("jq" "curl" "pwgen" "python3" "python3-pip" "python3-venv" "git" "bc" "zip" "cron" "lsof")
|
local REQUIRED_PACKAGES=("jq" "curl" "pwgen" "python3" "python3-pip" "python3-venv" "git" "bc" "zip" "cron" "lsof" "golang-go")
|
||||||
local MISSING_PACKAGES=()
|
local MISSING_PACKAGES=()
|
||||||
|
|
||||||
log_info "Checking required packages..."
|
log_info "Checking required packages..."
|
||||||
|
|||||||
73
upgrade.sh
73
upgrade.sh
@ -6,6 +6,7 @@ trap 'echo -e "\n❌ An error occurred. Aborting."; exit 1' ERR
|
|||||||
# ========== Variables ==========
|
# ========== Variables ==========
|
||||||
HYSTERIA_INSTALL_DIR="/etc/hysteria"
|
HYSTERIA_INSTALL_DIR="/etc/hysteria"
|
||||||
HYSTERIA_VENV_DIR="$HYSTERIA_INSTALL_DIR/hysteria2_venv"
|
HYSTERIA_VENV_DIR="$HYSTERIA_INSTALL_DIR/hysteria2_venv"
|
||||||
|
AUTH_BINARY_DIR="$HYSTERIA_INSTALL_DIR/core/scripts/auth"
|
||||||
REPO_URL="https://github.com/ReturnFI/Blitz"
|
REPO_URL="https://github.com/ReturnFI/Blitz"
|
||||||
REPO_BRANCH="main"
|
REPO_BRANCH="main"
|
||||||
GEOSITE_URL="https://raw.githubusercontent.com/Chocolate4U/Iran-v2ray-rules/release/geosite.dat"
|
GEOSITE_URL="https://raw.githubusercontent.com/Chocolate4U/Iran-v2ray-rules/release/geosite.dat"
|
||||||
@ -23,6 +24,37 @@ success() { echo -e "${GREEN}[$(date '+%Y-%m-%d %H:%M:%S')] [OK] - ${RESET} $1";
|
|||||||
warn() { echo -e "${YELLOW}[$(date '+%Y-%m-%d %H:%M:%S')] [WARN] - ${RESET} $1"; }
|
warn() { echo -e "${YELLOW}[$(date '+%Y-%m-%d %H:%M:%S')] [WARN] - ${RESET} $1"; }
|
||||||
error() { echo -e "${RED}[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] - ${RESET} $1"; }
|
error() { echo -e "${RED}[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] - ${RESET} $1"; }
|
||||||
|
|
||||||
|
# ========== New Function to Install Go and Compile Auth Binary ==========
|
||||||
|
install_go_and_compile_auth() {
|
||||||
|
info "Checking for Go and compiling authentication binary..."
|
||||||
|
if ! command -v go &>/dev/null; then
|
||||||
|
warn "Go is not installed. Attempting to install..."
|
||||||
|
apt-get update -y >/dev/null
|
||||||
|
apt-get install -y golang-go >/dev/null
|
||||||
|
success "Go installed successfully."
|
||||||
|
else
|
||||||
|
success "Go is already installed."
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -f "$AUTH_BINARY_DIR/user_auth.go" ]]; then
|
||||||
|
info "Found auth binary source. Compiling..."
|
||||||
|
(
|
||||||
|
cd "$AUTH_BINARY_DIR"
|
||||||
|
go mod init hysteria_auth >/dev/null 2>&1
|
||||||
|
go mod tidy >/dev/null 2>&1
|
||||||
|
if go build -o user_auth .; then
|
||||||
|
chmod +x user_auth
|
||||||
|
success "Authentication binary compiled successfully."
|
||||||
|
else
|
||||||
|
error "Failed to compile the authentication binary."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
)
|
||||||
|
else
|
||||||
|
warn "Authentication binary source not found. Skipping compilation."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# ========== Backup Files ==========
|
# ========== Backup Files ==========
|
||||||
cd /root
|
cd /root
|
||||||
TEMP_DIR=$(mktemp -d)
|
TEMP_DIR=$(mktemp -d)
|
||||||
@ -34,7 +66,6 @@ FILES=(
|
|||||||
"$HYSTERIA_INSTALL_DIR/.configs.env"
|
"$HYSTERIA_INSTALL_DIR/.configs.env"
|
||||||
"$HYSTERIA_INSTALL_DIR/nodes.json"
|
"$HYSTERIA_INSTALL_DIR/nodes.json"
|
||||||
"$HYSTERIA_INSTALL_DIR/core/scripts/telegrambot/.env"
|
"$HYSTERIA_INSTALL_DIR/core/scripts/telegrambot/.env"
|
||||||
# "$HYSTERIA_INSTALL_DIR/core/scripts/singbox/.env"
|
|
||||||
"$HYSTERIA_INSTALL_DIR/core/scripts/normalsub/.env"
|
"$HYSTERIA_INSTALL_DIR/core/scripts/normalsub/.env"
|
||||||
"$HYSTERIA_INSTALL_DIR/core/scripts/normalsub/Caddyfile.normalsub"
|
"$HYSTERIA_INSTALL_DIR/core/scripts/normalsub/Caddyfile.normalsub"
|
||||||
"$HYSTERIA_INSTALL_DIR/core/scripts/webpanel/.env"
|
"$HYSTERIA_INSTALL_DIR/core/scripts/webpanel/.env"
|
||||||
@ -77,15 +108,21 @@ for FILE in "${FILES[@]}"; do
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# ========== Update Configuration ==========
|
||||||
|
info "Updating Hysteria configuration for HTTP authentication..."
|
||||||
|
auth_block='{"type": "http", "http": {"url": "http://127.0.0.1:28262/auth"}}'
|
||||||
|
if [[ -f "$HYSTERIA_INSTALL_DIR/config.json" ]]; then
|
||||||
|
jq --argjson auth_block "$auth_block" '.auth = $auth_block' "$HYSTERIA_INSTALL_DIR/config.json" > "$HYSTERIA_INSTALL_DIR/config.json.tmp" && mv "$HYSTERIA_INSTALL_DIR/config.json.tmp" "$HYSTERIA_INSTALL_DIR/config.json"
|
||||||
|
success "config.json updated to use auth server."
|
||||||
|
else
|
||||||
|
warn "config.json not found after restore. Skipping auth update."
|
||||||
|
fi
|
||||||
|
|
||||||
# ========== Permissions ==========
|
# ========== Permissions ==========
|
||||||
info "Setting ownership and permissions..."
|
info "Setting ownership and permissions..."
|
||||||
chown hysteria:hysteria "$HYSTERIA_INSTALL_DIR/ca.key" "$HYSTERIA_INSTALL_DIR/ca.crt"
|
chown hysteria:hysteria "$HYSTERIA_INSTALL_DIR/ca.key" "$HYSTERIA_INSTALL_DIR/ca.crt"
|
||||||
chmod 640 "$HYSTERIA_INSTALL_DIR/ca.key" "$HYSTERIA_INSTALL_DIR/ca.crt"
|
chmod 640 "$HYSTERIA_INSTALL_DIR/ca.key" "$HYSTERIA_INSTALL_DIR/ca.crt"
|
||||||
|
|
||||||
# chown -R hysteria:hysteria "$HYSTERIA_INSTALL_DIR/core/scripts/singbox"
|
|
||||||
chown -R hysteria:hysteria "$HYSTERIA_INSTALL_DIR/core/scripts/telegrambot"
|
chown -R hysteria:hysteria "$HYSTERIA_INSTALL_DIR/core/scripts/telegrambot"
|
||||||
|
|
||||||
chmod +x "$HYSTERIA_INSTALL_DIR/core/scripts/hysteria2/user.sh"
|
|
||||||
chmod +x "$HYSTERIA_INSTALL_DIR/core/scripts/hysteria2/kick.py"
|
chmod +x "$HYSTERIA_INSTALL_DIR/core/scripts/hysteria2/kick.py"
|
||||||
|
|
||||||
# ========== Virtual Environment ==========
|
# ========== Virtual Environment ==========
|
||||||
@ -97,26 +134,32 @@ pip install --upgrade pip >/dev/null
|
|||||||
pip install -r requirements.txt >/dev/null
|
pip install -r requirements.txt >/dev/null
|
||||||
success "Python environment ready."
|
success "Python environment ready."
|
||||||
|
|
||||||
# ========== Scheduler ==========
|
# ========== Compile Go Binary ==========
|
||||||
info "Ensuring scheduler is set..."
|
install_go_and_compile_auth
|
||||||
|
|
||||||
|
# ========== Systemd Services ==========
|
||||||
|
info "Ensuring systemd services are configured..."
|
||||||
if source "$HYSTERIA_INSTALL_DIR/core/scripts/scheduler.sh"; then
|
if source "$HYSTERIA_INSTALL_DIR/core/scripts/scheduler.sh"; then
|
||||||
|
if ! check_auth_server_service; then
|
||||||
|
setup_hysteria_auth_server && success "Auth server service configured." || warn "Auth server setup failed."
|
||||||
|
else
|
||||||
|
success "Auth server service already configured."
|
||||||
|
fi
|
||||||
|
|
||||||
if ! check_scheduler_service; then
|
if ! check_scheduler_service; then
|
||||||
if setup_hysteria_scheduler; then
|
setup_hysteria_scheduler && success "Scheduler service configured." || warn "Scheduler setup failed."
|
||||||
success "Scheduler service configured."
|
|
||||||
else
|
else
|
||||||
warn "Scheduler setup failed, but continuing upgrade..."
|
success "Scheduler service already set."
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
success "Scheduler already set."
|
warn "Failed to source scheduler.sh, continuing without service setup..."
|
||||||
fi
|
|
||||||
else
|
|
||||||
warn "Failed to source scheduler.sh, continuing without scheduler setup..."
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ========== Restart Services ==========
|
# ========== Restart Services ==========
|
||||||
SERVICES=(
|
SERVICES=(
|
||||||
hysteria-caddy.service
|
hysteria-caddy.service
|
||||||
hysteria-server.service
|
hysteria-server.service
|
||||||
|
hysteria-auth.service
|
||||||
hysteria-scheduler.service
|
hysteria-scheduler.service
|
||||||
hysteria-telegram-bot.service
|
hysteria-telegram-bot.service
|
||||||
hysteria-normal-sub.service
|
hysteria-normal-sub.service
|
||||||
@ -130,7 +173,7 @@ for SERVICE in "${SERVICES[@]}"; do
|
|||||||
if systemctl status "$SERVICE" &>/dev/null; then
|
if systemctl status "$SERVICE" &>/dev/null; then
|
||||||
systemctl restart "$SERVICE" && success "$SERVICE restarted." || warn "$SERVICE failed to restart."
|
systemctl restart "$SERVICE" && success "$SERVICE restarted." || warn "$SERVICE failed to restart."
|
||||||
else
|
else
|
||||||
warn "$SERVICE not found or not installed. Skipping..."
|
warn "$SERVICE not found. Skipping..."
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user