Skip to content

Test CI: SOCKS5 proxy support#1

Open
usiegj00 wants to merge 4 commits intomasterfrom
add-socks5-proxy-support
Open

Test CI: SOCKS5 proxy support#1
usiegj00 wants to merge 4 commits intomasterfrom
add-socks5-proxy-support

Conversation

@usiegj00
Copy link
Copy Markdown

CI validation run

Adds native SOCKS5 proxy support (RFC 1928, RFC 1929) via new socket classes.

## New Files

| File | Purpose |
|------|---------|
| `lib/excon/socks5.rb` | Shared SOCKS5 protocol module |
| `lib/excon/socks5_socket.rb` | HTTP connections through SOCKS5 |
| `lib/excon/socks5_ssl_socket.rb` | HTTPS connections through SOCKS5 |

## Usage

```ruby
# Basic SOCKS5 proxy
Excon.get('http://example.com', socks5_proxy: 'localhost:1080')

# With authentication
Excon.get('https://example.com', socks5_proxy: 'user:pass@proxy:1080')

# URL format also supported
Excon.get('https://example.com', socks5_proxy: 'socks5://proxy:1080')
```

## Features

- RFC 1928 compliant SOCKS5 implementation
- RFC 1929 username/password authentication
- Remote DNS resolution (proxy resolves hostnames)
- Full SSL/TLS support for HTTPS targets
- Timeout support during SOCKS5 handshake
- Hostname length validation (max 255 bytes per RFC)

## Why This Is Needed

SOCKS5 proxies are commonly used to:
- Access Kubernetes clusters through bastion hosts
- Route traffic through SSH tunnels (ssh -D)
- Use VPN services like Tailscale that expose SOCKS5 proxies
- Access resources behind firewalls

Unlike HTTP proxies (which Excon already supports), SOCKS5 operates at
the TCP layer and can tunnel any protocol without understanding it.
Replace custom TCP connect and duplicated SSL setup with a proxy-swap
pattern: temporarily inject the SOCKS5 proxy as @DaTa[:proxy] so
Socket#connect handles the TCP connection (inheriting DNS resolution,
nonblock, retry, keepalive, reuseaddr, remote_ip tracking), then clear
:proxy and run the SOCKS5 handshake on the raw socket.

Key changes:
- SOCKS5SSLSocket now inherits SSLSocket instead of Socket, eliminating
  ~100 lines of duplicated SSL context/handshake code
- Remove connect_to_proxy and connect_nonblock_to_proxy from SOCKS5
  module (base class handles TCP connect)
- Register :socks5_proxy in VALID_CONNECTION_KEYS
- Add 25 RSpec tests: parsing, hierarchy, HTTP/HTTPS e2e through a
  fake SOCKS5 server, auth, error cases, and edge cases
Excon::Error::Socket#initialize expects an exception object (calls
.message and .backtrace), not a bare string. Wrap error messages in
Exception.new() to match the pattern used throughout the codebase.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant