Apache SSL/HTTPS 配置 #
SSL/TLS 基础 #
什么是 SSL/TLS? #
text
┌─────────────────────────────────────────────────────────────┐
│ SSL/TLS 概念 │
├─────────────────────────────────────────────────────────────┤
│ │
│ SSL (Secure Sockets Layer) │
│ TLS (Transport Layer Security) │
│ │
│ 作用: │
│ ├── 加密:保护数据传输安全 │
│ ├── 认证:验证服务器身份 │
│ └── 完整性:防止数据篡改 │
│ │
│ HTTPS = HTTP + TLS │
│ │
│ 工作流程: │
│ 1. 客户端发起 HTTPS 请求 │
│ 2. 服务器返回 SSL 证书 │
│ 3. 客户端验证证书 │
│ 4. 协商加密密钥 │
│ 5. 建立加密通道 │
│ 6. 安全传输数据 │
│ │
└─────────────────────────────────────────────────────────────┘
证书类型 #
text
┌─────────────────────────────────────────────────────────────┐
│ SSL 证书类型 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 按验证级别: │
│ ├── DV (Domain Validation) 域名验证,快速签发 │
│ ├── OV (Organization Validation) 组织验证,显示公司名 │
│ └── EV (Extended Validation) 扩展验证,最高信任级别 │
│ │
│ 按覆盖范围: │
│ ├── 单域名证书 保护一个域名 │
│ ├── 多域名证书 保护多个域名 │
│ └── 通配符证书 保护主域名及所有子域名 │
│ │
│ 证书颁发机构: │
│ ├── Let's Encrypt 免费自动签发 │
│ ├── DigiCert 商业证书 │
│ ├── Comodo 商业证书 │
│ └── GeoTrust 商业证书 │
│ │
└─────────────────────────────────────────────────────────────┘
启用 SSL 模块 #
加载必要模块 #
bash
# Ubuntu/Debian
sudo a2enmod ssl
sudo a2enmod socache_shmcb
sudo systemctl restart apache2
# CentOS/RHEL
# 在配置文件中取消注释
# LoadModule ssl_module modules/mod_ssl.so
sudo systemctl restart httpd
启用默认 SSL 站点 #
bash
# Ubuntu/Debian
sudo a2ensite default-ssl
sudo systemctl reload apache2
获取 SSL 证书 #
使用 Let’s Encrypt(推荐) #
bash
# 安装 Certbot
# Ubuntu/Debian
sudo apt install certbot python3-certbot-apache
# CentOS/RHEL
sudo yum install certbot python3-certbot-apache
# 自动获取并配置证书
sudo certbot --apache -d example.com -d www.example.com
# 仅获取证书
sudo certbot certonly --apache -d example.com
# 测试续期
sudo certbot renew --dry-run
# 自动续期(Cron)
# 0 0 * * * certbot renew --quiet
手动配置证书 #
bash
# 证书文件位置(Let's Encrypt)
/etc/letsencrypt/live/example.com/fullchain.pem # 证书链
/etc/letsencrypt/live/example.com/privkey.pem # 私钥
# 自签名证书(仅测试用)
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /etc/ssl/private/apache-selfsigned.key \
-out /etc/ssl/certs/apache-selfsigned.crt
SSL 虚拟主机配置 #
基础 HTTPS 配置 #
apache
# ============================================
# 基础 HTTPS 配置
# ============================================
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/html
# 启用 SSL
SSLEngine on
# 证书文件
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
# 证书链(如果需要)
SSLCertificateChainFile /etc/letsencrypt/live/example.com/chain.pem
# 目录配置
<Directory /var/www/html>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
# 日志
ErrorLog ${APACHE_LOG_DIR}/ssl-error.log
CustomLog ${APACHE_LOG_DIR}/ssl-access.log combined
</VirtualHost>
HTTP 到 HTTPS 重定向 #
apache
# ============================================
# HTTP 重定向到 HTTPS
# ============================================
# 方法 1:使用 Redirect
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
Redirect permanent / https://example.com/
</VirtualHost>
# 方法 2:使用 Rewrite
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</VirtualHost>
# 方法 3:统一到 www
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
RewriteEngine On
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [L,R=301]
</VirtualHost>
完整 HTTPS 配置 #
apache
# ============================================
# 完整 HTTPS 配置
# ============================================
# HTTP 重定向
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</VirtualHost>
# HTTPS 配置
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/html
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
# SSL 协议
SSLProtocol all -SSLv2 -SSLv3
# 加密套件
SSLCipherSuite HIGH:!aNULL:!MD5:!3DES
# 优先使用服务器加密套件
SSLHonorCipherOrder on
# HSTS
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
<Directory /var/www/html>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/ssl-error.log
CustomLog ${APACHE_LOG_DIR}/ssl-access.log combined
</VirtualHost>
SSL 高级配置 #
SSL 协议配置 #
apache
# ============================================
# SSL 协议配置
# ============================================
# 推荐配置(仅 TLS 1.2 和 1.3)
SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
# 或明确指定
SSLProtocol -all +TLSv1.2 +TLSv1.3
# 全局配置(在 apache2.conf 或 httpd.conf)
<IfModule mod_ssl.c>
SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
</IfModule>
加密套件配置 #
apache
# ============================================
# 加密套件配置
# ============================================
# 推荐配置
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
# 优先使用服务器顺序
SSLHonorCipherOrder on
# 禁用不安全加密
SSLCipherSuite HIGH:!aNULL:!MD5:!3DES:!RC4:!EXP
HSTS 配置 #
apache
# ============================================
# HSTS (HTTP Strict Transport Security)
# ============================================
# 基础 HSTS
Header always set Strict-Transport-Security "max-age=31536000"
# 包含子域名
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
# 包含预加载
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
# 注意:preload 需要提交到 hstspreload.org
OCSP Stapling #
apache
# ============================================
# OCSP Stapling
# ============================================
# 启用 OCSP Stapling
SSLUseStapling on
SSLStaplingResponderTimeout 5
SSLStaplingReturnResponderErrors off
# 全局配置
SSLStaplingCache shmcb:/var/run/ocsp(128000)
# 在虚拟主机中
<VirtualHost *:443>
ServerName example.com
SSLEngine on
SSLCertificateFile /etc/ssl/certs/example.com.crt
SSLCertificateKeyFile /etc/ssl/private/example.com.key
SSLUseStapling on
</VirtualHost>
SSL 会话配置 #
apache
# ============================================
# SSL 会话配置
# ============================================
# 会话缓存
SSLSessionCache shmcb:/var/run/ssl_scache(512000)
SSLSessionCacheTimeout 300
# 会话票据
SSLSessionTickets off
# 全局配置
<IfModule mod_ssl.c>
SSLSessionCache shmcb:/var/run/ssl_scache(512000)
SSLSessionCacheTimeout 300
SSLSessionTickets off
</IfModule>
安全头配置 #
完整安全头 #
apache
# ============================================
# 安全响应头配置
# ============================================
# 加载 headers 模块
LoadModule headers_module modules/mod_headers.so
<IfModule mod_headers.c>
# HSTS
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
# 防止点击劫持
Header always set X-Frame-Options "SAMEORIGIN"
# 防止 MIME 类型嗅探
Header always set X-Content-Type-Options "nosniff"
# XSS 保护
Header always set X-XSS-Protection "1; mode=block"
# Referrer 策略
Header always set Referrer-Policy "strict-origin-when-cross-origin"
# 内容安全策略
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';"
# 权限策略
Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"
# 禁用缓存敏感页面
<FilesMatch "\.(html|php)$">
Header set Cache-Control "no-cache, no-store, must-revalidate"
Header set Pragma "no-cache"
Header set Expires 0
</FilesMatch>
</IfModule>
SSL 测试与验证 #
测试 SSL 配置 #
bash
# 测试 SSL 配置
sudo apachectl configtest
# 查看 SSL 配置
sudo apache2ctl -M | grep ssl
# 使用 openssl 测试
openssl s_client -connect example.com:443
# 测试证书
openssl s_client -connect example.com:443 -servername example.com
# 查看证书详情
openssl x509 -in /etc/ssl/certs/example.com.crt -text -noout
# 测试 SSL 协议
openssl s_client -connect example.com:443 -tls1_2
openssl s_client -connect example.com:443 -tls1_3
在线测试工具 #
text
┌─────────────────────────────────────────────────────────────┐
│ SSL 测试工具 │
├─────────────────────────────────────────────────────────────┤
│ │
│ SSL Labs: │
│ https://www.ssllabs.com/ssltest/ │
│ 最权威的 SSL 配置测试 │
│ │
│ SSL Checker: │
│ https://www.sslshopper.com/ssl-checker.html │
│ 快速检查证书状态 │
│ │
│ Security Headers: │
│ https://securityheaders.com/ │
│ 检查安全响应头 │
│ │
│ HSTS Preload: │
│ https://hstspreload.org/ │
│ 提交 HSTS 预加载 │
│ │
└─────────────────────────────────────────────────────────────┘
证书续期 #
Let’s Encrypt 自动续期 #
bash
# 测试续期
sudo certbot renew --dry-run
# 手动续期
sudo certbot renew
# 续期后重载 Apache
sudo certbot renew --post-hook "systemctl reload apache2"
# 设置自动续期(systemd timer)
sudo systemctl enable certbot.timer
sudo systemctl start certbot.timer
Cron 自动续期 #
bash
# 编辑 crontab
sudo crontab -e
# 添加以下内容(每天检查两次)
0 0,12 * * * /usr/bin/certbot renew --quiet --post-hook "systemctl reload apache2"
常见问题 #
证书链问题 #
apache
# 如果浏览器提示证书不受信任,可能需要配置证书链
# 方法 1:使用 fullchain
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
# 方法 2:单独配置证书链
SSLCertificateFile /etc/letsencrypt/live/example.com/cert.pem
SSLCertificateChainFile /etc/letsencrypt/live/example.com/chain.pem
混合内容问题 #
apache
# 强制 HTTPS 资源
<IfModule mod_headers.c>
Header always set Content-Security-Policy "upgrade-insecure-requests"
</IfModule>
多域名证书 #
apache
# 多域名配置
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
ServerAlias api.example.com
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
</VirtualHost>
下一步 #
掌握了 SSL/HTTPS 配置后,继续学习 访问控制,了解如何配置 Apache 的访问控制和安全策略!
最后更新:2026-03-29