SSL/TLS#

TLS is the encryption-and-authentication layer that wraps almost every modern protocol (HTTPS, IMAPS, LDAPS, gRPC, MQTT, mail submission, the lot. SSL is the obsolete name (SSLv3 and earlier are broken; SSLv2 has been forbidden in browsers since 2011) but the term survives in tool names (openssl), config keywords (ssl_certificate), and conversation.

The operator cares about TLS for three reasons: it terminates somewhere they own (front-end, load balancer, redirector), it tells them whether traffic is trustworthy (cert chain, hostname, expiry, issuer), and it occasionally becomes the whole incident (expired cert at 03:00). Operator-facing TLS: handshake basics, the trust store, openssl s_client workflows, certificate issuance (Let’s Encrypt), and the common failure modes.

Handshake#

TLS 1.3 (RFC 8446, the current standard) compresses the handshake into one round trip; TLS 1.2 needs two. Both negotiate cipher suite, authenticate the server, and derive session keys.

        sequenceDiagram
    participant C as Client
    participant S as Server
    C->>S: ClientHello<br/>(versions, ciphers, SNI, key share)
    S->>C: ServerHello + cert + key share + Finished
    C->>S: Finished
    Note over C,S: TLS 1.3: 1-RTT handshake, app data flows
    C->>S: Application data (encrypted)
    S->>C: Application data (encrypted)
    

What gets verified:

Property

How

Server identity

Certificate signed by a trusted CA, CN / subjectAltName matches hostname (SNI)

Session integrity

AEAD cipher (AES-GCM, ChaCha20-Poly1305) over every record

Forward secrecy

ECDHE / DHE key exchange (mandatory in TLS 1.3)

Replay resistance

Sequence numbers in record layer

The trust store#

A client only trusts a cert if its issuing CA chain ends in a CA already in the local trust store.

Path

Distro / use

/etc/ssl/certs/ca-certificates.crt

Debian / Ubuntu bundle

/etc/pki/tls/certs/ca-bundle.crt

RHEL / Fedora bundle

/etc/ssl/cert.pem

Alpine

/usr/local/share/ca-certificates/

Debian: drop .crt here, run update-ca-certificates

/etc/pki/ca-trust/source/anchors/

RHEL: drop here, run update-ca-trust

$SSL_CERT_FILE / $SSL_CERT_DIR

Override at runtime (curl, openssl, many libs)

Inspect a server#

The operator’s Swiss-army knife is openssl s_client:

$ openssl s_client -connect example.com:443 -servername example.com
$ openssl s_client -connect example.com:443 -showcerts          # full chain
$ openssl s_client -connect smtp.example.com:25 -starttls smtp
$ openssl s_client -connect imap.example.com:143 -starttls imap

Quick certificate facts:

# subject, issuer, dates
$ openssl s_client -connect host:443 </dev/null 2>/dev/null \
    | openssl x509 -noout -subject -issuer -dates -ext subjectAltName

# fingerprint
$ openssl x509 -in cert.pem -noout -fingerprint -sha256

# decode a PKCS#12 / PFX
$ openssl pkcs12 -in bundle.p12 -nokeys -nodes

Issuing certificates#

Source

Use

Public CA

Trusted by browsers; via ACME (Let’s Encrypt, ZeroSSL, Buypass) or paid CAs (DigiCert, Sectigo). Always domain-validated; OV / EV exist but rarely matter operationally.

Private CA

Internal CA for VPN clients, service mesh, mTLS. cfssl, smallstep (step-ca), HashiCorp Vault PKI, OpenSSL ca are common choices.

Self-signed

Test only; nothing trusts it without manual install.

ACME (Let’s Encrypt) on a real host:

$ sudo apt install certbot python3-certbot-nginx
$ sudo certbot --nginx -d example.com -d www.example.com
$ sudo certbot renew --dry-run                    # test the renewal hook
$ sudo systemctl status certbot.timer             # auto-renew

Common failure modes#

Symptom

Likely cause

certificate has expired

Renewal didn’t run; check certbot.timer and the ACME challenge path.

hostname mismatch

Cert CN / subjectAltName doesn’t include the name the client connected with. Inspect with openssl x509 -ext subjectAltName.

unknown CA / not trusted

Intermediate cert missing from chain (use -showcerts to see what the server sends); or private CA not installed in trust store.

handshake_failure

Client and server share no common cipher / TLS version. Check with nmap --script ssl-enum-ciphers.

unable to get local issuer

Client trust store doesn’t include the issuing CA root. Update with update-ca-certificates / update-ca-trust.

See also#

  • HTTP, the protocol HTTPS wraps.

  • man openssl-s_client, man openssl-x509.

  • testssl.sh and sslyze, comprehensive TLS auditors.

  • RFC 8446 (TLS 1.3), RFC 5246 (TLS 1.2), RFC 8555 (ACME).