diff --git a/caddytest/integration/caddyfile_adapt/reverse_proxy_options.txt b/caddytest/integration/caddyfile_adapt/reverse_proxy_options.txt
index fc07698dd..29f6d2364 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 ebea49eb5..dfb30d804 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 54cdb70f9..e6ff188b9 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