diff --git a/caddyhttp/proxy/reverseproxy.go b/caddyhttp/proxy/reverseproxy.go
index ac0e3e1ef..bb7fd4b18 100644
--- a/caddyhttp/proxy/reverseproxy.go
+++ b/caddyhttp/proxy/reverseproxy.go
@@ -337,6 +337,26 @@ func (rp *ReverseProxy) UseOwnCACertificates(CaCertPool *x509.CertPool) {
 	}
 }
 
+// UseClientCertificates is used to facilitate HTTPS proxying
+// with locally provided certificate.
+func (rp *ReverseProxy) UseClientCertificates(keyPair *tls.Certificate) {
+        if transport, ok := rp.Transport.(*http.Transport); ok {
+                if transport.TLSClientConfig == nil {
+                        transport.TLSClientConfig = &tls.Config{}
+                }
+                transport.TLSClientConfig.Certificates = []tls.Certificate{ *keyPair }
+                // No http2.ConfigureTransport() here.
+                // For now this is only added in places where
+                // an http.Transport is actually created.
+        } else if transport, ok := rp.Transport.(*http3.RoundTripper); ok {
+                if transport.TLSClientConfig == nil {
+                        transport.TLSClientConfig = &tls.Config{}
+                }
+                transport.TLSClientConfig.Certificates = []tls.Certificate{ *keyPair }
+        }
+}
+
+
 // ServeHTTP serves the proxied request to the upstream by performing a roundtrip.
 // It is designed to handle websocket connection upgrades as well.
 func (rp *ReverseProxy) ServeHTTP(rw http.ResponseWriter, outreq *http.Request, respUpdateFn respUpdateFn) error {
diff --git a/caddyhttp/proxy/upstream.go b/caddyhttp/proxy/upstream.go
index 8c186dcbe..90ec9f0ee 100644
--- a/caddyhttp/proxy/upstream.go
+++ b/caddyhttp/proxy/upstream.go
@@ -76,6 +76,7 @@ type staticUpstream struct {
 	CaCertPool                   *x509.CertPool
 	upstreamHeaderReplacements   headerReplacements
 	downstreamHeaderReplacements headerReplacements
+	ClientKeyPair                *tls.Certificate
 }
 
 type srvResolver interface {
@@ -267,6 +268,10 @@ func (u *staticUpstream) NewHost(host string) (*UpstreamHost, error) {
 		uh.ReverseProxy.UseOwnCACertificates(u.CaCertPool)
 	}
 
+	if u.ClientKeyPair != nil {
+		uh.ReverseProxy.UseClientCertificates(u.ClientKeyPair)
+	}
+
 	return uh, nil
 }
 
@@ -564,6 +569,20 @@ func parseBlock(c *caddyfile.Dispenser, u *staticUpstream, hasSrv bool) error {
 			return c.Errf("unable to parse timeout duration '%s'", c.Val())
 		}
 		u.Timeout = dur
+	case "tls_client":
+		if !c.NextArg() {
+                        return c.ArgErr()
+                }
+                clientCertFile := c.Val()
+		if !c.NextArg() {
+                        return c.ArgErr()
+                }
+                clientKeyFile := c.Val()
+		clientKeyPair, err := tls.LoadX509KeyPair(clientCertFile, clientKeyFile)
+        	if (err != nil) {
+                	return c.Errf("unable to load keypair from certfile:%s keyfile:%s", clientCertFile, clientKeyFile)
+        	}
+		u.ClientKeyPair = &clientKeyPair
 	default:
 		return c.Errf("unknown property '%s'", c.Val())
 	}