ssl-tls-management

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

SSL/TLS Management

SSL/TLS 证书管理

Manage certificates and secure communications across web servers, Kubernetes clusters, and internal services.
跨Web服务器、Kubernetes集群和内部服务管理证书与安全通信。

When to Use This Skill

何时使用该技能

Use this skill when:
  • Setting up HTTPS for a new web application
  • Automating certificate renewal with Let's Encrypt
  • Deploying cert-manager in Kubernetes
  • Configuring TLS for internal service-to-service communication
  • Auditing cipher suites and TLS versions for compliance
  • Responding to an expiring or compromised certificate
在以下场景中使用本技能:
  • 为新Web应用配置HTTPS
  • 通过Let's Encrypt实现证书续期自动化
  • 在Kubernetes中部署cert-manager
  • 为内部服务间通信配置TLS
  • 审核加密套件与TLS版本以符合合规要求
  • 处理证书过期或泄露问题

Prerequisites

前置条件

  • Domain name with DNS control for public certificates
  • Root/sudo access on web servers
  • certbot
    installed for Let's Encrypt
  • openssl
    CLI available (installed by default on most Linux distros)
  • Kubernetes cluster with Helm for cert-manager deployment
  • Understanding of X.509 certificate chain of trust
  • 拥有可控制DNS的域名(用于公共证书)
  • Web服务器的Root/sudo权限
  • 已安装用于Let's Encrypt的
    certbot
  • 具备
    openssl
    命令行工具(多数Linux发行版默认安装)
  • 带有Helm的Kubernetes集群(用于部署cert-manager)
  • 了解X.509证书信任链

Let's Encrypt with Certbot

使用Certbot管理Let's Encrypt证书

Installation and Certificate Issuance

安装与证书签发

bash
undefined
bash
undefined

Install certbot (Ubuntu/Debian)

Install certbot (Ubuntu/Debian)

apt update && apt install -y certbot python3-certbot-nginx
apt update && apt install -y certbot python3-certbot-nginx

Obtain certificate for nginx (interactive)

Obtain certificate for nginx (interactive)

certbot --nginx -d example.com -d www.example.com
certbot --nginx -d example.com -d www.example.com

Non-interactive mode for automation

Non-interactive mode for automation

certbot certonly --nginx
-d example.com
-d www.example.com
--non-interactive
--agree-tos
--email admin@example.com
certbot certonly --nginx
-d example.com
-d www.example.com
--non-interactive
--agree-tos
--email admin@example.com

Standalone mode (when no web server is running)

Standalone mode (when no web server is running)

certbot certonly --standalone
-d example.com
--preferred-challenges http
certbot certonly --standalone
-d example.com
--preferred-challenges http

DNS challenge (for wildcard certs)

DNS challenge (for wildcard certs)

certbot certonly --manual
--preferred-challenges dns
-d "*.example.com"
-d example.com
certbot certonly --manual
--preferred-challenges dns
-d "*.example.com"
-d example.com

Using DNS plugin for automation (Cloudflare example)

Using DNS plugin for automation (Cloudflare example)

pip install certbot-dns-cloudflare cat > /etc/letsencrypt/cloudflare.ini << 'EOF' dns_cloudflare_api_token = YOUR_CLOUDFLARE_API_TOKEN EOF chmod 600 /etc/letsencrypt/cloudflare.ini
certbot certonly --dns-cloudflare
--dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini
-d "*.example.com"
-d example.com
undefined
pip install certbot-dns-cloudflare cat > /etc/letsencrypt/cloudflare.ini << 'EOF' dns_cloudflare_api_token = YOUR_CLOUDFLARE_API_TOKEN EOF chmod 600 /etc/letsencrypt/cloudflare.ini
certbot certonly --dns-cloudflare
--dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini
-d "*.example.com"
-d example.com
undefined

Renewal Automation

续期自动化

bash
undefined
bash
undefined

Test renewal

Test renewal

certbot renew --dry-run
certbot renew --dry-run

Systemd timer (preferred over cron)

Systemd timer (preferred over cron)

