强曰为道

与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

安全加固

安全加固

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 [email protected]

ServerTokens 选项:

选项Server 头输出
FullApache/2.4.58 (Ubuntu) PHP/8.2.0
OSApache/2.4.58 (Ubuntu)
MinorApache/2.4
MajorApache/2
ProdApache

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 [email protected]
    
    # 日志
    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. 注意事项

  1. 定期更新:及时应用安全补丁
  2. 最小权限:Apache 用户仅授予必要权限
  3. 监控告警:配置安全事件告警
  4. 备份配置:修改安全配置前备份
  5. 测试验证:安全配置可能影响正常功能
  6. 合规要求:根据 PCI DSS 等标准配置

10. 扩展阅读

11. 总结

Apache 安全加固是一个持续的过程:

  • 基础安全:隐藏信息、保护文件、安全头
  • 访问控制:IP 限制、用户认证
  • WAF 防护:ModSecurity 规则
  • 限流防护:防 DDoS、限流
  • 安全审计:定期检查、日志分析

多层防护是保障 Apache 安全的关键。