new changes
This commit is contained in:
Binary file not shown.
@@ -2,6 +2,7 @@
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
|
import socket
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
from fastapi import APIRouter, Depends, HTTPException
|
from fastapi import APIRouter, Depends, HTTPException
|
||||||
@@ -12,7 +13,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from app.core.database import get_db
|
from app.core.database import get_db
|
||||||
from app.core.config import get_runtime_config
|
from app.core.config import get_runtime_config
|
||||||
from app.core.utils import environment_with_system_path, read_file, nginx_reload_all_known, nginx_binary_candidates
|
from app.core.utils import environment_with_system_path, exec_shell_sync, read_file, nginx_reload_all_known, nginx_binary_candidates
|
||||||
from app.api.auth import get_current_user
|
from app.api.auth import get_current_user
|
||||||
from app.models.user import User
|
from app.models.user import User
|
||||||
from app.models.site import Site, Domain
|
from app.models.site import Site, Domain
|
||||||
@@ -125,6 +126,23 @@ def _reload_panel_and_common_nginx() -> tuple[bool, str]:
|
|||||||
return nginx_reload_all_known(timeout=60)
|
return nginx_reload_all_known(timeout=60)
|
||||||
|
|
||||||
|
|
||||||
|
def _localhost_accepts_tcp(port: int, timeout: float = 2.0) -> bool:
|
||||||
|
"""True if something accepts a TCP connection on this machine (checks IPv4 loopback)."""
|
||||||
|
try:
|
||||||
|
with socket.create_connection(("127.0.0.1", port), timeout=timeout):
|
||||||
|
return True
|
||||||
|
except OSError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def _ss_reports_listen_443() -> bool | None:
|
||||||
|
"""Parse ss/netstat output; None if the probe could not run."""
|
||||||
|
out, _ = exec_shell_sync("ss -tln 2>/dev/null || netstat -tln 2>/dev/null", timeout=5)
|
||||||
|
if not out or not out.strip():
|
||||||
|
return None
|
||||||
|
return bool(re.search(r":443\b", out))
|
||||||
|
|
||||||
|
|
||||||
@router.get("/domains")
|
@router.get("/domains")
|
||||||
async def ssl_domains(
|
async def ssl_domains(
|
||||||
current_user: User = Depends(get_current_user),
|
current_user: User = Depends(get_current_user),
|
||||||
@@ -362,9 +380,27 @@ async def ssl_diagnostics(current_user: User = Depends(get_current_user)):
|
|||||||
"Add the include below (or symlink this directory into /etc/nginx/conf.d/)."
|
"Add the include below (or symlink this directory into /etc/nginx/conf.d/)."
|
||||||
)
|
)
|
||||||
|
|
||||||
if effective_listen_443:
|
localhost_443_open = _localhost_accepts_tcp(443)
|
||||||
|
ss_443 = _ss_reports_listen_443()
|
||||||
|
|
||||||
|
if not localhost_443_open and not effective_listen_443:
|
||||||
hints.append(
|
hints.append(
|
||||||
"Loaded nginx configuration includes a 443 listener. If HTTPS still fails, open TCP port 443 on the OS firewall and cloud/VPS security group."
|
"This server is not accepting TCP on 127.0.0.1:443 — nothing is listening on 443 yet. "
|
||||||
|
"Fix nginx (listen 443 ssl + include panel vhosts) first; opening only the cloud firewall will not fix ERR_CONNECTION_REFUSED until nginx binds 443."
|
||||||
|
)
|
||||||
|
elif effective_listen_443 and localhost_443_open:
|
||||||
|
hints.append(
|
||||||
|
"Nginx loads HTTPS and 127.0.0.1:443 accepts connections on this host. "
|
||||||
|
"If browsers off this machine still see connection refused, allow inbound TCP 443: "
|
||||||
|
"sudo ufw allow 443/tcp && sudo ufw reload (or firewalld), and your VPS Security Group / provider firewall."
|
||||||
|
)
|
||||||
|
elif effective_listen_443 and not localhost_443_open:
|
||||||
|
hints.append(
|
||||||
|
"nginx -T reports listen 443, but connecting to 127.0.0.1:443 failed — check nginx error.log; nginx may have failed to bind (permission or address already in use)."
|
||||||
|
)
|
||||||
|
elif localhost_443_open and not effective_listen_443:
|
||||||
|
hints.append(
|
||||||
|
"127.0.0.1:443 accepts TCP, but nginx -T from panel binaries did not show listen 443 — another process may own 443; check ss -tlnp and which nginx serves port 80."
|
||||||
)
|
)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -375,6 +411,8 @@ async def ssl_diagnostics(current_user: User = Depends(get_current_user)):
|
|||||||
"nginx_effective_listen_443": effective_listen_443,
|
"nginx_effective_listen_443": effective_listen_443,
|
||||||
"panel_vhost_path_in_nginx_t": panel_include_in_effective_config,
|
"panel_vhost_path_in_nginx_t": panel_include_in_effective_config,
|
||||||
"nginx_t_probe_errors": nginx_t_errors,
|
"nginx_t_probe_errors": nginx_t_errors,
|
||||||
|
"localhost_443_accepts_tcp": localhost_443_open,
|
||||||
|
"ss_reports_443_listen": ss_443,
|
||||||
"hints": hints,
|
"hints": hints,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,10 @@ interface SslDiagnostics {
|
|||||||
nginx_effective_listen_443: boolean
|
nginx_effective_listen_443: boolean
|
||||||
panel_vhost_path_in_nginx_t: boolean
|
panel_vhost_path_in_nginx_t: boolean
|
||||||
nginx_t_probe_errors: string[]
|
nginx_t_probe_errors: string[]
|
||||||
|
/** Something accepted TCP when connecting to 127.0.0.1:443 from the panel process */
|
||||||
|
localhost_443_accepts_tcp: boolean
|
||||||
|
/** ss/netstat reported :443 in listen table, or null if probe unavailable */
|
||||||
|
ss_reports_443_listen: boolean | null
|
||||||
hints: string[]
|
hints: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,6 +118,32 @@ export function DomainsPage() {
|
|||||||
) : null}
|
) : null}
|
||||||
<div className="text-secondary mb-1">Include YakPanel vhosts inside the <code>http</code> block of the nginx process that serves your sites:</div>
|
<div className="text-secondary mb-1">Include YakPanel vhosts inside the <code>http</code> block of the nginx process that serves your sites:</div>
|
||||||
<code className="d-block user-select-all bg-body-secondary p-2 rounded small text-break">{diag.include_snippet}</code>
|
<code className="d-block user-select-all bg-body-secondary p-2 rounded small text-break">{diag.include_snippet}</code>
|
||||||
|
<div className="mt-3 small">
|
||||||
|
<strong>Port 443 on this machine</strong>
|
||||||
|
<ul className="mb-0 ps-3 mt-1">
|
||||||
|
<li>
|
||||||
|
Localhost TCP (127.0.0.1:443):{' '}
|
||||||
|
{diag.localhost_443_accepts_tcp ? (
|
||||||
|
<span className="text-success">accepting connections</span>
|
||||||
|
) : (
|
||||||
|
<span className="text-danger">refused / nothing listening</span>
|
||||||
|
)}
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Kernel listen table (ss):{' '}
|
||||||
|
{diag.ss_reports_443_listen === null ? (
|
||||||
|
<span className="text-secondary">not checked</span>
|
||||||
|
) : diag.ss_reports_443_listen ? (
|
||||||
|
<span className="text-success">443 in LISTEN</span>
|
||||||
|
) : (
|
||||||
|
<span className="text-danger">no 443 in LISTEN</span>
|
||||||
|
)}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p className="text-secondary mt-2 mb-0">
|
||||||
|
The panel cannot see your cloud provider firewall. If localhost shows open but browsers off-network fail, open TCP 443 in the VPS control panel (security group) and OS firewall.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
{diag.vhosts.length > 0 ? (
|
{diag.vhosts.length > 0 ? (
|
||||||
<div className="mt-2 text-secondary">
|
<div className="mt-2 text-secondary">
|
||||||
Panel configs scanned:{' '}
|
Panel configs scanned:{' '}
|
||||||
|
|||||||
Reference in New Issue
Block a user