cat > /etc/systemd/system/certbot-renewal.service << 'EOF' [Unit] Description=Certbot certificate renewal After=network-online.target
[Service] Type=oneshot ExecStart=/usr/bin/certbot renew --quiet --deploy-hook "systemctl reload nginx" EOF
cat > /etc/systemd/system/certbot-renewal.timer << 'EOF' [Unit] Description=Run certbot renewal twice daily
[Timer] OnCalendar=--* 00,12:00:00 RandomizedDelaySec=3600 Persistent=true
[Install] WantedBy=timers.target EOF
systemctl enable --now certbot-renewal.timer
cat > /etc/systemd/system/certbot-renewal.service << 'EOF' [Unit] Description=Certbot certificate renewal After=network-online.target
[Service] Type=oneshot ExecStart=/usr/bin/certbot renew --quiet --deploy-hook "systemctl reload nginx" EOF
cat > /etc/systemd/system/certbot-renewal.timer << 'EOF' [Unit] Description=Run certbot renewal twice daily
[Timer] OnCalendar=--* 00,12:00:00 RandomizedDelaySec=3600 Persistent=true
[Install] WantedBy=timers.target EOF
systemctl enable --now certbot-renewal.timer

Verify timer is active

Verify timer is active

systemctl list-timers certbot-renewal.timer
systemctl list-timers certbot-renewal.timer

Renewal hooks for post-renewal actions

Renewal hooks for post-renewal actions

mkdir -p /etc/letsencrypt/renewal-hooks/deploy cat > /etc/letsencrypt/renewal-hooks/deploy/reload-services.sh << 'HOOK' #!/bin/bash systemctl reload nginx
mkdir -p /etc/letsencrypt/renewal-hooks/deploy cat > /etc/letsencrypt/renewal-hooks/deploy/reload-services.sh << 'HOOK' #!/bin/bash systemctl reload nginx

Also reload other services using the cert

Also reload other services using the cert

systemctl reload haproxy 2>/dev/null || true HOOK chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-services.sh
undefined
systemctl reload haproxy 2>/dev/null || true HOOK chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-services.sh
undefined

cert-manager for Kubernetes

Kubernetes中的cert-manager

Installation

安装

bash
undefined
bash
undefined

Install with Helm

Install with Helm

helm repo add jetstack https://charts.jetstack.io helm repo update
helm install cert-manager jetstack/cert-manager
--namespace cert-manager
--create-namespace
--version v1.14.0
--set installCRDs=true
--set prometheus.enabled=true
helm repo add jetstack https://charts.jetstack.io helm repo update
helm install cert-manager jetstack/cert-manager
--namespace cert-manager
--create-namespace
--version v1.14.0
--set installCRDs=true
--set prometheus.enabled=true

Verify installation

Verify installation

kubectl get pods -n cert-manager kubectl get crds | grep cert-manager
undefined
kubectl get pods -n cert-manager kubectl get crds | grep cert-manager
undefined

ClusterIssuer Configurations

ClusterIssuer配置

yaml
undefined
yaml
undefined

letsencrypt-staging (use for testing first)

letsencrypt-staging (use for testing first)

apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-staging spec: acme: server: https://acme-staging-v02.api.letsencrypt.org/directory email: admin@example.com privateKeySecretRef: name: letsencrypt-staging solvers: - http01: ingress: class: nginx

apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-staging spec: acme: server: https://acme-staging-v02.api.letsencrypt.org/directory email: admin@example.com privateKeySecretRef: name: letsencrypt-staging solvers: - http01: ingress: class: nginx

letsencrypt-prod

letsencrypt-prod

apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-prod spec: acme: server: https://acme-v02.api.letsencrypt.org/directory email: admin@example.com privateKeySecretRef: name: letsencrypt-prod solvers: - http01: ingress: class: nginx

apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-prod spec: acme: server: https://acme-v02.api.letsencrypt.org/directory email: admin@example.com privateKeySecretRef: name: letsencrypt-prod solvers: - http01: ingress: class: nginx

DNS challenge solver (for wildcard certs with Cloudflare)

DNS challenge solver (for wildcard certs with Cloudflare)

apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-prod-dns spec: acme: server: https://acme-v02.api.letsencrypt.org/directory email: admin@example.com privateKeySecretRef: name: letsencrypt-prod-dns solvers: - dns01: cloudflare: apiTokenSecretRef: name: cloudflare-api-token key: api-token

apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-prod-dns spec: acme: server: https://acme-v02.api.letsencrypt.org/directory email: admin@example.com privateKeySecretRef: name: letsencrypt-prod-dns solvers: - dns01: cloudflare: apiTokenSecretRef: name: cloudflare-api-token key: api-token

Self-signed CA issuer for internal services

Self-signed CA issuer for internal services

apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: selfsigned-ca spec: selfSigned: {}
undefined
apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: selfsigned-ca spec: selfSigned: {}
undefined

Certificate Resources

证书资源

yaml
undefined
yaml
undefined

Public-facing certificate

Public-facing certificate

apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: example-cert namespace: default spec: secretName: example-tls issuerRef: name: letsencrypt-prod kind: ClusterIssuer dnsNames: - example.com - www.example.com duration: 2160h # 90 days renewBefore: 720h # 30 days before expiry

apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: example-cert namespace: default spec: secretName: example-tls issuerRef: name: letsencrypt-prod kind: ClusterIssuer dnsNames: - example.com - www.example.com duration: 2160h # 90 days renewBefore: 720h # 30 days before expiry

Wildcard certificate

Wildcard certificate

apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: wildcard-cert namespace: default spec: secretName: wildcard-tls issuerRef: name: letsencrypt-prod-dns kind: ClusterIssuer dnsNames: - "*.example.com" - example.com

apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: wildcard-cert namespace: default spec: secretName: wildcard-tls issuerRef: name: letsencrypt-prod-dns kind: ClusterIssuer dnsNames: - "*.example.com" - example.com

Ingress with automatic TLS

Ingress with automatic TLS

apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: example-ingress annotations: cert-manager.io/cluster-issuer: letsencrypt-prod spec: tls: - hosts: - example.com secretName: example-tls rules: - host: example.com http: paths: - path: / pathType: Prefix backend: service: name: web port: number: 80
undefined
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: example-ingress annotations: cert-manager.io/cluster-issuer: letsencrypt-prod spec: tls: - hosts: - example.com secretName: example-tls rules: - host: example.com http: paths: - path: / pathType: Prefix backend: service: name: web port: number: 80
undefined

OpenSSL Commands Reference

OpenSSL命令参考

bash
undefined
bash
undefined

Generate a private key

Generate a private key

openssl genrsa -out server.key 4096
openssl genrsa -out server.key 4096

Generate an ECDSA key (preferred for performance)

Generate an ECDSA key (preferred for performance)

openssl ecparam -genkey -name prime256v1 -out server-ec.key
openssl ecparam -genkey -name prime256v1 -out server-ec.key

Generate a CSR (Certificate Signing Request)

Generate a CSR (Certificate Signing Request)

openssl req -new -key server.key -out server.csr
-subj "/C=US/ST=California/L=San Francisco/O=Acme Corp/CN=example.com"
openssl req -new -key server.key -out server.csr
-subj "/C=US/ST=California/L=San Francisco/O=Acme Corp/CN=example.com"

Generate CSR with SAN (Subject Alternative Names)

Generate CSR with SAN (Subject Alternative Names)

openssl req -new -key server.key -out server.csr -config <(cat <<EOF [req] default_bits = 4096 distinguished_name = dn req_extensions = san prompt = no
[dn] CN = example.com O = Acme Corp C = US
[san] subjectAltName = DNS:example.com,DNS:www.example.com,DNS:api.example.com EOF )
openssl req -new -key server.key -out server.csr -config <(cat <<EOF [req] default_bits = 4096 distinguished_name = dn req_extensions = san prompt = no
[dn] CN = example.com O = Acme Corp C = US
[san] subjectAltName = DNS:example.com,DNS:www.example.com,DNS:api.example.com EOF )

Generate self-signed certificate (development/testing)

Generate self-signed certificate (development/testing)

openssl req -x509 -nodes -days 365 -newkey rsa:4096
-keyout selfsigned.key -out selfsigned.crt
-subj "/CN=localhost"
openssl req -x509 -nodes -days 365 -newkey rsa:4096
-keyout selfsigned.key -out selfsigned.crt
-subj "/CN=localhost"

View certificate details

View certificate details

openssl x509 -in cert.pem -noout -text
openssl x509 -in cert.pem -noout -text

Check certificate expiration date

Check certificate expiration date

openssl x509 -in cert.pem -noout -dates
openssl x509 -in cert.pem -noout -dates

Check remote certificate

Check remote certificate

openssl s_client -connect example.com:443 -servername example.com 2>/dev/null |
openssl x509 -noout -dates -subject -issuer
openssl s_client -connect example.com:443 -servername example.com 2>/dev/null |
openssl x509 -noout -dates -subject -issuer

Verify certificate chain

Verify certificate chain

openssl verify -CAfile ca-bundle.crt server.crt
openssl verify -CAfile ca-bundle.crt server.crt

Check certificate chain from remote server

Check certificate chain from remote server

openssl s_client -connect example.com:443 -showcerts 2>/dev/null |
openssl x509 -noout -text
openssl s_client -connect example.com:443 -showcerts 2>/dev/null |
openssl x509 -noout -text

Convert PEM to PKCS12

