diff --git a/caddytest/integration/caddyfile_adapt/reverse_proxy_options.txt b/caddytest/integration/caddyfile_adapt/reverse_proxy_options.txt index fc07698d..29f6d236 100644 --- a/caddytest/integration/caddyfile_adapt/reverse_proxy_options.txt +++ b/caddytest/integration/caddyfile_adapt/reverse_proxy_options.txt @@ -24,6 +24,7 @@ https://example.com { max_conns_per_host 5 keepalive_idle_conns_per_host 2 keepalive_interval 30s + renegotiation freely } } } @@ -91,7 +92,9 @@ https://example.com { ] }, "response_header_timeout": 8000000000, - "tls": {}, + "tls": { + "renegotiation": "freely" + }, "versions": [ "h2c", "2" diff --git a/modules/caddyhttp/reverseproxy/caddyfile.go b/modules/caddyhttp/reverseproxy/caddyfile.go index ebea49eb..dfb30d80 100644 --- a/modules/caddyhttp/reverseproxy/caddyfile.go +++ b/modules/caddyhttp/reverseproxy/caddyfile.go @@ -922,6 +922,20 @@ func (h *HTTPTransport) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { return d.ArgErr() } + case "renegotiation": + if h.TLS == nil { + h.TLS = new(TLSConfig) + } + if !d.NextArg() { + return d.ArgErr() + } + switch renegotiation := d.Val(); renegotiation { + case "never", "once", "freely": + h.TLS.Renegotiation = renegotiation + default: + return d.ArgErr() + } + case "tls": if h.TLS == nil { h.TLS = new(TLSConfig) diff --git a/modules/caddyhttp/reverseproxy/httptransport.go b/modules/caddyhttp/reverseproxy/httptransport.go index 54cdb70f..e6ff188b 100644 --- a/modules/caddyhttp/reverseproxy/httptransport.go +++ b/modules/caddyhttp/reverseproxy/httptransport.go @@ -324,6 +324,14 @@ type TLSConfig struct { // support placeholders because the TLS config is not provisioned on each // connection, so a static value must be used. ServerName string `json:"server_name,omitempty"` + + // TLS renegotiation level. TLS renegotiation is the act of performing + // subsequent handshakes on a connection after the first. + // The level can be: + // - "never": (the default) disables renegotiation. + // - "once": allows a remote server to request renegotiation once per connection. + // - "freely": allows a remote server to repeatedly request renegotiation. + Renegotiation string `json:"renegotiation,omitempty"` } // MakeTLSClientConfig returns a tls.Config usable by a client to a backend. @@ -393,6 +401,18 @@ func (t TLSConfig) MakeTLSClientConfig(ctx caddy.Context) (*tls.Config, error) { cfg.RootCAs = rootPool } + // Renegotiation + switch t.Renegotiation { + case "never": + cfg.Renegotiation = tls.RenegotiateNever + case "once": + cfg.Renegotiation = tls.RenegotiateOnceAsClient + case "freely": + cfg.Renegotiation = tls.RenegotiateFreelyAsClient + default: + return nil, fmt.Errorf("invalid TLS renegotiation level: %v", t.Renegotiation) + } + // override for the server name used verify the TLS handshake cfg.ServerName = t.ServerName