系列导读:本篇作为系列的收官之作,将深入讲解 Nginx + Tomcat 架构的安全加固与生产环境部署,包括 HTTPS 配置、安全防护、日志监控、自动化部署等核心技能。
文章目录
-
- 前言:安全与生产部署的重要性
- [一、HTTPS 安全配置](#一、HTTPS 安全配置)
-
- [1.1 SSL/TLS 证书获取](#1.1 SSL/TLS 证书获取)
- [1.2 Nginx HTTPS 配置](#1.2 Nginx HTTPS 配置)
- [1.3 生成 DH 参数](#1.3 生成 DH 参数)
- [1.4 Tomcat HTTPS 配置](#1.4 Tomcat HTTPS 配置)
- 二、安全防护策略
-
- [2.1 安全响应头配置](#2.1 安全响应头配置)
- [2.2 访问控制](#2.2 访问控制)
- [2.3 速率限制(防 DDoS)](#2.3 速率限制(防 DDoS))
- [2.4 WAF 规则(基础防护)](#2.4 WAF 规则(基础防护))
- [2.5 防盗链配置](#2.5 防盗链配置)
- 三、日志管理与监控
-
- [3.1 Nginx 日志配置](#3.1 Nginx 日志配置)
- [3.2 日志切割](#3.2 日志切割)
- [3.3 Tomcat 日志配置](#3.3 Tomcat 日志配置)
- [3.4 监控配置](#3.4 监控配置)
- 四、自动化部署
-
- [4.1 部署脚本](#4.1 部署脚本)
- [4.2 CI/CD 配置(Jenkins)](#4.2 CI/CD 配置(Jenkins))
- [4.3 Docker 部署](#4.3 Docker 部署)
- 五、高可用架构设计
-
- [5.1 架构图](#5.1 架构图)
- [5.2 Keepalived 配置](#5.2 Keepalived 配置)
- 六、生产环境检查清单
-
- [6.1 安全检查清单](#6.1 安全检查清单)
- [6.2 性能检查清单](#6.2 性能检查清单)
- [6.3 高可用检查清单](#6.3 高可用检查清单)
- [6.4 运维检查清单](#6.4 运维检查清单)
- 总结
- [📚 附录:常用资源](#📚 附录:常用资源)
前言:安全与生产部署的重要性
生产环境面临的安全威胁:
🚫 数据泄露:HTTP 明文传输,敏感信息被窃取
🚫 DDoS 攻击:恶意请求耗尽服务器资源
🚫 SQL 注入:恶意 SQL 语句攻击数据库
🚫 XSS 攻击:跨站脚本攻击窃取用户信息
🚫 配置泄露:敏感配置文件被访问
安全加固效果:
| 安全措施 | 防护能力 | 实施难度 |
|---|---|---|
| HTTPS 加密 | 防止数据窃取 | 低 |
| WAF 防护 | 防止常见攻击 | 中 |
| 限流配置 | 防止 DDoS | 低 |
| 安全响应头 | 防止 XSS/点击劫持 | 低 |
| 访问控制 | 防止未授权访问 | 中 |
一、HTTPS 安全配置
1.1 SSL/TLS 证书获取
方式一:Let's Encrypt 免费证书
bash
# 安装 certbot
sudo yum install -y certbot python3-certbot-nginx # CentOS
# 或
sudo apt install -y certbot python3-certbot-nginx # Ubuntu
# 申请证书
sudo certbot --nginx -d example.com -d www.example.com
# 自动续期测试
sudo certbot renew --dry-run
# 添加定时任务
sudo crontab -e
0 3 * * * certbot renew --quiet --post-hook "systemctl reload nginx"
方式二:购买商业证书
bash
# 生成私钥
openssl genrsa -out example.com.key 2048
# 生成 CSR
openssl req -new -key example.com.key -out example.com.csr
# 提交 CSR 给 CA 机构,获取证书文件
1.2 Nginx HTTPS 配置
nginx
server {
listen 80;
server_name example.com www.example.com;
# 强制跳转 HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name example.com www.example.com;
# ==================== SSL 证书配置 ====================
ssl_certificate /etc/nginx/ssl/example.com.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
# DH 参数(增强安全性)
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
# ==================== SSL 协议配置 ====================
# 仅支持 TLS 1.2 和 1.3
ssl_protocols TLSv1.2 TLSv1.3;
# 加密套件(推荐配置)
ssl_ciphers 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;
# 优先使用服务器端加密套件
ssl_prefer_server_ciphers off;
# ==================== 会话配置 ====================
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# ==================== OCSP Stapling ====================
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# ==================== HSTS ====================
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# ==================== 安全响应头 ====================
add_header X-Frame-Options "SAMEORIGIN" 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;
# ==================== 反向代理配置 ====================
location / {
proxy_pass http://tomcat_backend;
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;
}
}
1.3 生成 DH 参数
bash
# 生成 DH 参数(增强密钥交换安全性)
openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048
1.4 Tomcat HTTPS 配置
xml
<!-- Tomcat conf/server.xml -->
<!-- 方式一:使用 Nginx SSL 终端,Tomcat 仅处理 HTTP -->
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="443"
proxyPort="443"
scheme="https"
secure="true" />
<!-- 方式二:Tomcat 直接处理 HTTPS -->
<Connector port="8443" protocol="HTTP/1.1"
SSLEnabled="true"
maxThreads="150"
scheme="https"
secure="true"
keystoreFile="/opt/tomcat/ssl/keystore.jks"
keystorePass="yourpassword"
clientAuth="false"
sslProtocol="TLS" />
二、安全防护策略
2.1 安全响应头配置
nginx
server {
listen 443 ssl http2;
server_name example.com;
# ==================== 安全响应头 ====================
# HSTS(强制 HTTPS)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# 防止点击劫持
add_header X-Frame-Options "SAMEORIGIN" always;
# 防止 MIME 类型嗅探
add_header X-Content-Type-Options "nosniff" always;
# XSS 防护
add_header X-XSS-Protection "1; mode=block" always;
# 引用策略
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# 内容安全策略(CSP)
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.example.com; style-src 'self' 'unsafe-inline' https://cdn.example.com; img-src 'self' data: https:; font-src 'self' https://cdn.example.com; connect-src 'self' https://api.example.com; frame-ancestors 'self';" always;
# 权限策略
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
}
2.2 访问控制
nginx
server {
# ==================== IP 访问控制 ====================
# 管理后台限制 IP
location /admin {
allow 192.168.1.0/24; # 允许内网
allow 10.0.0.0/8; # 允许 VPN
deny all; # 拒绝其他
proxy_pass http://tomcat_backend;
}
# ==================== 敏感文件保护 ====================
# 禁止访问隐藏文件
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
# 禁止访问敏感文件
location ~* \.(env|git|svn|htaccess|htpasswd|bak|config|sql|log|sh|py|rb)$ {
deny all;
access_log off;
log_not_found off;
}
# ==================== 请求方法限制 ====================
if ($request_method !~ ^(GET|HEAD|POST|PUT|DELETE|OPTIONS)$) {
return 405;
}
# ==================== User-Agent 过滤 ====================
if ($http_user_agent ~* (bot|crawl|spider|scan|nikto|sqlmap|nmap)) {
return 403;
}
}
2.3 速率限制(防 DDoS)
nginx
http {
# ==================== 限流区域定义 ====================
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=api:10m rate=100r/s;
limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;
# 连接限制
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
# 限制状态码
limit_req_status 429;
limit_conn_status 429;
}
server {
# ==================== 全局限流 ====================
limit_req zone=general burst=20 nodelay;
limit_conn conn_limit 50;
# ==================== API 限流 ====================
location /api/ {
limit_req zone=api burst=50 nodelay;
proxy_pass http://tomcat_backend;
}
# ==================== 登录限流 ====================
location /login {
limit_req zone=login burst=5 nodelay;
proxy_pass http://tomcat_backend;
}
}
2.4 WAF 规则(基础防护)
nginx
server {
# ==================== SQL 注入防护 ====================
if ($query_string ~* "union.*select.*\(") {
return 403;
}
if ($query_string ~* "concat.*\(") {
return 403;
}
if ($query_string ~* "base64_") {
return 403;
}
# ==================== XSS 防护 ====================
if ($query_string ~* "<script.*>") {
return 403;
}
if ($query_string ~* "javascript:") {
return 403;
}
if ($query_string ~* "onerror=") {
return 403;
}
# ==================== 路径遍历防护 ====================
if ($query_string ~* "\.\./") {
return 403;
}
if ($query_string ~* "/etc/passwd") {
return 403;
}
# ==================== 命令注入防护 ====================
if ($query_string ~* "(;|\||`|&|\$\(|\$\{)") {
return 403;
}
}
2.5 防盗链配置
nginx
server {
listen 80;
server_name static.example.com;
# ==================== 图片防盗链 ====================
location ~* \.(jpg|jpeg|png|gif|webp|svg|ico)$ {
valid_referers none blocked
server_names
*.example.com
*.google.com
*.baidu.com;
if ($invalid_referer) {
return 403;
}
expires 1y;
add_header Cache-Control "public, immutable";
}
}
三、日志管理与监控
3.1 Nginx 日志配置
nginx
http {
# ==================== 日志格式 ====================
# 标准格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
# JSON 格式(便于 ELK 分析)
log_format json_combined escape=json
'{'
'"time":"$time_iso8601",'
'"remote_addr":"$remote_addr",'
'"request":"$request",'
'"status":"$status",'
'"body_bytes_sent":"$body_bytes_sent",'
'"request_time":"$request_time",'
'"upstream_response_time":"$upstream_response_time",'
'"http_referrer":"$http_referer",'
'"http_user_agent":"$http_user_agent"'
'}';
# 详细格式
log_format detailed
'$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'rt=$request_time uct="$upstream_connect_time" '
'uht="$upstream_header_time" urt="$upstream_response_time"';
# 访问日志
access_log /var/log/nginx/access.log main;
}
server {
# 按应用分离日志
access_log /var/log/nginx/app.access.log detailed;
error_log /var/log/nginx/app.error.log warn;
}
3.2 日志切割
nginx
# /etc/logrotate.d/nginx
/var/log/nginx/*.log {
daily # 每天切割
missingok # 文件不存在不报错
rotate 14 # 保留 14 天
compress # 压缩旧日志
delaycompress # 延迟压缩
notifempty # 空文件不切割
create 0640 nginx adm # 创建新文件权限
sharedscripts # 共享脚本
postrotate
[ -f /var/run/nginx.pid ] && kill -USR1 $(cat /var/run/nginx.pid)
endscript
}
3.3 Tomcat 日志配置
xml
<!-- Tomcat conf/server.xml -->
<!-- 访问日志配置 -->
<Valve className="org.apache.catalina.valves.AccessLogValve"
directory="logs"
prefix="localhost_access_log"
suffix=".txt"
pattern="%h %l %u %t "%r" %s %b %D"
rotatable="true"
fileDateFormat="yyyy-MM-dd" />
properties
# Tomcat conf/logging.properties
# 日志级别配置
.handlers = 1catalina.org.apache.juli.AsyncFileHandler
.level = INFO
1catalina.org.apache.juli.AsyncFileHandler.level = INFO
1catalina.org.apache.juli.AsyncFileHandler.directory = ${catalina.base}/logs
1catalina.org.apache.juli.AsyncFileHandler.prefix = catalina.
1catalina.org.apache.juli.AsyncFileHandler.maxDays = 30
3.4 监控配置
Nginx 状态监控:
nginx
server {
listen 80;
server_name localhost;
# Nginx 状态页面
location /nginx_status {
stub_status on;
access_log off;
allow 127.0.0.1;
allow 192.168.1.0/24;
deny all;
}
# 健康检查端点
location /health {
access_log off;
return 200 "OK\n";
add_header Content-Type text/plain;
}
}
Prometheus 监控集成:
yaml
# prometheus.yml
scrape_configs:
- job_name: 'nginx'
static_configs:
- targets: ['192.168.1.10:9113']
- job_name: 'tomcat'
static_configs:
- targets: ['192.168.1.10:9010']
四、自动化部署
4.1 部署脚本
bash
#!/bin/bash
# deploy.sh - 自动化部署脚本
APP_NAME="myapp"
TOMCAT_HOME="/opt/tomcat/current"
BACKUP_DIR="/opt/backup"
DATE=$(date +%Y%m%d_%H%M%S)
echo "========== 开始部署 =========="
# 1. 备份旧版本
echo "1. 备份旧版本..."
if [ -d "$TOMCAT_HOME/webapps/$APP_NAME" ]; then
mkdir -p $BACKUP_DIR
cp -r $TOMCAT_HOME/webapps/$APP_NAME $BACKUP_DIR/${APP_NAME}_${DATE}
echo "备份完成: $BACKUP_DIR/${APP_NAME}_${DATE}"
fi
# 2. 停止 Tomcat
echo "2. 停止 Tomcat..."
$TOMCAT_HOME/bin/shutdown.sh
sleep 5
# 强制停止
PID=$(ps aux | grep tomcat | grep -v grep | awk '{print $2}')
if [ -n "$PID" ]; then
kill -9 $PID
echo "强制停止 Tomcat: $PID"
fi
# 3. 清理旧文件
echo "3. 清理旧文件..."
rm -rf $TOMCAT_HOME/webapps/$APP_NAME
rm -rf $TOMCAT_HOME/webapps/${APP_NAME}.war
rm -rf $TOMCAT_HOME/work/Catalina/localhost/$APP_NAME
# 4. 部署新版本
echo "4. 部署新版本..."
cp /tmp/${APP_NAME}.war $TOMCAT_HOME/webapps/
# 5. 启动 Tomcat
echo "5. 启动 Tomcat..."
$TOMCAT_HOME/bin/startup.sh
# 6. 健康检查
echo "6. 健康检查..."
sleep 10
for i in {1..30}; do
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/$APP_NAME/health)
if [ "$HTTP_CODE" = "200" ]; then
echo "部署成功!"
exit 0
fi
echo "等待启动... ($i/30)"
sleep 2
done
echo "部署失败!"
exit 1
4.2 CI/CD 配置(Jenkins)
groovy
// Jenkinsfile
pipeline {
agent any
environment {
TOMCAT_SERVER = '192.168.1.10'
APP_NAME = 'myapp'
}
stages {
stage('Checkout') {
steps {
git 'https://github.com/your-repo/myapp.git'
}
}
stage('Build') {
steps {
sh 'mvn clean package -DskipTests'
}
}
stage('Test') {
steps {
sh 'mvn test'
}
}
stage('Deploy') {
steps {
sh '''
scp target/${APP_NAME}.war ${TOMCAT_SERVER}:/tmp/
ssh ${TOMCAT_SERVER} "/opt/scripts/deploy.sh"
'''
}
}
stage('Health Check') {
steps {
sh '''
curl -f http://${TOMCAT_SERVER}:80/${APP_NAME}/health || exit 1
'''
}
}
}
post {
success {
echo '部署成功!'
}
failure {
echo '部署失败!'
}
}
}
4.3 Docker 部署
dockerfile
# Dockerfile - Tomcat
FROM tomcat:9.0-jdk11
# 删除默认应用
RUN rm -rf /usr/local/tomcat/webapps/*
# 复制应用
COPY target/myapp.war /usr/local/tomcat/webapps/ROOT.war
# 复制配置
COPY conf/server.xml /usr/local/tomcat/conf/server.xml
COPY bin/setenv.sh /usr/local/tomcat/bin/setenv.sh
# 暴露端口
EXPOSE 8080
# 启动
CMD ["catalina.sh", "run"]
yaml
# docker-compose.yml
version: '3.8'
services:
nginx:
image: nginx:1.24
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d
- ./nginx/ssl:/etc/nginx/ssl
- ./nginx/logs:/var/log/nginx
depends_on:
- tomcat1
- tomcat2
tomcat1:
build: .
ports:
- "8081:8080"
environment:
- JAVA_OPTS=-Xms512m -Xmx1024m
volumes:
- ./logs/tomcat1:/usr/local/tomcat/logs
tomcat2:
build: .
ports:
- "8082:8080"
environment:
- JAVA_OPTS=-Xms512m -Xmx1024m
volumes:
- ./logs/tomcat2:/usr/local/tomcat/logs
redis:
image: redis:7
ports:
- "6379:6379"
volumes:
- redis_data:/data
volumes:
redis_data:
五、高可用架构设计
5.1 架构图
┌─────────────────────────────────────────────────────────────┐
│ 用户请求 │
└─────────────────────────┬───────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ Keepalived + Nginx │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Nginx Master │ VIP │ Nginx Backup │ │
│ │ 192.168.1.10 │ ◄─────────► │ 192.168.1.11 │ │
│ └─────────────────┘ └─────────────────┘ │
│ VIP: 192.168.1.100 │
└─────────────────────────┬───────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ Tomcat 集群 │
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│ │ Tomcat 1 │ │ Tomcat 2 │ │ Tomcat 3 │ │
│ └───────────┘ └───────────┘ └───────────┘ │
└─────────────────────────┬───────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ Redis 集群 (Session) │
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│ │ Redis 1 │ │ Redis 2 │ │ Redis 3 │ │
│ └───────────┘ └───────────┘ └───────────┘ │
└─────────────────────────────────────────────────────────────┘
5.2 Keepalived 配置
Master 节点:
# /etc/keepalived/keepalived.conf
global_defs {
router_id NGINX_MASTER
}
vrrp_script check_nginx {
script "/etc/keepalived/check_nginx.sh"
interval 2
weight -20
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.1.100
}
track_script {
check_nginx
}
}
Backup 节点:
# /etc/keepalived/keepalived.conf
global_defs {
router_id NGINX_BACKUP
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 51
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.1.100
}
}
Nginx 健康检查脚本:
bash
#!/bin/bash
# /etc/keepalived/check_nginx.sh
if [ $(ps -C nginx --no-header | wc -l) -eq 0 ]; then
systemctl start nginx
sleep 2
fi
if [ $(ps -C nginx --no-header | wc -l) -eq 0 ]; then
systemctl stop keepalived
fi
六、生产环境检查清单
6.1 安全检查清单
□ HTTPS 已配置并强制跳转
□ SSL 证书有效且未过期
□ 安全响应头已配置
□ 敏感文件访问已禁止
□ 管理后台 IP 限制已配置
□ 限流配置已启用
□ WAF 规则已配置
□ 防盗链已配置
□ 日志敏感信息已脱敏
6.2 性能检查清单
□ 静态资源由 Nginx 处理
□ Gzip 压缩已启用
□ 浏览器缓存已配置
□ 代理缓存已配置(适用场景)
□ Tomcat Connector 已优化
□ JVM 内存已合理配置
□ GC 策略已选择
□ 数据库连接池已优化
6.3 高可用检查清单
□ 负载均衡已配置
□ 健康检查已启用
□ 故障转移已测试
□ Session 共享已实施
□ Redis 高可用已配置
□ Keepalived 已配置
□ 备份策略已制定
6.4 运维检查清单
□ 日志切割已配置
□ 监控已部署
□ 告警规则已配置
□ 自动化部署脚本已准备
□ 回滚方案已制定
□ 应急预案已准备
□ 文档已完善
总结
本文作为 Nginx + Tomcat 整合系列的收官之作,我们全面讲解了:
✅ HTTPS 配置 :证书获取、SSL/TLS 配置、安全优化
✅ 安全防护 :响应头、访问控制、限流、WAF、防盗链
✅ 日志监控 :日志格式、切割、监控集成
✅ 自动化部署 :部署脚本、CI/CD、Docker 部署
✅ 高可用架构 :Keepalived、VIP、故障转移
✅ 生产检查清单:安全、性能、高可用、运维
系列回顾:
| 篇章 | 核心内容 |
|---|---|
| 第一篇 | 环境搭建、基础配置、整合入门 |
| 第二篇 | 反向代理、请求头、WebSocket、文件上传 |
| 第三篇 | 负载均衡、集群部署、会话管理 |
| 第四篇 | Session 管理、Redis 共享、JWT |
| 第五篇 | 性能优化、缓存策略、JVM 调优 |
| 第六篇 | 安全加固、生产部署、高可用架构 |
Nginx + Tomcat 整合最佳实践:
1. 动静分离:Nginx 处理静态资源,Tomcat 专注业务
2. 负载均衡:多 Tomcat 实例,流量均匀分发
3. Session 共享:Redis 集中存储,支持水平扩展
4. HTTPS 加密:SSL 终端在 Nginx,保护数据安全
5. 缓存优化:多级缓存,减轻后端压力
6. 监控告警:实时监控,快速响应故障
7. 自动化部署:CI/CD 流程,减少人为错误
8. 高可用架构:冗余设计,消除单点故障
希望这个系列能帮助你全面掌握 Nginx + Tomcat 整合的核心技能!
作者 :刘~浪地球
系列 :Nginx + Tomcat 整合实战(六)【完结】
更新时间:2026-04-01
📚 附录:常用资源
官方文档:
推荐工具:
- SSL 配置生成器:https://ssl-config.mozilla.org/
- Nginx 配置生成器:https://nginxconfig.io/
- JVM 调优工具:JConsole、VisualVM、Arthas
监控方案:
- Prometheus + Grafana
- ELK Stack(Elasticsearch + Logstash + Kibana)
- SkyWalking(APM)