Let Xray pick standard 443 or a custom listen port (v3.1.2).

Default to custom 8443 so 443 stays free unless the user chooses standard.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
orohimaru2
2026-08-09 19:23:49 +03:00
co-authored by Cursor
parent 4720d8f2bd
commit d915b91f01
8 changed files with 125 additions and 35 deletions
+1 -1
View File
@@ -103,7 +103,7 @@ else:
application_path = os.path.dirname(__file__)
DATA_FILE = os.path.join(application_path, 'data.json') # legacy JSON; used only for one-shot import / export
CURRENT_VERSION = "v3.1.1"
CURRENT_VERSION = "v3.1.2"
RELEASES_REPO_URL = repo_url()
RELEASES_API_LATEST = api_latest_url()
BIN_DIR = os.environ.get('TUNNEL_BIN_DIR', os.path.join(application_path, 'bin'))
+4 -2
View File
@@ -26,7 +26,7 @@ class XrayManager:
PROTOCOL = 'xray'
CONTAINER_NAME = 'amnezia-xray'
IMAGE_NAME = 'amneziavpn/amnezia-xray'
DEFAULT_PORT = 443
DEFAULT_PORT = 8443
def __init__(self, ssh_manager, protocol='xray'):
self.ssh = ssh_manager
@@ -298,13 +298,15 @@ chmod 644 {_q(self._cert_path())} {_q(self._key_path())}
stream = (inbound or {}).get('streamSettings') or {}
return str(stream.get('security') or '').lower() == 'reality'
def install_protocol(self, port=443, domain=None, email=None, site_name=None,
def install_protocol(self, port=8443, domain=None, email=None, site_name=None,
acme_method='cloudflare', cloudflare_token=None):
"""Install VLESS + XHTTP + TLS (Let's Encrypt via Cloudflare DNS or HTTP-01)."""
results = []
domain = self._validate_domain(domain or site_name)
email = self._validate_email(email)
port = int(port or self.DEFAULT_PORT)
if port < 1 or port > 65535:
raise ValueError('Port must be between 1 and 65535')
method = (acme_method or 'cloudflare').strip().lower()
if method in ('cf', 'dns', 'dns-01', 'cloudflare_dns'):
method = 'cloudflare'
+70 -7
View File
@@ -801,6 +801,21 @@
<div class="form-hint" id="xrayPortsWarning" style="margin-bottom: var(--space-md); padding: var(--space-sm) var(--space-md); border-radius: var(--radius-sm); background: rgba(234,179,8,0.12); border: 1px solid rgba(234,179,8,0.35); color: var(--text);">
{{ _('xray_ports_warning_cf') }}
</div>
<div class="form-group">
<label class="form-label">{{ _('xray_listen_port') }} *</label>
<div style="display:flex; flex-direction:column; gap:8px; margin-bottom:8px;">
<label style="display:flex; align-items:flex-start; gap:8px; cursor:pointer;">
<input type="radio" name="xrayPortMode" value="standard" onchange="updateXrayPortUi()">
<span>{{ _('xray_port_standard') }}</span>
</label>
<label style="display:flex; align-items:flex-start; gap:8px; cursor:pointer;">
<input type="radio" name="xrayPortMode" value="custom" checked onchange="updateXrayPortUi()">
<span>{{ _('xray_port_custom') }}</span>
</label>
</div>
<input class="form-input" type="number" id="installXrayPort" value="8443" min="1" max="65535" oninput="syncXrayPortToInstall()">
<div class="form-hint" id="xrayPortHint">{{ _('xray_port_hint') }}</div>
</div>
<div class="form-group">
<label class="form-label">{{ _('xray_domain') }} *</label>
<input class="form-input" type="text" id="installXrayDomain" placeholder="vpn.example.com" oninput="updateXrayDnsHint()">
@@ -2444,6 +2459,47 @@
return el ? el.value : 'cloudflare';
}
function getXrayPortMode() {
const el = document.querySelector('input[name="xrayPortMode"]:checked');
return el ? el.value : 'custom';
}
function syncXrayPortToInstall() {
const portInput = document.getElementById('installPort');
const xrPort = document.getElementById('installXrayPort');
if (!portInput || !xrPort) return;
if (getXrayPortMode() === 'standard') {
portInput.value = '443';
xrPort.value = '443';
} else {
const v = parseInt(xrPort.value, 10);
portInput.value = (v >= 1 && v <= 65535) ? String(v) : '8443';
}
}
function updateXrayPortUi() {
const mode = getXrayPortMode();
const xrPort = document.getElementById('installXrayPort');
const hint = document.getElementById('xrayPortHint');
if (xrPort) {
if (mode === 'standard') {
xrPort.value = '443';
xrPort.disabled = true;
} else {
xrPort.disabled = false;
if (!xrPort.value || xrPort.value === '443') {
xrPort.value = currentInstallAnother
? String(nextSuggestedPort(currentInstallProto, 8443))
: '8443';
}
}
}
if (hint) {
hint.textContent = mode === 'standard' ? _('xray_port_hint_standard') : _('xray_port_hint');
}
syncXrayPortToInstall();
}
function updateXrayAcmeUi() {
const method = getXrayAcmeMethod();
const cfGroup = document.getElementById('xrayCfTokenGroup');
@@ -2451,10 +2507,6 @@
if (cfGroup) cfGroup.style.display = method === 'cloudflare' ? '' : 'none';
if (warn) warn.textContent = method === 'cloudflare' ? _('xray_ports_warning_cf') : _('xray_ports_warning');
updateXrayDnsHint();
const portHint = document.getElementById('installPortHint');
if (portHint && protoBase(currentInstallProto) === 'xray' && !currentInstallAnother) {
portHint.textContent = method === 'cloudflare' ? _('port_xray_hint_cf') : _('port_xray_hint');
}
}
function updateXrayDnsHint() {
@@ -2503,15 +2555,18 @@
portInput.disabled = true;
portHint.textContent = _('dns_internal_hint');
} else if (base === 'xray') {
portLabel.textContent = _('port') + ' (TCP)';
if (portGroup) portGroup.style.display = 'none';
portInput.disabled = false;
portInput.value = currentInstallAnother ? nextSuggestedPort(currentInstallProto, 443) : '443';
portHint.textContent = currentInstallAnother ? _('port_next_instance_hint') : _('port_xray_hint');
if (xrayOpts) xrayOpts.style.display = 'block';
const xrDomain = document.getElementById('installXrayDomain');
const xrEmail = document.getElementById('installXrayEmail');
if (xrDomain && !xrDomain.value && SERVER_SSL_DOMAIN) xrDomain.value = SERVER_SSL_DOMAIN;
if (xrEmail && !xrEmail.value && SERVER_SSL_EMAIL) xrEmail.value = SERVER_SSL_EMAIL;
const stdRadio = document.querySelector('input[name="xrayPortMode"][value="standard"]');
const customRadio = document.querySelector('input[name="xrayPortMode"][value="custom"]');
if (customRadio) customRadio.checked = true;
if (stdRadio) stdRadio.checked = false;
updateXrayPortUi();
updateXrayAcmeUi();
} else if (base === 'telemt') {
portLabel.textContent = _('port') + ' (TCP)';
@@ -2599,10 +2654,16 @@
const xrEmail = (document.getElementById('installXrayEmail')?.value || '').trim();
const acme = getXrayAcmeMethod();
const cfToken = (document.getElementById('installXrayCfToken')?.value || '').trim();
syncXrayPortToInstall();
const xrPort = parseInt(document.getElementById('installPort')?.value, 10);
if (!xrDomain || !xrEmail) {
showToast(_('xray_domain') + ' / ' + _('xray_email'), 'error');
return;
}
if (!(xrPort >= 1 && xrPort <= 65535)) {
showToast(_('xray_listen_port'), 'error');
return;
}
if (acme === 'cloudflare' && !cfToken) {
showToast(_('xray_cf_token'), 'error');
return;
@@ -2667,6 +2728,8 @@
params.hysteria_domain = document.getElementById('installHysteriaDomain').value.trim();
params.hysteria_email = document.getElementById('installHysteriaEmail').value.trim();
} else if (protoBase(currentInstallProto) === 'xray') {
syncXrayPortToInstall();
params.port = document.getElementById('installPort').value;
params.xray_domain = (document.getElementById('installXrayDomain')?.value || '').trim();
params.xray_email = (document.getElementById('installXrayEmail')?.value || '').trim();
params.xray_acme_method = getXrayAcmeMethod();
+10 -5
View File
@@ -82,15 +82,20 @@
"no_connections_desc": "Add your first connection to generate a VPN configuration",
"install_protocol": "Install protocol",
"port_default_hint": "Default port: 55424. Make sure it\u0027s not busy",
"port_xray_hint": "Default 443/TCP. Prefer Cloudflare DNS ACME — port 80 is not needed. Point domain A-record (DNS only / grey cloud) to this server.",
"port_xray_hint_cf": "Default 443/TCP. Certificate via Cloudflare DNS — port 80 is not used. Keep Cloudflare proxy off (grey cloud).",
"port_xray_hint": "Choose standard 443/TCP or any free custom TCP port. Prefer Cloudflare DNS ACME — port 80 is not needed.",
"port_xray_hint_cf": "Choose 443 or a custom TCP port. Certificate via Cloudflare DNS — port 80 is not used. Keep Cloudflare proxy off (grey cloud).",
"xray_domain": "Domain",
"xray_email": "Let\u0027s Encrypt email",
"xray_dns_hint": "Create DNS record:",
"xray_dns_hint_cf": "Domain must be on Cloudflare. A-record (DNS only):",
"xray_install_hint": "Installs VLESS + XHTTP + TLS (Xray-core). Prefer Cloudflare API token (DNS-01) so TCP 80 stays free.",
"xray_ports_warning": "TCP 80 must be free during install (Let\u0027s Encrypt HTTP-01). Reinstall replaces the previous Xray stack.",
"xray_ports_warning_cf": "Cloudflare DNS ACME does not use port 80. Token needs Zone → DNS → Edit. Keep proxy off (grey cloud). Reinstall replaces the previous Xray stack.",
"xray_install_hint": "Installs VLESS + XHTTP + TLS (Xray-core). Prefer Cloudflare API token (DNS-01) so TCP 80 stays free. Port 443 is optional.",
"xray_ports_warning": "TCP 80 must be free during install (Let\u0027s Encrypt HTTP-01). Listen port can be 443 or any free TCP port. Reinstall replaces the previous Xray stack.",
"xray_ports_warning_cf": "Cloudflare DNS ACME does not use port 80. Listen on 443 or any free TCP port. Token needs Zone → DNS → Edit. Keep proxy off (grey cloud).",
"xray_listen_port": "Listen port (TCP)",
"xray_port_standard": "Standard — 443/TCP",
"xray_port_custom": "Custom port",
"xray_port_hint": "Any free TCP port (default 8443). Open it in the firewall. Does not occupy 443.",
"xray_port_hint_standard": "Uses 443/TCP. Make sure nothing else is bound to 443 on this server.",
"xray_acme_method": "Certificate method",
"xray_acme_cloudflare": "Cloudflare DNS (API token) — recommended, no port 80",
"xray_acme_http": "HTTP-01 — needs free TCP 80",
+10 -5
View File
@@ -80,15 +80,20 @@
"no_connections_desc": "اولین اتصال خود را برای ایجاد پیکربندی VPN اضافه کنید",
"install_protocol": "نصب پروتکل",
"port_default_hint": "پورت پیش‌فرض: 55424. مطمئن شوید این پورت آزاد است.",
"port_xray_hint": "Default 443/TCP. Prefer Cloudflare DNS ACME — port 80 is not needed.",
"port_xray_hint_cf": "Default 443/TCP. Certificate via Cloudflare DNS — port 80 is not used.",
"port_xray_hint": "Choose standard 443/TCP or any free custom TCP port. Prefer Cloudflare DNS ACME — port 80 is not needed.",
"port_xray_hint_cf": "Choose 443 or a custom TCP port. Certificate via Cloudflare DNS — port 80 is not used.",
"xray_domain": "Domain",
"xray_email": "Let\u0027s Encrypt email",
"xray_dns_hint": "Create DNS record:",
"xray_dns_hint_cf": "Domain must be on Cloudflare. A-record (DNS only):",
"xray_install_hint": "Installs VLESS + XHTTP + TLS. Prefer Cloudflare API token (DNS-01) so TCP 80 stays free.",
"xray_ports_warning": "TCP 80 must be free during install (Let\u0027s Encrypt HTTP-01).",
"xray_ports_warning_cf": "Cloudflare DNS ACME does not use port 80. Token needs Zone → DNS → Edit. Keep proxy off (grey cloud).",
"xray_install_hint": "Installs VLESS + XHTTP + TLS. Prefer Cloudflare API token (DNS-01) so TCP 80 stays free. Port 443 is optional.",
"xray_ports_warning": "TCP 80 must be free during install (Let\u0027s Encrypt HTTP-01). Listen port can be 443 or any free TCP port.",
"xray_ports_warning_cf": "Cloudflare DNS ACME does not use port 80. Listen on 443 or any free TCP port. Token needs Zone → DNS → Edit. Keep proxy off (grey cloud).",
"xray_listen_port": "Listen port (TCP)",
"xray_port_standard": "Standard — 443/TCP",
"xray_port_custom": "Custom port",
"xray_port_hint": "Any free TCP port (default 8443). Open it in the firewall. Does not occupy 443.",
"xray_port_hint_standard": "Uses 443/TCP. Make sure nothing else is bound to 443 on this server.",
"xray_acme_method": "Certificate method",
"xray_acme_cloudflare": "Cloudflare DNS (API token) — recommended, no port 80",
"xray_acme_http": "HTTP-01 — needs free TCP 80",
+10 -5
View File
@@ -80,15 +80,20 @@
"no_connections_desc": "Ajoutez votre première connexion pour générer un fichier VPN",
"install_protocol": "Installer le protocole",
"port_default_hint": "Port par défaut : 55424. Assurez-vous qu\u0027il est libre.",
"port_xray_hint": "Default 443/TCP. Prefer Cloudflare DNS ACME — port 80 is not needed.",
"port_xray_hint_cf": "Default 443/TCP. Certificate via Cloudflare DNS — port 80 is not used.",
"port_xray_hint": "Choose standard 443/TCP or any free custom TCP port. Prefer Cloudflare DNS ACME — port 80 is not needed.",
"port_xray_hint_cf": "Choose 443 or a custom TCP port. Certificate via Cloudflare DNS — port 80 is not used.",
"xray_domain": "Domain",
"xray_email": "Let\u0027s Encrypt email",
"xray_dns_hint": "Create DNS record:",
"xray_dns_hint_cf": "Domain must be on Cloudflare. A-record (DNS only):",
"xray_install_hint": "Installs VLESS + XHTTP + TLS. Prefer Cloudflare API token (DNS-01) so TCP 80 stays free.",
"xray_ports_warning": "TCP 80 must be free during install (Let\u0027s Encrypt HTTP-01).",
"xray_ports_warning_cf": "Cloudflare DNS ACME does not use port 80. Token needs Zone → DNS → Edit. Keep proxy off (grey cloud).",
"xray_install_hint": "Installs VLESS + XHTTP + TLS. Prefer Cloudflare API token (DNS-01) so TCP 80 stays free. Port 443 is optional.",
"xray_ports_warning": "TCP 80 must be free during install (Let\u0027s Encrypt HTTP-01). Listen port can be 443 or any free TCP port.",
"xray_ports_warning_cf": "Cloudflare DNS ACME does not use port 80. Listen on 443 or any free TCP port. Token needs Zone → DNS → Edit. Keep proxy off (grey cloud).",
"xray_listen_port": "Listen port (TCP)",
"xray_port_standard": "Standard — 443/TCP",
"xray_port_custom": "Custom port",
"xray_port_hint": "Any free TCP port (default 8443). Open it in the firewall. Does not occupy 443.",
"xray_port_hint_standard": "Uses 443/TCP. Make sure nothing else is bound to 443 on this server.",
"xray_acme_method": "Certificate method",
"xray_acme_cloudflare": "Cloudflare DNS (API token) — recommended, no port 80",
"xray_acme_http": "HTTP-01 — needs free TCP 80",
+10 -5
View File
@@ -82,15 +82,20 @@
"no_connections_desc": "Добавьте первое подключение для генерации VPN конфигурации",
"install_protocol": "Установить протокол",
"port_default_hint": "Порт по умолчанию: 55424. Убедитесь, что он не занят",
"port_xray_hint": "По умолчанию 443/TCP. Лучше Cloudflare DNS ACME — порт 80 не нужен. A-запись домена (только DNS / серое облако) на этот сервер.",
"port_xray_hint_cf": "По умолчанию 443/TCP. Сертификат через Cloudflare DNS — порт 80 не используется. Прокси Cloudflare выключите (серое облако).",
"port_xray_hint": "Можно взять стандартный 443/TCP или любой свободный порт. Лучше Cloudflare DNS ACME — порт 80 не нужен.",
"port_xray_hint_cf": "443 или свой TCP-порт. Сертификат через Cloudflare DNS — порт 80 не используется. Прокси Cloudflare выключите (серое облако).",
"xray_domain": "Домен",
"xray_email": "Email для Let\u0027s Encrypt",
"xray_dns_hint": "Создайте DNS-запись:",
"xray_dns_hint_cf": "Домен должен быть в Cloudflare. A-запись (только DNS):",
"xray_install_hint": "Ставит VLESS + XHTTP + TLS (Xray-core). Рекомендуется токен Cloudflare (DNS-01) — TCP 80 не занимается.",
"xray_ports_warning": "На время установки TCP 80 должен быть свободен (Let\u0027s Encrypt HTTP-01). Переустановка заменяет предыдущий Xray.",
"xray_ports_warning_cf": "Cloudflare DNS ACME не использует порт 80. Токену нужно Zone → DNS → Edit. Прокси выключите (серое облако). Переустановка заменяет предыдущий Xray.",
"xray_install_hint": "Ставит VLESS + XHTTP + TLS (Xray-core). Рекомендуется токен Cloudflare (DNS-01) — TCP 80 не занимается. Порт 443 необязателен.",
"xray_ports_warning": "На время установки TCP 80 должен быть свободен (Let\u0027s Encrypt HTTP-01). Слушающий порт — 443 или любой свободный. Переустановка заменяет предыдущий Xray.",
"xray_ports_warning_cf": "Cloudflare DNS ACME не использует порт 80. Слушайте на 443 или любом свободном TCP. Токену нужно Zone → DNS → Edit. Прокси выключите (серое облако).",
"xray_listen_port": "Порт прослушивания (TCP)",
"xray_port_standard": "Стандартный — 443/TCP",
"xray_port_custom": "Свой порт",
"xray_port_hint": "Любой свободный TCP-порт (по умолчанию 8443). Откройте его в файрволе. Порт 443 не занимает.",
"xray_port_hint_standard": "Использует 443/TCP. Убедитесь, что 443 на сервере свободен.",
"xray_acme_method": "Способ выпуска SSL",
"xray_acme_cloudflare": "Cloudflare DNS (API-токен) — рекомендуется, без порта 80",
"xray_acme_http": "HTTP-01 — нужен свободный TCP 80",
+10 -5
View File
@@ -80,15 +80,20 @@
"no_connections_desc": "添加首个连接以生成 VPN 配置文件",
"install_protocol": "安装协议",
"port_default_hint": "默认端口: 55424。请确保端口未被占用。",
"port_xray_hint": "Default 443/TCP. Prefer Cloudflare DNS ACME — port 80 is not needed.",
"port_xray_hint_cf": "Default 443/TCP. Certificate via Cloudflare DNS — port 80 is not used.",
"port_xray_hint": "Choose standard 443/TCP or any free custom TCP port. Prefer Cloudflare DNS ACME — port 80 is not needed.",
"port_xray_hint_cf": "Choose 443 or a custom TCP port. Certificate via Cloudflare DNS — port 80 is not used.",
"xray_domain": "Domain",
"xray_email": "Let\u0027s Encrypt email",
"xray_dns_hint": "Create DNS record:",
"xray_dns_hint_cf": "Domain must be on Cloudflare. A-record (DNS only):",
"xray_install_hint": "Installs VLESS + XHTTP + TLS. Prefer Cloudflare API token (DNS-01) so TCP 80 stays free.",
"xray_ports_warning": "TCP 80 must be free during install (Let\u0027s Encrypt HTTP-01).",
"xray_ports_warning_cf": "Cloudflare DNS ACME does not use port 80. Token needs Zone → DNS → Edit. Keep proxy off (grey cloud).",
"xray_install_hint": "Installs VLESS + XHTTP + TLS. Prefer Cloudflare API token (DNS-01) so TCP 80 stays free. Port 443 is optional.",
"xray_ports_warning": "TCP 80 must be free during install (Let\u0027s Encrypt HTTP-01). Listen port can be 443 or any free TCP port.",
"xray_ports_warning_cf": "Cloudflare DNS ACME does not use port 80. Listen on 443 or any free TCP port. Token needs Zone → DNS → Edit. Keep proxy off (grey cloud).",
"xray_listen_port": "Listen port (TCP)",
"xray_port_standard": "Standard — 443/TCP",
"xray_port_custom": "Custom port",
"xray_port_hint": "Any free TCP port (default 8443). Open it in the firewall. Does not occupy 443.",
"xray_port_hint_standard": "Uses 443/TCP. Make sure nothing else is bound to 443 on this server.",
"xray_acme_method": "Certificate method",
"xray_acme_cloudflare": "Cloudflare DNS (API token) — recommended, no port 80",
"xray_acme_http": "HTTP-01 — needs free TCP 80",