59 lines
1.5 KiB
Python
59 lines
1.5 KiB
Python
|
|
"""Resolve Nexus center IP for Baota API whitelist."""
|
||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import ipaddress
|
||
|
|
import logging
|
||
|
|
import socket
|
||
|
|
from urllib.parse import urlparse
|
||
|
|
|
||
|
|
from server.config import settings
|
||
|
|
|
||
|
|
logger = logging.getLogger("nexus.btpanel.source_ip")
|
||
|
|
|
||
|
|
|
||
|
|
def _is_ip(value: str) -> bool:
|
||
|
|
try:
|
||
|
|
ipaddress.ip_address(value.strip())
|
||
|
|
return True
|
||
|
|
except ValueError:
|
||
|
|
return False
|
||
|
|
|
||
|
|
|
||
|
|
def _host_from_url(url: str) -> str | None:
|
||
|
|
parsed = urlparse(url.strip())
|
||
|
|
host = (parsed.hostname or "").strip()
|
||
|
|
return host or None
|
||
|
|
|
||
|
|
|
||
|
|
def resolve_center_ip_from_dns(host: str) -> str | None:
|
||
|
|
if not host:
|
||
|
|
return None
|
||
|
|
if _is_ip(host):
|
||
|
|
return host
|
||
|
|
try:
|
||
|
|
infos = socket.getaddrinfo(host, None, type=socket.SOCK_STREAM)
|
||
|
|
for info in infos:
|
||
|
|
addr = info[4][0]
|
||
|
|
if _is_ip(addr):
|
||
|
|
return addr
|
||
|
|
except OSError as exc:
|
||
|
|
logger.warning("bt panel source ip dns failed host=%s: %s", host, exc)
|
||
|
|
return None
|
||
|
|
|
||
|
|
|
||
|
|
def get_bt_panel_source_ip() -> str | None:
|
||
|
|
"""Center outbound IP for Baota ``limit_addr`` (settings → API_BASE_URL DNS)."""
|
||
|
|
explicit = (getattr(settings, "BT_PANEL_SOURCE_IP", None) or "").strip()
|
||
|
|
if explicit and _is_ip(explicit):
|
||
|
|
return explicit
|
||
|
|
|
||
|
|
base = (settings.API_BASE_URL or "").strip()
|
||
|
|
host = _host_from_url(base) if base else None
|
||
|
|
if host:
|
||
|
|
resolved = resolve_center_ip_from_dns(host)
|
||
|
|
if resolved:
|
||
|
|
return resolved
|
||
|
|
|
||
|
|
return None
|