diff options
author | Mohammed Al Sahaf <[email protected]> | 2024-08-22 22:52:05 +0300 |
---|---|---|
committer | GitHub <[email protected]> | 2024-08-22 19:52:05 +0000 |
commit | 4ade967005929e98ae2265d9d7c89b33f1ca951b (patch) | |
tree | 1933e4b283afe4ade6412a51fd403da4af662e31 | |
parent | 8af646730be93f4a00b873d1822bfde6be106696 (diff) | |
download | caddy-4ade967005929e98ae2265d9d7c89b33f1ca951b.tar.gz caddy-4ade967005929e98ae2265d9d7c89b33f1ca951b.zip |
reverseproxy: allow user to define source address (#6504)
* reverseproxy: allow user to define source address
Closes #6503
Signed-off-by: Mohammed Al Sahaf <[email protected]>
* reverse_proxy: caddyfile support for local_address
Signed-off-by: Mohammed Al Sahaf <[email protected]>
---------
Signed-off-by: Mohammed Al Sahaf <[email protected]>
3 files changed, 91 insertions, 1 deletions
diff --git a/caddytest/integration/caddyfile_adapt/reverse_proxy_localaddr.caddyfiletest b/caddytest/integration/caddyfile_adapt/reverse_proxy_localaddr.caddyfiletest new file mode 100644 index 000000000..d734c9ce0 --- /dev/null +++ b/caddytest/integration/caddyfile_adapt/reverse_proxy_localaddr.caddyfiletest @@ -0,0 +1,57 @@ +https://example.com { + reverse_proxy http://localhost:54321 { + transport http { + local_address 192.168.0.1 + } + } +} + +---------- +{ + "apps": { + "http": { + "servers": { + "srv0": { + "listen": [ + ":443" + ], + "routes": [ + { + "match": [ + { + "host": [ + "example.com" + ] + } + ], + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "handler": "reverse_proxy", + "transport": { + "local_address": "192.168.0.1", + "protocol": "http" + }, + "upstreams": [ + { + "dial": "localhost:54321" + } + ] + } + ] + } + ] + } + ], + "terminal": true + } + ] + } + } + } + } +} diff --git a/modules/caddyhttp/reverseproxy/caddyfile.go b/modules/caddyhttp/reverseproxy/caddyfile.go index cd0e5d949..12e2b9b97 100644 --- a/modules/caddyhttp/reverseproxy/caddyfile.go +++ b/modules/caddyhttp/reverseproxy/caddyfile.go @@ -1326,7 +1326,11 @@ func (h *HTTPTransport) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { return d.Err("cannot specify \"tls_trust_pool\" twice in caddyfile") } h.TLS.CARaw = caddyconfig.JSONModuleObject(ca, "provider", modStem, nil) - + case "local_address": + if !d.NextArg() { + return d.ArgErr() + } + h.LocalAddress = d.Val() default: return d.Errf("unrecognized subdirective %s", d.Val()) } diff --git a/modules/caddyhttp/reverseproxy/httptransport.go b/modules/caddyhttp/reverseproxy/httptransport.go index 9a82341d0..9929ae5d1 100644 --- a/modules/caddyhttp/reverseproxy/httptransport.go +++ b/modules/caddyhttp/reverseproxy/httptransport.go @@ -132,6 +132,10 @@ type HTTPTransport struct { // to change or removal while experimental. Versions []string `json:"versions,omitempty"` + // Specify the address to bind to when connecting to an upstream. In other words, + // it is the address the upstream sees as the remote address. + LocalAddress string `json:"local_address,omitempty"` + // The pre-configured underlying HTTP transport. Transport *http.Transport `json:"-"` @@ -185,6 +189,31 @@ func (h *HTTPTransport) NewTransport(caddyCtx caddy.Context) (*http.Transport, e FallbackDelay: time.Duration(h.FallbackDelay), } + if h.LocalAddress != "" { + netaddr, err := caddy.ParseNetworkAddressWithDefaults(h.LocalAddress, "tcp", 0) + if err != nil { + return nil, err + } + if netaddr.PortRangeSize() > 1 { + return nil, fmt.Errorf("local_address must be a single address, not a port range") + } + switch netaddr.Network { + case "tcp", "tcp4", "tcp6": + dialer.LocalAddr, err = net.ResolveTCPAddr(netaddr.Network, netaddr.JoinHostPort(0)) + if err != nil { + return nil, err + } + case "unix", "unixgram", "unixpacket": + dialer.LocalAddr, err = net.ResolveUnixAddr(netaddr.Network, netaddr.JoinHostPort(0)) + if err != nil { + return nil, err + } + case "udp", "udp4", "udp6": + return nil, fmt.Errorf("local_address must be a TCP address, not a UDP address") + default: + return nil, fmt.Errorf("unsupported network") + } + } if h.Resolver != nil { err := h.Resolver.ParseAddresses() if err != nil { |