### Build Caddy from Source Source: https://github.com/caddyserver/forwardproxy/blob/master/README.md Instructions for building the Caddy binary from source, including installing Go and setting environment variables. ```bash go install github.com/caddyserver/forwardproxy/cmd/caddy@latest ``` -------------------------------- ### Fetch PAC File Example Source: https://context7.com/caddyserver/forwardproxy/llms.txt Demonstrates how to fetch the auto-generated PAC file from the configured endpoint. ```bash # Fetch the PAC file curl https://proxy.example.com/proxy.pac ``` -------------------------------- ### Build Caddy with forwardproxy Plugin Source: https://context7.com/caddyserver/forwardproxy/llms.txt Install xcaddy and build a Caddy binary that includes the forwardproxy plugin. Verify the module is registered using 'caddy list-modules'. ```bash # Install xcaddy go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest # Build caddy with forwardproxy xcaddy build --with github.com/caddyserver/forwardproxy # Verify the module is registered ./caddy list-modules | grep forward_proxy ``` -------------------------------- ### Probe Resistance Client Interaction Example Source: https://context7.com/caddyserver/forwardproxy/llms.txt Demonstrates the client interaction flow for probe resistance, including initial access and subsequent proxied requests. ```bash # 1. Client visits the secret domain to cache credentials in the browser curl -I https://proxy.example.com/ # → 200 OK (normal site, no proxy hint) curl -I https://my-hidden-proxy-9x7k.example.com/ # → 407 (browser caches creds) # 2. Now configure the OS/browser to use proxy.example.com:443 # Credentials are sent preemptively; all CONNECT tunnels work normally. # 3. Use the proxy to reach a target curl -x https://proxyuser:Sup3rS3cret!@proxy.example.com:443 \ https://www.example.com/ # → HTML content of www.example.com ``` -------------------------------- ### Caddyfile ACL Configuration Example Source: https://context7.com/caddyserver/forwardproxy/llms.txt Illustrates the equivalent Caddyfile syntax for defining ACL rules, including allow, deny, and the 'all' subject. ```caddyserver acl { allow *.caddyserver.com github.com golang.org deny 192.168.0.0/16 10.0.0.0/8 172.16.0.0/12 8.8.8.8 2001:4860::/32 allow all } ``` -------------------------------- ### Setting system-wide proxy for Go programs Source: https://context7.com/caddyserver/forwardproxy/llms.txt This example demonstrates how to set environment variables for HTTPS_PROXY and NO_PROXY to configure system-wide proxy settings. Go programs that use http.ProxyFromEnvironment will automatically respect these settings. ```bash export HTTPS_PROXY=https://user:pass@proxy.example.com:443 export NO_PROXY=localhost,127.0.0.1 go run main.go ``` -------------------------------- ### Upstream Chaining Test Handler Configuration Source: https://context7.com/caddyserver/forwardproxy/llms.txt Example configuration for an upstream handler used in testing, demonstrating authentication and upstream proxy settings. ```go // From caddyAuthedUpstreamEnter test (common_test.go): // caddyAuthedUpstreamEnter = Handler{ // Upstream: "https://test:pass@127.0.0.1:4891", // AuthCredentials: [][]byte{EncodeAuthCredentials("upstreamtest", "upstreampass")}, // } ``` -------------------------------- ### Client Usage Examples - curl Source: https://context7.com/caddyserver/forwardproxy/llms.txt Configure curl to use the forward proxy for HTTP and HTTPS connections. ```APIDOC ## Client Usage Examples Configure common HTTP clients to use the forward proxy. ### curl #### HTTP CONNECT tunnel (HTTPS target through HTTPS proxy) ```bash curl --proxy https://user:pass@proxy.example.com:443 \ https://www.example.com/ ``` #### Plain HTTP through the proxy ```bash curl --proxy https://user:pass@proxy.example.com:443 \ http://www.example.com/ ``` ``` -------------------------------- ### Configure Caddy Forward Proxy Source: https://github.com/caddyserver/forwardproxy/blob/master/README.md Use the `forward_proxy` directive in your Caddyfile to enable forward proxy functionality. Ensure addresses start with :443 for full origin support. This example shows various properties in use. ```caddyfile forward_proxy { basic_auth user1 0NtCL2JPJBgPPMmlPcJ basic_auth user2 密码 ports 80 443 hide_ip hide_via disable_insecure_upstreams_check probe_resistance secret-link-kWWL9Q.com # alternatively you can use a real domain, such as caddyserver.com serve_pac /secret-proxy.pac dial_timeout 30s max_idle_conns 50 max_idle_conns_per_host 2 upstream https://user:password@extra-upstream-hop.com acl { allow *.caddyserver.com deny 192.168.1.1/32 192.168.0.0/16 *.prohibitedsite.com *.localhost allow ::1/128 8.8.8.8 github.com *.github.io allow_file /path/to/whitelist.txt deny_file /path/to/blacklist.txt allow all deny all # unreachable rule, remaining requests are matched by `allow all` above } } ``` -------------------------------- ### Programmatically Configure forward_proxy Handler in Go Source: https://context7.com/caddyserver/forwardproxy/llms.txt Use the `EncodeAuthCredentials` helper function to base64-encode user credentials for programmatic configuration of the `forwardproxy.Handler` in Go. This example demonstrates setting up authentication, PAC path, IP/Via hiding, timeouts, connection pooling, host matching, ACLs, and probe resistance. ```go package main import ( "encoding/json" "fmt" "github.com/caddyserver/caddy/v2/modules/caddyhttp" "github.com/caddyserver/forwardproxy" ) func buildHandlerConfig() { h := &forwardproxy.Handler{ // Encode credentials for two users AuthCredentials: [][]byte{ forwardproxy.EncodeAuthCredentials("alice", "hunter2"), forwardproxy.EncodeAuthCredentials("bob", "correcthorsebatterystaple"), }, PACPath: "/proxy.pac", HideIP: true, HideVia: true, DialTimeout: 30_000_000_000, // 30 seconds in nanoseconds MaxIdleConns: 50, Hosts: caddyhttp.MatchHost{"proxy.example.com"}, ACL: []forwardproxy.ACLRule{ {Subjects: []string{"all"}, Allow: true}, }, ProbeResistance: &forwardproxy.ProbeResistance{ Domain: "my-secret-link.example.com", }, } b, _ := json.MarshalIndent(h, "", " ") fmt.Println(string(b)) // Output: // { // "pac_path": "/proxy.pac", // "hide_ip": true, // "hide_via": true, // "hosts": ["proxy.example.com"], // "probe_resistance": { "domain": "my-secret-link.example.com" }, // "dial_timeout": 30000000000, // "max_idle_conns": 50, // "acl": [{ "subjects": ["all"], "allow": true }], // "auth_credentials": ["YWxpY2U6aHVudGVyMg==", "Ym9iOmNvcnJlY3Rob3JzZWJhdHRlcnlzdGFwbGU="] // } } ``` -------------------------------- ### Configure forward_proxy Directive in Caddyfile Source: https://context7.com/caddyserver/forwardproxy/llms.txt Use the `forward_proxy` directive in your Caddyfile to configure proxy settings. This example shows basic authentication, port restrictions, IP/Via header hiding, probe resistance, PAC file serving, connection timeouts, upstream proxy chaining, and access control lists. ```caddyfile { # Override directive order so forward_proxy runs first order forward_proxy first } :443, proxy.example.com { forward_proxy { # Authentication (repeat for multiple users) basic_auth user1 s3cr3tP@ss basic_auth user2 密码 # Restrict allowed destination ports ports 80 443 # Privacy: hide client IP and proxy headers hide_ip hide_via # Probe resistance: appear as a regular site to scanners # Only basic_auth'd clients visiting this secret domain get a 407 probe_resistance secret-link-kWWL9Q.com # Serve PAC file at a secret path (critical when probe_resistance is on) serve_pac /secret-proxy.pac # Connection timeouts and pooling dial_timeout 30s max_idle_conns 100 max_idle_conns_per_host 5 # Chain through an upstream proxy upstream https://user:password@next-hop.example.com # Access control list (evaluated top to bottom; first match wins) acl { allow *.caddyserver.com github.com deny 192.168.1.0/24 10.0.0.0/8 *.prohibited.example.com allow ::1/128 8.8.8.8 allow_file /etc/caddy/acl-whitelist.txt deny_file /etc/caddy/acl-blacklist.txt allow all } } } ``` -------------------------------- ### Configure curl to Use PAC File Source: https://context7.com/caddyserver/forwardproxy/llms.txt Example of configuring curl to use a PAC file for proxy settings, demonstrating how traffic is routed through the proxy. ```bash # Configure curl to use the PAC file (via environment proxy for demo) curl -x https://proxyuser:pass@proxy.example.com:443 \ -v https://httpbin.org/ip # Expected response body: {"origin": "203.0.113.1"} ← the proxy's IP, not yours ``` -------------------------------- ### Forward Proxy Handler JSON Configuration Source: https://context7.com/caddyserver/forwardproxy/llms.txt Configure the forward proxy handler using JSON. This example demonstrates various settings including hosts, authentication, probe resistance, ACLs, and upstream proxy chaining. ```json { "handler": "forward_proxy", "hosts": ["proxy.example.com"], "auth_credentials": ["dGVzdDpwYXNz"], "probe_resistance": { "domain": "secret-link-kWWL9Q.com" }, "hide_ip": true, "hide_via": true, "disable_insecure_upstreams_check": false, "pac_path": "/proxy.pac", "dial_timeout": 30000000000, "max_idle_conns": 50, "max_idle_conns_per_host": 2, "upstream": "https://user:password@upstream-proxy.example.com:443", "acl": [ { "subjects": ["*.caddyserver.com", "github.com"], "allow": true }, { "subjects": ["192.168.0.0/16", "10.0.0.0/8"], "allow": false }, { "subjects": ["all"], "allow": true } ], "allowed_ports": [80, 443] } ``` -------------------------------- ### Build Caddy with Forward Proxy Module Source: https://github.com/caddyserver/forwardproxy/blob/master/README.md Use xcaddy to build Caddy with the forward proxy module included. This is a prerequisite for using the module. ```bash xcaddy build --with github.com/caddyserver/forwardproxy ``` -------------------------------- ### Basic Caddyfile Configuration for Forward Proxy Source: https://github.com/caddyserver/forwardproxy/blob/master/README.md Configure Caddy to act as a simple, unauthenticated forward proxy using the Caddyfile. Replace example.com with your domain. This configuration is for testing only. ```caddyfile :443, example.com { # UNAUTHENTICATED! USE ONLY FOR TESTING forward_proxy } ``` -------------------------------- ### Build and Run Caddy Forward Proxy Docker Image Source: https://context7.com/caddyserver/forwardproxy/llms.txt Build a Docker image for Caddy with the forward proxy module and run it. Environment variables can be used to configure the proxy, or a Caddyfile can be mounted. ```bash # Build the image docker build -t caddy-forwardproxy ./docker-build/ # Run with basic auth and probe resistance docker run -d \ -p 80:80 -p 443:443 \ -e SITE_ADDRESS=proxy.example.com \ -e PROXY_USERNAME=myuser \ -e PROXY_PASSWORD=mypassword \ -e PROBE_RESISTANT=true \ -e SECRET_LINK=hidden-9x7k.example.com \ -v /data/caddy:/root/.caddy \ --restart always \ caddy-forwardproxy # Run with a manually provided Caddyfile docker run -d \ -p 443:443 \ -v /path/to/my/Caddyfile:/etc/caddy/Caddyfile \ -v /data/caddy:/root/.caddy \ caddy-forwardproxy # Test the proxy curl -x https://myuser:mypassword@proxy.example.com:443 \ https://ifconfig.me # → 203.0.113.1 (the server's IP) ``` -------------------------------- ### Docker Deployment Source: https://context7.com/caddyserver/forwardproxy/llms.txt Build and run a Caddy + forwardproxy Docker image using the included `docker-build/` directory. The container auto-generates a Caddyfile from environment variables. ```APIDOC ## Docker Deployment Build and run a Caddy + forwardproxy Docker image using the included `docker-build/` directory. The container auto-generates a Caddyfile from environment variables. ### Build Image ```bash docker build -t caddy-forwardproxy ./docker-build/ ``` ### Run with Basic Auth and Probe Resistance ```bash docker run -d \ -p 80:80 -p 443:443 \ -e SITE_ADDRESS=proxy.example.com \ -e PROXY_USERNAME=myuser \ -e PROXY_PASSWORD=mypassword \ -e PROBE_RESISTANT=true \ -e SECRET_LINK=hidden-9x7k.example.com \ -v /data/caddy:/root/.caddy \ --restart always \ caddy-forwardproxy ``` ### Run with a Manually Provided Caddyfile ```bash docker run -d \ -p 443:443 \ -v /path/to/my/Caddyfile:/etc/caddy/Caddyfile \ -v /data/caddy:/root/.caddy \ caddy-forwardproxy ``` ### Test the Proxy ```bash curl -x https://myuser:mypassword@proxy.example.com:443 \ https://ifconfig.me # → 203.0.113.1 (the server's IP) ``` ``` -------------------------------- ### Configure Probe Resistance for Forward Proxy Source: https://context7.com/caddyserver/forwardproxy/llms.txt Enable probe resistance to prevent 407 responses on failed credentials, making the proxy appear as a plain web server. Requires basic_auth. ```caddyfile :443, proxy.example.com { forward_proxy { basic_auth proxyuser Sup3rS3cret! probe_resistance my-hidden-proxy-9x7k.example.com serve_pac /hidden-9x7k.pac # PAC path must also be secret } # The rest of the site looks like a normal static site file_server { root /var/www/html } } ``` -------------------------------- ### Caddy JSON API - Dynamic Configuration Source: https://context7.com/caddyserver/forwardproxy/llms.txt Configure the forward proxy at runtime using Caddy's admin API without restarting the server. ```APIDOC ## Caddy JSON API — Dynamic Configuration Configure the forward proxy at runtime using Caddy's admin API without restarting the server. ### Endpoint `POST /load` ### Description Loads a new Caddy configuration. ### Request Body ```json { "apps": { "http": { "servers": { "proxy": { "listen": [":443"], "routes": [{ "handle": [{ "handler": "forward_proxy", "auth_credentials": ["dGVzdDpwYXNz"], "hide_ip": true, "hide_via": true, "dial_timeout": 30000000000, "max_idle_conns": 50, "acl": [ {"subjects": ["all"], "allow": true} ] }] }] } } } } } ``` ### Response - `200 OK` - Configuration loaded successfully. ### Example Usage ```bash # POST a complete Caddy config including the forward_proxy handler curl -s -X POST http://localhost:2019/load \ -H "Content-Type: application/json" \ -d '{ "apps": { "http": { "servers": { "proxy": { "listen": [":443"], "routes": [{ "handle": [{ "handler": "forward_proxy", "auth_credentials": ["dGVzdDpwYXNz"], "hide_ip": true, "hide_via": true, "dial_timeout": 30000000000, "max_idle_conns": 50, "acl": [ { "subjects": ["all"], "allow": true } ] }] }] } } } } }' # Verify the module is active curl -s http://localhost:2019/config/apps/http/servers/proxy/ | jq '.routes[0].handle[0].handler' # Use the proxy curl -x https://test:pass@localhost:443 https://example.com/ ``` ``` -------------------------------- ### Build Caddy Forward Proxy Docker Image Source: https://github.com/caddyserver/forwardproxy/blob/master/docker-build/README.md Use this command to build the Docker image locally. Ensure you are in the directory containing the Dockerfile. ```docker docker build -t caddy-forwardproxy . ``` -------------------------------- ### Using wget with HTTPS_PROXY environment variable Source: https://context7.com/caddyserver/forwardproxy/llms.txt This command configures wget to use an HTTPS proxy by setting the HTTPS_PROXY environment variable. It then downloads a file from a URL and outputs it to stdout. ```bash https_proxy=https://user:pass@proxy.example.com:443 \ wget https://www.example.com/ -O - ``` -------------------------------- ### Create HTTP CONNECT Dialer in Go Source: https://context7.com/caddyserver/forwardproxy/llms.txt Use `httpclient.NewHTTPConnectDialer` to create a dialer that tunnels connections through an HTTPS proxy. It supports HTTP/2 and caches connections. ```go package main import ( "context" "fmt" "io" "net/http" "github.com/caddyserver/forwardproxy/httpclient" ) func main() { // Create a dialer that goes through an HTTPS proxy dialer, err := httpclient.NewHTTPConnectDialer("https://user:pass@proxy.example.com:443") if err != nil { panic(err) } // Optional: override TLS dialing (e.g., for localhost testing) // dialer.DialTLS = func(network, address string) (net.Conn, string, error) { ... } // Use the dialer to establish a tunneled TCP connection conn, err := dialer.DialContext(context.Background(), "tcp", "api.github.com:443") if err != nil { panic(err) // e.g. "Proxy responded with non 200 code: 407 Proxy Auth Required" } defer conn.Close() // Send an HTTP request over the tunnel req, _ := http.NewRequest("GET", "https://api.github.com/", nil) req.Write(conn) buf := make([]byte, 4096) n, _ := conn.Read(buf) fmt.Printf("Response: %s\n", buf[:n]) } ``` -------------------------------- ### Handler.UnmarshalCaddyfile Source: https://context7.com/caddyserver/forwardproxy/llms.txt Demonstrates how the `Handler.UnmarshalCaddyfile` method parses Caddyfile blocks into the `Handler` configuration, detailing supported subdirectives and their mapping to struct fields. ```APIDOC ## `Handler.UnmarshalCaddyfile(d *caddyfile.Dispenser) error` Parses a Caddyfile block into the `Handler`. This method is called automatically by the Caddy framework; it is also useful to understand which subdirective tokens are legal and how they map to struct fields. Supported subdirectives: `basic_auth`, `hosts`, `ports`, `hide_ip`, `hide_via`, `disable_insecure_upstreams_check`, `probe_resistance`, `serve_pac`, `dial_timeout`, `max_idle_conns`, `max_idle_conns_per_host`, `upstream`, `acl`. ```go package forwardproxy_test import ( "strings" "testing" "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" "github.com/caddyserver/forwardproxy" ) func TestUnmarshalCaddyfile(t *testing.T) { input := `forward_proxy { basic_auth admin s3cr3t ports 80 443 hide_ip hide_via probe_resistance secret-link.example.com serve_pac /my.pac dial_timeout 15s max_idle_conns 100 max_idle_conns_per_host 4 acl { allow *.example.com deny 192.168.0.0/16 allow all } }` d := caddyfile.NewTestDispenser(input) var h forwardproxy.Handler if err := h.UnmarshalCaddyfile(d); err != nil { t.Fatal(err) } // h.AuthCredentials now holds base64("admin:s3cr3t") // h.AllowedPorts == []int{80, 443} // h.HideIP == true // h.HideVia == true // h.ProbeResistance.Domain == "secret-link.example.com" // h.PACPath == "/my.pac" // h.ACL has 3 rules } ``` ``` -------------------------------- ### Configure Forward Proxy via Caddy JSON API Source: https://context7.com/caddyserver/forwardproxy/llms.txt Dynamically configure the forward proxy handler by POSTing a JSON configuration to the Caddy Admin API. This allows runtime updates without restarting the server. ```bash # POST a complete Caddy config including the forward_proxy handler curl -s -X POST http://localhost:2019/load \ -H "Content-Type: application/json" \ -d '{ \ "apps": { \ "http": { \ "servers": { \ "proxy": { \ "listen": [":443"], \ "routes": [{ \ "handle": [{ \ "handler": "forward_proxy", \ "auth_credentials": ["dGVzdDpwYXNz"], \ "hide_ip": true, \ "hide_via": true, \ "dial_timeout": 30000000000, \ "max_idle_conns": 50, \ "acl": [ \ {"subjects": ["all"], "allow": true} \ ] \ }] \ }] \ } \ } \ } \ } \ }' # Response: 200 OK # Verify the module is active curl -s http://localhost:2019/config/apps/http/servers/proxy/ | jq '.routes[0].handle[0].handler' # "forward_proxy" # Use the proxy curl -x https://test:pass@localhost:443 https://example.com/ ``` -------------------------------- ### Test Caddyfile Unmarshaling for forward_proxy Handler Source: https://context7.com/caddyserver/forwardproxy/llms.txt This Go test demonstrates how to use `UnmarshalCaddyfile` to parse a Caddyfile block into a `forwardproxy.Handler` struct. It verifies that subdirectives like `basic_auth`, `ports`, `hide_ip`, `hide_via`, `probe_resistance`, `serve_pac`, `dial_timeout`, `max_idle_conns`, `max_idle_conns_per_host`, and `acl` are correctly processed. ```go package forwardproxy_test import ( "strings" "testing" "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" "github.com/caddyserver/forwardproxy" ) func TestUnmarshalCaddyfile(t *testing.T) { input := `forward_proxy { basic_auth admin s3cr3t ports 80 443 hide_ip hide_via probe_resistance secret-link.example.com serve_pac /my.pac dial_timeout 15s max_idle_conns 100 max_idle_conns_per_host 4 acl { allow *.example.com deny 192.168.0.0/16 allow all } }` d := caddyfile.NewTestDispenser(input) var h forwardproxy.Handler if err := h.UnmarshalCaddyfile(d); err != nil { t.Fatal(err) } // h.AuthCredentials now holds base64("admin:s3cr3t") // h.AllowedPorts == []int{80, 443} // h.HideIP == true // h.HideVia == true // h.ProbeResistance.Domain == "secret-link.example.com" // h.PACPath == "/my.pac" // h.ACL has 3 rules } ``` -------------------------------- ### Programmatic Upstream Proxy Chaining Configuration Source: https://context7.com/caddyserver/forwardproxy/llms.txt Construct a chained-proxy handler programmatically using the forwardproxy package, specifying authentication and the upstream proxy. ```go // Programmatic construction of a chained-proxy handler import "github.com/caddyserver/forwardproxy" h := &forwardproxy.Handler{ AuthCredentials: [][]byte{ forwardproxy.EncodeAuthCredentials("entryuser", "entrypass"), }, Upstream: "https://exituser:exitpass@exit.example.com:443", // NOTE: acl and allowed_ports are ignored when upstream is set } ``` -------------------------------- ### Configure Upstream Proxy Chaining Source: https://context7.com/caddyserver/forwardproxy/llms.txt Set up the forward proxy to route all traffic through a secondary upstream proxy. Supports various protocols for localhost and remote upstreams. ```caddyfile # Entry node (public-facing) — clients connect here :443, entry.example.com { forward_proxy { basic_auth entryuser entrypass upstream https://exituser:exitpass@exit.example.com:443 } } ``` -------------------------------- ### Configure ACL Rules for Forward Proxy Source: https://context7.com/caddyserver/forwardproxy/llms.txt Define access control lists using ACLRule structs to manage allowed and denied subjects. Supports CIDR/IP, hostnames, wildcards, and a catch-all 'all'. ```go aclConfig := []forwardproxy.ACLRule{ // Allow specific trusted domains and their subdomains { Subjects: []string{"*.caddyserver.com", "github.com", "golang.org"}, Allow: true, }, // Deny specific IP ranges { Subjects: []string{ "192.168.0.0/16", "10.0.0.0/8", "172.16.0.0/12", "8.8.8.8", // single IPv4 → treated as /32 "2001:4860::/32", // IPv6 CIDR }, Allow: false, }, // Default: allow everything else { Subjects: []string{"all"}, Allow: true, }, } ``` -------------------------------- ### Handler Struct - JSON Configuration Source: https://context7.com/caddyserver/forwardproxy/llms.txt This section details the JSON configuration for the `forward_proxy` handler. All fields map directly to JSON keys and can be used to configure the proxy via the Caddy API. Fields not specified will use their default values. ```APIDOC ## Handler Struct — JSON Configuration `Handler` is the Caddy module struct. All fields map 1:1 to JSON keys when configuring via the Caddy API. Fields omitted from JSON use the defaults described below. ```json { "handler": "forward_proxy", "hosts": ["proxy.example.com"], "auth_credentials": ["dGVzdDpwYXNz"], "probe_resistance": { "domain": "secret-link-kWWL9Q.com" }, "hide_ip": true, "hide_via": true, "disable_insecure_upstreams_check": false, "pac_path": "/proxy.pac", "dial_timeout": 30000000000, "max_idle_conns": 50, "max_idle_conns_per_host": 2, "upstream": "https://user:password@upstream-proxy.example.com:443", "acl": [ { "subjects": ["*.caddyserver.com", "github.com"], "allow": true }, { "subjects": ["192.168.0.0/16", "10.0.0.0/8"], "allow": false }, { "subjects": ["all"], "allow": true } ], "allowed_ports": [80, 443] } ``` **Key fields:** | JSON key | Go field | Default | Description | |---|---|---|---| | `auth_credentials` | `AuthCredentials [][]byte` | `nil` (no auth) | Base64-encoded `user:pass` credentials | | `probe_resistance` | `ProbeResistance *ProbeResistance` | `nil` | Hides proxy existence; requires auth | | `hide_ip` | `HideIP bool` | `false` | Suppresses `Forwarded: for=...` header | | `hide_via` | `HideVia bool` | `false` | Suppresses `Via:` header | | `pac_path` | `PACPath string` | `""` | Path to serve the auto-generated PAC file | | `dial_timeout` | `DialTimeout caddy.Duration` | `30s` | TCP connection timeout to target | | `max_idle_conns` | `MaxIdleConns int` | `50` (`-1` = unlimited) | Global idle connection pool size | | `max_idle_conns_per_host` | `MaxIdleConnsPerHost int` | `0` (Go default: 2) | Per-host idle connection pool size | | `upstream` | `Upstream string` | `""` | Upstream proxy URL (https/socks5/http to localhost) | | `acl` | `ACL []ACLRule` | deny RFC-1918 + allow all | Ordered ACL rules | | `allowed_ports` | `AllowedPorts []int` | `[]` (all ports) | Whitelist of allowed destination ports | ``` -------------------------------- ### Serve PAC File for Forward Proxy Source: https://context7.com/caddyserver/forwardproxy/llms.txt Configure the forward proxy to automatically generate and serve a Proxy Auto-Config (PAC) file. The PAC file routes non-localhost traffic through the proxy. ```caddyfile # Caddyfile: serve_pac /proxy.pac (or a secret path when probe_resistance is on) ``` -------------------------------- ### httpclient.ContextKeyHeader Source: https://context7.com/caddyserver/forwardproxy/llms.txt Used to inject extra HTTP headers into the outgoing CONNECT request by embedding them in the context. ```APIDOC ## `httpclient.ContextKeyHeader{}` — Injecting Headers into CONNECT Requests Pass extra HTTP headers (e.g., `Forwarded`, `X-Forwarded-For`) into the outgoing CONNECT request by embedding them in the context under the `ContextKeyHeader{}` key. Used internally by `Handler` to propagate the client's `Forwarded` header when `hide_ip` is not set. ### Parameters #### Request Body - `ContextKeyHeader{}` (struct) - The key type for context value, must be used as is. - `http.Header` (map[string][]string) - The headers to be injected into the CONNECT request. ### Request Example ```go import ( "context" "net" "net/http" "github.com/caddyserver/forwardproxy/httpclient" ) func dialWithHeaders(dialer *httpclient.HTTPConnectDialer, target string) (net.Conn, error) { // Build headers to inject into the CONNECT request extraHeaders := make(http.Header) extraHeaders.Set("Forwarded", `for="203.0.113.5"`) extraHeaders.Set("X-Custom-Proxy-Header", "my-value") ctx := context.WithValue( context.Background(), httpclient.ContextKeyHeader{}, extraHeaders, ) // DialContext will merge these headers into the CONNECT request, // overriding any colliding defaults in dialer.DefaultHeader return dialer.DialContext(ctx, "tcp", target) } ``` ``` -------------------------------- ### Caddyfile Directive - forward_proxy Source: https://context7.com/caddyserver/forwardproxy/llms.txt Configuration of the forward proxy using the `forward_proxy` directive in Caddyfile. This includes settings for authentication, port restrictions, privacy, probe resistance, timeouts, connection pooling, upstream proxies, and access control lists. ```APIDOC ## Caddyfile Directive — `forward_proxy` The `forward_proxy` directive is the primary way to configure the plugin. It is registered with default order after `file_server`. ```caddyfile { # Override directive order so forward_proxy runs first order forward_proxy first } :443, proxy.example.com { forward_proxy { # Authentication (repeat for multiple users) basic_auth user1 s3cr3tP@ss basic_auth user2 密码 # Restrict allowed destination ports ports 80 443 # Privacy: hide client IP and proxy headers hide_ip hide_via # Probe resistance: appear as a regular site to scanners # Only basic_auth'd clients visiting this secret domain get a 407 probe_resistance secret-link-kWWL9Q.com # Serve PAC file at a secret path (critical when probe_resistance is on) serve_pac /secret-proxy.pac # Connection timeouts and pooling dial_timeout 30s max_idle_conns 100 max_idle_conns_per_host 5 # Chain through an upstream proxy upstream https://user:password@next-hop.example.com # Access control list (evaluated top to bottom; first match wins) acl { allow *.caddyserver.com github.com deny 192.168.1.0/24 10.0.0.0/8 *.prohibited.example.com allow ::1/128 8.8.8.8 allow_file /etc/caddy/acl-whitelist.txt deny_file /etc/caddy/acl-blacklist.txt allow all } } } ``` ``` -------------------------------- ### Inject Headers into CONNECT Requests Source: https://context7.com/caddyserver/forwardproxy/llms.txt Embed custom HTTP headers into the CONNECT request using `context.WithValue` with `httpclient.ContextKeyHeader{}`. This is useful for passing headers like `Forwarded` or `X-Forwarded-For`. ```go import ( "context" "net/http" "github.com/caddyserver/forwardproxy/httpclient" ) func dialWithHeaders(dialer *httpclient.HTTPConnectDialer, target string) (net.Conn, error) { // Build headers to inject into the CONNECT request extraHeaders := make(http.Header) extraHeaders.Set("Forwarded", `for="203.0.113.5"`) extraHeaders.Set("X-Custom-Proxy-Header", "my-value") ctx := context.WithValue( context.Background(), httpclient.ContextKeyHeader{}, extraHeaders, ) // DialContext will merge these headers into the CONNECT request, // overriding any colliding defaults in dialer.DefaultHeader return dialer.DialContext(ctx, "tcp", target) } ``` -------------------------------- ### Override Directive Order for Forward Proxy Source: https://github.com/caddyserver/forwardproxy/blob/master/README.md Set the 'forward_proxy' directive to execute first using the 'order' global option in the Caddyfile. This can be useful for specific routing needs. ```caddyfile { order forward_proxy first } :443, example.com { # UNAUTHENTICATED! USE ONLY FOR TESTING forward_proxy } ``` -------------------------------- ### httpclient.NewHTTPConnectDialer Source: https://context7.com/caddyserver/forwardproxy/llms.txt Creates a dialer that tunnels connections through an HTTPS proxy using HTTP CONNECT. Implements golang.org/x/net/proxy.Dialer. Automatically negotiates HTTP/2 (h2) or HTTP/1.1 based on ALPN, and caches H2 connections for reuse. ```APIDOC ## `httpclient.NewHTTPConnectDialer(proxyURLStr string) (*HTTPConnectDialer, error)` Creates a dialer that tunnels connections through an HTTPS proxy using HTTP CONNECT. Implements `golang.org/x/net/proxy.Dialer`. Automatically negotiates HTTP/2 (`h2`) or HTTP/1.1 based on ALPN, and caches H2 connections for reuse (`EnableH2ConnReuse: true` by default). ### Parameters #### Path Parameters - `proxyURLStr` (string) - Required - The URL of the HTTPS proxy. ### Request Example ```go package main import ( "context" "fmt" "io" "net" "net/http" "github.com/caddyserver/forwardproxy/httpclient" ) func main() { // Create a dialer that goes through an HTTPS proxy dialer, err := httpclient.NewHTTPConnectDialer("https://user:pass@proxy.example.com:443") if err != nil { panic(err) } // Optional: override TLS dialing (e.g., for localhost testing) // dialer.DialTLS = func(network, address string) (net.Conn, string, error) { ... } // Use the dialer to establish a tunneled TCP connection conn, err := dialer.DialContext(context.Background(), "tcp", "api.github.com:443") if err != nil { panic(err) // e.g. "Proxy responded with non 200 code: 407 Proxy Auth Required" } defer conn.Close() // Send an HTTP request over the tunnel req, _ := http.NewRequest("GET", "https://api.github.com/", nil) req.Write(conn) buf := make([]byte, 4096) n, _ := conn.Read(buf) fmt.Printf("Response: %s\n", buf[:n]) } ``` ### Response #### Success Response - `*HTTPConnectDialer` - A dialer that tunnels connections through the specified HTTPS proxy. - `error` - An error if the dialer could not be created. ``` -------------------------------- ### Using PAC file with curl Source: https://context7.com/caddyserver/forwardproxy/llms.txt This command uses curl to fetch a PAC file from a proxy server and then requests a URL through that proxy. The --proxy-insecure flag bypasses certificate validation for the proxy. ```bash curl --proxy-insecure \ --proxy-auto \ https://proxy.example.com/proxy.pac \ https://www.example.com/ ``` -------------------------------- ### Default ACL Configuration Source: https://github.com/caddyserver/forwardproxy/blob/master/README.md This is the default access control list configuration for the forward proxy. It denies access to private IP ranges and localhost, then allows all other traffic. ```caddyfile acl { deny 10.0.0.0/8 127.0.0.0/8 172.16.0.0/12 192.168.0.0/16 ::1/128 fe80::/10 allow all } ``` -------------------------------- ### EncodeAuthCredentials Source: https://context7.com/caddyserver/forwardproxy/llms.txt A helper function to base64-encode user and password credentials for programmatic use in Go, typically when constructing a `Handler` directly. ```APIDOC ## `EncodeAuthCredentials(user, pass string) []byte` Helper function that base64-encodes a `user:pass` pair into the byte slice expected by `Handler.AuthCredentials`. Use this when constructing a `Handler` programmatically in Go (e.g., in tests or dynamic Caddy configuration). ```go package main import ( "encoding/json" "fmt" "github.com/caddyserver/caddy/v2/modules/caddyhttp" "github.com/caddyserver/forwardproxy" ) func buildHandlerConfig() { h := &forwardproxy.Handler{ // Encode credentials for two users AuthCredentials: [][]byte{ forwardproxy.EncodeAuthCredentials("alice", "hunter2"), forwardproxy.EncodeAuthCredentials("bob", "correcthorsebatterystaple"), }, PACPath: "/proxy.pac", HideIP: true, HideVia: true, DialTimeout: 30_000_000_000, // 30 seconds in nanoseconds MaxIdleConns: 50, Hosts: caddyhttp.MatchHost{"proxy.example.com"}, ACL: []forwardproxy.ACLRule{ {Subjects: []string{"all"}, Allow: true}, }, ProbeResistance: &forwardproxy.ProbeResistance{ Domain: "my-secret-link.example.com", }, } b, _ := json.MarshalIndent(h, "", " ") fmt.Println(string(b)) // Output: // { // "pac_path": "/proxy.pac", // "hide_ip": true, // "hide_via": true, // "hosts": ["proxy.example.com"], // "probe_resistance": { "domain": "my-secret-link.example.com" }, // "dial_timeout": 30000000000, // "max_idle_conns": 50, // "acl": [{ "subjects": ["all"], "allow": true }], // "auth_credentials": ["YWxpY2U6aHVudGVyMg==", "Ym9iOmNvcnJlY3Rob3JzZWJhdHRlcnlzdGFwbGU="] // } } ``` ``` -------------------------------- ### Curl HTTP CONNECT Tunnel Source: https://context7.com/caddyserver/forwardproxy/llms.txt Use `curl --proxy` to establish an HTTP CONNECT tunnel through an HTTPS proxy to reach an HTTPS target. This is useful for testing HTTPS connections through a proxy. ```bash # HTTP CONNECT tunnel (HTTPS target through HTTPS proxy) curl --proxy https://user:pass@proxy.example.com:443 \ https://www.example.com/ ``` -------------------------------- ### Curl Plain HTTP through Proxy Source: https://context7.com/caddyserver/forwardproxy/llms.txt Use `curl --proxy` to route a plain HTTP request through an HTTPS proxy. This demonstrates basic HTTP traffic forwarding. ```bash # Plain HTTP through the proxy curl --proxy https://user:pass@proxy.example.com:443 \ http://www.example.com/ ``` -------------------------------- ### Auto-Generated PAC File Content Source: https://context7.com/caddyserver/forwardproxy/llms.txt The JavaScript content of the auto-generated PAC file, which directs traffic based on the host. ```javascript // Response body (auto-generated): function FindProxyForURL(url, host) { if (host === "127.0.0.1" || host === "::1" || host === "localhost") return "DIRECT"; return "HTTPS proxy.example.com"; } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.