Golang TLS Server、Kube-Apiserver 校验客户端证书原理

本文深入探讨了使用Golang实现TLS Server时,如何通过不同的ClientAuth策略来控制是否及如何验证客户端证书,揭示了即使配置了CA证书,Server端也不一定会校验客户端证书的细节。

当我们用Golang写一个TLS Server的时候,假设给Server端配置了CA证书,那么Server端一定会校验客户端的证书吗?答案是,即使我们给Server端配置了CA证书,Server端也不一定会校验客户端的证书

看一个TLS Server端的例子:

package main

import (
    "log"
    "crypto/tls"
    "net"
    "fmt"
    "crypto/x509"
    "bufio"
    "io/ioutil"
)

func main() {
    log.SetFlags(log.Lshortfile)

    cer, err := tls.LoadX509KeyPair("server.crt", "server.key")
    if err != nil {
        log.Println(err)
        return
    }

    ca, err := ioutil.ReadFile("client-CA.crt")
    
    pool := x509.NewCertPool()
    ok := pool.AppendCertsFromPEM(ca)
	if !ok {
		panic(fmt.Errorf("fail to load ca content"))
	}    

    
    tlsConfig := &tls.Config{
        ClientCAs:    pool,
        ClientAuth:  tls.RequireAnyClientCert,
        Certificates: []tls.Certificate{cer},
    }

    ln, err := tls.Listen("tcp", ":443", tlsConfig) 
    if err != nil {
        log.Println(err)
        return
    }
    defer ln.Close()

    for {
        conn, err := ln.Accept()
        if err != nil {
            log.Println(err)
            continue
        }
        go handleConnection(conn)
    }
}

func handleConnection(conn net.Conn) {
    defer conn.Close()
    r := bufio.NewReader(conn)
    for {
        msg, err := r.ReadString('\n')
        if err != nil {
            log.Println(err)
            return
        }

        println(msg)

        n, err := conn.Write([]byte("world\n"))
        if err != nil {
            log.Println(n, err)
            return
        }
    }
}

 

我们在tlsConfig中可以看到,配置了验证客户端正的CA ClientCAs,还有服务端的证书Certificates。除此之外还有一个很重要的字段——ClientAuth,在Golang中,ClientAuth决定了Server端如何验证客户端的证书。

// ClientAuthType declares the policy the server will follow for
// TLS Client Authentication.
type ClientAuthType int

const (
	NoClientCert ClientAuthType = iota
	RequestClientCert
	RequireAnyClientCert
	VerifyClientCertIfGiven
	RequireAndVerifyClientCert
)

 

ClientAuth有五种类型,分别是 NoClientCert、RequestClientCert、RequireAnyClientCert、VerifyClientCertIfGiven、RequireAndVerifyClientCert,各自的含义是:

 

  • NoClientCert:忽略任何客户端证书,即客户端可以不提供证书。
  • RequestClientCert:要求客户端提供证书,但是如果客户端没有提供证书,服务端还是会继续处理请求。
  • RequireAnyClientCert:需要客户端提供证书,但不用ClientCA来验证证书的有效性。
  • VerifyClientCertIfGiven:如果客户端提供了证书,则用ClientCA来验证证书的有效性。 如果客户端没提供,则会继续处理请求。
  • RequireAndVerifyClientCert:需要客户端提供证书,且会用ClientCA来验证证书的有效性。

 

在tlsConfig中如果不显式的指定ClientAuth,则默认值是NoClientCert。即使Server端配置了CA,也不会校验客户端证书。

 

在K8s中我们知道Kube-Apiserver是有多种认证方式的,包括账号密码、Token、证书等。其实它的ClientAuth设置的就是RequestClientCert。即在Tls这层是不强校验客户端证书的。这样才能保证Tls能接受多种来自客户端的凭据。

if s.ClientCA != nil {
		// Populate PeerCertificates in requests, but don't reject connections without certificates
		// This allows certificates to be validated by authenticators, while still allowing other auth types
		tlsConfig.ClientAuth = tls.RequestClientCert
	}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值