mirror of
https://github.com/caddyserver/caddy.git
synced 2025-10-28 01:02:49 -04:00
reverseproxy: do not disable keepalive if proxy protocol is used (#7300)
This commit is contained in:
parent
156ce99d3a
commit
8aca108d2c
@ -285,3 +285,6 @@ type ProxyProtocolInfo struct {
|
|||||||
// tlsH1OnlyVarKey is the key used that indicates the connection will use h1 only for TLS.
|
// tlsH1OnlyVarKey is the key used that indicates the connection will use h1 only for TLS.
|
||||||
// https://github.com/caddyserver/caddy/issues/7292
|
// https://github.com/caddyserver/caddy/issues/7292
|
||||||
const tlsH1OnlyVarKey = "reverse_proxy.tls_h1_only"
|
const tlsH1OnlyVarKey = "reverse_proxy.tls_h1_only"
|
||||||
|
|
||||||
|
// proxyVarKey is the key used that indicates the proxy server used for a request.
|
||||||
|
const proxyVarKey = "reverse_proxy.proxy"
|
||||||
|
|||||||
@ -24,6 +24,7 @@ import (
|
|||||||
weakrand "math/rand"
|
weakrand "math/rand"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"slices"
|
"slices"
|
||||||
@ -267,15 +268,15 @@ func (h *HTTPTransport) NewTransport(caddyCtx caddy.Context) (*http.Transport, e
|
|||||||
}
|
}
|
||||||
|
|
||||||
dialContext := func(ctx context.Context, network, address string) (net.Conn, error) {
|
dialContext := func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||||
// For unix socket upstreams, we need to recover the dial info from
|
// The network is usually tcp, and the address is the host in http.Request.URL.Host
|
||||||
// the request's context, because the Host on the request's URL
|
// and that's been overwritten in directRequest
|
||||||
// will have been modified by directing the request, overwriting
|
// However, if proxy is used according to http.ProxyFromEnvironment or proxy providers,
|
||||||
// the unix socket filename.
|
// address will be the address of the proxy server.
|
||||||
// Also, we need to avoid overwriting the address at this point
|
|
||||||
// when not necessary, because http.ProxyFromEnvironment may have
|
// This means we can safely use the address in dialInfo if proxy is not used (the address and network will be same any way)
|
||||||
// modified the address according to the user's env proxy config.
|
// or if the upstream is unix (because there is no way socks or http proxy can be used for unix address).
|
||||||
if dialInfo, ok := GetDialInfo(ctx); ok {
|
if dialInfo, ok := GetDialInfo(ctx); ok {
|
||||||
if strings.HasPrefix(dialInfo.Network, "unix") {
|
if caddyhttp.GetVar(ctx, proxyVarKey) == nil || strings.HasPrefix(dialInfo.Network, "unix") {
|
||||||
network = dialInfo.Network
|
network = dialInfo.Network
|
||||||
address = dialInfo.Address
|
address = dialInfo.Address
|
||||||
}
|
}
|
||||||
@ -376,9 +377,19 @@ func (h *HTTPTransport) NewTransport(caddyCtx caddy.Context) (*http.Transport, e
|
|||||||
return nil, fmt.Errorf("network_proxy module is not `(func(*http.Request) (*url.URL, error))``")
|
return nil, fmt.Errorf("network_proxy module is not `(func(*http.Request) (*url.URL, error))``")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// we need to keep track if a proxy is used for a request
|
||||||
|
proxyWrapper := func(req *http.Request) (*url.URL, error) {
|
||||||
|
u, err := proxy(req)
|
||||||
|
if u == nil || err != nil {
|
||||||
|
return u, err
|
||||||
|
}
|
||||||
|
// there must be a proxy for this request
|
||||||
|
caddyhttp.SetVar(req.Context(), proxyVarKey, u)
|
||||||
|
return u, nil
|
||||||
|
}
|
||||||
|
|
||||||
rt := &http.Transport{
|
rt := &http.Transport{
|
||||||
Proxy: proxy,
|
Proxy: proxyWrapper,
|
||||||
DialContext: dialContext,
|
DialContext: dialContext,
|
||||||
MaxConnsPerHost: h.MaxConnsPerHost,
|
MaxConnsPerHost: h.MaxConnsPerHost,
|
||||||
ResponseHeaderTimeout: time.Duration(h.ResponseHeaderTimeout),
|
ResponseHeaderTimeout: time.Duration(h.ResponseHeaderTimeout),
|
||||||
@ -457,14 +468,6 @@ func (h *HTTPTransport) NewTransport(caddyCtx caddy.Context) (*http.Transport, e
|
|||||||
rt.IdleConnTimeout = time.Duration(h.KeepAlive.IdleConnTimeout)
|
rt.IdleConnTimeout = time.Duration(h.KeepAlive.IdleConnTimeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The proxy protocol header can only be sent once right after opening the connection.
|
|
||||||
// So single connection must not be used for multiple requests, which can potentially
|
|
||||||
// come from different clients.
|
|
||||||
if !rt.DisableKeepAlives && h.ProxyProtocol != "" {
|
|
||||||
caddyCtx.Logger().Warn("disabling keepalives, they are incompatible with using PROXY protocol")
|
|
||||||
rt.DisableKeepAlives = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if h.Compression != nil {
|
if h.Compression != nil {
|
||||||
rt.DisableCompression = !*h.Compression
|
rt.DisableCompression = !*h.Compression
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1198,7 +1198,7 @@ func (lb LoadBalancing) tryAgain(ctx caddy.Context, start time.Time, retries int
|
|||||||
|
|
||||||
// directRequest modifies only req.URL so that it points to the upstream
|
// directRequest modifies only req.URL so that it points to the upstream
|
||||||
// in the given DialInfo. It must modify ONLY the request URL.
|
// in the given DialInfo. It must modify ONLY the request URL.
|
||||||
func (Handler) directRequest(req *http.Request, di DialInfo) {
|
func (h *Handler) directRequest(req *http.Request, di DialInfo) {
|
||||||
// we need a host, so set the upstream's host address
|
// we need a host, so set the upstream's host address
|
||||||
reqHost := di.Address
|
reqHost := di.Address
|
||||||
|
|
||||||
@ -1209,6 +1209,13 @@ func (Handler) directRequest(req *http.Request, di DialInfo) {
|
|||||||
reqHost = di.Host
|
reqHost = di.Host
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add client address to the host to let transport differentiate requests from different clients
|
||||||
|
if ht, ok := h.Transport.(*HTTPTransport); ok && ht.ProxyProtocol != "" {
|
||||||
|
if proxyProtocolInfo, ok := caddyhttp.GetVar(req.Context(), proxyProtocolInfoVarKey).(ProxyProtocolInfo); ok {
|
||||||
|
reqHost = proxyProtocolInfo.AddrPort.String() + "->" + reqHost
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
req.URL.Host = reqHost
|
req.URL.Host = reqHost
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user