feat: route raw TCP traffic through SOCKS5 proxy

Add create_connection and open_connection helpers to the shared proxy
module, covering portcheck, whois, tlscheck, and crtsh live-cert check.
UDP-based plugins (dns, blacklist, subdomain) stay direct.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
user
2026-02-15 16:01:17 +01:00
parent 97bbc6a825
commit 1bdba0ea06
6 changed files with 97 additions and 12 deletions

View File

@@ -1,9 +1,11 @@
"""Proxy-aware HTTP helpers -- routes outbound traffic through SOCKS5."""
"""Proxy-aware HTTP/TCP helpers -- routes outbound traffic through SOCKS5."""
import asyncio
import socket
import ssl
import urllib.request
import socks
from socks import SOCKS5
from sockshandler import SocksiPyConnectionS, SocksiPyHandler
@@ -46,3 +48,37 @@ def build_opener(*handlers, context=None):
"""Proxy-aware drop-in for urllib.request.build_opener."""
proxy = _ProxyHandler(context=context)
return urllib.request.build_opener(proxy, *handlers)
def create_connection(address, *, timeout=None):
"""SOCKS5-proxied drop-in for socket.create_connection.
Returns a connected socksocket (usable as context manager).
"""
host, port = address
sock = socks.socksocket()
sock.set_proxy(SOCKS5, _PROXY_ADDR, _PROXY_PORT, rdns=True)
if timeout is not None:
sock.settimeout(timeout)
sock.connect((host, port))
return sock
async def open_connection(host, port, *, timeout=None):
"""SOCKS5-proxied drop-in for asyncio.open_connection.
SOCKS5 handshake runs in a thread executor; returns (reader, writer).
"""
loop = asyncio.get_running_loop()
def _connect():
sock = socks.socksocket()
sock.set_proxy(SOCKS5, _PROXY_ADDR, _PROXY_PORT, rdns=True)
if timeout is not None:
sock.settimeout(timeout)
sock.connect((host, port))
sock.setblocking(False)
return sock
sock = await loop.run_in_executor(None, _connect)
return await asyncio.open_connection(sock=sock)