A minimal, testable Go tool for running network diagnostics through proxies
Built with AI assistance — This project was developed with contributions from:
- GitHub Copilot and OpenCode (code development and implementation)
- GPT 5.5 and Gemini Pro (architecture review, especially pull request code review)
The Problem: You're behind a corporate proxy or using a VPN, and things break mysteriously:
- Sites don't load (proxy misconfiguration?)
- Your IP leaks even through a "private" proxy
- You can't tell if the problem is your proxy, DNS, or the site itself
The Solution: ProxyDoctor is a lightweight diagnostic tool that:
- Runs network checks through any proxy (HTTP, HTTPS, SOCKS4, SOCKS5)
- Compares results between direct connection and proxied connection
- Identifies which specific layer is failing (DNS? TLS? IP leak?)
- Gives you actionable insights in seconds
- Then lets you use that proxy: expose the tested proxy as a local forward proxy and browse, curl, wget or download through it — no more copy-pasting proxy settings into every app
Perfect for:
- Developers debugging proxy issues
- DevOps engineers troubleshooting VPN connectivity
- Security teams validating proxy implementations
- Privacy users who want to route their whole browser through a tested SOCKS/HTTP proxy
- Anyone tired of guessing what's broken
ProxyDoctor is a CLI-first tool to:
- Run network checks (DNS resolution, IP detection, TLS certificate validation, port connectivity)
- Compare results between direct connections and proxy-routed connections
- Route tracing with country flags in the GUI and country names in CLI output
- Identify connectivity issues and proxy misconfigurations
- Expose the proxy you just tested as a local forward proxy, from the CLI or the web GUI
This version was reviewed and bug-fixed with OpenCode using GPT 5.5 before delivery.
v0.4.0 (Beta)
- ✅ Local forward proxy plugin (
local_proxy) — expose the proxy you just tested on127.0.0.1:8081and browse/curl/wget/download through it. Credentials never leave your machine - ✅ Local proxy in the web GUI — one-click start/stop, copy-ready
curl/wgetcommands and browser proxy address - ✅ Install in one command —
go install, Homebrew cask, and cross-compiled release binaries (GoReleaser) - ✅ Hermetic integration tests for every adapter (HTTP, HTTPS, SOCKS4, SOCKS5, auth, TLS-through-proxy) via
internal/testproxyfixtures — offline and CI-friendly - ✅ Fixed SOCKS5 authentication being silently dropped; fixed CONNECT-over-proxy response handling that stalled port checks
- ✅ Core engine with check registry and dependency DAG
- ✅ CLI with
diagnoseandlist-checkscommands - ✅ HTTP/HTTPS/SOCKS4/SOCKS5 proxy support (full protocol implementation, SOCKS4a domain support, SOCKS5 auth per RFC 1929)
- ✅ HTTP server wired to the core engine, with a web GUI at
/and/api/checks,/api/diagnose,/api/local-proxy/*JSON endpoints - ✅ 6 built-in checks: public_ip, dns_resolve, tls_certificate, port_connectivity, route_trace, ipv6_leak
- ✅ Plugin system (CheckPlugin, ExportPlugin, MiddlewarePlugin interfaces)
- ✅ MCP server plugin (Model Context Protocol, exposes diagnose/compare tools on port
:9090) - 🧭 Focused backlog for optional checks such as DNS leak, WebRTC leak, geolocation and IP reputation
- Go >= 1.25
- Git
Install in one command — no cloning required.
# Option 1 — go install (installs the binary as `cli`; add an alias if you prefer `proxydoctor`)
go install github.com/francomano/proxydoctor/cmd/cli@latest
alias proxydoctor="$(go env GOPATH)/bin/cli" # optional
# Option 2 — Homebrew (cask auto-published in this repo on each release, binary named `proxydoctor`)
brew install francomano/proxydoctor/proxydoctor
# Option 3 — download a release binary (named `proxydoctor`)
# Grab the latest archive from https://github.com/francomano/ProxyDoctor/releasesBoth the proxydoctor (CLI) and proxydoctor-server (web GUI) binaries are
cross-compiled for Linux, macOS, Windows, and FreeBSD on every release.
git clone https://github.com/francomano/proxydoctor
cd ProxyDoctor
./setup.shThis script will:
- Verify Go installation
- Download and verify dependencies
- Run all tests
- Build CLI and server binaries
# Start the server
./run.sh server
# Open in browser
open http://localhost:8080Fill in the URL (and optionally a proxy + proxy type), hit "Run diagnosis" — it runs the same core/engine.DiagnosisOrchestrator the CLI uses and renders the results as cards.
Once the proxy works, click Start local proxy and point your browser, curl or wget at it. The GUI shows the ready-to-copy commands and the proxy address.
Three JSON endpoints back the GUI, and can be called directly:
# List available checks
curl http://localhost:8080/api/checks
# Run a diagnosis
curl -X POST http://localhost:8080/api/diagnose \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com","proxy":"socks5://77.245.76.107:1080","proxy_type":"socks5"}'
# Local forward proxy lifecycle
curl http://localhost:8080/api/local-proxy/status
curl -X POST http://localhost:8080/api/local-proxy/start \
-H "Content-Type: application/json" -d '{"proxy":"socks5://77.245.76.107:1080","proxy_type":"socks5"}'
curl -X POST http://localhost:8080/api/local-proxy/stop# Get help
./run.sh cli --help
# List available checks
./run.sh cli list-checks
# Run diagnostics (direct connection)
./run.sh cli diagnose --url https://example.com
# Run diagnostics with a custom timeout
./run.sh cli diagnose --url https://example.com --timeout 10s
# Run only selected checks
./run.sh cli diagnose --url https://example.com --checks public_ip,dns_resolve
# Run diagnostics through an HTTP proxy
./run.sh cli diagnose --url https://example.com --proxy http://127.0.0.1:3128 --proxy-type http
# Run diagnostics through a SOCKS5 proxy (with scheme)
./run.sh cli diagnose --url https://example.com --proxy socks5://127.0.0.1:1080 --proxy-type socks5
# Run diagnostics through a SOCKS5 proxy (bare host:port + type)
./run.sh cli diagnose --url https://example.com --proxy 127.0.0.1:1080 --proxy-type socks5
# Compare direct and proxied diagnosis results
./run.sh cli diagnose --url https://example.com --proxy socks5://127.0.0.1:1080 --compare
# Export results as JSON
./run.sh cli diagnose --url https://example.com --export json --output report.json# Start HTTP server on :8080
./run.sh server# Run all tests
./run.sh test
# Or directly
go test -v ./...ProxyDoctor has a plugin system for extending functionality. Plugins can add new checks or long-running services.
Available plugins are loaded via the --plugins flag on ./run.sh cli.
| Plugin | ID | Type | Description |
|---|---|---|---|
| Route Trace | route_trace |
check | Traces network hops and annotates public hops with country information |
| MCP Server | mcp_server |
standalone | Exposes diagnose/compare/list_checks tools via the Model Context Protocol on :9090 |
| Local Proxy | local_proxy |
standalone | Exposes the tested proxy as a local forward proxy on 127.0.0.1:8081 for browsing and downloads |
route_trace — registers a new check you can use with diagnose:
./run.sh cli diagnose --url https://example.com --plugins route_tracemcp_server — starts a standalone JSON-RPC 2.0 server:
./run.sh cli --plugins mcp_serverOnce started, send requests to POST http://localhost:9090/mcp:
{"jsonrpc":"2.0","id":1,"method":"tools/list"}{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"diagnose","arguments":{"url":"https://example.com"}}}{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"compare","arguments":{"url":"https://example.com","proxy":"socks5://77.245.76.107:1080"}}}local_proxy — exposes the proxy you tested as a local forward proxy, so your browser, curl and wget route through it:
./run.sh cli --plugins local_proxy --proxy socks5://77.245.76.107:1080 --proxy-type socks5You will see the local address and the ready-to-copy commands:
🚀 Local forward proxy ready — route your traffic through it:
Browser → set HTTP/HTTPS proxy to http://127.0.0.1:8081
curl → curl -x http://127.0.0.1:8081 https://example.com
wget → wget -e use_proxy=yes -e http_proxy=http://127.0.0.1:8081 https://example.com
The exact same flow is available in the web GUI (./run.sh server → Start local proxy), with nothing to install. The upstream proxy credentials stay on your machine.
ProxyDoctor's MCP server is compatible with OpenCode and any MCP-compatible AI coding assistant. The opencode.jsonc file registers it as a remote MCP server:
Once the MCP server is running, the assistant can use diagnose, compare, and list_checks as native tools — no curl needed.
./run.sh cli --plugins route_trace,mcp_serverimport (
"github.com/francomano/proxydoctor/core/engine"
"github.com/francomano/proxydoctor/core/plugin"
)
type MyPlugin struct{}
func (p *MyPlugin) ID() string { return "my-plugin" }
func (p *MyPlugin) Name() string { return "My Plugin" }
func (p *MyPlugin) Version() string { return "0.1.0" }
func (p *MyPlugin) Description() string { return "Adds custom checks" }
func (p *MyPlugin) Init(_ *plugin.Context) error { return nil }
func (p *MyPlugin) Shutdown() error { return nil }
func (p *MyPlugin) RegisterChecks(r *engine.CheckRegistry) error {
r.Register(myNewCheck())
return nil
}
// Register the plugin in core/plugins/registry.goPlugin interfaces: CheckPlugin, ExportPlugin, MiddlewarePlugin.
docs/CODEBASE_GUIDE.mdexplains where to add checks, adapter behavior, CLI features and GUI/API behavior.docs/ISSUE_STARTING_POINTS.mdmaps each open roadmap issue to concrete codebase entry points.
ProxyDoctor/
├── setup.sh ← One-time setup (install deps, test, build)
├── run.sh ← Convenience launcher (cli, server, test)
├── .goreleaser.yaml ← Cross-compiled release binaries + Homebrew cask
├── cmd/
│ ├── cli/ ← CLI application (diagnose, list-checks, version)
│ └── server/ ← HTTP API server + web GUI (diagnose + local proxy)
├── core/
│ ├── engine/ ← Orchestration engine (tests included)
│ ├── check/ ← Result types and interfaces (tests included)
│ ├── checks/ ← Built-in diagnostic checks (public_ip, dns_resolve, tls_cert, port_scan, ipv6_leak)
│ ├── adapters/ ← Proxy implementations (Direct, HTTP, HTTPS, SOCKS4, SOCKS5) + dial helpers
│ ├── plugin/ ← Plugin system interfaces and lifecycle manager
│ ├── plugins/ ← Plugin implementations (route_trace, mcp_server, local_proxy)
│ └── utils/ ← Shared helpers (proxy URL parsing)
├── internal/testproxy/ ← Hermetic proxy fixtures for integration tests
├── go.mod, go.sum ← Go modules
├── README.md
├── ARCHITECTURE.md
├── CHANGELOG.md
├── NEXT_STEPS.md
└── VERSION
| Check | Category | Description |
|---|---|---|
public_ip |
network | Detects public IP address via ipify.org, icanhazip.com, ifconfig.me |
dns_resolve |
network | Resolves hostname to IP addresses through the current connection |
tls_certificate |
tls | Validates TLS certificate (issuer, expiry, cipher suite, TLS version) |
port_connectivity |
network | Tests TCP connectivity to ports 80, 443, 8080, 8443 |
ipv6_leak |
leak | Detects whether IPv6 traffic bypasses the configured proxy/tunnel and exposes the system's real public IPv6 address |
| Check | Category | Plugin ID | Description |
|---|---|---|---|
route_trace |
network | route_trace |
Traces network hops to the target and annotates public hops with country information |
The CLI and GUI accept proxy URLs in multiple formats:
| Format | Example | Notes |
|---|---|---|
scheme://host:port |
socks5://77.245.76.107:1080 |
Auto-detects type from scheme |
scheme://host:port |
socks4://77.245.76.107:1080 |
SOCKS4a domain support included |
scheme://host:port |
http://proxy.example:3128 |
HTTP and HTTPS (CONNECT) forward proxies |
host:port + type |
77.245.76.107:1080 + --proxy-type socks5 |
Requires explicit type |
host + type |
77.245.76.107 + --proxy-type http |
Uses default port (1080 for SOCKS, 8080 for HTTP) |
| With auth | socks5://user:pass@host:port |
Credentials extracted from URL |
Contributions are welcome! Please read our Contributing Guide for details on how to get started.
Please read our Code of Conduct before contributing.
- Optional DNS leak, WebRTC leak, geolocation, and IP reputation checks are tracked as future work in NEXT_STEPS.md.



{ "mcp": { "proxydoctor": { "type": "remote", "url": "http://localhost:9090/mcp", "enabled": true } } }