DEV Community

全网低价IP
全网低价IP

Posted on Originally published at socks5ip.com.cn

Proxy Pool Health Monitoring: Turning "It Works" into Metrics You Can Act On

Most proxy pools die quietly. Nothing throws an exception, and one morning a third of your requests time out while the dashboard still says 200 OK — because a scraper that retries three times and finally succeeds looks identical to one that never had a problem.

That is the real failure mode: you are measuring your application, not your infrastructure.

Why "it works" is not a health check

A ping is not a proxy check, and neither is a TCP connect. What you need is whether a complete, correctly authenticated protocol exchange can carry traffic now — and how fast:

Layer What breaks A naive check reports
Network Host unreachable, port filtered Down (correct)
TCP Port open, no service behind it Up (wrong)
Protocol Handshake rejected, bad credentials Up (wrong)
Identity Exit IP moved, or is not where you expect Up (wrong)
Capacity Handshake fine, throughput collapsed Up (wrong)

Only the first row is caught by a ping — which is why a pool reporting "100% alive" can still cost you a day.

The five metrics that matter

Track these per endpoint, not per pool — averages hide the endpoints you need to evict.

Metric Definition Why it earns its place
Handshake latency Time to complete protocol negotiation Earliest sign of congestion
Rolling success rate Successes / attempts over last N runs Catches flapping, not just hard down
Exit IP stability Did the observed exit IP change Detects rotation you did not ask for
Exit IP correctness Is the exit in the expected region and ASN Catches silent rerouting
Throughput Bytes per second on a fixed transfer Catches "connected but useless"

Latency alone is not enough: a common trick is an endpoint that handshakes in 40 ms and then delivers 30 KB/s — the metric looks great while your pipeline stalls.

Measuring it with stdlib Python

You do not need a framework — a socket, a timer, and a small request are the whole check. The SOCKS5 version, following RFC 1928:

import socket, struct, time

def socks5_check(host, port, user=None, pwd=None, timeout=8.0):
    """Return (ok, handshake_ms, error)."""
    t0 = time.perf_counter()
    try:
        s = socket.create_connection((host, port), timeout=timeout)
    except OSError as e:
        return False, None, 'tcp:%s' % e
    try:
        s.sendall(b'\x05\x02\x00\x02' if user else b'\x05\x01\x00')
        ver, method = s.recv(2)
        if ver != 5 or method == 0xFF:
            return False, None, 'no acceptable auth method'
        if method == 0x02:                        # RFC 1929 user/pass exchange
            u, p = user.encode(), pwd.encode()
            s.sendall(b'\x01' + bytes([len(u)]) + u + bytes([len(p)]) + p)
            if s.recv(2)[1] != 0x00:
                return False, None, 'auth rejected'
        # CONNECT 1.1.1.1:443 -> reply VER REP RSV ATYP BND.ADDR BND.PORT
        s.sendall(b'\x05\x01\x00\x01' + socket.inet_aton('1.1.1.1') + struct.pack('!H', 443))
        rep = s.recv(10)[1]
        if rep != 0x00:
            return False, None, 'REP=0x%02x' % rep
        return True, (time.perf_counter() - t0) * 1000, None
    except (OSError, IndexError) as e:
        return False, None, 'handshake:%s' % e
    finally:
        s.close()
Enter fullscreen mode Exit fullscreen mode

The timing wraps the entire exchange, not just connect() — that is what makes it a metric about the proxy rather than the network. And the structured error string matters: when half the pool fails at once, tcp: versus REP=0x05 separates a routing incident from a credentials incident.

To verify the exit IP, reuse the socket after the handshake: send GET / HTTP/1.1 with Host: api.ipify.org and read the body. A stable exit IP is a feature you pay for; a changing one is either a documented rotating product or a misconfiguration.

Thresholds worth alerting on

Absolute latency means little without your route, so set thresholds against a rolling per-endpoint baseline:

Signal Condition Action
Latency drift p95 > 2× 7-day baseline Warn — usually congestion
Success rate < 95% over last 20 runs Quarantine the endpoint
Consecutive failures 3 in a row Evict from the active set
Exit IP change Any change outside a maintenance window Warn, verify it is intended
Throughput < 50% of baseline for 3 runs Demote; keep alive but deprioritize

The key word is quarantine, not delete. Keep a failing endpoint in a slow retry lane so it can re-earn its place — endpoints that fail during a maintenance window come back; endpoints that fail for three days do not.

Common mistakes

1. Checking the pool average instead of per endpoint. A pool at 90% success looks healthy until you notice all 10% of failures are the same three endpoints serving your most important account.

2. Only testing on failure. A check that runs when the pipeline breaks is a debugger, not a monitor. Run it on a schedule independent of traffic.

3. Treating one failure as death. Transient packet loss is real, so require a few consecutive failures before evicting.

4. Ignoring time of day. Your provider's peak hours are not yours, so compare like with like.

5. Forgetting the identity layer. Latency and success rate say nothing about whether the exit is still in the country you need. Check exit IP, region, and ASN together.

6. One aggressive probe. A tight loop looks like an attack and gets your IP rate-limited. Space your probes and rotate your sample.

FAQ

How often should I probe each endpoint?
A rolling sample every 2-5 minutes is plenty for a pool in the dozens. Probing everything every 30 seconds buys nothing and looks abusive.

What success rate should I target?
For a static pool, 95% over a 20-run window is a reasonable floor. For rotating pools expect lower and push the burden onto bounded per-request retries.

Does a failed UDP check mean the proxy is broken?
Usually not. Most SOCKS5 and HTTP proxy products do not forward UDP at all, so for HTTP or TCP workloads a UDP failure is expected.

How do I know a high-latency endpoint is actually bad?
Measure throughput, not just handshake time. Some endpoints negotiate fast and then collapse on bulk transfer; a fixed-size transfer test on a small slice of the pool surfaces them.

Where to go next

The signals above match what our public checking tools expose — a reference to compare your script against:

Measure first, then buy. A pool whose health you can see beats a slightly cheaper pool you have to guess about.

Top comments (0)