Skip to content

digital-shokunin/crabbyproxy

Repository files navigation

crabbyproxy 🦀

Named for Ferris, Rust's unofficial crab mascot.

Lightweight Rust SOCKS5 proxy that binds outgoing connections to a specific network interface via macOS IP_BOUND_IF, enabling domain-based split tunneling where IP-based routing falls short.

Built for WireGuard on macOS, where the Network Extension intercepts all packets before the routing table — making traditional split tunneling (AllowedIPs, route add) unreliable for domain-based exclusions.

Why?

When running a VPN for security testing, bug bounty, or general privacy, certain sites block or restrict traffic from known VPN/datacenter IP ranges (CAPTCHAs, bot checks, degraded service). For sites like YouTube or Reddit, anonymization isn't a priority — and it may actually be preferable to keep personal traffic off VPN IPs that are associated with security testing. crabbyproxy lets you selectively route specific domains through your home connection while keeping everything else tunneled.

How it works

crabbyproxy traffic flow

  1. Browser PAC file routes target domains to the local SOCKS5 proxy
  2. Proxy resolves DNS via DoH — bypasses VPN DNS, gets geo-correct CDN IPs
  3. Proxy binds outgoing sockets to the physical interface (IP_BOUND_IF)
  4. macOS honors the binding even with VPN active — traffic goes direct
  5. All other traffic goes through the VPN as normal

Features

  • Domain-based split tunneling — route by domain, not IP ranges
  • DNS-over-HTTPS — Cloudflare, Google, and Quad9 with automatic fallback
  • TTL-aware DNS cache — minimal DoH queries
  • Interface auto-detection — finds en0/en6/en1 automatically
  • Zero config WireGuard — no AllowedIPs changes, no PostUp/PostDown
  • PAC file HTTP server — serves proxy.pac over HTTP on port 1081 (Chrome compatible)
  • WireGuard watcher — detects when WireGuard becomes active, injects PAC into SCDynamicStore so Chrome picks it up automatically
  • LaunchAgent — starts at login, auto-restarts on crash
  • ~2MB binary — async Rust with tokio

Install

From source

git clone https://github.com/digital-shokunin/crabbyproxy.git
cd crabbyproxy
./install.sh

This builds the binary, installs it to ~/.local/bin/, sets up default configs, and starts the LaunchAgent.

Manual

cargo build --release
cp target/release/crabbyproxy ~/.local/bin/
mkdir -p ~/.config/crabbyproxy
cp doh.conf.default ~/.config/crabbyproxy/doh.conf
cp proxy.pac ~/.config/crabbyproxy/proxy.pac
cp com.digisho.crabbyproxy.plist ~/Library/LaunchAgents/
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.digisho.crabbyproxy.plist

Browser setup

Set http://127.0.0.1:1081/proxy.pac as the automatic proxy configuration URL in every browser:

  • Firefox: Settings > Network Settings > Automatic proxy configuration URL
  • Chrome/Safari: System Settings > Network > Wi-Fi > Details > Proxies > Automatic Proxy Configuration

When WireGuard is active, crabbyproxy automatically injects the PAC URL into the system network state (SCDynamicStore) so Chrome/Safari pick it up without any manual configuration.

Configuration

All settings live in ~/.config/crabbyproxy/config.toml:

[doh]
servers = [
    "https://1.1.1.1/dns-query",      # Cloudflare
    "https://8.8.8.8/dns-query",      # Google
    "https://9.9.9.9:5053/dns-query", # Quad9
]

[proxy]
socks_port = 1080
pac_port = 1081
domains = [
    "*.youtube.com",
    "youtube.com",
    "*.example.com",  # add your domains here
]

The PAC file is generated in memory from the domains list — no separate proxy.pac needed.

Restart after changes: launchctl kickstart -k gui/$(id -u)/com.digisho.crabbyproxy

Why not just use AllowedIPs?

WireGuard's AllowedIPs is IP-based, not domain-based. Services like YouTube use thousands of dynamic CDN IPs across dozens of subnets. Excluding them all creates hundreds of CIDR ranges that can break the tunnel. The macOS WireGuard app's Network Extension also intercepts packets before the routing table, making route add commands ineffective.

crabbyproxy operates at the application layer (browser proxy) instead of the network layer, sidestepping these limitations entirely.

Uninstall

launchctl bootout gui/$(id -u)/com.digisho.crabbyproxy
rm ~/.local/bin/crabbyproxy
rm ~/Library/LaunchAgents/com.digisho.crabbyproxy.plist
rm -rf ~/.config/crabbyproxy

License

MIT

About

Lightweight Rust SOCKS5 proxy that binds outgoing connections to a specific network interface (IP_BOUND_IF), enabling domain-based split tunneling where IP-based routing falls short (e.g., WireGuard on macOS).

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors