mirror of
				https://github.com/tailscale/tailscale.git
				synced 2025-11-04 00:55:11 +00:00 
			
		
		
		
	Making way for a future Probe struct to encapsulate per-probe state. Signed-off-by: David Anderson <danderson@tailscale.com>
		
			
				
	
	
		
			47 lines
		
	
	
		
			1.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			47 lines
		
	
	
		
			1.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright (c) 2022 Tailscale Inc & AUTHORS All rights reserved.
 | 
						|
// Use of this source code is governed by a BSD-style
 | 
						|
// license that can be found in the LICENSE file.
 | 
						|
 | 
						|
package prober
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"crypto/tls"
 | 
						|
	"fmt"
 | 
						|
	"net"
 | 
						|
	"time"
 | 
						|
)
 | 
						|
 | 
						|
// TLS returns a Probe that healthchecks a TLS endpoint.
 | 
						|
//
 | 
						|
// The ProbeFunc connects to hostname, does a TLS handshake, verifies
 | 
						|
// that the hostname matches the presented certificate, and that the
 | 
						|
// certificate expires in more than 7 days from the probe time.
 | 
						|
func TLS(hostname string) ProbeFunc {
 | 
						|
	return func(ctx context.Context) error {
 | 
						|
		return probeTLS(ctx, hostname)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func probeTLS(ctx context.Context, hostname string) error {
 | 
						|
	var d net.Dialer
 | 
						|
	conn, err := tls.DialWithDialer(&d, "tcp", hostname+":443", nil)
 | 
						|
	if err != nil {
 | 
						|
		return fmt.Errorf("connecting to %q: %w", hostname, err)
 | 
						|
	}
 | 
						|
	if err := conn.Handshake(); err != nil {
 | 
						|
		return fmt.Errorf("TLS handshake error with %q: %w", hostname, err)
 | 
						|
	}
 | 
						|
	if err := conn.VerifyHostname(hostname); err != nil {
 | 
						|
		return fmt.Errorf("Host %q TLS verification failed: %w", hostname, err)
 | 
						|
	}
 | 
						|
 | 
						|
	latestAllowedExpiration := time.Now().Add(7 * 24 * time.Hour) // 7 days from now
 | 
						|
	if expires := conn.ConnectionState().PeerCertificates[0].NotAfter; latestAllowedExpiration.After(expires) {
 | 
						|
		left := expires.Sub(time.Now())
 | 
						|
		return fmt.Errorf("TLS certificate for %q expires in %v", hostname, left)
 | 
						|
	}
 | 
						|
 | 
						|
	return nil
 | 
						|
}
 |