3.5 Web 服务器进阶——Apache httpd 深入与 SSL 卸载

预计阅读时间:16 分钟

📖 目录

Apache httpd 在模块生态、.htaccess 分布式配置、动态内容处理方面仍有独到优势。本文深入 httpd 核心配置,并讲解 SSL 卸载、mTLS 双向认证、CDN 回源等企业级实践。

环境说明 本章示例基于 CentOS/RHEL 系(路径 /etc/httpd//etc/pki/tls/certs/、命令 httpd/apachectl)。Ubuntu/Debian 用户对应替换为 apache2 包、/etc/apache2/a2enmod,配置语法与本节内容完全一致。

学习目标

  • 掌握 Apache httpd 的 VirtualHost 与 .htaccess 分布式配置机制,理解 AllowOverride 的作用
  • 理解 mod_rewrite、IP 访问控制、基本认证等常用模块的配置方法
  • 能部署 SSL 卸载架构:前端 Nginx/CDN 终止 TLS,后端 httpd 只处理 HTTP 明文
  • 能配置 mTLS 双向认证,处理客户端证书验证与健康检查排除问题
  • 能基于 X-Forwarded-* 头与 RemoteIPTrustedProxy 正确处理 CDN 回源与客户端真实 IP
  • 能根据业务场景在 Nginx 与 Apache httpd 之间做出合理选型并组合使用

前置知识

  • 3.4:Nginx Web服务器 Nginx Web 服务器配置与管理——SSL 卸载场景中通常由 Nginx 担任前端,且与 httpd 互为对比参照
  • 3.11:SSL/TLS 证书管理 SSL/TLS 证书管理——mTLS 与 SSL 卸载依赖证书签发、证书链与续期知识
  • sec_web01 WAF:ModSecurity 配置——反向代理层防护与 WAF 部署架构呼应
  • 3.3:实战:搭建个人网站 实战:搭建个人网站——Nginx 静态站、HTTPS 与域名绑定的实战基础

1. Apache httpd 核心配置

1.1 VirtualHost 基础

# /etc/httpd/conf.d/vhosts.conf(CentOS/RHEL)
<VirtualHost *:80>
    ServerName www.example.com
    DocumentRoot /var/www/example
    ErrorLog /var/log/httpd/example_error.log
    CustomLog /var/log/httpd/example_access.log combined

    <Directory /var/www/example>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

1.2 .htaccess 分布式配置

httpd 支持 .htaccess 在目录级别覆盖主配置(需要 AllowOverride All),适合共享主机或无法重启 httpd 的场景:

# /var/www/example/.htaccess
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

ErrorDocument 404 /errors/404.html

# IP 访问控制(注意合并语义:并列的 Require 之间默认是 OR;
# 若想"白名单 + 密码"同时满足,需用  包住 IP 与 valid-user)
# 下面用 RequireAll 包两个网段时是 AND 关系——两个不相交网段恒为假,等价于谁都无法通过,
# 所以并列网段用两条 Require 即可(OR):
<RequireAll>
    Require ip 10.0.0.0/8
    Require ip 192.168.1.0/24
    AuthType Basic
    AuthName "Restricted Area"
    AuthUserFile /etc/httpd/.htpasswd
    Require valid-user
</RequireAll>
.htaccess 性能开销 每次请求 httpd 都会逐级扫描目录中的 .htaccess 文件。高并发场景应尽量将配置写入 VirtualHost 块,仅在共享主机环境下使用 .htaccess。

1.3 mod_rewrite URL 重写

RewriteEngine On
LogLevel alert rewrite:trace6

# 非 www 跳转到 www
RewriteCond %{HTTP_HOST} ^example\.com [NC]
RewriteRule ^(.*)$ http://www.example.com/$1 [L,R=301]

# 去除 .html 后缀(伪静态)
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule ^(.+)$ $1.html [L]

# WordPress 式固定链接
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ /index.php?/$1 [QSA,L]

# 反向代理到后端
RewriteCond %{HTTP_HOST} ^api\.example\.com
RewriteRule ^/(.*)$ http://127.0.0.1:8080/$1 [P,L]
标记含义
L最后一条规则,停止处理
R=301/302301 永久重定向 / 302 临时重定向
QSA追加原始查询字符串
P代理请求(需 mod_proxy)
NC不区分大小写

1.4 Apache 性能调优:MPM 与 KeepAlive

MPM(多进程处理模块)决定 httpd 处理并发的方式,是性能调优的第一决策点。三种 MPM 各有适用场景:

维度preforkworkerevent
模型一进程一线程多进程 × 多线程worker + 事件驱动(基于 epoll)
并发能力低(受进程数限制)高,最适合 KeepAlive 长连接
内存占用最高(每进程独立内存)低(空闲连接不占线程)
兼容性mod_php 等非线程安全模块线程安全模块同 worker,PHP-FPM 场景最佳
适用场景老 LAMP(mod_php)、兼容性优先混合负载高并发静态/反向代理
# CentOS/RHEL 选择 event MPM(2.4 默认)
LoadModule mpm_event_module modules/mod_mpm_event.so

# event 调优示例
<IfModule mpm_event_module>
    StartServers            3
    MinSpareThreads        25
    MaxSpareThreads        75
    ThreadLimit            64
    ThreadsPerChild        25
    MaxRequestWorkers     400   # 峰值并发上限,按内存估算
    MaxConnectionsPerChild 10000  # 定期回收进程,防内存碎片
</IfModule>

# 查看当前 MPM 与并发上限
httpd -V | grep -i mpm

KeepAlive 允许同一 TCP 连接复用多次请求,对含大量静态资源的页面收益明显,但要防止空闲连接长期占线程:

# /etc/httpd/conf/httpd.conf
KeepAlive On
MaxKeepAliveRequests 100      # 单连接最大请求数,0 为不限
KeepAliveTimeout 5            # 空闲 5 秒即关闭,不宜过大(防资源占用)

# 验证效果:同一命令带两个 URL,同连接连续请求,第二个请求复用连接不再 TCP 握手
curl -v http://localhost/ http://localhost/ 2>&1 | grep -E "Re-using"

2. SSL 卸载(SSL Termination)

SSL 卸载是指在反向代理层(Nginx、HAProxy 或 CDN)终止 TLS 握手,后端只处理 HTTP 明文。好处:减少后端 TLS 计算开销、统一证书管理、简化后端架构。

# 前端 Nginx(SSL 卸载)
server {
    listen 443 ssl http2;
    server_name www.example.com;
    ssl_certificate     /etc/nginx/ssl/example.com.pem;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;

    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;

    location / {
        proxy_pass http://10.0.0.5:80;  # 后端 httpd,明文 HTTP
    }
}

server {
    listen 80;
    server_name www.example.com;
    return 301 https://$host$request_uri;
}
# 后端 httpd 信任代理头(否则会导致 HTTPS 重定向死循环)
LoadModule remoteip_module modules/mod_remoteip.so
RemoteIPTrustedProxy 10.0.0.0/8

RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

如果后端 httpd 需要直接对外提供 HTTPS(无前置 Nginx/CDN),则由 httpd 自己终止 TLS。完整配置如下,注意证书链、会话缓存与 OCSP Stapling 三项缺一不可:

# /etc/httpd/conf.d/ssl-example.conf
Listen 443

<VirtualHost *:443>
    ServerName www.example.com
    DocumentRoot /var/www/example

    SSLEngine On
    # 证书链:服务器证书 + 中间 CA 拼接在一个文件中
    SSLCertificateFile    /etc/pki/tls/certs/example.com-fullchain.pem
    SSLCertificateKeyFile /etc/pki/tls/private/example.com.key
    SSLCACertificateFile  /etc/pki/tls/certs/root-ca.pem

    # 只允许 TLS 1.2/1.3
    SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
    SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
    SSLHonorCipherOrder on

    # 性能参数 1:会话缓存(免去重复握手,减 2 个 RTT)
    SSLSessionCache "shmcb:/run/httpd/sslcache(512000)"
    SSLSessionCacheTimeout 300

    # 性能参数 2:OCSP Stapling(客户端无需再向 CA 查询吊销状态)
    SSLUseStapling On
    SSLStaplingResponderTimeout 5
    SSLStaplingReturnResponderErrors Off
    SSLStaplingCache "shmcb:/run/httpd/ocsp_cache(128000)"

    # 可选:HSTS 与安全响应头
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
</VirtualHost>
# 验证 SSL 配置
httpd -t
apachectl configtest
curl -I https://localhost/ -k

# 检查证书链与 OCSP Stapling 是否生效
openssl s_client -connect www.example.com:443 -status -tlsextdebug 2>/dev/null | grep -A5 "OCSP response"
# 输出 "OCSP Response Status: successful" 表示 Stapling 正常

3. mTLS 双向认证

mTLS(Mutual TLS)要求客户端也提供证书,服务端验证客户端身份。适用于微服务间通信、API 网关认证、零信任架构。

3.1 生成证书

# 生成 CA
openssl genrsa -out ca.key 4096
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt \
  -subj "/C=CN/ST=Beijing/O=MyOrg/CN=MyCA"

# 生成服务端证书
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr \
  -subj "/C=CN/ST=Beijing/O=MyOrg/CN=example.com"
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
  -CAcreateserial -out server.crt -days 365

# 生成客户端证书
openssl genrsa -out client.key 2048
openssl req -new -key client.key -out client.csr \
  -subj "/C=CN/ST=Beijing/O=MyOrg/CN=api-client-01"
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key \
  -CAcreateserial -out client.crt -days 365

3.2 httpd 配置 mTLS

<VirtualHost *:443>
    ServerName api.example.com
    SSLEngine On
    SSLCertificateFile    /etc/httpd/ssl/server.crt
    SSLCertificateKeyFile /etc/httpd/ssl/server.key
    SSLCACertificateFile  /etc/httpd/ssl/ca.crt

    # mTLS 核心:强制客户端证书
    SSLVerifyClient require
    SSLVerifyDepth 2

    # 将客户端证书信息传递给后端应用
    RequestHeader set X-SSL-Client-CN "%{SSL_CLIENT_S_DN_CN}s"
    RequestHeader set X-SSL-Client-Verify "%{SSL_CLIENT_VERIFY}s"
    DocumentRoot /var/www/api
</VirtualHost>

3.2.1 客户端证书测试与撤销

# 带客户端证书访问(.crt/.key 分文件)
curl -sS --cert client.crt --key client.key \
     -H "Host: api.example.com" https://api.example.com/ping

# 证书 + 私钥打包为 PEM 后访问(更常见)
openssl pkcs12 -export -out client.p12 -inkey client.key \
  -in client.crt -certfile ca.crt -passout pass:client-password
curl -sS --cert-type p12 --cert client.p12:client-password \
     https://api.example.com/ping

# 不带证书访问应被拒绝(验证 mTLS 生效)
curl -sS https://api.example.com/ping
# 期望输出: TLS 握手阶段被拒:curl: (35) SSL connect error
#           SSL alert number 116 (certificate required)(收不到 HTTP 400,握手就失败了)

# 在服务端查看验证结果
# 请求头 X-SSL-Client-Verify 应为 SUCCESS,X-SSL-Client-CN 为客户端 CN

客户端证书泄露或人员离职时必须吊销。httpd 通过 SSLCARevocationFile 加载 CRL:

# 生成 CRL 并在 httpd 中引用
# 注意:openssl ca 需要 CA 的配置文件(index.txt 数据库等),
# 若客户端证书是用 openssl x509 -req 直接签发的(未进 ca 数据库),
# 吊销会失败——生产环境请用 openssl ca 统一签发并维护 index.txt:
#   openssl ca -config ca.cnf -in client.csr -out client.crt
openssl ca -gencrl -config ca.cnf -out crl.pem -crldays 30
# 追加到 httpd 配置
# SSLCARevocationFile /etc/pki/tls/certs/crl.pem
# SSLCARevocationCheck chain

# 吊销某张客户端证书(证书必须存在于 ca 的 index.txt 中)
openssl ca -revoke client.crt -config ca.cnf
openssl ca -gencrl -config ca.cnf -out crl.pem -crldays 30
systemctl reload httpd

3.3 Nginx 做 mTLS 卸载

server {
    listen 443 ssl;
    server_name api.example.com;
    ssl_certificate     /etc/nginx/ssl/server.crt;
    ssl_certificate_key /etc/nginx/ssl/server.key;
    ssl_trusted_certificate /etc/nginx/ssl/ca.crt;

    ssl_client_certificate /etc/nginx/ssl/ca.crt;
    ssl_verify_client on;

    proxy_set_header X-SSL-Client-CN $ssl_client_s_dn_cn;
    proxy_set_header X-SSL-Client-Verify $ssl_client_verify;

    location / {
        proxy_pass http://127.0.0.1:8080;
    }
}

4. Nginx vs Apache httpd 对比选型

维度NginxApache httpd
架构事件驱动,异步非阻塞进程/线程模型(MPM)
静态文件性能极高,内存占用低良好,prefork 模式下较高
动态内容FastCGI 代理(PHP-FPM)原生 mod_php 嵌入
分布式配置不支持 .htaccess支持 .htaccess(共享主机友好)
URL 重写原生 rewrite,性能好mod_rewrite 功能更强
反向代理原生强项,负载均衡丰富mod_proxy,功能齐全但性能略逊
SSL/TLS原生支持,配置简洁依赖 mod_ssl,配置稍繁琐
适用场景反向代理、高并发、CDN 边缘传统 LAMP、共享主机、.htaccess 需求
选型建议 现代架构中 Nginx 通常做反向代理 + SSL 卸载,后端 httpd 处理业务。高并发场景首选 Nginx;需要 .htaccess 或 Apache 模块生态时选 httpd。两者可组合使用。

httpd 性能监控指标

指标说明告警阈值
BusyWorkers当前处理请求的 worker 数> MaxRequestWorkers × 80%
IdleWorkers空闲的 worker 数< 5(可能请求堆积)
ReqPerSec每秒处理请求数按基线调整
BytesPerSec每秒发送字节数接近带宽上限
Load5服务器负载> CPU 核心数 × 2
# 查看 httpd 状态页(需启用 mod_status)
# httpd.conf 中添加:
# ExtendedStatus On
# <Location /server-status>
#     SetHandler server-status
#     Require ip 127.0.0.1
# </Location>

curl http://localhost/server-status?auto

4.1 场景选型对照

业务场景推荐方案理由
高并发静态站 / CDN 边缘Nginx事件驱动,内存占用低,天然扛长连接
传统 PHP 站点(mod_php)Apache prefork非线程安全模块的唯一选择,兼容老代码
PHP-FPM + 高并发Nginx 前端 + httpd event 后端(或纯 Nginx)event MPM 或 Nginx 都适合 FastCGI 代理
共享主机多租户Apache.htaccess 让用户免重启改配置
反向代理 + 负载均衡Nginxupstream 健康检查、加权轮询开箱即用
复杂 URL 重写规则Apache mod_rewriteRewriteCond/RewriteRule 表达力强,支持多条件回溯
企业内网系统 / 旧应用迁移Apache模块生态全,LDAP、SSO 等模块成熟
组合架构参考 入口 Nginx(TLS + 静态资源 + 限流)→ 后端 Apache(动态请求 + 应用逻辑),两边都启用 X-Forwarded-For 透传与 real IP 恢复,是目前兼容性与性能平衡最好的落地形态。

5. CDN 回源配置要点

用户 → CDN 边缘节点(TLS 终止)
         ↓(HTTP 明文或 mTLS)
       回源服务器(Nginx / httpd)

回源协议选择:
  HTTP 明文 → CDN 边缘到源站加密链路不保证(内网可用)
  HTTPS     → 源站需配 TLS 证书,CDN 二次 TLS 终止
  mTLS      → CDN 到源站双向认证(高安全场景)
# CDN 回源关键配置
# 回源 Host 用源站域名,避免 httpd 虚拟主机匹配错误
# Header 透传:X-Real-IP / X-Forwarded-For / X-Forwarded-Proto

# 源站 httpd 信任 CDN 回源代理段
RemoteIPTrustedProxy 100.100.0.0/16
RemoteIPTrustedProxy 47.88.0.0/14

# 防止 HTTPS 重定向死循环
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
CDN + mTLS 回源 部分 CDN 支持回源 mTLS(如 Cloudflare Origin Certificates)。CDN 边缘与源站之间使用专用证书双向认证,防止源站被直接访问。在 CDN 控制台上传源站 CA 证书,源站 httpd 配置 SSLCACertificateFile 指向 CDN 的 CA。

5.1 mod_remoteip 获取真实 IP

CDN 回源后,httpd 的 %h 记录的是 CDN 边缘 IP。用 mod_remoteip 解析 X-Forwarded-For,把客户端真实 IP 写入访问日志,并让 Require ip、限流规则都基于真实 IP 生效:

# /etc/httpd/conf.modules.d/00-remoteip.conf
LoadModule remoteip_module modules/mod_remoteip.so

# 信任 CDN 回源网段(务必精确,不要用 0.0.0.0/0)
RemoteIPHeader X-Forwarded-For
RemoteIPTrustedProxy 100.100.0.0/16   # 阿里云 CDN 回源段
RemoteIPTrustedProxy 47.88.0.0/14     # 自定义边缘段

# 访问日志改用 %a(mod_remoteip 重写后的真实 IP)
LogFormat "%a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined_real
CustomLog /var/log/httpd/example_access.log combined_real

5.2 回源校验与源站保护

# 方案一:IP 白名单——源站只接受 CDN 回源段访问
<VirtualHost *:80>
    ServerName www.example.com
    <Location />
        Require ip 100.100.0.0/16
        Require ip 47.88.0.0/14
        Require ip 127.0.0.1          # 本机健康检查
    </Location>
</VirtualHost>

# 方案二:自定义头校验——CDN 回源时注入固定 Token
# CDN 控制台回源配置:回源请求头 X-Origin-Token: 9f8a7b6c...
RewriteEngine On
RewriteCond %{HTTP:X-Origin-Token} !=9f8a7b6c...
RewriteRule ^ - [F]

# 方案三:隐藏源站地址
# 源站域名不发布 DNS 记录,仅 CDN 通过 CNAME 或回源配置访问;
# 源站安全组只放行 CDN 回源 IP 段的 80/443 端口
安全提醒 X-Forwarded-For 可被伪造。TrustedProxy 必须只包含 CDN/代理的真实网段,否则攻击者可伪造 IP 绕过 Require ip 白名单或触发限流误杀。

CDN 回源配置案例

# 完整的 CDN 回源 httpd 配置
# /etc/httpd/conf.d/cdn-origin.conf

# 信任 CDN 回源 IP 段
LoadModule remoteip_module modules/mod_remoteip.so
RemoteIPHeader X-Forwarded-For
RemoteIPTrustedProxy 100.100.0.0/16   # 阿里云 CDN
RemoteIPTrustedProxy 173.245.48.0/20  # Cloudflare

# 防止 HTTPS 重定向死循环
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

# 访问日志使用真实 IP
LogFormat "%a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" cdn_real
CustomLog /var/log/httpd/cdn_access.log cdn_real

# 源站保护:只接受 CDN 回源请求
<Location />
    Require ip 100.100.0.0/16
    Require ip 173.245.48.0/20
    Require ip 127.0.0.1
</Location>

常见错误

1. HTTPS 重定向死循环

症状:浏览器反复提示重定向次数过多。原因:后端 httpd 未信任前端代理的 X-Forwarded-Proto 头,导致 httpd 误判请求为 HTTP 并再次重定向。

排查:检查是否配置了 RemoteIPTrustedProxy 并在 RewriteCond 中判断 %{HTTP:X-Forwarded-Proto}

2. mTLS 客户端证书验证失败(SSL_ERROR_RX_RECORD_TOO_LONG)

症状:curl 报 SSL_ERROR_RX_RECORD_TOO_LONG,或浏览器报 ERR_SSL_PROTOCOL_ERROR。原因:httpd 未启用 SSL 或 443 端口被其他服务占用。

排查:httpd -t 检查配置语法,ss -tlnp | grep 443 确认端口监听,openssl s_client -connect localhost:443 测试 TLS 握手。

3. .htaccess 规则不生效

症状:URL 重写无效果。原因:VirtualHost 中 AllowOverride None(默认值)禁止了 .htaccess 解析。

排查:确认对应 <Directory> 块中设置了 AllowOverride All,并重启 httpd 使配置生效。

4. SSL 证书链不完整导致客户端报不受信任

症状:部分浏览器正常、部分报证书不受信任。原因:SSLCertificateFile 中只放了服务器证书,缺少中间 CA 证书。

排查:用 openssl s_client -showcerts -connect example.com:443 检查证书链,将中间证书拼接到服务器证书文件中。

5. SSLVerifyClient require 后所有请求返回 400

症状:配置 mTLS 后正常浏览器请求也返回 400 Bad Request。原因:没有排除健康检查或静态资源的客户端证书验证。

排查:在需要排除的 Location 中设置 SSLVerifyClient none,或使用 SSLVerifyClient optional_no_ca 做选择性验证。

最佳实践

1. SSL 卸载放在反向代理层

证书管理集中在 Nginx/CDN,后端 httpd 只处理 HTTP 明文。统一续期、统一管理,后端无需暴露 443 端口。

2. .htaccess 仅在必要时使用

高并发站点应在 VirtualHost 块中直接写入配置,避免 .htaccess 的逐目录扫描开销。共享主机或无法重启 httpd 时才考虑 .htaccess。

3. mTLS 证书设置合理有效期与轮换周期

客户端证书有效期建议 1 年,配合自动化续期。定期轮换 CA 证书,吊销列表(CRL)或 OCSP 应及时更新。

4. CDN 回源务必信任代理 IP 段

源站 httpd 必须配置 RemoteIPTrustedProxy 添加 CDN 回源 IP 段,否则客户端真实 IP 会丢失,且可能触发错误的 HTTPS 重定向。

5. 禁用 SSLv3 和 TLS 1.0/1.1

在 httpd 和 Nginx 配置中显式指定 SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1,只允许 TLS 1.2+,避免已知安全漏洞。

故障排查案例:SSL 证书链不完整

现象:Chrome 浏览器正常访问,但 curl 和部分移动端报 SSL certificate problem: unable to get local issuer certificate

排查:执行 openssl s_client -connect example.com:443 -showcerts,输出中只显示了服务器证书,缺少中间 CA 证书。

根因:httpd 的 SSLCertificateFile 中只包含服务器证书,未拼接中间 CA 证书。Chrome 内置 AIA(Authority Information Access)可以自动补全中间证书,但 curl 和旧版 Android 不支持此机制。

修复:将中间证书拼接到服务器证书文件中,顺序为:服务器证书在前,中间 CA 在后。

# 拼接证书链
cat server.crt intermediate-ca.crt > /etc/httpd/ssl/example.com-fullchain.pem

# 验证证书链完整性
openssl verify -CAfile root-ca.crt example.com-fullchain.pem
# 输出: example.com-fullchain.pem: OK

# 重载 httpd
apachectl graceful

# 再次测试
curl -v https://example.com/ 2>&1 | grep -E "SSL certificate|subject|issuer"

练习题

1. 配置 SSL 卸载

假设源站 httpd 运行在 80 端口,前端 Nginx 做 SSL 卸载。请写出:(a) Nginx 的 443 端口 VirtualHost 配置(含证书路径和 proxy_pass);(b) httpd 需要添加的 mod_remoteip 配置,使其信任 Nginx 所在网段 10.1.0.0/16。

2. 排查重定向死循环

某站点前端是阿里云 CDN(回源 HTTP),后端 httpd 配置了 HTTPS 重定向规则。用户访问时浏览器报 ERR_TOO_MANY_REDIRECTS。请列出 3 个可能的原因和对应的修复方法。

3. mTLS 证书签发与配置

为一个微服务 API 网关配置 mTLS:(a) 用 openssl 生成 CA、服务端证书、客户端证书的命令;(b) httpd VirtualHost 中启用 mTLS 并将客户端 CN 传递给后端应用的完整配置。

学习检查点

学完本章后,请检验自己是否掌握以下内容:

检查项自测问题验证方法
概念理解能用自己的话解释 SSL 卸载的概念和作用尝试向他人讲解
命令操作能不查文档完成 httpd SSL 配置、mTLS 证书生成在终端实际执行
原理掌握能说出 Apache httpd 的模块化架构和工作原理画出流程图
故障排查能独立排查 HTTPS 重定向死循环、SSL 证书错误模拟故障并修复
最佳实践能说明为什么需要在 CDN 环境中正确处理 X-Forwarded-Proto对比不同方案

本章总结

Apache httpd 凭借模块生态与 .htaccess 分布式配置在共享主机和传统 LAMP 场景中仍有不可替代的价值,但高并发场景应将 SSL 卸载与 mTLS 终结交给 Nginx/CDN,后端 httpd 专注业务处理。CDN 回源必须信任代理 IP 段并正确处理 X-Forwarded-Proto,否则会陷入 HTTPS 重定向死循环。选型的关键不是谁更好,而是让每层组件做自己擅长的事。

延伸阅读

↑ 回到顶部