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 {