Nginx / Apache / Tomcat 安全配置实战

1. Nginx 生产安全配置(完整模板)

1.1 nginx.conf 安全基线

user nginx;
worker_processes auto;
worker_rlimit_nofile 65535;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
    worker_connections 2048;
    multi_accept on;
    use epoll;
}

http {
    # === 版本隐藏 ===
    server_tokens off;

    # === 基础 ===
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    client_max_body_size 20m;
    client_body_buffer_size 128k;
    client_header_buffer_size 4k;
    large_client_header_buffers 4 16k;
    server_names_hash_bucket_size 128;

    # === 超时(防御 Slowloris)===
    client_body_timeout 12;
    client_header_timeout 12;
    send_timeout 10;
    keepalive_requests 100;

    # === gzip ===
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss application/rss+xml image/svg+xml;

    # === 日志 ===
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';
    access_log /var/log/nginx/access.log main buffer=32k flush=5m;

    # === 引入安全片段 ===
    include /etc/nginx/conf.d/security.conf;

    server {
        listen 80;
        listen [::]:80;
        server_name _;
        return 301 https://$host$request_uri;
    }

    include /etc/nginx/conf.d/*.conf;
}

1.2 security.conf(安全响应头)

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=()";
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; connect-src 'self'; frame-ancestors 'none'; object-src 'none';" always;
# 禁止在响应中暴露代理信息
proxy_hide_header X-Powered-By;
proxy_hide_header X-AspNet-Version;
proxy_hide_header X-Generator;

1.3 业务站点 server 配置

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name app.example.com;

    # === TLS 配置(TLS 1.3 优先)===
    ssl_certificate /etc/letsencrypt/live/app.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/app.example.com/chain.pem;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
    ssl_prefer_server_ciphers on;
    ssl_ecdh_curve secp384r1;
    ssl_session_cache shared:SSL:20m;
    ssl_session_timeout 20m;
    ssl_session_tickets off;

    # OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 1.1.1.1 valid=300s;
    resolver_timeout 5s;

    # === 根目录 ===
    root /var/www/app/current/public;
    index index.html index.htm index.php;

    # === 隐藏文件拦截 ===
    location ~ /. {
        deny all;
        access_log off;
        log_not_found off;
    }

    # === 禁止访问编译文件 ===
    location ~* .(bak|old|orig|save|swp|tmp|log|sql|tgz|zip|tar.gz)$ {
        deny all;
    }

    # === 禁止暴露配置 ===
    location ~* .(conf|ini|env|yml|yaml|json)$ {
        # 允许某些静态配置
        try_files $uri =404;
    }

    # === 禁止访问 .git / .svn ===
    location ~ /.(git|svn|hg|bzr|DS_Store) {
        deny all;
    }

    # === 禁止目录遍历 ===
    autoindex off;

    # === WordPress / PHP 常见防护(按需)===
    location ~* /(wp-config|wp-login|xmlrpc).php {
        allow 10.0.0.0/8;
        deny all;
    }

    # === Reverse Proxy 到后端 ===
    location /api/ {
        proxy_pass http://backend_app:3000;
        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;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_buffering on;
        proxy_buffer_size 128k;
        proxy_buffers 4 256k;
    }

    # === 静态资源缓存 ===
    location ~* .(js|css|png|jpg|jpeg|gif|ico|svg|woff2?|ttf|eot)$ {
        expires 30d;
        access_log off;
        add_header Cache-Control "public, immutable";
    }

    # === 错误页 ===
    error_page 404 /404.html;
    error_page 500 502 503 504 /50x.html;
}

1.4 速率限制(Nginx Plus 或社区版配合)

# 在 http 块中定义
limit_req_zone $binary_remote_addr zone=api:10m rate=30r/s;
limit_conn_zone $binary_remote_addr zone=addr:10m;

# 使用
location /api/ {
    limit_req zone=api burst=50 nodelay;
    limit_conn addr 20;
    proxy_pass http://backend_app:3000;
}

2. Apache httpd 安全配置

2.1 httpd.conf 基础加固

# 隐藏版本
ServerTokens Prod
ServerSignature Off

# 禁用目录列表
Options -Indexes -FollowSymLinks -ExecCGI
AllowOverride None

# 默认拒绝
<Directory />
    Require all denied
</Directory>

# 开放文档根
<Directory "/var/www/html">
    Require all granted
    Options -Indexes
    AllowOverride None
</Directory>

# 隐藏文件拒绝
<FilesMatch "^.|^(config|bak|old|orig|log|sql|ini|env|yml|yaml).*">
    Require all denied
</FilesMatch>

# 禁止访问 .git / .svn
<DirectoryMatch "/(.git|.svn|.hg)/">
    Require all denied
</DirectoryMatch>

# 禁止 phpMyAdmin / wp-login 公网访问
<LocationMatch "/(phpmyadmin|phpMyAdmin|wp-login|wp-config)">
    Require ip 10.0.0.0/8
    Require ip 172.16.0.0/12
</LocationMatch>

2.2 Apache TLS 配置

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

    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/app.example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/app.example.com/privkey.pem
    SSLCertificateChainFile /etc/letsencrypt/live/app.example.com/chain.pem

    SSLProtocol -all +TLSv1.2 +TLSv1.3
    SSLCipherSuite TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
    SSLHonorCipherOrder on
    SSLOptions +StdEnvVars -LegacyDNSStyle

    # 安全响应头
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-Frame-Options "DENY"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
    Header always unset X-Powered-By
    Header always unset Server

    # OCSP Stapling (Apache 2.4.10+)
    SSLStaplingCache "shmcb:logs/stapling.cache(128000)"
    SSLStaplingResponderTimeout 5
    SSLStaplingReturnResponderErrors off
</VirtualHost>

2.3 mod_security WAF

# 启用 mod_security
SecRuleEngine On
SecResponseBodyAccess On

# 基础规则
SecRule ARGS "@rx (\{\{|\{%|__class__|__mro__|__subclasses__)" "id:900001,phase:2,deny,status:403,msg:'SSTI Attempt'"
SecRule ARGS "@rx (<script|onerror=|onload=)" "id:900002,phase:2,deny,status:403,msg:'XSS Attempt'"
SecRule ARGS "@rx (SELECT.*FROM|UNION.*SELECT|DROP.*TABLE|OR\s+1=1)" "id:900003,phase:2,deny,status:403,msg:'SQLi Attempt'"
SecRule ARGS "@rx (\$\(.*\)|\`.*\`|;\s*(cat|ls|id|whoami|wget|curl|nc)\s)" "id:900004,phase:2,deny,status:403,msg:'Command Injection'"
SecRule URI "@rx (\.env$|\.git$|\.git/)" "id:900005,phase:1,deny,status:403"

3. Apache Tomcat 安全配置

3.1 server.xml 加固

<!-- 关闭 AJP(CVE-2020-1938 Ghostcat 的攻击入口)-->
<!-- 直接注释掉 AJP Connector -->

<!-- HTTP Connector 禁用 HTTP/1.0、禁用目录遍历 -->
<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
           maxThreads="200" acceptCount="100"
           connectionTimeout="20000" redirectPort="8443"
           server=" "
           enableLookups="false"
           allowTrace="false"
           maxHttpHeaderSize="8192"
           URIEncoding="UTF-8"
           relaxedQueryChars="[]|{}^&apos;&quot;&lt;&gt;" />

<!-- HTTPS Connector -->
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
           maxThreads="200"
           SSLEnabled="true" scheme="https" secure="true"
           sslProtocol="TLS"
           protocols="TLSv1.2,TLSv1.3"
           ciphers="TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256,TLS_AES_128_GCM_SHA256,ECDHE-ECDSA-AES256-GCM-SHA384,ECDHE-RSA-AES256-GCM-SHA384,ECDHE-ECDSA-AES128-GCM-SHA256,ECDHE-RSA-AES128-GCM-SHA256"
           honorCipherOrder="true"
           certificateKeystoreFile="/etc/tomcat/keystore.p12"
           certificateKeystoreType="PKCS12"
           certificateKeystorePassword="${keystore.password}"
           server=" " />

<!-- 关闭管理应用和示例应用 -->
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
    <!-- 不部署 ROOT / manager / examples / docs / host-manager / examples-docs -->
    <Valve className="org.apache.catalina.valves.ErrorReportValve" showReport="false" showServerInfo="false" />
    <Valve className="org.apache.catalina.valves.AccessLogValve"
           directory="logs" prefix="localhost_access_log." suffix=".txt"
           pattern="%h %l %u %t "%r" %s %b" />
</Host>

3.2 Catalina web.xml 全局安全

<!-- conf/web.xml -->
<web-app>
    <mime-mapping>
        <extension>htaccess</extension>
        <mime-type>text/plain</mime-type>
    </mime-mapping>
    <security-constraint>
        <display-name>Restrict access to debug endpoints</display-name>
        <web-resource-collection>
            <web-resource-name>protected</web-resource-name>
            <url-pattern>/manager/*</url-pattern>
            <url-pattern>/host-manager/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>manager-gui</role-name>
        </auth-constraint>
        <user-data-constraint>
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
        </user-data-constraint>
    </security-constraint>

    <session-config>
        <session-timeout>30</session-timeout>
        <cookie-config>
            <http-only>true</http-only>
            <secure>true</secure>
        </cookie-config>
        <tracking-mode>COOKIE</tracking-mode>
    </session-config>

    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>

    <listener>
        <listener-class>org.apache.catalina.core.JreMemoryLeakPreventionListener</listener-class>
    </listener>
</web-app>

3.3 禁用 AJP / shutdown 端口

server.xml 注释掉 AJP 8009 连接器,将 shutdown 端口绑定到 localhost 且启用强密码:

<Server port="8005" shutdown="SECRET_SHUTDOWN_PASSWORD">
    <!-- 注释掉 AJP -->
    <!-- <Connector port="8009" protocol="AJP/1.3" ... /> -->
</Server>

3.4 隐藏版本信息

<Connector port="8080" server=" " />

Valve 配置:

<Valve className="org.apache.catalina.valves.ErrorReportValve"
       showReport="false" showServerInfo="false" />

4. Apache HTTP Server 安全配置

4.1 httpd.conf 核心设置

ServerTokens Prod
ServerSignature Off
TraceEnable Off
FileETag None

# 禁用目录列表
Options -Indexes -FollowSymLinks +SymLinksIfOwnerMatch

# 禁止 .git / .env / .idea / .svn 等隐藏文件
<FilesMatch "^\.">
    Order allow,deny
    Deny from all
</FilesMatch>

# 禁止访问常见备份文件
<FilesMatch "\.(bak|old|orig|swp|swo|tmp|save|log|sql)$">
    Order allow,deny
    Deny from all
</FilesMatch>

# 禁止访问 phpMyAdmin 等敏感路径
<LocationMatch "/(phpmyadmin|pma|myadmin|adminer|mysql|phpinfo)">
    Order allow,deny
    Allow from 10.0.0.0/8
    Allow from 172.16.0.0/12
    Allow from 192.168.0.0/16
    Deny from all
</LocationMatch>

# 安全响应头
Header always set X-Frame-Options "DENY"
Header always set X-Content-Type-Options "nosniff"
Header always set X-XSS-Protection "1; mode=block"
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Content-Security-Policy "default-src 'self'"

# 限制请求方法
<LimitExcept GET POST HEAD OPTIONS>
    Require all denied
</LimitExcept>

# 禁用 TRACE / CONNECT
RewriteEngine On
RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK|CONNECT) [NC]
RewriteRule .* - [F,L]

# Keep-Alive
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5

# 超时
Timeout 30
RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500

# 限制请求体大小
LimitRequestBody 10485760

# 启用 mod_security
Include conf/extra/httpd-modsecurity.conf
SecRuleEngine On
SecStatusEngine On

4.2 虚拟主机配置模板

<VirtualHost *:80>
    ServerName app.example.com
    Redirect permanent / https://app.example.com/
</VirtualHost>

<VirtualHost *:443>
    ServerName app.example.com
    DocumentRoot /var/www/html/app/current/public

    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/app.example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/app.example.com/privkey.pem
    SSLCertificateChainFile /etc/letsencrypt/live/app.example.com/chain.pem

    SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
    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
    SSLSessionTickets off
    SSLVerifyClient none

    Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"

    # 反代到 Flask
    <Proxy *>
        Require all granted
    </Proxy>
    ProxyPreserveHost On
    ProxyPass /api http://127.0.0.1:5000/api timeout=30
    ProxyPassReverse /api http://127.0.0.1:5000/api
</VirtualHost>

4.3 CVE 历史

  • CVE-2021-41773 / CVE-2021-42013 (Apache httpd 2.4.49 / 2.4.50):%2e%2e/%2e%2e 路径穿越 RCE;
  • CVE-2023-27522:反向代理 SSRF;
  • CVE-2023-45802:HTTP/2 内存泄漏 DoS;
  • CVE-2024-27316:HTTP/2 内容长度不一致 DoS。

5. Nginx 安全配置

5.1 nginx.conf 全局安全

user www-data;
worker_processes auto;
worker_cpu_affinity auto;

pid /var/run/nginx.pid;

worker_rlimit_nofile 65535;

events {
    worker_connections 4096;
    use epoll;
    multi_accept on;
}

http {
    # 基础
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    server_tokens off;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    # 日志
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log warn;

    # 性能
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

    # 安全头
    add_header X-Frame-Options "DENY" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

    # 限速
    limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
    limit_req_zone $binary_remote_addr zone=login_limit:10m rate=1r/m;
    limit_conn_zone $binary_remote_addr zone=conn_limit:10m;

    # 请求体
    client_max_body_size 20m;
    client_body_timeout 30s;
    client_header_timeout 30s;
    send_timeout 30s;

    # 隐藏文件
    location ~ /\. { deny all; access_log off; log_not_found off; }

    # 备份文件
    location ~* \.(bak|old|orig|swp|swo|tmp|save|log|sql|ini|sh)$ {
        deny all;
    }

    # 禁止访问隐藏目录
    location ~ /(\.git|\.svn|\.idea|\.vscode|\.env|\.DS_Store|node_modules)/ {
        deny all;
    }

    # 禁止常见敏感路径
    location ~* /(phpmyadmin|pma|adminer|phpinfo|test|debug|console|swagger|actuator|graphql) {
        allow 10.0.0.0/8;
        allow 172.16.0.0/12;
        allow 192.168.0.0/16;
        deny all;
    }

    # 限制 HTTP 方法
    if ($request_method !~ ^(GET|POST|HEAD|OPTIONS|PUT|DELETE|PATCH)$) {
        return 405;
    }

    # 禁止 User-Agent 为空或扫描器
    if ($http_user_agent = "") { return 403; }
    if ($http_user_agent ~* "sqlmap|nikto|nmap|masscan|gobuster|dirb|wpscan") { return 403; }

    # 禁止可疑 URI
    if ($request_uri ~* "(\.(php|asp|jsp))(/|%2f)") { return 403; }
    if ($request_uri ~* "(\\x|\\u00|\\c0|\\e0|%2e%2e|\.\./)") { return 403; }
    if ($args ~* "(select |union |insert |drop |update |exec |declare |information_schema)") { return 403; }
    if ($args ~* "(<script|javascript:|onerror|onload|eval\(|document\.)") { return 403; }

    # SSL 参数
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;

    include /etc/nginx/conf.d/*.conf;
}

5.2 反代到 Flask/Django/Express

server {
    listen 443 ssl http2;
    server_name app.example.com;

    ssl_certificate     /etc/letsencrypt/live/app.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;

    # WebSocket 反代
    location /ws/ {
        proxy_pass http://127.0.0.1:8080/ws/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_read_timeout 3600s;
    }

    # API 反代
    location /api/ {
        proxy_pass http://127.0.0.1:8000;
        proxy_http_version 1.1;
        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;
        proxy_connect_timeout 10s;
        proxy_send_timeout 30s;
        proxy_read_timeout 30s;
        limit_req zone=api_limit burst=20 nodelay;
    }

    # 登录限速
    location /api/login {
        proxy_pass http://127.0.0.1:8000;
        limit_req zone=login_limit burst=2 nodelay;
    }

    # 静态文件直出
    location /static/ {
        alias /var/www/static/;
        expires 7d;
        add_header Cache-Control "public, immutable";
        try_files $uri =404;
    }

    # 前端 SPA fallback
    location / {
        try_files $uri $uri/ /index.html;
    }
}

server {
    listen 80;
    server_name app.example.com;
    return 301 https://$host$request_uri;
}

5.3 关键 CVE 历史

  • CVE-2013-4547(目录穿越 /files..%2f 绕过);
  • CVE-2019-20372(HTTP request smuggling);
  • CVE-2021-3618(正则 ReDoS 导致 worker 挂死);
  • CVE-2024-7646(HTTP/2 内存泄露)。

6. 三件套对比加固清单

配置项 Nginx Apache Tomcat
隐藏版本 server_tokens off ServerTokens Prod showServerInfo=false
关闭目录列表 autoindex off Options -Indexes listings=false
限制方法 if ($request_method ...) LimitExcept httpMethods allowed
HSTS add_header Strict-Transport-Security Header always set Strict-Transport-Security (需 filter 或反代)
TLS 1.3 ssl_protocols TLSv1.2 TLSv1.3 SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1 sslProtocol="TLS" protocols="TLSv1.2,TLSv1.3"
禁止 .git location ~ /. FilesMatch "^." Resources antiResourceLocking
访问控制 allow/deny Require/Order valve RemoteIpValve
日志隔离 access_log per location CustomLog AccessLogValve

7. 综合加固脚本

#!/bin/bash
# 一键加固 Nginx/Apache/Tomcat

set -e
echo "[*] Hardening Nginx..."
cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak 2>/dev/null || true
sed -i 's/server_tokens on/server_tokens off/g' /etc/nginx/nginx.conf 2>/dev/null || true
sed -i 's/# server_tokens off/server_tokens off/g' /etc/nginx/nginx.conf 2>/dev/null || true

echo "[*] Hardening Apache..."
cp /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf.bak 2>/dev/null || true
sed -i 's/^ServerTokens Full/ServerTokens Prod/' /etc/httpd/conf/httpd.conf 2>/dev/null || true
sed -i 's/^ServerSignature On/ServerSignature Off/' /etc/httpd/conf/httpd.conf 2>/dev/null || true

echo "[*] Hardening Tomcat..."
TOMCAT_HOME=${TOMCAT_HOME:-/opt/tomcat}
if [ -f "$TOMCAT_HOME/conf/server.xml" ]; then
    sed -i 's/connector.executor.threads="200"/connector.executor.threads="50"/' $TOMCAT_HOME/conf/server.xml
fi

echo "[*] Firewall rules..."
iptables -P INPUT ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -p icmp --icmp-type echo-request -j DROP
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
iptables -A INPUT -j DROP

echo "[+] Hardening complete."

8. 小结

Nginx / Apache / Tomcat 作为基础设施,一次错误的配置就能导致全站沦陷。常见场景包括:Nginx alias 路径穿越(CVE-2016-0742 同类)、Apache mod_rewrite 正则 ReDoS、Tomcat manager 弱口令 + AJP 未授权访问。生产环境务必做到:分层防御、最小权限、定期审计