@marcel91200 / caddy Mirror · read-only / commits / 4ade9670
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 12, 09:30 UTC

reverseproxy: allow user to define source address (#6504)

* reverseproxy: allow user to define source address Closes #6503 Signed-off-by: Mohammed Al Sahaf <msaa1990@gmail.com> * reverse_proxy: caddyfile support for local_address Signed-off-by: Mohammed Al Sahaf <msaa1990@gmail.com> --------- Signed-off-by: Mohammed Al Sahaf <msaa1990@gmail.com>

Mohammed Al Sahaf committed Aug 22, 2024 at 22:52 UTC 4ade967005929e98ae2265d9d7c89b33f1ca951b
3 files changed +91 -1
caddytest/integration/caddyfile_adapt/reverse_proxy_localaddr.caddyfiletest new
+57
@@ -0,0 +1,57 @@
1 +https://example.com {
2 + reverse_proxy http://localhost:54321 {
3 + transport http {
4 + local_address 192.168.0.1
5 + }
6 + }
7 +}
8 +
9 +----------
10 +{
11 + "apps": {
12 + "http": {
13 + "servers": {
14 + "srv0": {
15 + "listen": [
16 + ":443"
17 + ],
18 + "routes": [
19 + {
20 + "match": [
21 + {
22 + "host": [
23 + "example.com"
24 + ]
25 + }
26 + ],
27 + "handle": [
28 + {
29 + "handler": "subroute",
30 + "routes": [
31 + {
32 + "handle": [
33 + {
34 + "handler": "reverse_proxy",
35 + "transport": {
36 + "local_address": "192.168.0.1",
37 + "protocol": "http"
38 + },
39 + "upstreams": [
40 + {
41 + "dial": "localhost:54321"
42 + }
43 + ]
44 + }
45 + ]
46 + }
47 + ]
48 + }
49 + ],
50 + "terminal": true
51 + }
52 + ]
53 + }
54 + }
55 + }
56 + }
57 +}
modules/caddyhttp/reverseproxy/caddyfile.go
+5 -1
@@ -1326,7 +1326,11 @@ func (h *HTTPTransport) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
1326 return d.Err("cannot specify \"tls_trust_pool\" twice in caddyfile")
1327 }
1328 h.TLS.CARaw = caddyconfig.JSONModuleObject(ca, "provider", modStem, nil)
1329 -
1329 + case "local_address":
1330 + if !d.NextArg() {
1331 + return d.ArgErr()
1332 + }
1333 + h.LocalAddress = d.Val()
1334 default:
1335 return d.Errf("unrecognized subdirective %s", d.Val())
1336 }
modules/caddyhttp/reverseproxy/httptransport.go
+29
@@ -132,6 +132,10 @@ type HTTPTransport struct {
132 // to change or removal while experimental.
133 Versions []string `json:"versions,omitempty"`
134
135 + // Specify the address to bind to when connecting to an upstream. In other words,
136 + // it is the address the upstream sees as the remote address.
137 + LocalAddress string `json:"local_address,omitempty"`
138 +
139 // The pre-configured underlying HTTP transport.
140 Transport *http.Transport `json:"-"`
141
@@ -185,6 +189,31 @@ func (h *HTTPTransport) NewTransport(caddyCtx caddy.Context) (*http.Transport, e
189 FallbackDelay: time.Duration(h.FallbackDelay),
190 }
191
192 + if h.LocalAddress != "" {
193 + netaddr, err := caddy.ParseNetworkAddressWithDefaults(h.LocalAddress, "tcp", 0)
194 + if err != nil {
195 + return nil, err
196 + }
197 + if netaddr.PortRangeSize() > 1 {
198 + return nil, fmt.Errorf("local_address must be a single address, not a port range")
199 + }
200 + switch netaddr.Network {
201 + case "tcp", "tcp4", "tcp6":
202 + dialer.LocalAddr, err = net.ResolveTCPAddr(netaddr.Network, netaddr.JoinHostPort(0))
203 + if err != nil {
204 + return nil, err
205 + }
206 + case "unix", "unixgram", "unixpacket":
207 + dialer.LocalAddr, err = net.ResolveUnixAddr(netaddr.Network, netaddr.JoinHostPort(0))
208 + if err != nil {
209 + return nil, err
210 + }
211 + case "udp", "udp4", "udp6":
212 + return nil, fmt.Errorf("local_address must be a TCP address, not a UDP address")
213 + default:
214 + return nil, fmt.Errorf("unsupported network")
215 + }
216 + }
217 if h.Resolver != nil {
218 err := h.Resolver.ParseAddresses()
219 if err != nil {