Show SOCKS5 proxy exit IP
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user