Convert PEM to PKCS12

openssl pkcs12 -export -out cert.pfx -inkey server.key -in server.crt -certfile ca.crt
openssl pkcs12 -export -out cert.pfx -inkey server.key -in server.crt -certfile ca.crt

Convert PKCS12 to PEM

Convert PKCS12 to PEM

openssl pkcs12 -in cert.pfx -out cert.pem -nodes
openssl pkcs12 -in cert.pfx -out cert.pem -nodes

Test TLS connection and cipher negotiation

Test TLS connection and cipher negotiation

openssl s_client -connect example.com:443 -tls1_3 openssl s_client -connect example.com:443 -cipher 'ECDHE-RSA-AES256-GCM-SHA384'
undefined
openssl s_client -connect example.com:443 -tls1_3 openssl s_client -connect example.com:443 -cipher 'ECDHE-RSA-AES256-GCM-SHA384'
undefined

Strong TLS Configuration

安全TLS配置

Nginx

Nginx

nginx
server {
    listen 443 ssl http2;
    server_name example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    # Protocol versions
    ssl_protocols TLSv1.2 TLSv1.3;

    # Cipher suites (TLS 1.2)
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;

    # Session settings
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:10m;
    ssl_session_tickets off;

    # OCSP stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 5s;

    # Security headers
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
    add_header X-Content-Type-Options nosniff always;
    add_header X-Frame-Options DENY always;

    # HTTP to HTTPS redirect (in separate server block)
}

server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}
nginx
server {
    listen 443 ssl http2;
    server_name example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    # Protocol versions
    ssl_protocols TLSv1.2 TLSv1.3;

    # Cipher suites (TLS 1.2)
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;

    # Session settings
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:10m;
    ssl_session_tickets off;

    # OCSP stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 5s;

    # Security headers
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
    add_header X-Content-Type-Options nosniff always;
    add_header X-Frame-Options DENY always;

    # HTTP to HTTPS redirect (in separate server block)
}

server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

Apache

Apache

apache
<VirtualHost *:443>
    ServerName example.com

    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem

    SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
    SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
    SSLHonorCipherOrder off

    SSLUseStapling on
    SSLStaplingCache shmcb:/tmp/stapling_cache(128000)

    Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
</VirtualHost>
apache
<VirtualHost *:443>
    ServerName example.com

    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem

    SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
    SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
    SSLHonorCipherOrder off

    SSLUseStapling on
    SSLStaplingCache shmcb:/tmp/stapling_cache(128000)

    Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
</VirtualHost>

Certificate Monitoring

证书监控

bash
#!/bin/bash
bash
#!/bin/bash

cert-monitor.sh - Monitor certificate expiration across hosts

cert-monitor.sh - Monitor certificate expiration across hosts

WARN_DAYS=30 CRIT_DAYS=7 HOSTS=( "example.com:443" "api.example.com:443" "admin.example.com:443" )
for host in "${HOSTS[@]}"; do expiry=$(echo | openssl s_client -connect "$host" -servername "${host%%:*}" 2>/dev/null |
openssl x509 -noout -enddate 2>/dev/null | cut -d= -f2)
if [ -z "$expiry" ]; then echo "ERROR: Cannot connect to $host" continue fi
expiry_epoch=$(date -d "$expiry" +%s) now_epoch=$(date +%s) days_left=$(( (expiry_epoch - now_epoch) / 86400 ))
if [ "$days_left" -le "$CRIT_DAYS" ]; then echo "CRITICAL: $host expires in $days_left days ($expiry)" elif [ "$days_left" -le "$WARN_DAYS" ]; then echo "WARNING: $host expires in $days_left days ($expiry)" else echo "OK: $host expires in $days_left days ($expiry)" fi done
undefined
WARN_DAYS=30 CRIT_DAYS=7 HOSTS=( "example.com:443" "api.example.com:443" "admin.example.com:443" )
for host in "${HOSTS[@]}"; do expiry=$(echo | openssl s_client -connect "$host" -servername "${host%%:*}" 2>/dev/null |
openssl x509 -noout -enddate 2>/dev/null | cut -d= -f2)
if [ -z "$expiry" ]; then echo "ERROR: Cannot connect to $host" continue fi
expiry_epoch=$(date -d "$expiry" +%s) now_epoch=$(date +%s) days_left=$(( (expiry_epoch - now_epoch) / 86400 ))
if [ "$days_left" -le "$CRIT_DAYS" ]; then echo "CRITICAL: $host expires in $days_left days ($expiry)" elif [ "$days_left" -le "$WARN_DAYS" ]; then echo "WARNING: $host expires in $days_left days ($expiry)" else echo "OK: $host expires in $days_left days ($expiry)" fi done
undefined

