How can I use TLS/SSL Client Authentication for specific Hosts when using a reverse proxy like httprouter by julienschmidt?
I could set a Client Certificate in a global matter with http.DefaultTransport
.
transport := &http.Transport{
TLSClientConfig: &tls.Config{
Certificates: []tls.Certificate{cert},
},
}
http.DefaultTransport = transport
But want to use Client Certificate only for specific hosts, like:
- cert1 for host1
- cert2 for host2
- everything else with no Client Certificate
Update
I expected that the callback GetConfigForClientHandler
or
GetCertificateHandler
would be called. At this point I could react on the info.ServerName
. But only GetClientCertificate
get called with no information about the target info.ServerName
.
func main() {
transport := &http.Transport{
TLSClientConfig: &tls.Config{
GetConfigForClient: GetConfigForClientHandler,
GetClientCertificate: GetClientCertificateHandler,
GetCertificate: GetCertificateHandler,
},
}
http.DefaultTransport = transport
// Host which enforce client certificate authentication
resp, err := http.Get("https://example.com")
if err != nil {
fmt.Println("Error", err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
func GetClientCertificateHandler(info *tls.CertificateRequestInfo) (*tls.Certificate, error) {
fmt.Println("GetClientCertificateHandler")
panic("GetClientCertificateHandler")
}
func GetConfigForClientHandler(info *tls.ClientHelloInfo) (*tls.Config, error) {
fmt.Println("GetConfigForClientHandler for:", info.ServerName)
panic("GetConfigForClientHandler")
}
func GetCertificateHandler(info *tls.ClientHelloInfo) (*tls.Certificate, error) {
fmt.Println("GetCertificateHandler for:", info.ServerName)
panic("GetCertificateHandler")
}
Config.GetConfigForClient
handler.ClientHelloInfo.ServerName
. That is the requested host. You then modify the TLS config to require client auth there (Config.ClientAuth
).tls.NewListener
net.Listener
inhttp.Serve
(here is where you could then use httprouter)