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

@@ -7,12 +7,12 @@ totals (expired/valid), and flag domains still serving expired certs.
import asyncio
import json
import logging
import socket
import ssl
import urllib.request
from concurrent.futures import ThreadPoolExecutor
from datetime import datetime, timezone
from derp.http import create_connection as _create_connection
from derp.http import urlopen as _urlopen
from derp.plugin import command
@@ -43,7 +43,7 @@ def check_live_cert(domain: str) -> dict | None:
for ctx_factory in (_make_verified_ctx, _make_unverified_ctx):
ctx = ctx_factory()
try:
with socket.create_connection((domain, 443), timeout=10) as sock:
with _create_connection((domain, 443), timeout=10) as sock:
with ctx.wrap_socket(sock, server_hostname=domain) as ssock:
return ssock.getpeercert()
except (OSError, ssl.SSLError):

View File

@@ -1,4 +1,4 @@
"""Plugin: async TCP port scanner (pure stdlib)."""
"""Plugin: async TCP port scanner (SOCKS5-proxied)."""
from __future__ import annotations
@@ -6,6 +6,7 @@ import asyncio
import ipaddress
import time
from derp.http import open_connection as _open_connection
from derp.plugin import command
_TIMEOUT = 3.0
@@ -49,7 +50,7 @@ async def _check_port(host: str, port: int, timeout: float) -> tuple[int, bool,
t0 = time.monotonic()
try:
_, writer = await asyncio.wait_for(
asyncio.open_connection(host, port), timeout=timeout,
_open_connection(host, port, timeout=timeout), timeout=timeout,
)
rtt = (time.monotonic() - t0) * 1000
writer.close()

View File

@@ -1,13 +1,13 @@
"""Plugin: TLS certificate and cipher inspector (pure stdlib)."""
"""Plugin: TLS certificate and cipher inspector (SOCKS5-proxied)."""
from __future__ import annotations
import asyncio
import hashlib
import socket
import ssl
from datetime import datetime, timezone
from derp.http import create_connection as _create_connection
from derp.plugin import command
_TIMEOUT = 10
@@ -35,7 +35,7 @@ def _inspect(host: str, port: int) -> dict:
ctx.verify_mode = ssl.CERT_NONE
try:
with socket.create_connection((host, port), timeout=_TIMEOUT) as sock:
with _create_connection((host, port), timeout=_TIMEOUT) as sock:
with ctx.wrap_socket(sock, server_hostname=host) as ssock:
result["version"] = ssock.version() or ""
cipher = ssock.cipher()

View File

@@ -1,10 +1,11 @@
"""Plugin: WHOIS lookup (raw TCP, port 43, pure stdlib)."""
"""Plugin: WHOIS lookup (raw TCP, port 43, SOCKS5-proxied)."""
from __future__ import annotations
import asyncio
import ipaddress
from derp.http import open_connection as _open_connection
from derp.plugin import command
# Referral servers for common TLDs
@@ -51,7 +52,7 @@ def _pick_server(target: str) -> tuple[str, str]:
async def _whois(server: str, query: str) -> str:
"""Send a WHOIS query and return the response text."""
reader, writer = await asyncio.wait_for(
asyncio.open_connection(server, 43), timeout=_TIMEOUT,
_open_connection(server, 43, timeout=_TIMEOUT), timeout=_TIMEOUT,
)
try:
writer.write(f"{query}\r\n".encode("utf-8"))