Prometheus cert-manager Metrics

Prometheus cert-manager指标

yaml
undefined
yaml
undefined

Alert on expiring certificates in Kubernetes

Alert on expiring certificates in Kubernetes

groups:
  • name: cert-manager rules:
    • alert: CertificateExpiringSoon expr: certmanager_certificate_expiration_timestamp_seconds - time() < 7 * 24 * 3600 for: 1h labels: severity: critical annotations: summary: "Certificate {{ $labels.name }} expires in less than 7 days"
    • alert: CertificateNotReady expr: certmanager_certificate_ready_status{condition="True"} == 0 for: 15m labels: severity: warning annotations: summary: "Certificate {{ $labels.name }} is not ready"
undefined
groups:
  • name: cert-manager rules:
    • alert: CertificateExpiringSoon expr: certmanager_certificate_expiration_timestamp_seconds - time() < 7 * 24 * 3600 for: 1h labels: severity: critical annotations: summary: "Certificate {{ $labels.name }} expires in less than 7 days"
    • alert: CertificateNotReady expr: certmanager_certificate_ready_status{condition="True"} == 0 for: 15m labels: severity: warning annotations: summary: "Certificate {{ $labels.name }} is not ready"
undefined

Troubleshooting

故障排查

ProblemCauseSolution
Certbot fails with "connection refused"Port 80 blocked by firewallOpen port 80 for ACME HTTP-01 challenge
"Too many certificates already issued"Let's Encrypt rate limit hitUse staging endpoint for testing; wait for rate limit reset
cert-manager challenge stuck pendingIngress or DNS misconfiguredCheck
kubectl describe challenge
; verify DNS records
Mixed content warningsHTTP resources on HTTPS pageUpdate all asset URLs to HTTPS; use CSP headers
OCSP stapling not workingResolver not configuredAdd
resolver
directive in nginx; verify outbound DNS
Intermediate cert missingIncomplete chain servedUse
fullchain.pem
not
cert.pem
; verify with
openssl s_client -showcerts
TLS handshake failureClient doesn't support offered ciphersAdd TLS 1.2 support; check cipher suite compatibility
问题原因解决方案
Certbot提示“connection refused”防火墙阻断了80端口开放80端口以支持ACME HTTP-01挑战
“Too many certificates already issued”触发了Let's Encrypt的速率限制使用测试环境端点进行测试;等待速率限制重置
cert-manager挑战处于pending状态Ingress或DNS配置错误查看
kubectl describe challenge
;验证DNS记录
混合内容警告HTTPS页面中存在HTTP资源将所有资源URL更新为HTTPS;使用CSP头部
OCSP stapling无法工作未配置解析器在nginx中添加
resolver
指令;验证出站DNS
缺少中间证书证书链不完整使用
fullchain.pem
而非
cert.pem
;通过
openssl s_client -showcerts
验证
TLS握手失败客户端不支持提供的加密套件添加TLS 1.2支持;检查加密套件兼容性

Best Practices

最佳实践

  • Automate renewal with systemd timers or cert-manager
  • Monitor expiration dates with alerting (30-day and 7-day warnings)
  • Use only TLS 1.2 and TLS 1.3
  • Enable HSTS with long max-age and includeSubDomains
  • Enable OCSP stapling to improve handshake performance
  • Use ECDSA keys for better performance where possible
  • Test configuration with SSL Labs (ssllabs.com/ssltest)
  • Keep private keys secure with proper file permissions (0600)
  • Rotate certificates before expiry, not after
  • Maintain a certificate inventory across all services
  • 使用systemd定时器或cert-manager实现续期自动化
  • 设置告警监控证书过期(提前30天和7天预警)
  • 仅使用TLS 1.2和TLS 1.3版本
  • 启用HSTS并设置较长的max-age及includeSubDomains
  • 启用OCSP stapling以提升握手性能
  • 尽可能使用ECDSA密钥以获得更好性能
  • 使用SSL Labs(ssllabs.com/ssltest)测试配置
  • 通过正确的文件权限(0600)保护私钥安全
  • 在证书过期前完成轮换,而非过期后
  • 维护所有服务的证书清单

Related Skills

相关技能

  • hashicorp-vault - PKI management
  • waf-setup - Web protection
  • zero-trust - mTLS and identity-based access
  • hashicorp-vault - PKI管理
  • waf-setup - Web防护
  • zero-trust - mTLS与基于身份的访问