Frontend Labs
⋯

Day 38 — TLS Handshake

Learning Objectives

  • Understand what happens during a TLS handshake (why cert expiry causes incidents)
  • Inspect live TLS connections: version, cipher, expiry
  • Build a cert expiry monitor — the tool that prevents your next outage

Key Concepts

TLS 1.3 Handshake (simplified):
  Client → ClientHello (supported ciphers, TLS version, random)
  Server ← ServerHello (chosen cipher, TLS version, random)
  Server ← Certificate (server's cert chain)
  Server ← CertificateVerify (signature proves server has the private key)
  Server ← Finished
  Client → Finished
  ─────── Handshake complete (~1 RTT ───────
  Client ⟺ Server: encrypted application data

Why cert expiry causes outages:
  - Browser/client rejects expired cert → connection fails
  - No graceful fallback — hard failure
  - "Certificate expired" is in the top 5 causes of security incidents

Certificate fields you need to know:
  Subject     → who the cert is for (CommonName, SANs)
  Issuer      → who signed it (CA)
  NotBefore   → valid from
  NotAfter    → valid until (expiry)
  SANs        → Subject Alternative Names (DNS names and IPs the cert covers)
  KeyUsage    → what the cert can be used for

Exercise: TLS Inspector + Cert Monitor

package main

import (
    "crypto/tls"
    "crypto/x509"
    "fmt"
    "net"
    "time"
)

type CertInfo struct {
    Host        string
    TLSVersion  string
    CipherSuite string
    Subject     string
    Issuer      string
    NotAfter    time.Time
    SANs        []string
    DaysLeft    int
    Warning     string
}

func tlsVersionName(v uint16) string {
    switch v {
    case tls.VersionTLS10: return "TLS 1.0 (INSECURE)"
    case tls.VersionTLS11: return "TLS 1.1 (DEPRECATED)"
    case tls.VersionTLS12: return "TLS 1.2"
    case tls.VersionTLS13: return "TLS 1.3"
    default: return fmt.Sprintf("unknown(0x%x)", v)
    }
}

func inspectTLS(host string) (*CertInfo, error) {
    conf := &tls.Config{
        ServerName: host,
        // InsecureSkipVerify: false — NEVER skip verification in production
    }

    conn, err := tls.DialWithDialer(
        &net.Dialer{Timeout: 10 * time.Second},
        "tcp", host+":443", conf,
    )
    if err != nil {
        return nil, fmt.Errorf("TLS connect: %w", err)
    }
    defer conn.Close()

    state := conn.ConnectionState()
    cert := state.PeerCertificates[0] // leaf cert (server's cert)
    daysLeft := int(time.Until(cert.NotAfter).Hours() / 24)

    info := &CertInfo{
        Host:        host,
        TLSVersion:  tlsVersionName(state.Version),
        CipherSuite: tls.CipherSuiteName(state.CipherSuite),
        Subject:     cert.Subject.CommonName,
        Issuer:      cert.Issuer.CommonName,
        NotAfter:    cert.NotAfter,
        SANs:        cert.DNSNames,
        DaysLeft:    daysLeft,
    }

    if daysLeft < 7 {
        info.Warning = fmt.Sprintf("CRITICAL: cert expires in %d days!", daysLeft)
    } else if daysLeft < 30 {
        info.Warning = fmt.Sprintf("WARNING: cert expires in %d days", daysLeft)
    }

    return info, nil
}

func main() {
    hosts := []string{"example.com", "golang.org", "cloudflare.com"}
    for _, host := range hosts {
        info, err := inspectTLS(host)
        if err != nil {
            fmt.Printf("[%s] ERROR: %v\n", host, err)
            continue
        }
        fmt.Printf("[%s]\n", info.Host)
        fmt.Printf("  TLS:     %s\n", info.TLSVersion)
        fmt.Printf("  Cipher:  %s\n", info.CipherSuite)
        fmt.Printf("  Subject: %s\n", info.Subject)
        fmt.Printf("  Issuer:  %s\n", info.Issuer)
        fmt.Printf("  Expiry:  %s (%d days)\n", info.NotAfter.Format("2006-01-02"), info.DaysLeft)
        fmt.Printf("  SANs:    %v\n", info.SANs)
        if info.Warning != "" {
            fmt.Printf("  *** %s ***\n", info.Warning)
        }
        fmt.Println()
    }
}

Real-World Context

Cert expiry is one of the top causes of security incidents. Facebook had a major outage in 2019 partly due to a cert issue. LinkedIn, Spotify, and many others have had cert expiry outages. Build a monitoring tool that checks every cert in your fleet daily and alerts at 30 days. This code is that tool.


Generated from week6.md · 8 Oct 2026 16:36