Certyfikaty Wildcard SSL/TLS - Najlepsze Praktyki i Pułapki
Certyfikaty wildcard to potężne narzędzie w arsenale każdego administratora, ale jak mówi Spider-Man - “z wielką mocą przychodzi wielka odpowiedzialność”. W tym artykule pokażemy, kiedy używać certyfikatów wildcard, jak je bezpiecznie wdrażać i jakich pułapek unikać.
Czym Jest Certyfikat Wildcard?
Certyfikat wildcard to certyfikat SSL/TLS, który zabezpiecza główną domenę oraz wszystkie jej subdomeny pierwszego poziomu. Używa znaku gwiazdki (*) jako wieloznacznika.
Przykład
Certyfikat dla *.example.com zabezpiecza:
- ✅
blog.example.com - ✅
shop.example.com - ✅
api.example.com - ❌
example.com(domena główna - trzeba dodać osobno) - ❌
admin.api.example.com(subdomena drugiego poziomu)
Multi-Domain Wildcard
Możesz połączyć wildcard z SAN (Subject Alternative Names):
Common Name: *.example.com
SAN:
- *.example.com
- example.com
- *.staging.example.com
To zabezpieczy:
example.comblog.example.comshop.example.comapi.staging.example.com
Kiedy Używać Certyfikatów Wildcard?
✅ Dobre Przypadki Użycia
1. Środowiska Deweloperskie i Testowe
dev-feature1.staging.example.com
dev-feature2.staging.example.com
dev-feature3.staging.example.com
Certyfikat wildcard dla *.staging.example.com pokrywa wszystkie branch deployments.
2. Aplikacje SaaS z Subdomenami dla Klientów
customer1.app.example.com
customer2.app.example.com
customer3.app.example.com
Jeden certyfikat dla *.app.example.com zamiast setek pojedynczych.
3. Mikroservices z Dynamicznymi Subdomenami
service-auth.internal.example.com
service-api.internal.example.com
service-db.internal.example.com
4. CDN i Load Balancers
cdn1.assets.example.com
cdn2.assets.example.com
cdn3.assets.example.com
❌ Złe Przypadki Użycia
1. Pojedyncze Aplikacje Produkcyjne
Jeśli masz tylko www.example.com i api.example.com, lepiej użyj certyfikatu multi-domain (SAN) niż wildcard.
2. Wysokie Wymagania Bezpieczeństwa
Dla wrażliwych systemów (banking, healthcare) lepiej izolować certyfikaty.
3. Różni Właściciele Subdomen
Jeśli różne zespoły zarządzają różnymi subdomenami, współdzielenie certyfikatu może być problematyczne.
4. Gdy Potrzebujesz EV Certificates
Extended Validation certificates nie są dostępne jako wildcard.
Bezpieczeństwo Certyfikatów Wildcard
Ryzyko Kompromitacji
Problem: Jeśli klucz prywatny zostanie skompromitowany, wszystkie subdomeny są narażone.
Rozwiązanie:
- Hardware Security Modules (HSM)
# Przechowuj klucze w HSM
# Nigdy nie eksportuj kluczy w postaci plaintext
- Ograniczony Dostęp
# Permissions dla klucza prywatnego
chmod 600 /etc/ssl/private/wildcard.key
chown root:root /etc/ssl/private/wildcard.key
- Rotacja Kluczy
# Odnawiaj certyfikat z nowym kluczem co 3-6 miesięcy
# Nie używaj tej samej pary klucz/certyfikat przez lata
Certificate Pinning
Dla aplikacji mobilnych używających wildcard certificates:
// Android - Certificate Pinning
CertificatePinner certificatePinner = new CertificatePinner.Builder()
.add("*.example.com", "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
.add("*.example.com", "sha256/BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=") // backup
.build();
OkHttpClient client = new OkHttpClient.Builder()
.certificatePinner(certificatePinner)
.build();
// iOS - Certificate Pinning
let evaluator = PinnedCertificatesTrustEvaluator(
certificates: [Certificates.wildcard],
acceptSelfSignedCertificates: false,
performDefaultValidation: true,
validateHost: true
)
let serverTrustManager = ServerTrustManager(evaluators: ["*.example.com": evaluator])
Monitoring i Auditing
# Monitoring dostępu do klucza prywatnego (auditd)
auditctl -w /etc/ssl/private/wildcard.key -p rwxa -k wildcard_key_access
# Przegląd logów
ausearch -k wildcard_key_access
Uzyskiwanie Certyfikatów Wildcard
Let’s Encrypt z DNS-01 Challenge
Dlaczego DNS-01? HTTP-01 nie działa dla wildcard, ponieważ Let’s Encrypt nie może zweryfikować wszystkich możliwych subdomen.
Z Cloudflare
# Instalacja certbot z pluginem Cloudflare
apt-get install certbot python3-certbot-dns-cloudflare
# Plik z credentials
cat > /root/.cloudflare.ini <<EOF
dns_cloudflare_api_token = your-cloudflare-api-token
EOF
chmod 600 /root/.cloudflare.ini
# Uzyskanie certyfikatu
certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials /root/.cloudflare.ini \
-d example.com \
-d *.example.com \
--email [email protected] \
--agree-tos \
--non-interactive
# Automatyczne odnowienie
echo "0 3 * * * certbot renew --quiet" | crontab -
Z Route53 (AWS)
# Instalacja pluginu
apt-get install certbot python3-certbot-dns-route53
# Credentials przez AWS CLI lub IAM role
aws configure
# Uzyskanie certyfikatu
certbot certonly \
--dns-route53 \
-d example.com \
-d *.example.com \
--email [email protected] \
--agree-tos \
--non-interactive
Z acme.sh (Universal)
# Instalacja
curl https://get.acme.sh | sh
# Cloudflare
export CF_Token="your-cloudflare-api-token"
acme.sh --issue --dns dns_cf -d example.com -d *.example.com
# Route53
export AWS_ACCESS_KEY_ID="your-access-key"
export AWS_SECRET_ACCESS_KEY="your-secret-key"
acme.sh --issue --dns dns_aws -d example.com -d *.example.com
# Google Cloud DNS
export GCE_PROJECT="your-project"
export GCE_SERVICE_ACCOUNT_FILE="/path/to/key.json"
acme.sh --issue --dns dns_gcloud -d example.com -d *.example.com
Komercyjne CA
Większość komercyjnych CA oferuje wildcard certificates:
- DigiCert: $295-2995/rok
- Sectigo: $99-299/rok
- GlobalSign: $249-1299/rok
- GoDaddy: $300-500/rok
Wybór komercyjnego CA ma sens gdy:
- Potrzebujesz wsparcia 24/7
- Potrzebujesz ubezpieczenia (warranty)
- Klient wymaga konkretnego CA
- Nie możesz używać Let’s Encrypt (np. brak dostępu do DNS API)
Konfiguracja Serwerów Web
Nginx
server {
listen 443 ssl http2;
server_name *.example.com example.com;
# Certyfikat wildcard
ssl_certificate /etc/ssl/certs/wildcard.example.com.crt;
ssl_certificate_key /etc/ssl/private/wildcard.example.com.key;
# Modern SSL configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# HSTS
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/ssl/certs/chain.pem;
# Routing based on subdomain
location / {
if ($host ~ ^([^.]+)\.example\.com$) {
set $subdomain $1;
proxy_pass http://backend-$subdomain;
}
if ($host = example.com) {
proxy_pass http://backend-main;
}
}
}
Apache
<VirtualHost *:443>
ServerName example.com
ServerAlias *.example.com
SSLEngine on
SSLCertificateFile /etc/ssl/certs/wildcard.example.com.crt
SSLCertificateKeyFile /etc/ssl/private/wildcard.example.com.key
SSLCertificateChainFile /etc/ssl/certs/chain.pem
# Modern SSL configuration
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384
SSLHonorCipherOrder off
# HSTS
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
# OCSP Stapling
SSLUseStapling on
SSLStaplingCache "shmcb:logs/ssl_stapling(32768)"
# Routing
RewriteEngine On
RewriteCond %{HTTP_HOST} ^([^.]+)\.example\.com$ [NC]
RewriteRule ^(.*)$ http://backend-%1$1 [P]
</VirtualHost>
Traefik (Docker/Kubernetes)
# docker-compose.yml
version: '3.8'
services:
traefik:
image: traefik:v2.10
command:
- "--providers.docker=true"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.letsencrypt.acme.dnschallenge=true"
- "--certificatesresolvers.letsencrypt.acme.dnschallenge.provider=cloudflare"
- "[email protected]"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
environment:
- [email protected]
- CF_API_KEY=your-cloudflare-api-key
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./letsencrypt:/letsencrypt
ports:
- "443:443"
app:
image: myapp:latest
labels:
- "traefik.enable=true"
- "traefik.http.routers.app.rule=Host(`*.example.com`)"
- "traefik.http.routers.app.entrypoints=websecure"
- "traefik.http.routers.app.tls.certresolver=letsencrypt"
- "traefik.http.routers.app.tls.domains[0].main=example.com"
- "traefik.http.routers.app.tls.domains[0].sans=*.example.com"
Najczęstsze Problemy i Rozwiązania
Problem 1: Certyfikat Nie Działa dla Głównej Domeny
Objaw:
✅ https://blog.example.com - działa
✅ https://api.example.com - działa
❌ https://example.com - certyfikat invalid
Rozwiązanie: Wildcard *.example.com nie obejmuje głównej domeny. Musisz dodać obie:
certbot certonly --dns-cloudflare \
-d example.com \
-d *.example.com
Problem 2: Subdomena Drugiego Poziomu
Objaw:
✅ https://api.example.com - działa
❌ https://v1.api.example.com - certyfikat invalid
Rozwiązanie: Wildcard działa tylko dla jednego poziomu. Potrzebujesz:
# Opcja 1: Dodaj kolejny wildcard
certbot certonly --dns-cloudflare \
-d *.example.com \
-d *.api.example.com
# Opcja 2: Multi-level wildcard (rzadko wspierany)
# Niektóre CA oferują multi-level wildcard
Problem 3: DNS Propagacja
Objaw: DNS-01 challenge fails z timeout
Rozwiązanie:
# Zwiększ timeout dla DNS propagation
certbot certonly --dns-cloudflare \
--dns-cloudflare-propagation-seconds 60 \
-d example.com \
-d *.example.com
# Sprawdź DNS przed próbą
dig _acme-challenge.example.com TXT
Problem 4: API Rate Limits
Objaw: Let’s Encrypt zwraca “too many requests”
Rozwiązanie:
# Testuj na staging
certbot certonly --dns-cloudflare \
--staging \
-d example.com \
-d *.example.com
# Po testach użyj produkcji
certbot certonly --dns-cloudflare \
-d example.com \
-d *.example.com
Monitoring Certyfikatów Wildcard
Check Script
#!/bin/bash
# check-wildcard.sh
DOMAIN="*.example.com"
CERT_FILE="/etc/ssl/certs/wildcard.example.com.crt"
# Sprawdź datę wygaśnięcia
EXPIRY=$(openssl x509 -in "$CERT_FILE" -noout -enddate | cut -d= -f2)
EXPIRY_EPOCH=$(date -d "$EXPIRY" +%s)
CURRENT_EPOCH=$(date +%s)
DAYS_LEFT=$(( ($EXPIRY_EPOCH - $CURRENT_EPOCH) / 86400 ))
echo "Certificate for $DOMAIN expires in $DAYS_LEFT days"
if [ $DAYS_LEFT -lt 30 ]; then
echo "WARNING: Certificate expires soon!"
# Wyślij alert
curl -X POST https://your-webhook.com/alert \
-d "Certificate $DOMAIN expires in $DAYS_LEFT days"
fi
# Sprawdź czy certyfikat jest wildcard
SUBJECT=$(openssl x509 -in "$CERT_FILE" -noout -subject)
if [[ $SUBJECT == *"CN = *.example.com"* ]]; then
echo "✓ Valid wildcard certificate"
else
echo "✗ Not a wildcard certificate!"
fi
# Sprawdź czy obejmuje główną domenę
SAN=$(openssl x509 -in "$CERT_FILE" -noout -text | grep -A1 "Subject Alternative Name")
if [[ $SAN == *"DNS:example.com"* ]]; then
echo "✓ Main domain included in SAN"
else
echo "✗ Main domain NOT in certificate"
fi
Prometheus Monitoring
# prometheus-rules.yaml
groups:
- name: wildcard-certificates
rules:
- alert: WildcardCertificateExpiring
expr: (ssl_certificate_expiry_seconds{cn="*.example.com"} - time()) / 86400 < 30
for: 24h
labels:
severity: warning
annotations:
summary: "Wildcard certificate expiring soon"
description: "Certificate for *.example.com expires in {{ $value }} days"
- alert: WildcardCertificateExpired
expr: (ssl_certificate_expiry_seconds{cn="*.example.com"} - time()) < 0
labels:
severity: critical
annotations:
summary: "Wildcard certificate EXPIRED"
description: "Certificate for *.example.com has expired!"
CrtMgr Integration
CrtMgr może monitorować certyfikaty wildcard:
- Dodaj domenę z wildcard:
*.example.com - CrtMgr automatycznie wykryje wildcard
- Monitoruje datę wygaśnięcia
- Wysyła alerty 30/14/7/1 dni przed wygaśnięciem
- API integration dla automatyzacji
Best Practices - Podsumowanie
✅ DO
- Używaj DNS-01 Challenge dla wildcard certificates
- Dodawaj główną domenę do SAN
- Rotuj klucze regularnie (co 3-6 miesięcy)
- Monitoruj wygaśnięcie z alertami
- Ograniczaj dostęp do klucza prywatnego
- Testuj na staging przed produkcją
- Dokumentuj gdzie certyfikat jest używany
- Backup certyfikatów i kluczy (zaszyfrowane!)
❌ DON’T
- Nie używaj wildcard dla pojedynczych domen
- Nie współdziel kluczy między środowiskami
- Nie przechowuj kluczy w plaintext w repo
- Nie ignoruj alertów o wygasających certyfikatach
- Nie używaj tego samego klucza latami
- Nie daj dostępu do klucza wszystkim
- Nie zapomnij o odnowieniu przed wygaśnięciem
- Nie zakładaj że wildcard obejmuje wszystkie poziomy subdomen
Checklist Wdrożeniowa
Przed wdrożeniem certyfikatu wildcard:
- Zweryfikuj czy wildcard jest potrzebny (vs multi-domain)
- Wybierz metodę challenge (DNS-01 dla wildcard)
- Skonfiguruj DNS API access
- Przetestuj na staging environment
- Dodaj główną domenę do SAN
- Skonfiguruj automatyczne odnowienie
- Ustaw monitoring i alerty
- Ograniczysz permissions na kluczu prywatnym
- Stwórz backup klucza (zaszyfrowany)
- Zdokumentuj konfigurację
- Przetestuj wszystkie subdomeny
- Skonfiguruj HSTS i OCSP stapling
Podsumowanie
Certyfikaty wildcard to potężne narzędzie, które może znacznie uprościć zarządzanie SSL/TLS dla wielu subdomen. Kluczowe punkty:
- Używaj rozsądnie - nie dla wszystkiego, ale tam gdzie ma sens
- Bezpieczeństwo przede wszystkim - wildcard zwiększa ryzyko kompromitacji
- Automatyzuj - DNS-01 challenge z automatycznym odnowieniem
- Monitoruj - jeden wygasły wildcard = wszystkie subdomeny w dół
- Dokumentuj - wiedz gdzie certyfikat jest używany
Potrzebujesz prostego narzędzia do monitorowania certyfikatów wildcard? Sprawdź CrtMgr - automatycznie wykrywa i monitoruje certyfikaty wildcard z alertami przed wygaśnięciem.
Wildcard certificates - używaj mądrze, monitoruj pilnie, śpij spokojnie.