A PAC-aware HTTP/HTTPS proxy with HTTP and SOCKS5 upstream support.
pacproxy is a lightweight local HTTP/HTTPS proxy that applies PAC (Proxy Auto-Config) rules to dynamically route traffic either directly or through upstream HTTP / SOCKS5 proxies.
It is designed for tools that only support static HTTP_PROXY / HTTPS_PROXY environment variables but do not understand PAC files (e.g., AI CLI tools, SDKs, WebFetch implementations).
- PAC Support: Automatically fetches and parses PAC files
- Multiple Upstream Types: Supports DIRECT, HTTP, SOCKS5 proxies
- HTTP/HTTPS Support: Handles both HTTP requests and HTTPS CONNECT tunnels
- Concurrent Connections: Efficiently handles multiple simultaneous connections
- Graceful Shutdown: Clean shutdown on interrupt signals
- Configurable Logging: Multiple log levels (debug, info, warn, error)
go install github.com/mengbo/pacproxy@latestgit clone https://github.com/mengbo/pacproxy.git
cd pacproxy
go build -o pacproxy .make build # Build binary
make test # Run tests
make clean # Clean build artifacts# Start pacproxy with default settings
# Default: listens on 127.0.0.1:1080, uses http://clash-server:9090/ui/proxy.pac
./pacproxy
# Or specify custom PAC URL and listen address
./pacproxy --pac-url http://your-pac-server/proxy.pac --listen 127.0.0.1:8080Flags:
-h, --help help for pacproxy
-l, --listen string Listen address (default "127.0.0.1:1080")
--log-level string Log level (debug, info, warn, error) (default "info")
-p, --pac-url string PAC file URL (default "http://clash-server:9090/ui/proxy.pac")
-v, --version version for pacproxy
Once pacproxy is running, configure your tools to use it:
# Set environment variables
export HTTP_PROXY=http://127.0.0.1:1080
export HTTPS_PROXY=http://127.0.0.1:1080
export ALL_PROXY=http://127.0.0.1:1080# Using environment variable
export HTTP_PROXY=http://127.0.0.1:1080
curl https://example.com
# Using command-line option
curl -x http://127.0.0.1:1080 https://example.comwget -e use_proxy=yes -e http_proxy=http://127.0.0.1:1080 https://example.comimport os
os.environ['HTTP_PROXY'] = 'http://127.0.0.1:1080'
os.environ['HTTPS_PROXY'] = 'http://127.0.0.1:1080'
import requests
response = requests.get('https://example.com')export HTTP_PROXY=http://127.0.0.1:1080
export HTTPS_PROXY=http://127.0.0.1:1080
npm installgit config --global http.proxy http://127.0.0.1:1080
git config --global https.proxy http://127.0.0.1:1080# Build with proxy
docker build --build-arg HTTP_PROXY=http://127.0.0.1:1080 .
# Or configure Docker daemon
# ~/.docker/config.json
{
"proxies": {
"default": {
"httpProxy": "http://127.0.0.1:1080",
"httpsProxy": "http://127.0.0.1:1080"
}
}
}- Client Request: Client sends HTTP request or HTTPS CONNECT to pacproxy
- PAC Evaluation: pacproxy evaluates the URL against the PAC file rules
- Routing Decision: Based on PAC result (DIRECT, PROXY, SOCKS5), selects appropriate upstream
- Connection: Establishes connection to target (directly or via upstream proxy)
- Data Transfer: Proxies data between client and target
┌─────────────┐ HTTP/HTTPS ┌─────────────┐
│ Client │ ──────────────────▶ │ pacproxy │
│ (curl/git) │ │ (127.0.0.1)│
└─────────────┘ └──────┬──────┘
│
┌──────────────────────┼──────────────────────┐
│ │ │
▼ ▼ ▼
┌─────────┐ ┌──────────┐ ┌──────────┐
│ DIRECT │ │ HTTP │ │ SOCKS5 │
│ │ │ Proxy │ │ Proxy │
└─────────┘ └──────────┘ └──────────┘
pacproxy/
├── cmd/ # CLI implementation
│ └── root.go
├── internal/
│ └── config/ # Configuration
│ ├── config.go
│ └── config_test.go
├── pac/ # PAC file handling
│ ├── engine.go # JavaScript execution
│ ├── fetcher.go # PAC file fetching
│ ├── parser.go # Proxy directive parsing
│ ├── engine_test.go
│ └── parser_test.go
├── proxy/ # HTTP proxy server
│ ├── handler.go # Request handlers
│ ├── router.go # PAC-based routing
│ └── server.go # HTTP server
├── upstream/ # Upstream connectors
│ ├── connector.go # Connector interface
│ ├── direct.go # Direct connection
│ ├── http.go # HTTP proxy connector
│ └── socks5.go # SOCKS5 connector
├── main.go # Entry point
├── go.mod # Go module
├── go.sum # Dependencies
├── Makefile # Build automation
├── LICENSE # MIT License
└── README.md # This file
go test ./...
go test -v ./... # Verbose output
go test -race ./... # Race condition detection# Build for current platform
go build -o pacproxy .
# Build for all platforms
make build-all
# Cross-compile examples
GOOS=linux GOARCH=amd64 go build -o pacproxy-linux-amd64 .
GOOS=darwin GOARCH=arm64 go build -o pacproxy-darwin-arm64 .
GOOS=windows GOARCH=amd64 go build -o pacproxy-windows-amd64.exe .- Go 1.21 or later
- PAC file accessible via HTTP/HTTPS
- Upstream proxy (if PAC rules specify proxy usage)
- PAC file must be accessible via HTTP/HTTPS URL
- JavaScript PAC functions are executed in a sandbox with limited built-in functions
- No authentication support for PAC file fetching
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- goja - JavaScript engine for Go
- cobra - CLI framework
- golang.org/x/net/proxy - SOCKS5 support
- genpac - PAC file generator
- SwitchyOmega - Browser extension for proxy switching