Client Certificates

Configure client certificate verification

Client certificates allow the internal web server to verify a web connection is coming from a Pritunl Zero server. Connections that do not have a valid certificate will be blocked by the internal web server. This prevents unauthenticated connections even if the remote user has network access to the internal web server. The Pritunl Zero server manages the certificate authority for the client certificates and uses regularly renewed certificates that are valid for 30 seconds.

Client certificates offer similar functionality to JWT tokens without requiring significant changes to the internal web server. Most web servers and web frameworks have support for client certificate authentication without the need for any plugins or modifications to the internal application. Client certificates will not effect web technologies such as WebSockets or long polling connections.

Create Authority

Authorities in Pritunl Zero represent a public key pair with a certificate authority. Multiple authorities can be created and a different one can be used for each internal web service if required. Open the Authorities tab in the Pritunl Zero web console and create an authority if one does not exists. No authority options need to be configured for client certificates. The certificate expire option is unrelated to client certificates.

Configure Service

Open the Services tab and select the authority created above in the Client Certificate Authority option. To minimize downtime this step should be done before configuring the internal web server. Adding a client certificate to the service will not effect connections to the internal web server, the client certificate is only sent when requested by the internal server. The connection to the internal server must also use HTTPS. The internal server must allow HTTPS connections but does not require a valid certificate if the internal server is configured with an IP address in Pritunl Zero. If a hostname is used in Pritunl Zero the internal server must have a valid certificate.

Configure Internal Server

Open the Authorities tab and select the Root Certificate tab. This will display the root CA certificate that will be used for client certificates. This CA certificate must be copied to the internal web server and stored in the paths shown in the examples below.

Configuring the internal server will depend on what software is used. Below is an example configuration for Nginx, Gitlab and Go.

ssl_client_certificate /etc/nginx/client.crt;
ssl_verify_client on;
sudo nano /etc/gitlab/gitlab.rb
##! Most root CA's are included by default
nginx['ssl_client_certificate'] = "/etc/gitlab/ssl/client.crt"

##! enable/disable 2-way SSL client authentication
nginx['ssl_verify_client'] = "on"

sudo gitlab-ctl reconfigure
const clientCa = `-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
`

func main() {
    certPool := x509.NewCertPool()
    certPool.AppendCertsFromPEM([]byte(clientCa))

    tlsConfig := &tls.Config{
        ClientAuth: tls.RequireAndVerifyClientCert,
        ClientCAs:  certPool,
    }

    listener, err := tls.Listen("tcp", ":8443", tlsConfig)
    if err != nil {
        panic(err)
    }

    server := &http.Server{
        Addr:    ":8443",
        Handler: engine,
    }

    err = server.Serve(listener)
    if err != nil {
        panic(err)
    }
}

Test Internal Server

Once configured connections directly to the internal web server should display a certificate error similar to the one shown below.

Connections from the Pritunl Zero server should work without any errors.