Apache HTTP Server 完全指南 / 安全加固
安全加固
Apache 安全加固是保护 Web 服务器免受攻击的重要措施。本章介绍访问控制、ModSecurity WAF、限流等安全技术。
1. 基础安全配置
1.1 隐藏版本信息
# /etc/apache2/conf-available/security.conf
# 隐藏 Apache 版本
ServerTokens Prod
ServerSignature Off
# 隐藏 PHP 版本
# php.ini 中设置:
# expose_php = Off
# 隐藏操作系统信息
ServerAdmin admin@example.com
ServerTokens 选项:
| 选项 | Server 头输出 |
|---|---|
Full | Apache/2.4.58 (Ubuntu) PHP/8.2.0 |
OS | Apache/2.4.58 (Ubuntu) |
Minor | Apache/2.4 |
Major | Apache/2 |
Prod | Apache |
1.2 目录安全
# 根目录 - 拒绝所有访问
<Directory />
Options -Indexes -FollowSymLinks -Includes
AllowOverride None
Require all denied
</Directory>
# 文档根目录 - 允许访问
<Directory "/var/www/html">
Options -Indexes +FollowSymLinks
AllowOverride None
Require all granted
</Directory>
# 禁止目录列表
Options -Indexes
# 禁止符号链接跟随
Options -FollowSymLinks
# 禁止 SSI
Options -Includes
1.3 敏感文件保护
# 保护隐藏文件(.htaccess, .git, .env 等)
<FilesMatch "^\.">
Require all denied
</FilesMatch>
# 保护特定文件类型
<FilesMatch "\.(conf|log|bak|sql|sh|py|rb|env|git|htaccess|htpasswd)$">
Require all denied
</FilesMatch>
# 保护特定文件
<Files "config.php">
Require all denied
</Files>
# 保护包含敏感信息的目录
<DirectoryMatch "^/var/www/html/(config|logs|tmp|backup)">
Require all denied
</DirectoryMatch>
1.4 安全头配置
<IfModule mod_headers.c>
# HSTS(严格传输安全)
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
# 防止 MIME 类型嗅探
Header always set X-Content-Type-Options "nosniff"
# 防止点击劫持
Header always set X-Frame-Options "SAMEORIGIN"
# XSS 保护
Header always set X-XSS-Protection "1; mode=block"
# 引用来源
Header always set Referrer-Policy "strict-origin-when-cross-origin"
# 权限策略
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"
# CSP(内容安全策略)
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self'; frame-ancestors 'self'"
# 移除服务器头
Header always unset Server
Header always unset X-Powered-By
</IfModule>
2. 访问控制
2.1 IP 访问控制
# Apache 2.4+ 语法
<Directory "/var/www/admin">
Require ip 192.168.1.0/24
Require ip 10.0.0.0/8
Require ip 172.16.0.0/12
</Directory>
# 拒绝特定 IP
<Directory "/var/www/html">
Require all granted
Require not ip 192.168.1.100
Require not ip 10.0.0.50
</Directory>
# 复杂访问控制
<Directory "/var/www/admin">
<RequireAny>
Require ip 192.168.1.0/24
Require ip 10.0.0.0/8
</RequireAny>
</Directory>
# 同时满足多个条件
<Directory "/var/www/sensitive">
<RequireAll>
Require ip 192.168.1.0/24
Require user admin
</RequireAll>
</Directory>
2.2 基于用户的认证
# 创建密码文件
# htpasswd -c /etc/apache2/.htpasswd admin
# htpasswd /etc/apache2/.htpasswd user1
# 基本认证
<Directory "/var/www/admin">
AuthType Basic
AuthName "Admin Area"
AuthUserFile /etc/apache2/.htpasswd
Require valid-user
</Directory>
# 基于组的认证
# 创建组文件 /etc/apache2/.htgroup
# admins: admin superadmin
# users: user1 user2
<Directory "/var/www/admin">
AuthType Basic
AuthName "Admin Area"
AuthUserFile /etc/apache2/.htpasswd
AuthGroupFile /etc/apache2/.htgroup
Require group admins
</Directory>
# 摘要认证(更安全)
<Directory "/var/www/secure">
AuthType Digest
AuthName "Secure Area"
AuthUserFile /etc/apache2/.htdigest
Require valid-user
</Directory>
# 创建摘要密码文件
# htdigest -c /etc/apache2/.htdigest "Secure Area" admin
2.3 组合访问控制
# IP + 用户认证
<Directory "/var/www/admin">
AuthType Basic
AuthName "Admin Area"
AuthUserFile /etc/apache2/.htpasswd
<RequireAll>
Require ip 192.168.1.0/24
Require user admin
</RequireAll>
</Directory>
# 条件访问
<Directory "/var/www/portal">
<RequireAny>
Require ip 192.168.1.0/24
<RequireAll>
AuthType Basic
AuthName "Portal"
AuthUserFile /etc/apache2/.htpasswd
Require valid-user
</RequireAll>
</RequireAny>
</Directory>
3. ModSecurity(WAF)
3.1 安装 ModSecurity
# Debian/Ubuntu
sudo apt install libapache2-mod-security2
sudo a2enmod security2
# CentOS/RHEL
sudo yum install mod_security mod_security_crs
# 安装 OWASP CRS(核心规则集)
cd /etc/apache2/modsecurity
sudo git clone https://github.com/coreruleset/coreruleset.git
sudo cp coreruleset/crs-setup.conf.example coreruleset/crs-setup.conf
3.2 基本配置
# /etc/apache2/mods-available/security2.conf
<IfModule mod_security2.c>
# 启用 ModSecurity
SecRuleEngine On
# 请求体处理
SecRequestBodyAccess On
SecRequestBodyLimit 13107200
SecRequestBodyNoFilesLimit 131072
SecRequestBodyLimitAction Reject
# 响应体处理
SecResponseBodyAccess On
SecResponseBodyMimeType text/plain text/html text/xml application/json
SecResponseBodyLimit 524288
SecResponseBodyLimitAction ProcessPartial
# 临时文件
SecTmpDir /tmp/modsecurity/tmp
SecDataDir /tmp/modsecurity/data
SecUploadDir /tmp/modsecurity/upload
# 日志
SecAuditEngine RelevantOnly
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
SecAuditLogParts ABIJDEFHZ
SecAuditLogType Serial
SecAuditLog /var/log/apache2/modsec_audit.log
# 调试日志
# SecDebugLog /var/log/apache2/modsec_debug.log
# SecDebugLogLevel 3
# 规则集
IncludeOptional /etc/apache2/modsecurity/coreruleset/crs-setup.conf
IncludeOptional /etc/apache2/modsecurity/coreruleset/rules/*.conf
# 排除规则
# SecRuleRemoveById 942100
# SecRuleRemoveByTag "attack-sqli"
</IfModule>
3.3 自定义规则
# /etc/apache2/modsecurity/custom-rules.conf
# 阻止特定 User-Agent
SecRule REQUEST_HEADERS:User-Agent "sqlmap" \
"id:100001,phase:1,t:none,t:lowercase,deny,status:403,msg:'Blocked sqlmap User-Agent'"
# 阻止 SQL 注入
SecRule ARGS "@detectSQLi" \
"id:100002,phase:2,t:none,t:urlDecodeUni,deny,status:403,msg:'SQL Injection Attack'"
# 阻止 XSS
SecRule ARGS "@detectXSS" \
"id:100003,phase:2,t:none,t:urlDecodeUni,deny,status:403,msg:'XSS Attack'"
# 阻止目录遍历
SecRule REQUEST_URI "\.\./" \
"id:100004,phase:1,t:none,t:urlDecodeUni,deny,status:403,msg:'Directory Traversal'"
# 限制请求方法
SecRule REQUEST_METHOD "!^GET|HEAD|POST|PUT|DELETE|PATCH|OPTIONS$" \
"id:100005,phase:1,t:none,deny,status:405,msg:'Method Not Allowed'"
# 限制文件上传大小
SecRule FILES_SIZE "@gt 10485760" \
"id:100006,phase:1,t:none,deny,status:413,msg:'File Too Large'"
# 保护 API 端点
SecRule REQUEST_URI "^/api/" \
"id:100007,phase:1,t:none,pass,nolog,setvar:tx.paranoia_level=2"
3.4 规则排除
# 排除特定规则
SecRuleRemoveById 942100 # 排除特定 ID
SecRuleRemoveByTag "attack-sqli" # 排除特定标签
# 排除特定路径
<LocationMatch "^/api/upload">
SecRuleEngine Off
</LocationMatch>
# 或仅排除特定规则
<LocationMatch "^/admin">
SecRuleRemoveById 941100 # XSS 规则
SecRuleRemoveById 942100 # SQL 注入规则
</LocationMatch>
# 使用 ctl 动作
SecRule REQUEST_URI "^/api/upload" \
"id:100010,phase:1,t:none,pass,nolog,ctl:ruleEngine=Off"
3.5 ModSecurity 日志分析
# 查看审计日志
tail -f /var/log/apache2/modsec_audit.log
# 分析攻击类型
grep -oP 'msg ".*?"' /var/log/apache2/modsec_audit.log | sort | uniq -c | sort -rn
# 按 IP 统计
grep -oP 'client "\K[^"]+' /var/log/apache2/modsec_audit.log | sort | uniq -c | sort -rn
# 常见误报处理
# 1. 识别误报规则
# 2. 调整规则或添加排除
# 3. 测试验证
4. 限流与防 DDoS
4.1 mod_ratelimit
sudo a2enmod ratelimit
sudo systemctl reload apache2
# 限制带宽
<IfModule mod_ratelimit.c>
<Location "/downloads">
SetOutputFilter RATE_LIMIT
SetEnv rate-limit 400 # KB/s
</Location>
</IfModule>
4.2 mod_reqtimeout
# 请求超时设置(防慢速攻击)
<IfModule mod_reqtimeout.c>
RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500
</IfModule>
4.3 mod_evasive(防 DDoS)
# 安装 mod_evasive
sudo apt install libapache2-mod-evasive
sudo a2enmod evasive
<IfModule mod_evasive20.c>
DOSHashTableSize 3097
DOSPageCount 2
DOSSiteCount 50
DOSPageInterval 1
DOSSiteInterval 1
DOSBlockingPeriod 10
# 邮件通知
DOSEmailNotify admin@example.com
# 日志
DOSLogDir /var/log/mod_evasive
# 白名单
DOSWhitelist 127.0.0.1
DOSWhitelist 192.168.1.*
</IfModule>
4.4 基于 mod_rewrite 限流
# 限制并发连接
<IfModule mod_rewrite.c>
RewriteEngine On
# 基于 IP 的访问控制(简易版)
RewriteMap hosts-iplist txt:/etc/apache2/iplist.txt
RewriteCond %{REMOTE_ADDR} ^(.*)$
RewriteCond ${hosts-iplist:%1|BLOCK} ^BLOCK$ [NC]
RewriteRule .* - [F]
</IfModule>
5. 防火墙集成
5.1 iptables 集成
# 限制连接速率
iptables -A INPUT -p tcp --dport 80 -m state --state NEW -m recent --set
iptables -A INPUT -p tcp --dport 80 -m state --state NEW -m recent --update --seconds 60 --hitcount 100 -j DROP
# 限制每个 IP 的连接数
iptables -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 50 -j DROP
5.2 fail2ban 集成
# /etc/fail2ban/jail.local
[apache-auth]
enabled = true
port = http,https
filter = apache-auth
logpath = /var/log/apache2/error.log
maxretry = 3
bantime = 3600
[apache-botsearch]
enabled = true
port = http,https
filter = apache-botsearch
logpath = /var/log/apache2/access.log
maxretry = 2
bantime = 86400
[apache-noscript]
enabled = true
port = http,https
filter = apache-noscript
logpath = /var/log/apache2/error.log
maxretry = 6
bantime = 86400
6. SSL 安全加固
6.1 SSL 配置安全
# 强制 HTTPS
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>
# HSTS
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
# 安全协议
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLProtocol TLSv1.2 TLSv1.3
# 强密码套件
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
SSLHonorCipherOrder on
SSLCompression off
7. 安全审计
7.1 安全检查脚本
#!/bin/bash
# apache-security-audit.sh
echo "=== Apache 安全审计 ==="
# 检查版本
echo "1. Apache 版本:"
apachectl -v
# 检查模块
echo "2. 已加载模块:"
apachectl -M | wc -l
# 检查配置
echo "3. 配置语法检查:"
apachectl configtest
# 检查监听端口
echo "4. 监听端口:"
ss -tlnp | grep apache
# 检查权限
echo "5. 文档根目录权限:"
ls -la /var/www/
# 检查敏感文件
echo "6. 检查敏感文件暴露:"
for ext in .env .git .htaccess .bak .sql .log; do
curl -s -o /dev/null -w "%{http_code}" "http://localhost$ext"
echo " - $ext"
done
# 检查 SSL
echo "7. SSL 配置检查:"
if apachectl -M | grep -q ssl; then
echo " SSL 模块已启用"
else
echo " SSL 模块未启用"
fi
echo "=== 审计完成 ==="
7.2 安全基线检查表
| 检查项 | 状态 | 说明 |
|---|---|---|
| ServerTokens Prod | ✅/❌ | 隐藏版本信息 |
| ServerSignature Off | ✅/❌ | 隐藏签名 |
| 目录列表禁用 | ✅/❌ | Options -Indexes |
| .htaccess 保护 | ✅/❌ | FilesMatch |
| SSL 启用 | ✅/❌ | HTTPS 配置 |
| HSTS 配置 | ✅/❌ | 严格传输安全 |
| ModSecurity 启用 | ✅/❌ | WAF 防护 |
| 访问控制配置 | ✅/❌ | IP/用户限制 |
| 日志记录完整 | ✅/❌ | 访问和错误日志 |
| 定期更新 | ✅/❌ | 安全补丁 |
8. 业务场景
8.1 电商网站安全
<VirtualHost *:443>
ServerName shop.example.com
# SSL 配置
SSLEngine on
SSLCertificateFile /etc/ssl/certs/shop.crt
SSLCertificateKeyFile /etc/ssl/private/shop.key
# 安全头
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
Header always set Content-Security-Policy "upgrade-insecure-requests"
# 支付页面特殊保护
<Location "/checkout/payment">
<RequireAll>
Require ip 10.0.0.0/8
AuthType Basic
AuthName "Payment Area"
AuthUserFile /etc/apache2/.htpasswd
Require user payment_user
</RequireAll>
</Location>
# ModSecurity 规则加强
<IfModule mod_security2.c>
SecRuleEngine On
SecAuditEngine On
</IfModule>
</VirtualHost>
8.2 API 安全
<VirtualHost *:443>
ServerName api.example.com
# API 限流
<IfModule mod_ratelimit.c>
<Location "/api">
SetOutputFilter RATE_LIMIT
SetEnv rate-limit 1024
</Location>
</IfModule>
# API 认证
<Location "/api/v1">
AuthType Basic
AuthName "API"
AuthUserFile /etc/apache2/.htpasswd-api
Require valid-user
</Location>
# CORS 配置
<IfModule mod_headers.c>
Header always set Access-Control-Allow-Origin "https://www.example.com"
Header always set Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
Header always set Access-Control-Allow-Headers "Authorization, Content-Type"
</IfModule>
</VirtualHost>
9. 注意事项
- 定期更新:及时应用安全补丁
- 最小权限:Apache 用户仅授予必要权限
- 监控告警:配置安全事件告警
- 备份配置:修改安全配置前备份
- 测试验证:安全配置可能影响正常功能
- 合规要求:根据 PCI DSS 等标准配置
10. 扩展阅读
11. 总结
Apache 安全加固是一个持续的过程:
- 基础安全:隐藏信息、保护文件、安全头
- 访问控制:IP 限制、用户认证
- WAF 防护:ModSecurity 规则
- 限流防护:防 DDoS、限流
- 安全审计:定期检查、日志分析
多层防护是保障 Apache 安全的关键。