Show SOCKS5 proxy exit IP

This commit is contained in:
2026-05-28 20:59:21 +08:00
parent d9ddf83fd2
commit 661078c3bf
2 changed files with 36 additions and 5 deletions
+35 -4
View File
@@ -324,13 +324,13 @@ class Notifier:
return {"channel": name, "ok": False, "error": repr(e)}
async def socks5_connect(proxy: dict[str, Any], timeout: float) -> None:
async def socks5_open_connection(proxy: dict[str, Any], timeout: float, target_host: str | None = None, target_port: int | None = None) -> tuple[asyncio.StreamReader, asyncio.StreamWriter]:
host = proxy["host"]
port = int(proxy["port"])
username = proxy.get("username") or ""
password = proxy.get("password") or ""
target_host = proxy.get("target_host", "1.1.1.1")
target_port = int(proxy.get("target_port", 443))
target_host = str(target_host or proxy.get("target_host") or "www.baidu.com")
target_port = int(target_port or proxy.get("target_port", 443))
reader, writer = await asyncio.wait_for(asyncio.open_connection(host, port), timeout=timeout)
try:
methods = [0x00]
@@ -360,6 +360,33 @@ async def socks5_connect(proxy: dict[str, Any], timeout: float) -> None:
elif atyp == 0x03: await reader.readexactly((await reader.readexactly(1))[0])
elif atyp == 0x04: await reader.readexactly(16)
await reader.readexactly(2)
return reader, writer
except Exception:
writer.close()
with contextlib.suppress(Exception): await writer.wait_closed()
raise
async def socks5_connect(proxy: dict[str, Any], timeout: float) -> None:
reader, writer = await socks5_open_connection(proxy, timeout)
writer.close()
with contextlib.suppress(Exception): await writer.wait_closed()
async def get_exit_ip_via_socks(proxy: dict[str, Any], timeout: float) -> str | None:
"""Fetch the public egress IP through the SOCKS5 proxy without failing health checks."""
reader, writer = await socks5_open_connection(proxy, timeout, "api.ipify.org", 80)
try:
req = b"GET /?format=text HTTP/1.1\r\nHost: api.ipify.org\r\nUser-Agent: socks5-monitor/1.0\r\nConnection: close\r\n\r\n"
writer.write(req); await writer.drain()
raw = await asyncio.wait_for(reader.read(8192), timeout=timeout)
text = raw.decode("utf-8", "replace")
body = text.split("\r\n\r\n", 1)[-1].strip()
m = re.search(r"\b(?:\d{1,3}\.){3}\d{1,3}\b", body)
if m:
return m.group(0)
m = re.search(r"\b[0-9a-fA-F:]{3,}\b", body)
return m.group(0) if m else None
finally:
writer.close()
with contextlib.suppress(Exception): await writer.wait_closed()
@@ -370,7 +397,11 @@ async def check_proxy(proxy: dict[str, Any]) -> tuple[bool, int | None, str | No
start = time.perf_counter()
try:
await socks5_connect(proxy, timeout)
return True, int((time.perf_counter() - start) * 1000), None, None
latency = int((time.perf_counter() - start) * 1000)
exit_ip = None
with contextlib.suppress(Exception):
exit_ip = await get_exit_ip_via_socks(proxy, timeout)
return True, latency, None, exit_ip
except Exception as e:
return False, int((time.perf_counter() - start) * 1000), str(e), None