gomtls

mTLS with go: client certificate not sent to server


I'm trying to establish a mTLS connection with the server being the Caddy admin-API and the client being go. Certificates are set up and working - verified with curl.

There are plenty of explanations and code snippets out there explaining this setup in go, yet I always receive the error remote error: tls: certificate required

The error log server side is {"level":"debug","ts":1721118435.5978072,"logger":"admin.remote","msg":"http: TLS handshake error from ___:65411: tls: client didn't provide a certificate"}

What am I doing wrong?

Here is my code for testing:

package main

import (
    "crypto/tls"
    "flag"
    "fmt"
    "io"
    "log"
    "net/http"
)

func main() {
    cert := flag.String("cert", "./cert.pem", "TLS client certificate in PEM format")
    key := flag.String("key", "./key.pem", "TLS client key in PEM format")
    flag.Parse()

    keypair, err := tls.LoadX509KeyPair(*cert, *key)
    if err != nil {
        log.Fatal(err)
    }
    client := http.Client{
        Transport: &http.Transport{
            TLSClientConfig: &tls.Config{
                Certificates: []tls.Certificate{keypair},
                MinVersion:   tls.VersionTLS13,
            },
        },
    }
    res, err := client.Get("https://caddy.influxdb.eco2web.de:2021/config/")
    if err != nil {
        log.Fatal(err)
    }
    defer res.Body.Close()
    body, err := io.ReadAll(res.Body)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(string(body))
}

Solution

  • I have the same problem and have tried to replace the GetClientCertificate function so that the client certificate I want is returned "unchecked". It seems to have accepted this so far, but unfortunately I am now getting the "tls - bad certificate" response from the server, even though the whole thing has been accepted as a valid client certificate via curl.

    I have also entered all CA certificates under both RootCAs and ClientCAs.