TLS身份验证:每个证书需要包含哪些内容?

I'm writing a config daemon.

It works like this:

accepts

  • GET (read)
  • POST (update)
  • PUT (create)
  • DELETE (delete)

methods

example:

PUT http://server1/key (body = value)

stores value under key

GET http://server1/key

returns value in response body

Now, when a PUT, POST, DELETE is made it duplicates this request and sends it to peers, so that every node has the same data and any node can be queried in case one of the nodes is unavailable. It adds a header so the nodes know that they shouldn't duplicate a request and send out to other nodes.

Ok, this works so far, but now I'd like to only allow the nodes and a WebUI to be able to transmit requests to those nodes. And here is where TLS comes into play.

As far as I understand I need a rootCA, so I can sign server and client certificates. And I'd like to have valid certificates, not "self-signed" because I would use Go and crypto/tls and it should verify the certificates.

My question is:

Which extensions or fields do each of the certificates need? I wouldn't want to re-generate the server and client certs when a new node is added to the config server pool.

I would connect by IP address, not by hostname/dnsname (to skip hostname lookups and the potential eavesdropping of a third party by assigning an IP to their own dnsname, e.g. s1.myserver.com is mine with IP 1.2.3.4 and random dude creates a DNS entry with random.dude.com 1.2.3.4, because I get a list of all nodes by doing a NS lookup of clustercfg.mydomain.com)

On each new node I'd need to create a server cert (this is me, verify that it's true)

On each new node I'd need to create a client cert (so I can authenticate that this client node is valid and is allowed to access this server node)

The question is:

X509v3 extensions:
    X509v3 Key Usage: critical
        Digital Signature, Key Encipherment, Certificate Sign
    X509v3 Extended Key Usage: 
        TLS Web Server Authentication
    X509v3 Basic Constraints: critical
        CA:TRUE
    X509v3 Subject Alternative Name: 
        DNS:server1.myserver.com, IP Address:2a02::0:0:0:0:0:0:2, IP Address:1.2.3.4

What does a rootCA, a server certificate, a client certificate need so I'm able to do "TLS Authentication"?

You can use a normal server certificate like the ones you use in a web server for the server. Go will check that properly when you connect.

As for client certificates, here is a gist showing how to generate and use the client certificates from Go.

I've uses this code for a similar secure system of clients contacting servers.

You don't need to connect by IP address as the client will check the server's certificate matches the hostname which is an extremely good check.

Hope that helps!

What is needed?

  1. A Certificate Authority (CA)
  2. Another CA signed by the first CA
  3. More CAs if you like

2 and 3 are optional

CAs need template.KeyUsage = x509.KeyUsageCertSign | x509.KeyUsageCRLSign

  1. A server certificate and key

Sign the certificate with the least CA created. The least CA will be the one you will use to verify client certificates

This certificate also acts as a client certificate, so it needs

template.KeyUsage = x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature
template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}

If you need more security add SANs.

template.DNSNames
template.IPAddresses
  1. In your server

a

var (
    selfname string
    certFile = flag.String("cert", "", "server certificate file.")
    keyFile  = flag.String("key", "", "server private key file.")
    rootCA   = flag.String("ca", "cacerts.pem", "rootca")
)
certpool := x509.NewCertPool()
pem, err := ioutil.ReadFile(*rootCA)
if err != nil {
log.Fatalf("Failed to read client certificate authority: %v", err)
}
if !certpool.AppendCertsFromPEM(pem) {
    log.Fatalf("Can't parse client certificate authority")
}

config := &tls.Config{
    ServerName: selfname, // os.Hostname()
    ClientAuth: tls.RequireAndVerifyClientCert,
    ClientCAs:  certpool,
    MinVersion: tls.VersionTLS10,
}

server := http.Server{
    Addr:         ":12345",
    ReadTimeout:  time.Second * 10,
    WriteTimeout: time.Second * 10,
    TLSConfig:    config,
}
log.Fatalln(server.ListenAndServeTLS(*certFile, *keyFile))