feat: add support for awg2, mtproxy, and aivpn protocols, and implement user role-based access control.

This commit is contained in:
infosave2007
2026-04-04 09:56:49 +03:00
parent 19078b03dd
commit 26a6ca526d
9 changed files with 726 additions and 9 deletions
+1
View File
@@ -68,3 +68,4 @@ scripts/regen_qr.php
scripts/test_xray_install.sh
scripts/test_online.php
API_AWG_DOCS.md
log.txt
+30 -1
View File
@@ -800,8 +800,18 @@ SH;
$res['client_id'] = $m[1];
}
// Extract secret (for MTProxy and similar protocols)
if (preg_match('/Secret:\s*([a-fA-F0-9]+)/i', $output, $m)) {
$res['secret'] = $m[1];
}
// Extract server host/IP
if (preg_match('/Server\s*Host:\s*(\S+)/i', $output, $m)) {
$res['server_host'] = trim($m[1], "'\"");
}
// Generic variable extraction (Variable: KEY=VALUE)
if (preg_match_all('/Variable:\\s*([a-zA-Z0-9_]+)=(.*)/', $output, $matches, PREG_SET_ORDER)) {
if (preg_match_all('/Variable:\s*([a-zA-Z0-9_]+)=(.*)/', $output, $matches, PREG_SET_ORDER)) {
foreach ($matches as $m) {
$key = trim($m[1]);
$val = trim($m[2]);
@@ -811,6 +821,25 @@ SH;
}
}
// Fallback: parse any remaining "Key: Value" lines not yet captured
// This catches protocol-specific variables like custom fields
$lines = preg_split('/\r?\n/', $output);
foreach ($lines as $line) {
$line = trim($line);
if ($line === '') continue;
// Skip set -x trace lines (start with +)
if (preg_match('/^\+/', $line)) continue;
if (preg_match('/^([A-Za-z][A-Za-z0-9 _-]*?)\s*:\s*(.+)$/', $line, $m)) {
$rawKey = trim($m[1]);
$rawVal = trim($m[2], " \t'\"");
$normalized = strtolower(preg_replace('/\s+/', '_', $rawKey));
// Don't overwrite already extracted keys
if (!array_key_exists($normalized, $res)) {
$res[$normalized] = $rawVal;
}
}
}
return $res;
}
+6 -1
View File
@@ -295,6 +295,8 @@ class InstallProtocolManager
'server_public_key' => $result['server_public_key'] ?? null,
'preshared_key' => $result['preshared_key'] ?? null,
'awg_params' => $result['awg_params'] ?? null,
'secret' => $result['secret'] ?? null,
'server_host' => $result['server_host'] ?? null,
];
if (($protocol['slug'] ?? '') === 'xray-vless') {
foreach (['client_id', 'container_name', 'server_port', 'xray_port', 'reality_public_key', 'reality_private_key', 'reality_short_id', 'reality_server_name'] as $k) {
@@ -653,6 +655,9 @@ class InstallProtocolManager
'privatekey' => 'reality_private_key',
'shortid' => 'reality_short_id',
'servername' => 'reality_server_name',
'secret' => 'secret',
'serverhost' => 'server_host',
'server_host' => 'server_host',
];
$finalKey = $keyMap[$normalizedKey] ?? $normalizedKey;
@@ -899,7 +904,7 @@ class InstallProtocolManager
*/
private static function isAwgProtocol(string $slug, array $protocol): bool
{
if (in_array($slug, ['amnezia-wg', 'amnezia-wg-advanced'], true)) {
if (in_array($slug, ['amnezia-wg', 'amnezia-wg-advanced', 'awg2'], true)) {
return true;
}
$installScript = (string) ($protocol['install_script'] ?? '');
+7 -6
View File
@@ -67,7 +67,7 @@ class VpnClient
$protoRow = $stmtProto2->fetch();
}
$slug = $protoRow['slug'] ?? ($serverData['install_protocol'] ?? 'amnezia-wg');
$isWireguard = in_array($slug, ['amnezia-wg-advanced', 'wireguard-standard', 'amnezia-wg'], true);
$isWireguard = in_array($slug, ['amnezia-wg-advanced', 'wireguard-standard', 'amnezia-wg', 'awg2'], true);
// Auto-sync server keys from container EVERY TIME for WireGuard protocols
// This ensures we always use current container configuration even if it was recreated
@@ -1121,7 +1121,7 @@ class VpnClient
$stmt = $pdo->prepare('SELECT slug FROM protocols WHERE id = ?');
$stmt->execute([$protocolId]);
$slug = (string) $stmt->fetchColumn();
return in_array($slug, ['amnezia-wg-advanced', 'wireguard-standard', 'amnezia-wg'], true);
return in_array($slug, ['amnezia-wg-advanced', 'wireguard-standard', 'amnezia-wg', 'awg2'], true);
} catch (Exception $e) {
return true;
}
@@ -1309,7 +1309,7 @@ class VpnClient
$protoRow = $stmt->fetch();
}
$slug = $protoRow['slug'] ?? '';
$isWireguard = in_array($slug, ['amnezia-wg-advanced', 'wireguard-standard', 'amnezia-wg'], true);
$isWireguard = in_array($slug, ['amnezia-wg-advanced', 'wireguard-standard', 'amnezia-wg', 'awg2'], true);
if (!$isWireguard) {
return ['success' => false, 'error' => 'not_wireguard_protocol', 'protocol_slug' => $slug];
@@ -1335,7 +1335,7 @@ class VpnClient
// If AWG params are missing (common after reinstall), fetch them directly from wg0.conf
// to avoid falling back to template defaults that will not match the server.
if ($slug === 'amnezia-wg-advanced') {
if (in_array($slug, ['amnezia-wg-advanced', 'awg2'], true)) {
$needKeys = ['JC', 'JMIN', 'JMAX', 'S1', 'S2', 'H1', 'H2', 'H3', 'H4'];
$missing = false;
foreach ($needKeys as $k) {
@@ -1346,8 +1346,9 @@ class VpnClient
}
if ($missing) {
$containerName = $serverData['container_name'] ?? 'amnezia-awg';
$direct = self::extractAwgParamsFromWg0Conf($server, $containerName, '/opt/amnezia/awg/wg0.conf');
$containerName = $serverData['container_name'] ?? ($slug === 'awg2' ? 'amnezia-awg2' : 'amnezia-awg');
$configDir = $slug === 'awg2' ? '/opt/amnezia/awg2' : '/opt/amnezia/awg';
$direct = self::extractAwgParamsFromWg0Conf($server, $containerName, $configDir . '/wg0.conf');
if (empty($direct)) {
$direct = self::extractAwgParamsFromWg0Conf($server, $containerName, '/etc/wireguard/wg0.conf');
}
+32
View File
@@ -0,0 +1,32 @@
-- Migration: Add user roles and permissions
-- Date: 2025-11-10
-- User roles table
CREATE TABLE IF NOT EXISTS user_roles (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL UNIQUE,
display_name VARCHAR(100) NOT NULL,
description TEXT,
permissions JSON NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Add role to users table
ALTER TABLE users
ADD COLUMN role VARCHAR(50) DEFAULT 'viewer' AFTER ldap_dn,
ADD INDEX idx_role (role);
-- Insert default roles
INSERT IGNORE INTO user_roles (name, display_name, description, permissions) VALUES
('admin', 'Administrator', 'Full access to all features', JSON_ARRAY('*')),
('manager', 'Manager', 'Can manage servers and clients', JSON_ARRAY('servers.view', 'servers.create', 'servers.edit', 'clients.view', 'clients.create', 'clients.edit', 'clients.delete')),
('viewer', 'Viewer', 'Can only view own clients', JSON_ARRAY('clients.view_own', 'clients.download_own'));
-- Insert default LDAP group mappings (examples)
INSERT IGNORE INTO ldap_group_mappings (ldap_group, role_name, description) VALUES
('vpn-admins', 'admin', 'VPN administrators with full access'),
('vpn-managers', 'manager', 'VPN managers who can create and manage clients'),
('vpn-users', 'viewer', 'Regular VPN users with view-only access');
-- Update existing users to admin role (backward compatibility)
UPDATE users SET role = 'admin' WHERE role IS NULL OR role = '';
+381
View File
@@ -0,0 +1,381 @@
-- =====================================================================
-- Migration 058: Add AmneziaWG 2.0 protocol (amneziawg-go userspace)
-- Uses amneziawg-go (Go userspace) instead of kernel module
-- https://github.com/amnezia-vpn/amneziawg-go
-- =====================================================================
-- 1. Insert the protocol entry (clone output_template from amnezia-wg-advanced)
INSERT INTO protocols (name, slug, description, install_script, uninstall_script, output_template, ubuntu_compatible, is_active, definition, created_at, updated_at)
SELECT
'AmneziaWG 2.0',
'awg2',
'AmneziaWG 2.0 — userspace Go implementation (amneziawg-go). No kernel module required.',
'#!/bin/bash
set -euo pipefail
# Use exported variables from panel (SERVER_PORT, SERVER_CONTAINER) or defaults
CONTAINER_NAME="${SERVER_CONTAINER:-amnezia-awg2}"
PORT_RANGE_START=${PORT_RANGE_START:-30000}
PORT_RANGE_END=${PORT_RANGE_END:-65000}
VPN_PORT="${SERVER_PORT:-$((RANDOM % (PORT_RANGE_END - PORT_RANGE_START + 1) + PORT_RANGE_START))}"
MTU=${MTU:-1420}
# Install git if not available
if ! command -v git &> /dev/null; then
apt-get update -qq && apt-get install -y -qq git >/dev/null 2>&1
fi
mkdir -p /opt/amnezia/awg2
# Clone amneziawg-go source for Docker build
if [ ! -d /opt/amnezia/awg2/src ]; then
git clone --depth=1 https://github.com/amnezia-vpn/amneziawg-go.git /opt/amnezia/awg2/src
fi
# Build Docker image using the repo Dockerfile (multi-stage: Go compile + tools)
docker build --no-cache -t amnezia-awg2 /opt/amnezia/awg2/src
# Run container (userspace: no SYS_MODULE, no /lib/modules)
EXISTING=$(docker ps -aq -f "name=$CONTAINER_NAME" 2>/dev/null | head -1)
if [ -z "$EXISTING" ]; then
docker run -d --name "$CONTAINER_NAME" --restart always --cap-add=NET_ADMIN --device /dev/net/tun -p "${VPN_PORT}:${VPN_PORT}/udp" -v /opt/amnezia/awg2:/opt/amnezia/awg amnezia-awg2 sh -c "while [ ! -f /opt/amnezia/awg/wg0.conf ]; do sleep 1; done; WG_QUICK_USERSPACE_IMPLEMENTATION=amneziawg-go awg-quick up /opt/amnezia/awg/wg0.conf && sleep infinity"
sleep 2
else
STATUS=$(docker inspect --format="{{.State.Status}}" "$CONTAINER_NAME" 2>/dev/null || echo "")
if [ \"$STATUS\" != \"running\" ]; then
docker start \"$CONTAINER_NAME\" >/dev/null 2>&1 || true
fi
fi
# Check for existing config
if [ -f /opt/amnezia/awg2/wg0.conf ]; then
PORT=$(grep -E "^ListenPort" /opt/amnezia/awg2/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
PSK=$(cat /opt/amnezia/awg2/wireguard_psk.key 2>/dev/null || true)
if [ -z "$PSK" ]; then
PSK=$(grep -E "^PresharedKey" /opt/amnezia/awg2/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
fi
PUBKEY=$(cat /opt/amnezia/awg2/wireguard_server_public_key.key 2>/dev/null || true)
if [ -z "$PUBKEY" ]; then
PRIVKEY=$(cat /opt/amnezia/awg2/wireguard_server_private_key.key 2>/dev/null || true)
if [ -n "$PRIVKEY" ]; then
PUBKEY=$(echo "$PRIVKEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
fi
fi
echo "Using existing AmneziaWG 2.0 configuration"
echo "Port: ${PORT:-$VPN_PORT}"
if [ -n "${PUBKEY:-}" ]; then echo "Server Public Key: $PUBKEY"; fi
if [ -n "${PSK:-}" ]; then echo "PresharedKey = $PSK"; fi
EXTERNAL_IP=$(curl -s -4 ifconfig.me 2>/dev/null || curl -s -4 icanhazip.com 2>/dev/null || echo "YOUR_SERVER_IP")
echo "Server Host: $EXTERNAL_IP"
# Output AWG params from existing config
for P in Jc Jmin Jmax S1 S2 S3 S4 H1 H2 H3 H4; do
VAL=$(grep -E "^$P " /opt/amnezia/awg2/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
if [ -n "$VAL" ]; then echo "Variable: $P=$VAL"; fi
done
echo "Variable: dns_servers=1.1.1.1, 1.0.0.1"
exit 0
fi
# Generate keys
PRIVATE_KEY=$(docker exec "$CONTAINER_NAME" wg genkey)
PUBLIC_KEY=$(echo "$PRIVATE_KEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
PRESHARED_KEY=$(docker exec "$CONTAINER_NAME" wg genpsk)
# AWG obfuscation parameters
JC=5
JMIN=50
JMAX=1000
S1_VAL=50
S2_VAL=100
S3_VAL=20
S4_VAL=10
# H1-H4: header ranges (string format "x-y" per AWG2 spec)
H1_VAL="1-4294967295"
H2_VAL="1-4294967295"
H3_VAL="1-4294967295"
H4_VAL="1-4294967295"
# Write config
cat > /opt/amnezia/awg2/wg0.conf << EOF
[Interface]
PrivateKey = $PRIVATE_KEY
Address = 10.8.1.1/24
ListenPort = $VPN_PORT
MTU = $MTU
Jc = $JC
Jmin = $JMIN
Jmax = $JMAX
S1 = $S1_VAL
S2 = $S2_VAL
S3 = $S3_VAL
S4 = $S4_VAL
H1 = $H1_VAL
H2 = $H2_VAL
H3 = $H3_VAL
H4 = $H4_VAL
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
PublicKey =
PresharedKey = $PRESHARED_KEY
AllowedIPs = 10.8.1.2/32
EOF
echo "$PRIVATE_KEY" > /opt/amnezia/awg2/wireguard_server_private_key.key
echo "$PUBLIC_KEY" > /opt/amnezia/awg2/wireguard_server_public_key.key
echo "$PRESHARED_KEY" > /opt/amnezia/awg2/wireguard_psk.key
echo "[]" > /opt/amnezia/awg2/clientsTable
# Get external IP
EXTERNAL_IP=$(curl -s -4 ifconfig.me 2>/dev/null || curl -s -4 icanhazip.com 2>/dev/null || echo "YOUR_SERVER_IP")
echo "AmneziaWG 2.0 installed successfully"
echo "Port: $VPN_PORT"
echo "Server Public Key: $PUBLIC_KEY"
echo "PresharedKey = $PRESHARED_KEY"
echo "Server Host: $EXTERNAL_IP"
echo "Variable: Jc=$JC"
echo "Variable: Jmin=$JMIN"
echo "Variable: Jmax=$JMAX"
echo "Variable: S1=$S1_VAL"
echo "Variable: S2=$S2_VAL"
echo "Variable: S3=$S3_VAL"
echo "Variable: S4=$S4_VAL"
echo "Variable: H1=$H1_VAL"
echo "Variable: H2=$H2_VAL"
echo "Variable: H3=$H3_VAL"
echo "Variable: H4=$H4_VAL"
echo "Variable: dns_servers=1.1.1.1, 1.0.0.1"',
'#!/bin/bash
set -euo pipefail
CONTAINER_NAME="${CONTAINER_NAME:-amnezia-awg2}"
docker stop "$CONTAINER_NAME" 2>/dev/null || true
docker rm -fv "$CONTAINER_NAME" 2>/dev/null || true
docker image rm amnezia-awg2 2>/dev/null || true
rm -rf /opt/amnezia/awg2 2>/dev/null || true
echo "{\"success\":true,\"message\":\"AmneziaWG 2.0 uninstalled\"}"',
p.output_template,
1,
1,
JSON_OBJECT(
'engine', 'shell',
'metadata', JSON_OBJECT(
'container_name', 'amnezia-awg2',
'vpn_subnet', '10.8.1.0/24',
'port_range', JSON_ARRAY(30000, 65000),
'config_dir', '/opt/amnezia/awg2'
)
),
NOW(),
NOW()
FROM protocols p
WHERE p.slug = 'amnezia-wg-advanced'
AND NOT EXISTS (SELECT 1 FROM protocols WHERE slug = 'awg2');
-- 2. Clone protocol variables from amnezia-wg-advanced to awg2
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT
(SELECT id FROM protocols WHERE slug = 'awg2' LIMIT 1),
src.variable_name,
src.variable_type,
src.default_value,
src.description,
src.required
FROM protocol_variables src
WHERE src.protocol_id = (SELECT id FROM protocols WHERE slug = 'amnezia-wg-advanced' LIMIT 1)
AND NOT EXISTS (
SELECT 1 FROM protocol_variables ev
WHERE ev.protocol_id = (SELECT id FROM protocols WHERE slug = 'awg2' LIMIT 1)
AND ev.variable_name = src.variable_name
);
-- 3. Clone protocol templates from amnezia-wg-advanced to awg2
INSERT INTO protocol_templates (protocol_id, template_name, template_content, is_default)
SELECT
(SELECT id FROM protocols WHERE slug = 'awg2' LIMIT 1),
src.template_name,
src.template_content,
src.is_default
FROM protocol_templates src
WHERE src.protocol_id = (SELECT id FROM protocols WHERE slug = 'amnezia-wg-advanced' LIMIT 1)
AND NOT EXISTS (
SELECT 1 FROM protocol_templates et
WHERE et.protocol_id = (SELECT id FROM protocols WHERE slug = 'awg2' LIMIT 1)
AND et.template_name = src.template_name
);
-- 4. Update install_script for existing awg2 protocol (in case migration was already run)
UPDATE protocols SET install_script = '#!/bin/bash
set -euo pipefail
CONTAINER_NAME="${SERVER_CONTAINER:-amnezia-awg2}"
PORT_RANGE_START=${PORT_RANGE_START:-30000}
PORT_RANGE_END=${PORT_RANGE_END:-65000}
VPN_PORT="${SERVER_PORT:-$((RANDOM % (PORT_RANGE_END - PORT_RANGE_START + 1) + PORT_RANGE_START))}"
MTU=${MTU:-1420}
if ! command -v git &> /dev/null; then
apt-get update -qq && apt-get install -y -qq git >/dev/null 2>&1
fi
mkdir -p /opt/amnezia/awg2
if [ ! -d /opt/amnezia/awg2/src ]; then
git clone --depth=1 https://github.com/amnezia-vpn/amneziawg-go.git /opt/amnezia/awg2/src
fi
docker build --no-cache -t amnezia-awg2 /opt/amnezia/awg2/src
EXISTING=$(docker ps -aq -f "name=$CONTAINER_NAME" 2>/dev/null | head -1)
if [ -z "$EXISTING" ]; then
docker run -d --name "$CONTAINER_NAME" --restart always --cap-add=NET_ADMIN --device /dev/net/tun -p "${VPN_PORT}:${VPN_PORT}/udp" -v /opt/amnezia/awg2:/opt/amnezia/awg amnezia-awg2 sh -c "while [ ! -f /opt/amnezia/awg/wg0.conf ]; do sleep 1; done; WG_QUICK_USERSPACE_IMPLEMENTATION=amneziawg-go awg-quick up /opt/amnezia/awg/wg0.conf && sleep infinity"
sleep 2
else
STATUS=$(docker inspect --format="{{.State.Status}}" "$CONTAINER_NAME" 2>/dev/null || echo "")
if [ \"$STATUS\" != \"running\" ]; then
docker start \"$CONTAINER_NAME\" >/dev/null 2>&1 || true
fi
fi
if [ -f /opt/amnezia/awg2/wg0.conf ]; then
PORT=$(grep -E "^ListenPort" /opt/amnezia/awg2/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
PSK=$(cat /opt/amnezia/awg2/wireguard_psk.key 2>/dev/null || true)
if [ -z "$PSK" ]; then
PSK=$(grep -E "^PresharedKey" /opt/amnezia/awg2/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
fi
PUBKEY=$(cat /opt/amnezia/awg2/wireguard_server_public_key.key 2>/dev/null || true)
if [ -z "$PUBKEY" ]; then
PRIVKEY=$(cat /opt/amnezia/awg2/wireguard_server_private_key.key 2>/dev/null || true)
if [ -n "$PRIVKEY" ]; then
PUBKEY=$(echo "$PRIVKEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
fi
fi
echo "Using existing AmneziaWG 2.0 configuration"
echo "Port: ${PORT:-$VPN_PORT}"
if [ -n "${PUBKEY:-}" ]; then echo "Server Public Key: $PUBKEY"; fi
if [ -n "${PSK:-}" ]; then echo "PresharedKey = $PSK"; fi
EXTERNAL_IP=$(curl -s -4 ifconfig.me 2>/dev/null || curl -s -4 icanhazip.com 2>/dev/null || echo "YOUR_SERVER_IP")
echo "Server Host: $EXTERNAL_IP"
for P in Jc Jmin Jmax S1 S2 S3 S4 H1 H2 H3 H4; do
VAL=$(grep -E "^$P " /opt/amnezia/awg2/wg0.conf | cut -d= -f2 | tr -d "[:space:]")
if [ -n "$VAL" ]; then echo "Variable: $P=$VAL"; fi
done
echo "Variable: dns_servers=1.1.1.1, 1.0.0.1"
exit 0
fi
PRIVATE_KEY=$(docker exec "$CONTAINER_NAME" wg genkey)
PUBLIC_KEY=$(echo "$PRIVATE_KEY" | docker exec -i "$CONTAINER_NAME" wg pubkey)
PRESHARED_KEY=$(docker exec "$CONTAINER_NAME" wg genpsk)
JC=5
JMIN=50
JMAX=1000
S1_VAL=50
S2_VAL=100
S3_VAL=20
S4_VAL=10
H1_VAL="1-4294967295"
H2_VAL="1-4294967295"
H3_VAL="1-4294967295"
H4_VAL="1-4294967295"
cat > /opt/amnezia/awg2/wg0.conf << EOF
[Interface]
PrivateKey = $PRIVATE_KEY
Address = 10.8.1.1/24
ListenPort = $VPN_PORT
MTU = $MTU
Jc = $JC
Jmin = $JMIN
Jmax = $JMAX
S1 = $S1_VAL
S2 = $S2_VAL
S3 = $S3_VAL
S4 = $S4_VAL
H1 = $H1_VAL
H2 = $H2_VAL
H3 = $H3_VAL
H4 = $H4_VAL
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
PublicKey =
PresharedKey = $PRESHARED_KEY
AllowedIPs = 10.8.1.2/32
EOF
echo "$PRIVATE_KEY" > /opt/amnezia/awg2/wireguard_server_private_key.key
echo "$PUBLIC_KEY" > /opt/amnezia/awg2/wireguard_server_public_key.key
echo "$PRESHARED_KEY" > /opt/amnezia/awg2/wireguard_psk.key
echo "[]" > /opt/amnezia/awg2/clientsTable
EXTERNAL_IP=$(curl -s -4 ifconfig.me 2>/dev/null || curl -s -4 icanhazip.com 2>/dev/null || echo "YOUR_SERVER_IP")
echo "AmneziaWG 2.0 installed successfully"
echo "Port: $VPN_PORT"
echo "Server Public Key: $PUBLIC_KEY"
echo "PresharedKey = $PRESHARED_KEY"
echo "Server Host: $EXTERNAL_IP"
echo "Variable: Jc=$JC"
echo "Variable: Jmin=$JMIN"
echo "Variable: Jmax=$JMAX"
echo "Variable: S1=$S1_VAL"
echo "Variable: S2=$S2_VAL"
echo "Variable: S3=$S3_VAL"
echo "Variable: S4=$S4_VAL"
echo "Variable: H1=$H1_VAL"
echo "Variable: H2=$H2_VAL"
echo "Variable: H3=$H3_VAL"
echo "Variable: H4=$H4_VAL"
echo "Variable: dns_servers=1.1.1.1, 1.0.0.1"'
WHERE slug = 'awg2';
-- 5. Update output_template for AWG2 (add S3/S4 padding params)
UPDATE protocols SET output_template = '[Interface]
PrivateKey = {{private_key}}
Address = {{client_ip}}/32
DNS = {{dns_servers}}
MTU = 1280
Jc = {{Jc}}
Jmin = {{Jmin}}
Jmax = {{Jmax}}
S1 = {{S1}}
S2 = {{S2}}
S3 = {{S3}}
S4 = {{S4}}
H1 = {{H1}}
H2 = {{H2}}
H3 = {{H3}}
H4 = {{H4}}
[Peer]
PublicKey = {{server_public_key}}
PresharedKey = {{preshared_key}}
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = {{server_host}}:{{server_port}}
PersistentKeepalive = 25'
WHERE slug = 'awg2';
-- 6. Add S3/S4 protocol variables for awg2
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'S3', 'number', '20', 'Padding of handshake cookie message', false
FROM protocols p WHERE p.slug = 'awg2'
AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id = p.id AND variable_name = 'S3');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'S4', 'number', '10', 'Padding of transport messages', false
FROM protocols p WHERE p.slug = 'awg2'
AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id = p.id AND variable_name = 'S4');
+113
View File
@@ -0,0 +1,113 @@
-- =====================================================================
-- Migration 059: Add MTProxy (Telegram) protocol
-- https://hub.docker.com/r/telegrammessenger/proxy/
-- Zero-configuration Telegram MTProto proxy server
-- =====================================================================
-- 1. Insert the MTProxy protocol
INSERT INTO protocols (name, slug, description, install_script, uninstall_script, output_template, show_text_content, ubuntu_compatible, is_active, definition, created_at, updated_at)
SELECT
'MTProxy (Telegram)',
'mtproxy',
'Telegram MTProto proxy — zero-configuration proxy server for Telegram messenger.',
'#!/bin/bash
set -euo pipefail
# Use exported variables from panel (SERVER_PORT, SERVER_CONTAINER) or defaults
CONTAINER_NAME="${SERVER_CONTAINER:-amnezia-mtproxy}"
PORT_RANGE_START=${PORT_RANGE_START:-30000}
PORT_RANGE_END=${PORT_RANGE_END:-65000}
MTPROXY_PORT="${SERVER_PORT:-$((RANDOM % (PORT_RANGE_END - PORT_RANGE_START + 1) + PORT_RANGE_START))}"
mkdir -p /opt/amnezia/mtproxy
# Generate secret if not exists
if [ -f /opt/amnezia/mtproxy/secret ]; then
SECRET=$(cat /opt/amnezia/mtproxy/secret)
echo "Using existing MTProxy secret"
else
SECRET=$(cat /dev/urandom | tr -dc a-f0-9 | head -c 32 || true)
echo "$SECRET" > /opt/amnezia/mtproxy/secret
fi
# Store port
echo "$MTPROXY_PORT" > /opt/amnezia/mtproxy/port
# Remove existing container
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
# Run MTProxy container (single line for heredoc compatibility)
docker run -d --name "$CONTAINER_NAME" --restart always -p "${MTPROXY_PORT}:443" -v /opt/amnezia/mtproxy:/data -e SECRET="$SECRET" telegrammessenger/proxy:latest
sleep 3
# Get external IP
EXTERNAL_IP=$(curl -s -4 ifconfig.me 2>/dev/null || curl -s -4 icanhazip.com 2>/dev/null || echo "YOUR_SERVER_IP")
echo "MTProxy installed successfully"
echo "Port: $MTPROXY_PORT"
echo "Secret: $SECRET"
echo "Server Host: $EXTERNAL_IP"',
'#!/bin/bash
set -euo pipefail
CONTAINER_NAME="${CONTAINER_NAME:-amnezia-mtproxy}"
docker stop "$CONTAINER_NAME" 2>/dev/null || true
docker rm -fv "$CONTAINER_NAME" 2>/dev/null || true
docker image rm telegrammessenger/proxy:latest 2>/dev/null || true
rm -rf /opt/amnezia/mtproxy 2>/dev/null || true
echo "{\"success\":true,\"message\":\"MTProxy uninstalled\"}"',
'tg://proxy?server={{server_host}}&port={{server_port}}&secret={{secret}}',
1,
1,
1,
JSON_OBJECT(
'engine', 'shell',
'metadata', JSON_OBJECT(
'container_name', 'amnezia-mtproxy',
'port_range', JSON_ARRAY(30000, 65000),
'config_dir', '/opt/amnezia/mtproxy'
)
),
NOW(),
NOW()
WHERE NOT EXISTS (SELECT 1 FROM protocols WHERE slug = 'mtproxy');
-- 2. Add protocol variables for MTProxy
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'secret', 'string', '', 'MTProxy secret (32 hex chars)', true
FROM protocols p WHERE p.slug = 'mtproxy'
AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id = p.id AND variable_name = 'secret');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'server_host', 'string', '', 'Server hostname or IP', true
FROM protocols p WHERE p.slug = 'mtproxy'
AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id = p.id AND variable_name = 'server_host');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'server_port', 'number', '443', 'MTProxy external port', true
FROM protocols p WHERE p.slug = 'mtproxy'
AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id = p.id AND variable_name = 'server_port');
-- 3. Add default template for MTProxy
INSERT INTO protocol_templates (protocol_id, template_name, template_content, is_default)
SELECT p.id, 'Default MTProxy', 'tg://proxy?server={{server_host}}&port={{server_port}}&secret={{secret}}', true
FROM protocols p WHERE p.slug = 'mtproxy'
AND NOT EXISTS (SELECT 1 FROM protocol_templates WHERE protocol_id = p.id AND template_name = 'Default MTProxy');
-- 4. Add QR code template (same as output)
UPDATE protocols SET
qr_code_template = 'tg://proxy?server={{server_host}}&port={{server_port}}&secret={{secret}}',
qr_code_format = 'raw'
WHERE slug = 'mtproxy';
-- 5. Add translations for MTProxy
INSERT INTO translations (locale, category, key_name, translation) VALUES
('en', 'protocols', 'protocol_mtproxy', 'MTProxy (Telegram)')
ON DUPLICATE KEY UPDATE translation = VALUES(translation);
INSERT INTO translations (locale, category, key_name, translation) VALUES
('ru', 'protocols', 'protocol_mtproxy', 'MTProxy (Telegram)')
ON DUPLICATE KEY UPDATE translation = VALUES(translation);
+153
View File
@@ -0,0 +1,153 @@
-- =====================================================================
-- Migration 060: Add AIVPN protocol (AI-powered VPN with traffic disguise)
-- https://github.com/infosave2007/aivpn
-- Neural Resonance AI for DPI bypass, Zero-RTT, PFS
-- =====================================================================
-- 1. Insert the AIVPN protocol
INSERT INTO protocols (name, slug, description, install_script, uninstall_script, output_template, show_text_content, ubuntu_compatible, is_active, definition, created_at, updated_at)
SELECT
'AIVPN',
'aivpn',
'AIVPN — AI-powered VPN с маскировкой трафика под реальные приложения (Zoom, TikTok, DNS). Neural Resonance для обхода DPI.',
'#!/bin/bash
set -euo pipefail
# Use exported variables from panel (SERVER_PORT, SERVER_CONTAINER) or defaults
CONTAINER_NAME="${SERVER_CONTAINER:-aivpn-server}"
VPN_PORT="${SERVER_PORT:-443}"
CONFIG_DIR="/etc/aivpn"
# Install git and iptables if not available
if ! command -v git &> /dev/null || ! command -v iptables &> /dev/null; then
apt-get update -qq
if ! command -v git &> /dev/null; then
apt-get install -y -qq git >/dev/null 2>&1
fi
if ! command -v iptables &> /dev/null; then
apt-get install -y -qq iptables >/dev/null 2>&1
fi
fi
# Install Docker if not available
if ! command -v docker &> /dev/null; then
apt-get update -qq
apt-get install -y -qq apt-transport-https ca-certificates curl gnupg lsb-release >/dev/null 2>&1
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" > /etc/apt/sources.list.d/docker.list
apt-get update -qq && apt-get install -y -qq docker-ce docker-ce-cli containerd.io >/dev/null 2>&1
fi
mkdir -p "$CONFIG_DIR"
# Enable IP forwarding
sysctl -w net.ipv4.ip_forward=1 2>/dev/null || true
# Generate server key if not exists
if [ ! -f "$CONFIG_DIR/server.key" ]; then
openssl rand 32 > "$CONFIG_DIR/server.key"
chmod 600 "$CONFIG_DIR/server.key"
echo "Generated new AIVPN server key"
else
echo "Using existing AIVPN server key"
fi
# Setup NAT
iptables -t nat -C POSTROUTING -s 10.0.0.0/24 -o eth0 -j MASQUERADE 2>/dev/null || \
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 -j MASQUERADE
# Get external IP
EXTERNAL_IP=$(curl -s -4 ifconfig.me 2>/dev/null || curl -s -4 icanhazip.com 2>/dev/null || echo "YOUR_SERVER_IP")
# Clone AIVPN source for Docker build
if [ ! -d /opt/amnezia/aivpn ]; then
git clone --depth=1 https://github.com/infosave2007/aivpn.git /opt/amnezia/aivpn
fi
# Build Docker image
cd /opt/amnezia/aivpn
docker build --no-cache -t aivpn-server -f Dockerfile .
# Remove existing container
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
# Run AIVPN container
docker run -d --name "$CONTAINER_NAME" --restart always --cap-add=NET_ADMIN --device /dev/net/tun --network host -v "$CONFIG_DIR:/etc/aivpn" aivpn-server --listen "0.0.0.0:${VPN_PORT}" --key-file /etc/aivpn/server.key
sleep 3
# Check container status
STATUS=$(docker inspect --format="{{.State.Status}}" "$CONTAINER_NAME" 2>/dev/null || echo "unknown")
if [ "$STATUS" != "running" ]; then
echo "ERROR: AIVPN container is not running"
docker logs "$CONTAINER_NAME" 2>&1
exit 1
fi
echo "AIVPN installed successfully"
echo "Port: $VPN_PORT"
echo "ExternalIP: $EXTERNAL_IP"
echo "ConfigDir: $CONFIG_DIR"',
'#!/bin/bash
set -euo pipefail
CONTAINER_NAME="${CONTAINER_NAME:-aivpn-server}"
docker stop "$CONTAINER_NAME" 2>/dev/null || true
docker rm -fv "$CONTAINER_NAME" 2>/dev/null || true
docker image rm aivpn-server 2>/dev/null || true
rm -rf /opt/amnezia/aivpn 2>/dev/null || true
# Remove NAT rules
iptables -t nat -D POSTROUTING -s 10.0.0.0/24 -o eth0 -j MASQUERADE 2>/dev/null || true
echo "{\"success\":true,\"message\":\"AIVPN uninstalled\"}"',
'aivpn://{{connection_key}}',
1,
1,
1,
JSON_OBJECT(
'engine', 'shell',
'metadata', JSON_OBJECT(
'container_name', 'aivpn-server',
'port_range', JSON_ARRAY(443, 443),
'config_dir', '/etc/aivpn',
'vpn_subnet', '10.0.0.0/24',
'requires_docker_build', true,
'git_repo', 'https://github.com/infosave2007/aivpn.git'
)
),
NOW(),
NOW()
WHERE NOT EXISTS (SELECT 1 FROM protocols WHERE slug = 'aivpn');
-- 2. Add protocol variables for AIVPN
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'connection_key', 'string', '', 'AIVPN connection key (generated by server)', true
FROM protocols p WHERE p.slug = 'aivpn'
AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id = p.id AND variable_name = 'connection_key');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'server_host', 'string', '', 'Server hostname or IP', true
FROM protocols p WHERE p.slug = 'aivpn'
AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id = p.id AND variable_name = 'server_host');
INSERT INTO protocol_variables (protocol_id, variable_name, variable_type, default_value, description, required)
SELECT p.id, 'server_port', 'number', '443', 'AIVPN server port', true
FROM protocols p WHERE p.slug = 'aivpn'
AND NOT EXISTS (SELECT 1 FROM protocol_variables WHERE protocol_id = p.id AND variable_name = 'server_port');
-- 3. Add default template for AIVPN
INSERT INTO protocol_templates (protocol_id, template_name, template_content, is_default)
SELECT p.id, 'Default AIVPN', 'aivpn://{{connection_key}}', true
FROM protocols p WHERE p.slug = 'aivpn'
AND NOT EXISTS (SELECT 1 FROM protocol_templates WHERE protocol_id = p.id AND template_name = 'Default AIVPN');
-- 4. Add translations for AIVPN
INSERT INTO translations (locale, category, key_name, translation) VALUES
('en', 'protocols', 'protocol_aivpn', 'AIVPN (AI-Powered)')
ON DUPLICATE KEY UPDATE translation = VALUES(translation);
INSERT INTO translations (locale, category, key_name, translation) VALUES
('ru', 'protocols', 'protocol_aivpn', 'AIVPN (ИИ-протокол)')
ON DUPLICATE KEY UPDATE translation = VALUES(translation);
+3 -1
View File
@@ -1152,7 +1152,7 @@ Router::get('/clients/{id}', function ($params) {
}
if ($protocol && ($protocol['output_template'] ?? '') !== '') {
$slug = $protocol['slug'] ?? '';
$isWireguard = in_array($slug, ['amnezia-wg-advanced', 'wireguard-standard', 'amnezia-wg'], true);
$isWireguard = in_array($slug, ['amnezia-wg-advanced', 'wireguard-standard', 'amnezia-wg', 'awg2'], true);
if ($isWireguard) {
// For WG, we dont render protocol_output; config is downloadable
$protocolOutput = '';
@@ -1771,6 +1771,8 @@ Router::post('/api/servers/create', function () {
'port' => $port,
'username' => $username,
'password' => $password,
'install_protocol' => trim($input['install_protocol'] ?? ''),
'install_options' => $input['install_options'] ?? null,
]);
http_response_code(201);