A high-performance proxy that can: (1) expose an HTTP proxy that forwards via an upstream SOCKS5, (2) expose a SOCKS5 server that forwards via an upstream SOCKS5, and (3) optionally run both listeners at the same time on different ports.
sthp can run as an HTTP proxy on top of a SOCKS5 upstream, a SOCKS5→SOCKS5 forwarder, or both concurrently (HTTP+SOCKS).
It uses hyper library HTTP proxy example and adds functionality to connect via Socks5
Follow these instructions to compile
- Ensure you have current version of
cargoand Rust installed - Clone the project
$ git clone https://github.com/KaranGauswami/socks-to-http-proxy.git && cd socks-to-http-proxy - Build the project
$ cargo build --release - Once complete, the binary will be located at
target/release/sthp
sthp -p 8080 -s 127.0.0.1:1080This will create proxy server on 8080 and use localhost:1080 as a Socks5 Proxy
See "Advanced Usage Examples" below for authentication and domain whitelist configurations.
Run HTTP and SOCKS5 listeners at the same time (different ports):
sthp --http-port 8080 --socks-port 1081 -s 127.0.0.1:1080
# HTTP client
http_proxy=http://127.0.0.1:8080 curl http://example.com/
# SOCKS client (server resolves domain)
curl --socks5-hostname 127.0.0.1:1081 http://example.com/Optional inbound SOCKS auth (for the local SOCKS server):
sthp --http-port 8080 --socks-port 1081 -s 127.0.0.1:1080 --socks-in-auth user:pass
curl --socks5-hostname --socks5-user user --socks5-pass pass 127.0.0.1:1081 http://example.com/Expose only a local SOCKS5 server that forwards via upstream SOCKS5:
sthp --mode socks -p 1081 -s 127.0.0.1:1080 [--socks-in-auth user:pass]Note (SOCKS inbound, security):
- Handshake reads enforce a 10s per-step timeout to mitigate slowloris attacks
- The SOCKS request reserved field (RSV) must be 0x00; non-zero RSV is rejected with a general failure (REP=0x01)
- Require HTTP proxy auth and allow only example.com (apex + subdomains):
sthp -p 8080 -s 127.0.0.1:1080 \
--http-basic user:pass --no-httpauth=0 \
--allowed-domains .example.com- Allow multiple domains (exact apex and subdomains):
sthp -p 8080 -s 127.0.0.1:1080 \
--http-basic user:pass --no-httpauth=0 \
--allowed-domains example.com,*.test.org- Higher throughput (allow HTTP/1.1 keep-alive). Use with monitoring:
sthp -p 8080 -s 127.0.0.1:1080 --force-close=false- Limit per-IP connections (e.g., 300):
sthp -p 8080 -s 127.0.0.1:1080 --conn-per-ip 300- Auth + whitelist + per-IP limit:
sthp -p 8080 -s 127.0.0.1:1080 \
--http-basic user:pass --no-httpauth=0 \
--allowed-domains .example.com \
--conn-per-ip 300- Keep-alive + per-IP cap (throughput with guardrails):
sthp -p 8080 -s 127.0.0.1:1080 --force-close=false --conn-per-ip 300- High-throughput with auth + whitelist + per-IP cap (keep-alive):
sthp -p 8080 -s 127.0.0.1:1080 \
--force-close=false \
--http-basic user:pass --no-httpauth=0 \
--allowed-domains .example.com \
--conn-per-ip 300There are a few options for using sthp.
Usage: sthp [OPTIONS]
Options:
-p, --port <PORT> Port where HTTP proxy should listen [default: 8080]
--listen-ip <LISTEN_IP> [default: 0.0.0.0]
-u, --username <USERNAME> Socks5 username
-P, --password <PASSWORD> Socks5/vendor password (-P): SOAX=package_key; Connpnt=vendor password
--http-basic <USER:PASSWD> HTTP Basic Auth
--mode <http|socks> Listen mode [default: http]
--http-port <PORT> HTTP listen port (overrides -p/--port)
--socks-port <PORT> Additional SOCKS5 listener port (enables dual listeners)
--no-httpauth <1/0> Ignore HTTP Basic Auth [default: 1]
-s, --socks-address <SOCKS_ADDRESS> Socks5 proxy address [default: 127.0.0.1:1080]
--socks-in-auth <USER:PASSWD> Inbound SOCKS5 auth for local SOCKS server
--allowed-domains <ALLOWED_DOMAINS> Comma-separated list of allowed domains (supports exact, *.domain, .domain, or *)
--idle-timeout <IDLE_TIMEOUT> Idle timeout in seconds for CONNECT tunnels and regular HTTP requests [default: 540]
--force-close <FORCE_CLOSE> Force 'Connection: close' on forwarded HTTP requests [default: true]
Set to false to allow HTTP/1.1 keep-alive for higher throughput
--conn-per-ip <CONN_PER_IP> Maximum connections per client IP [default: 500]
--stats-dir <STATS_DIR> Directory to persist traffic stats files (per-port). Default: current dir
--stats-interval <SECONDS> Interval seconds to log and persist traffic stats [default: 60]
-h, --help Print help information
-V, --version Print version information
--soax-country <COUNTRY>: SOAX target country (ISO 3166-1 alpha-2 code or full name), e.g., "US" or "United States".--soax-region <REGION>: SOAX target region/state/province within the country, e.g., "California" or "CA".--soax-city <CITY>: SOAX target city name, e.g., "Los Angeles".--soax-isp <ISP>: SOAX target ISP/carrier name, e.g., "AT&T".
--connpnt-enable 1to enable this vendor mode--connpnt-user <BASE_USER>: base username provided by vendor (e.g.,ku2605kbkxid)-P, --password <PASSWORD>: vendor password (e.g.,kjjacvbu7huwd)--connpnt-country <CC>: country code (e.g.,US,BR)--connpnt-keeptime <MINUTES>: session keeptime in minutes (0 = unlimited)--connpnt-project <NAME>: optional project name; ipstr becomesNAME$<random>to isolate per-project IP traversal--connpnt-entry-hosts <H1,H2,...>: entry hosts list; default depends on country:US→pv3.connpnt134.com,pv2.connpnt134.com- others →
pv5.connpnt134.com,pv4.connpnt134.com
--connpnt-socks-port <PORT>: SOCKS port (default: 9135)
Example:
# Start HTTP proxy that uses Connpnt SOCKS vendor under the hood
sthp \
-p 8080 \
--connpnt-enable 1 \
--connpnt-user ku2605kbkxid \
--connpnt-country BR \
--connpnt-keeptime 0 \
-P kjjacvbu7huwd
# Client traffic via local HTTP proxy on 8080
curl -x http://127.0.0.1:8080 https://ipinfo.ioNotes:
- Username is constructed per connection as
BASE-<ipstr>-<keeptime>-<country>-N.<ipstr>is randomized each connection; if--connpnt-project NAMEis set, it becomesNAME$<random>to isolate projects.- When switching
country, a new<ipstr>is generated automatically to ensure the change takes effect.
- One of the configured entry hosts is pseudo-randomly selected per connection; each entry host maps to an independent IP pool.
-
Default for production: keep
--force-close=true(historical default; now configurable). This forcesConnection: closeon forwarded HTTP requests and helps prevent lingering sockets/CLOSE_WAIT buildup. It slightly reduces throughput for large non-CONNECT HTTP transfers but yields more predictable resource usage. -
When to consider
--force-close=false: in trusted, well-behaved upstream environments where you want higher throughput via HTTP/1.1 keep-alive. Monitor connection counts and memory closely; revert totrueif you observe resource pressure. -
Pair with
--conn-per-ipto bound per-client impact during spikes; start with 500 and tune based on upstream capacity and concurrency patterns. -
CONNECT (HTTPS tunneling) is unaffected by
--force-closeand will remain stable with the existing idle timeout. -
Keep the idle timeout (
--idle-timeout, default 540s) aligned with your operational requirements. For CONNECT tunnels it acts as an idle timer (resets on traffic; closes after a quiet window). For normal HTTP (non-CONNECT) requests it acts as a per-request timeout: exceeding it aborts the upstream connection and returns 504 Gateway Timeout. Lower the value to reclaim idle/stuck connections more aggressively in resource-constrained environments.
- Production (recommended):
sthp -p 8080 -s 127.0.0.1:1080 --force-close=true- Higher throughput experiment (only if you can tolerate longer-lived HTTP/1.1 connections):
sthp -p 8080 -s 127.0.0.1:1080 --force-close=false- Configure credentials with
--http-basic <USER:PASSWD>. - Control whether authentication is enforced with
--no-httpauth <1/0>(default:1, meaning HTTP auth is ignored/disabled). Set to0to require authentication. - Behavior when authentication is required (
--no-httpauth=0):- Missing or incorrect
Proxy-Authorizationheader results in407 Proxy Authentication Requiredand includesProxy-Authenticate: Basic realm="proxy".
- Missing or incorrect
- Require authentication:
sthp -p 8080 -s 127.0.0.1:1080 --http-basic user:pass --no-httpauth=0- Client usage with curl:
curl -x http://127.0.0.1:8080 --proxy-user user:pass http://example.com/
# or explicitly set header
curl -x http://127.0.0.1:8080 -H "Proxy-Authorization: Basic $(printf 'user:pass' | base64)" http://example.com/Use --allowed-domains with a comma-separated list. Supported patterns:
example.com— exact match of the apex only*.example.com— any subdomain of example.com (a.example.com, a.b.example.com), not the apex.example.com— apex and any subdomain (example.com, a.example.com)*— allow all domains
Note: The whitelist is applied to both normal HTTP requests and CONNECT tunnels. Matching is based on the request Host only.
# Allow only example.com and its subdomains
sthp -p 8080 -s 127.0.0.1:1080 --allowed-domains .example.com
# Allow multiple domains
sthp -p 8080 -s 127.0.0.1:1080 --allowed-domains example.com,*.test.org
# Allow all (not recommended unless you trust the environment)
sthp -p 8080 -s 127.0.0.1:1080 --allowed-domains "*"--force-close(default: true): ForcesConnection: closeon forwarded HTTP (non-CONNECT) requests. This has been the historical default; the flag simply makes it configurable. It favors stability and resource predictability over maximum throughput.--idle-timeout(default: 540s): Applies to both CONNECT tunnels and normal HTTP requests.- CONNECT: idle timer resets on traffic; when no bytes flow in either direction for the timeout window, the tunnel is closed.
- HTTP (non-CONNECT): acts as a per-request timeout; when exceeded, the upstream connection is aborted and a 504 Gateway Timeout is returned.
--conn-per-ip(default: 500): Enforces a per-client IP cap. New connections beyond the cap are immediately closed on accept.
Recommendations:
- Keep
--force-close=truein production unless you have measured benefits and sufficient headroom to allow keep-alive. - Tune
--idle-timeoutaccording to workload (shorter for highly ephemeral tunnels, longer for long-lived ones). - Adjust
--conn-per-ipto reflect your multi-tenant policy and upstream capacity.
- RAII buffer management: pooled buffers are automatically returned on scope exit, including error and early-return paths. This reduces memory churn and avoids leaks when many tunnels are opened/closed.
- Per-IP connection limiting: enforcement uses an atomic check-and-increment under a single lock to prevent races that could temporarily exceed the configured cap.
-
Per-port cumulative byte counters (RX from client, TX to client)
-
Persistence: one file per listening port:
traffic_stats_{port}.txtin--stats-dir(default: current directory) -
Periodic logging and persistence every
--stats-intervalseconds (default: 60) -
Management endpoints (apply the same HTTP auth policy as the proxy itself):
GET /stats→{"port":<u16>,"rx":<u64>,"tx":<u64>}POST /stats/reset→{"ok":true}and immediately persists zeros
-
In dual-listener mode, these endpoints are available only on the HTTP listener.
Examples:
# If authentication is required (recommended), include Proxy-Authorization
curl -s http://127.0.0.1:8080/stats \
-H "Proxy-Authorization: Basic $(printf 'user:pass' | base64)"
# Reset counters and persist immediately
curl -s -X POST http://127.0.0.1:8080/stats/reset \
-H "Proxy-Authorization: Basic $(printf 'user:pass' | base64)"
# Start with custom stats directory and 30s interval
sthp -p 8080 -s 127.0.0.1:1080 --stats-dir ./stats --stats-interval 30- Run all tests:
cargo test - End-to-end (E2E) coverage:
- Dual listeners running concurrently (HTTP + SOCKS): verifies real accept loops on two ports and concurrent client traffic
- Test:
dual_listeners_end_to_end
- Test:
- Inbound SOCKS5 authentication (RFC 1929) on the local SOCKS server:
- Test:
socks_inbound_auth_end_to_end
- Test:
- Dual listeners running concurrently (HTTP + SOCKS): verifies real accept loops on two ports and concurrent client traffic
- Notes:
- Tests bind to
127.0.0.1using ephemeral ports and do not reach the external network - They simulate an upstream SOCKS5 server in-process and validate a full HTTP round-trip (
200 OK) - To run a single test:
cargo test dual_listeners_end_to_end cargo test socks_inbound_auth_end_to_end
- Tests bind to
sthp uses structured logging with different levels to help you monitor and debug the proxy. By default, it runs at warn level for optimal performance in production environments.
- error: Only critical errors that may cause service interruption
- warn: Warnings including connection errors, timeouts, and important status changes (default)
- info: General information including service startup, high connection counts, and large file transfers
- debug: Detailed debugging information including all connections and data transfers
Default (warn level) - Recommended for production:
sthp -p 8080 -s 127.0.0.1:1080Enable debug logging for troubleshooting:
RUST_LOG=sthp=debug sthp -p 8080 -s 127.0.0.1:1080Show only errors:
RUST_LOG=sthp=error sthp -p 8080 -s 127.0.0.1:1080Enable info level logging:
RUST_LOG=sthp=info sthp -p 8080 -s 127.0.0.1:1080Advanced logging configuration:
# Enable debug for sthp but warn for other crates
RUST_LOG=sthp=debug,warn sthp -p 8080 -s 127.0.0.1:1080
# Log to file
RUST_LOG=sthp=info sthp -p 8080 -s 127.0.0.1:1080 > proxy.log 2>&1- warn/error: Minimal performance impact, recommended for production
- info: Slight performance impact, good for monitoring
- debug: Noticeable performance impact, use only for troubleshooting
Error Level:
- Service startup failures
- Critical connection limits reached
- Severe system errors
Warn Level (Default):
- Connection errors and timeouts
- SOCKS5 authentication failures
- Domain access violations
- I/O errors during data transfer
Info Level:
- Service startup information
- Connection count warnings
- Large file transfer completions (>10MB)
- System status updates
Debug Level:
- Individual connection details
- Request/response timing
- Detailed error traces
- Connection lifecycle events
- Getting 407 Proxy Authentication Required:
- If you configured credentials, ensure
--no-httpauth=0and the client sendsProxy-Authorization: Basic <base64(user:pass)>. - With curl:
curl -x http://127.0.0.1:8080 --proxy-user user:pass http://example.com/
- If you configured credentials, ensure
- Request blocked or 403 due to domain whitelist:
- Verify
--allowed-domainspatterns. Use.example.comfor apex+subdomains,*.example.comfor subdomains only,example.comfor apex only, or*to allow all. - Matching is based on the HTTP Host (for CONNECT, the target host).
- Verify
- Connection closes immediately on accept:
- Per-IP limit reached. Increase
--conn-per-ipor reduce client concurrency. See warn logs for IP counts.
- Per-IP limit reached. Increase
- Long-lived or stuck connections consuming resources:
- Prefer
--force-close=true(default) for non-CONNECT requests. Tune--idle-timeout(applies to both CONNECT tunnels and normal HTTP requests).
- Prefer
- Bind error / port already in use:
- Choose a different port with
-p <PORT>or adjust--listen-ip.
- Choose a different port with
- Need more details to diagnose:
- Temporarily increase log verbosity:
- Unix-like:
RUST_LOG=sthp=debug sthp -p 8080 -s 127.0.0.1:1080 - Windows PowerShell:
$env:RUST_LOG="sthp=debug"; sthp -p 8080 -s 127.0.0.1:1080
- Unix-like:
- Lower overhead alternative:
sthp=info - Save to file:
RUST_LOG=sthp=info sthp -p 8080 -s 127.0.0.1:1080 > proxy.log 2>&1
- Temporarily increase log verbosity: