跳到主要内容Nginx 安全加固与 HTTPS 部署实战 | 极客日志Shell / Bash
Nginx 安全加固与 HTTPS 部署实战
本文详细介绍了 Nginx 服务器的安全防护配置与 HTTPS 部署实战。内容包括隐藏版本号、限制危险请求方法、防御 CC 及 DDoS 攻击(连接数限制、动态黑名单)、防止慢速攻击及 HTTP 走私等高级防护策略。同时涵盖了 HTTPS 证书准备、基础与强化配置、性能优化、多域名支持及自动化脚本编写。通过合理的 Nginx 配置与安全头设置,有效提升 Web 服务的安全性与稳定性。
MqEngine0 浏览 一、核心安全配置
1. 隐藏版本号
隐藏 Nginx 版本号是安全加固的第一步,可以防止攻击者针对特定版本漏洞进行攻击。
# 1. 修改 nginx.conf 全局配置
http {
# 隐藏版本号
server_tokens off;
# 自定义错误页面(可选,避免泄露信息)
error_page 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 421 422 423 424 425 426 428 429 431 451 500 501 502 503 504 505 /error.html;
}
server {
listen 80;
server_name example.com;
# 关闭版本号显示
server_tokens off;
# 自定义错误页面
error_page 404 /404.html;
location = /404.html {
root /usr/share/nginx/html;
internal;
}
}
# 2. 修改源码彻底隐藏(需要编译)
# 在编译前修改 src/core/nginx.h 文件
# vi src/core/nginx.h
# 修改以下行:
#define NGINX_VERSION "2.4.6"
#define NGINX_VER "Apache/" NGINX_VERSION
# 或修改为自定义字符串
#define NGINX_VER "Microsoft-IIS/10.0"
# 3. 修改 fastcgi 参数(防止 PHP 泄露)
location ~ \.php$ {
fastcgi_param SERVER_SOFTWARE "Microsoft-IIS/10.0";
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;
}
# 4. 验证配置
# curl -I http://example.com
# 响应头中不应包含 Server: nginx/版本号
# 应为 Server: nginx 或自定义名称
2. 限制危险请求方法
HTTP 协议定义了多种请求方法,其中一些可能存在安全风险,需要限制使用。
# 1. 全局限制危险请求方法
server {
listen 80;
server_name example.com;
# 只允许 GET、HEAD、POST 方法
if ($request_method !~ ^(GET|HEAD|POST)$) {
return 405;
}
# 更精细的控制
location / {
limit_except GET HEAD POST {
deny all;
}
}
}
# 2. 针对 API 接口的限制
location /api/ {
# API 只允许 GET 和 POST
limit_except GET POST {
deny all;
}
# 禁止 TRACE 方法
if ($request_method = TRACE) {
return 405;
}
proxy_pass http://backend;
}
# 3. 禁止特定方法
location / {
# 拒绝 DELETE、PUT 等方法
if ($request_method ~ ^(DELETE|PUT|PATCH|TRACE|CONNECT|OPTIONS)$) {
return 405;
}
}
# 4. 只允许 GET 的静态资源
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
# 静态资源只允许 GET 和 HEAD
limit_except GET HEAD {
deny all;
}
expires 30d;
access_log off;
}
# 5. OPTIONS 方法处理(CORS 预检请求)
location / {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
}
3. 请求限制(CC 攻击防御)
3.1 连接数限制
# 1. 定义限制区域
http {
# 限制每个 IP 的连接数
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
# 限制每个 IP 的请求速率
limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;
# 动态黑名单(结合 geo 模块)
geo $blacklist {
default 0;
192.168.1.100 1; # 手动加入黑名单的 IP
10.0.0.0/24 1;
}
server {
listen 80;
server_name example.com;
# 2. 应用连接数限制
location / {
# 每个 IP 最多同时 10 个连接
limit_conn conn_limit 10;
# 请求速率限制:平均 10r/s,突发 20
limit_req zone=req_limit burst=20 nodelay;
# 返回状态码
limit_conn_status 503;
limit_req_status 503;
# 日志级别
limit_conn_log_level warn;
limit_req_log_level warn;
proxy_pass http://backend;
}
# 3. 针对不同 URL 设置不同限制
location /api/ {
# API 接口限制更严格
limit_req zone=req_limit burst=5 nodelay;
limit_conn conn_limit 5;
proxy_pass http://api_backend;
}
location /login/ {
# 登录接口限制(防止暴力破解)
limit_req zone=req_limit burst=3 nodelay;
limit_conn conn_limit 2;
proxy_pass http://login_backend;
}
location /static/ {
# 静态资源不限制
limit_req off;
limit_conn off;
expires 30d;
}
}
}
3.2 带宽限制
# 1. 限制下载速度
http {
# 定义限制区域
limit_rate_zone $binary_remote_addr zone=rate_limit:10m;
server {
listen 80;
# 2. 全局速度限制
location /download/ {
# 每个连接限速 200KB/s
limit_rate 200k;
# 超过 1MB 后开始限速
limit_rate_after 1m;
root /data/downloads;
autoindex on;
}
# 3. 不同用户不同速度
location /files/ {
if ($http_user_agent ~* "mobile") {
set $limit_rate 100k; # 移动用户限速 100KB/s
}
if ($http_user_agent ~* "bot") {
set $limit_rate 50k; # 爬虫限速 50KB/s
}
limit_rate $limit_rate;
root /data/files;
}
# 4. 大文件下载限速
location /bigfile/ {
alias /data/bigfiles/;
# 限制总带宽
limit_conn conn_limit 5;
limit_rate 500k;
# 大文件分段下载支持
add_header Accept-Ranges bytes;
}
}
}
3.3 CC 攻击防御综合配置
# /etc/nginx/conf.d/cc_defense.conf
http {
# 1. 定义多个限制区域
# 基于 IP 的请求限制
limit_req_zone $binary_remote_addr zone=per_ip:10m rate=10r/s;
# 基于 User-Agent 的限制
limit_req_zone $http_user_agent zone=agent:10m rate=20r/s;
# 基于 URI 的限制
limit_req_zone $request_uri zone=uri:10m rate=30r/s;
# 连接数限制
limit_conn_zone $binary_remote_addr zone=addr:10m;
# 2. 动态黑名单
# 使用 map 定义黑名单条件
map $remote_addr $limit_ip {
default 1;
192.168.1.0/24 0; # 内网不限制
10.0.0.0/8 0;
}
server {
listen 80;
server_name example.com;
# 3. 综合限制
location / {
# IP 请求限制
limit_req zone=per_ip burst=20 delay=5;
# 连接数限制
limit_conn addr 20;
# 异常请求判断
if ($http_user_agent ~* (bot|spider|crawler)) {
set $bot_limit 1;
}
# 高频访问 IP 记录
access_log /var/log/nginx/access.log combined;
proxy_pass http://backend;
}
# 4. 验证码验证(需要第三方模块)
location /captcha {
captcha on;
captcha_secret your_secret_key;
captcha_mode image;
if ($http_cookie !~* "captcha_pass") {
return 302 /captcha?return=$request_uri;
}
}
# 5. JS 挑战(防 CC)
location /challenge {
js_challenge on;
js_challenge_secret your_secret;
if ($http_cookie !~* "js_pass") {
return 302 /challenge?return=$request_uri;
}
}
# 6. 记录攻击 IP
location @blocked {
access_log /var/log/nginx/blocked.log combined;
return 503;
}
# 7. 封禁 IP 列表
include /etc/nginx/blockips.conf;
}
}
3.4 动态黑名单配置
#!/bin/bash
BLOCK_LOG="/var/log/nginx/blocked.log"
BLOCK_CONF="/etc/nginx/blockips.conf"
NGINX_CONF="/etc/nginx/nginx.conf"
THRESHOLD=100
INTERVAL=300
analyze_log() {
local time_ago=$(date -d "$INTERVAL seconds ago" +"%Y-%m-%d %H:%M:%S")
awk -v time="$time_ago" -v threshold="$THRESHOLD" '
$4 >= time {count[$1]++}
END { for (ip in count) { if (count[ip] > threshold) { print ip, count[ip] } } }
' $BLOCK_LOG | sort -k2 -nr
}
generate_block_conf() {
local tmp_conf="${BLOCK_CONF}.tmp"
cat > $tmp_conf << EOF
# 自动生成的 IP 黑名单
# 更新时间:$(date)
EOF
while read ip count; do
echo "deny $ip; # 请求数:$count" >> $tmp_conf
done < <(analyze_log)
if [ -f $BLOCK_CONF ]; then
if ! cmp -s $BLOCK_CONF $tmp_conf; then
mv $tmp_conf $BLOCK_CONF
return 0
else
rm -f $tmp_conf
return 1
fi
else
mv $tmp_conf $BLOCK_CONF
return 0
fi
}
reload_nginx() {
nginx -t && systemctl reload nginx
echo "$(date): 黑名单已更新,Nginx 重载完成" >> /var/log/blacklist.log
}
main() {
if generate_block_conf; then
reload_nginx
else
echo "$(date): 黑名单无变化" >> /var/log/blacklist.log
fi
}
二、高级防护
1. 防止 DDoS 攻击
# /etc/nginx/conf.d/ddos_protection.conf
http {
# 1. SYN Flood 防护(需要内核配合)
# sysctl -w net.ipv4.tcp_syncookies=1
# 2. 连接限制
limit_conn_zone $binary_remote_addr zone=ddos_conn:10m;
limit_req_zone $binary_remote_addr zone=ddos_req:10m rate=50r/s;
# 3. 缓冲区大小限制
client_body_buffer_size 8k;
client_header_buffer_size 1k;
large_client_header_buffers 4 8k;
client_max_body_size 10m;
# 4. 超时设置
client_body_timeout 10s;
client_header_timeout 10s;
keepalive_timeout 10s;
send_timeout 10s;
server {
listen 80;
server_name example.com;
# 5. DDoS 防护配置
location / {
# 连接数限制
limit_conn ddos_conn 10;
# 请求速率限制
limit_req zone=ddos_req burst=100 nodelay;
# 限制特定 User-Agent
if ($http_user_agent ~* (slowhttptest|python|perl|ruby)) {
return 403;
}
# 限制空 User-Agent
if ($http_user_agent = "") {
return 403;
}
# 限制特定 Referer
if ($http_referer ~* (spam|bot|crawler)) {
return 403;
}
proxy_pass http://backend;
}
# 6. 验证码保护
location /captcha/ {
# 需要安装第三方模块
captcha on;
captcha_secret your_secret;
captcha_mode image;
captcha_expire 300;
}
}
}
2. 防止慢速攻击
# /etc/nginx/conf.d/slow_attack.conf
http {
# 1. 限制请求头大小
client_header_buffer_size 1k;
large_client_header_buffers 4 8k;
# 2. 限制请求体大小
client_body_buffer_size 8k;
client_max_body_size 10m;
# 3. 超时设置(防止慢速连接)
client_body_timeout 10s; # 读取请求体超时
client_header_timeout 10s; # 读取请求头超时
keepalive_timeout 10s; # keepalive 超时
send_timeout 10s; # 发送响应超时
# 4. 限制每个连接的数据量
limit_rate 100k; # 每个连接限速 100KB/s
server {
listen 80;
# 5. 针对慢速攻击的防护
location / {
# 如果请求头太大,直接拒绝
if ($http_content_length > 10485760) {
return 413;
}
# 限制请求时间
fastcgi_read_timeout 30s;
proxy_read_timeout 30s;
proxy_pass http://backend;
}
# 6. 监控慢速连接
location /nginx_status {
stub_status on;
access_log off;
allow 127.0.0.1;
deny all;
}
}
}
3. 防止 HTTP 走私攻击
# /etc/nginx/conf.d/smuggling_protection.conf
http {
# 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;
# 2. 规范化请求
# 删除重复的 Transfer-Encoding 头
set $transfer_encoding $http_transfer_encoding;
if ($http_transfer_encoding ~* "chunked") {
set $transfer_encoding "";
}
# 3. 限制 HTTP 版本
if ($server_protocol !~* "HTTP/1\.(0|1)" ) {
return 405;
}
server {
listen 80;
# 4. 检查 Content-Length
location / {
# 如果同时存在 Transfer-Encoding 和 Content-Length
if ($http_transfer_encoding ~* "chunked") {
if ($http_content_length) {
return 400;
}
}
# 检查 Content-Length 格式
if ($http_content_length !~ "^[0-9]+$") {
return 400;
}
proxy_pass http://backend;
}
}
}
4. 防止 DNS Rebinding 攻击
# /etc/nginx/conf.d/dns_rebinding.conf
http {
# 1. 验证 Host 头
server {
listen 80;
server_name example.com www.example.com;
# 2. 拒绝无效 Host
if ($host !~* ^(example\.com|www\.example\.com)$) {
return 444;
}
# 3. 检查 Host 头长度
if ($http_host) {
if ($http_host ~ "^.{255,}") {
return 400;
}
}
}
# 4. 防止 IP 直接访问
server {
listen 80 default_server;
server_name _;
# 如果是 IP 访问,返回 444
if ($host ~* "^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$") {
return 444;
}
return 444;
}
}
三、Nginx HTTPS 配置
1. HTTPS 概念
HTTPS(Hypertext Transfer Protocol Secure) 是 HTTP 的安全版本,通过 SSL/TLS 协议提供加密通信。
text
HTTP (80) → 明文传输
HTTPS (443) → 加密传输
2. HTTP 为什么不安全
text
1. 明文传输
├── 数据可被窃听(抓包)
├── 数据可被篡改(中间人攻击)
└── 身份可被伪造(钓鱼网站)
2. 无身份验证
├── 无法确认服务器身份
└── 无法确认客户端身份
3. 无完整性校验
├── 无法检测数据是否被修改
└── 无法防止重放攻击
3. 安全通信的四大原则
text
1. 机密性(Confidentiality)
├── 数据加密,防止窃听
└── 使用对称加密算法(AES、ChaCha20)
2. 完整性(Integrity)
├── 数据不可篡改
└── 使用消息认证码(MAC)
3. 身份验证(Authentication)
├── 验证通信双方身份
└── 使用数字证书(CA 签发)
4. 不可否认性(Non-repudiation)
├── 无法否认已发送的数据
└── 使用数字签名
4. HTTPS 通信原理简述
text
HTTPS 握手过程:
1. TCP 三次握手
Client → Server: SYN
Server → Client: SYN+ACK
Client → Server: ACK
2. TLS 握手(以 TLS 1.3 为例)
Client → Server: ClientHello (支持的加密套件、随机数)
Server → Client: ServerHello (选择的加密套件、随机数)
Server → Client: Certificate (服务器证书)
Server → Client: ServerFinished (握手完成)
3. 密钥交换
Client → Server: ClientFinished (加密的握手消息)
Server → Client: 应用数据 (加密传输)
4. 加密通信
Client ↔ Server: 加密的应用数据
5. HTTPS 证书准备
openssl genrsa -out example.com.key 2048
openssl req -new -key example.com.key -out example.com.csr
openssl x509 -req -days 365 -in example.com.csr -signkey example.com.key -out example.com.crt
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout example.com.key \
-out example.com.crt \
-subj "/C=CN/ST=Beijing/L=Beijing/O=Example/CN=example.com" \
-addext "subjectAltName=DNS:example.com,DNS:www.example.com"
certbot --nginx -d example.com -d www.example.com
certbot renew --dry-run
openssl x509 -in example.com.crt -text -noout
openssl x509 -in example.com.crt -noout -enddate
6. 基础 HTTPS 配置
# /etc/nginx/conf.d/example.com-ssl.conf
server {
listen 443 ssl http2;
server_name example.com www.example.com;
# 证书路径
ssl_certificate /etc/nginx/ssl/example.com.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
# 网站根目录
root /var/www/example.com;
index index.html index.php;
# 访问日志
access_log /var/log/nginx/example.com-ssl_access.log main;
error_log /var/log/nginx/example.com-ssl_error.log warn;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# 静态资源缓存
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 30d;
add_header Cache-Control "public, immutable";
access_log off;
}
}
# HTTP 重定向到 HTTPS
server {
listen 80;
server_name example.com www.example.com;
# 永久重定向
return 301 https://$server_name$request_uri;
# 或者保留请求方法的重定向
# return 308 https://$server_name$request_uri;
}
7. 强化 HTTPS 配置
# /etc/nginx/conf.d/ssl_hardening.conf
server {
listen 443 ssl http2;
server_name example.com;
# 证书配置
ssl_certificate /etc/nginx/ssl/example.com.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
ssl_trusted_certificate /etc/nginx/ssl/chain.crt;
# 1. 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 on;
# 2. DH 参数(提高安全性)
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
# 生成 DH 参数
# openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048
# 3. 会话缓存
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# 4. OCSP Stapling(提高性能和安全)
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/nginx/ssl/chain.crt;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# 5. HSTS(强制 HTTPS)
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
# 6. 安全响应头
# 防止 XSS 攻击
add_header X-XSS-Protection "1; mode=block" always;
# 防止 MIME 类型嗅探
add_header X-Content-Type-Options "nosniff" always;
# 点击劫持防护
add_header X-Frame-Options "SAMEORIGIN" always;
# 内容安全策略
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https:; style-src 'self' 'unsafe-inline' https:; img-src 'self' data: https:; font-src 'self' https:; connect-src 'self' https:;" always;
# 限制引用策略
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# 7. 特征移除
# 隐藏 Nginx 版本
server_tokens off;
# 移除 X-Powered-By
proxy_hide_header X-Powered-By;
fastcgi_hide_header X-Powered-By;
# 8. 证书透明度
# 如果需要,可以添加 SCT(Signed Certificate Timestamps)
# ssl_ct on;
location / {
proxy_pass http://backend;
include /etc/nginx/proxy_params;
}
}
8. HTTPS 性能优化
# /etc/nginx/conf.d/ssl_performance.conf
http {
# 1. SSL 会话复用
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 4h;
# 2. SSL 缓冲区大小
ssl_buffer_size 4k;
server {
listen 443 ssl http2;
server_name example.com;
# HTTP/2 优化
http2_max_concurrent_streams 128;
http2_idle_timeout 300s;
# 3. OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
# 4. 减少 TLS 握手
ssl_session_tickets on;
# 5. 启用压缩(注意:压缩可能带来安全风险,谨慎使用)
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml application/json application/javascript application/xml+rss application/atom+xml image/svg+xml;
# 6. 静态资源优化
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 365d;
add_header Cache-Control "public, immutable";
access_log off;
# 开启 sendfile
sendfile on;
tcp_nopush on;
}
# 7. 代理优化
location / {
proxy_pass http://backend;
# 启用缓存
proxy_cache my_cache;
proxy_cache_valid 200 302 60m;
proxy_cache_valid 404 1m;
# 减少数据拷贝
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 8k;
# 保持连接
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
}
9. 多域名 HTTPS 配置
# /etc/nginx/conf.d/multi-domain.conf
# 1. 多证书配置(传统方式)
server {
listen 443 ssl http2;
server_name domain1.com www.domain1.com;
ssl_certificate /etc/nginx/ssl/domain1.com.crt;
ssl_certificate_key /etc/nginx/ssl/domain1.com.key;
root /var/www/domain1;
# ... 其他配置
}
server {
listen 443 ssl http2;
server_name domain2.com www.domain2.com;
ssl_certificate /etc/nginx/ssl/domain2.com.crt;
ssl_certificate_key /etc/nginx/ssl/domain2.com.key;
root /var/www/domain2;
# ... 其他配置
}
# 2. SNI(Server Name Indication)配置
# Nginx 自动支持 SNI,可以一个 IP 多个证书
# 3. 通配符证书
server {
listen 443 ssl http2;
server_name *.example.com;
ssl_certificate /etc/nginx/ssl/wildcard.example.com.crt;
ssl_certificate_key /etc/nginx/ssl/wildcard.example.com.key;
# 根据域名分发到不同后端
location / {
if ($host ~* ^api\.example\.com$) {
proxy_pass http://api_backend;
break;
}
if ($host ~* ^admin\.example\.com$) {
proxy_pass http://admin_backend;
break;
}
proxy_pass http://default_backend;
}
}
10. HTTPS 监控和调试
#!/bin/bash
DOMAINS="example.com www.example.com api.example.com"
EMAIL="[email protected]"
WARN_DAYS=30
SSL_DIR="/etc/nginx/ssl"
check_expiry() {
local domain=$1
local cert_file="${SSL_DIR}/${domain}.crt"
if [ ! -f "$cert_file" ]; then
echo "证书文件不存在:$cert_file"
return 1
fi
expiry_date=$(openssl x509 -in "$cert_file" -noout -enddate | cut -d= -f2)
expiry_timestamp=$(date -d "$expiry_date" +%s)
current_timestamp=$(date +%s)
days_left=$(( ($expiry_timestamp - $current_timestamp) / 86400 ))
echo "域名:$domain"
echo "过期时间:$expiry_date"
echo "剩余天数:$days_left"
if [ $days_left -lt $WARN_DAYS ]; then
echo "警告:证书即将过期!"
return 1
elif [ $days_left -lt 0 ]; then
echo "错误:证书已过期!"
return 2
fi
return 0
}
check_chain() {
local domain=$1
local cert_file="${SSL_DIR}/${domain}.crt"
echo "验证证书链..."
openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt "$cert_file"
}
check_ocsp() {
local domain=$1
echo "检查 OCSP Stapling..."
echo QUIT | openssl s_client -connect ${domain}:443 -status 2>/dev/null | grep -A 20 "OCSP response"
}
test_ssllabs() {
local domain=$1
echo "SSL Labs 评分:https://www.ssllabs.com/ssltest/analyze.html?d=$domain"
}
send_alert() {
local subject="SSL 证书监控告警"
local message="$1"
echo "$message" | mail -s "$subject" "$EMAIL"
}
main() {
for domain in $DOMAINS; do
echo "================================="
echo "检查域名:$domain"
echo "================================="
check_expiry $domain
if [ $? -ne 0 ]; then
send_alert "域名 $domain 证书即将过期,请及时更新"
fi
check_chain $domain
check_ocsp $domain
echo ""
done
}
11. 自动化证书更新
#!/bin/bash
DOMAINS="example.com www.example.com"
EMAIL="[email protected]"
WEBROOT="/var/www/html"
LE_PATH="/usr/bin/certbot"
NGINX_SERVICE="nginx"
renew_cert() {
$LE_PATH certonly --webroot -w $WEBROOT \
--email $EMAIL \
--agree-tos \
--no-eff-email \
--force-renewal \
-d ${DOMAINS// / -d }
if [ $? -eq 0 ]; then
echo "$(date): 证书更新成功" >> /var/log/ssl-renew.log
systemctl reload $NGINX_SERVICE
echo "SSL 证书已更新" | mail -s "SSL Renewal Success" $EMAIL
else
echo "$(date): 证书更新失败" >> /var/log/ssl-renew.log
echo "SSL 证书更新失败,请手动检查" | mail -s "SSL Renewal Failed" $EMAIL
fi
}
check_needs_renewal() {
for domain in $DOMAINS; do
cert_file="/etc/letsencrypt/live/$domain/fullchain.pem"
if [ -f "$cert_file" ]; then
if ! openssl x509 -in "$cert_file" -checkend 2592000 > /dev/null; then
return 0
fi
else
return 0
fi
done
return 1
}
main() {
if check_needs_renewal; then
renew_cert
else
echo "$(date): 证书仍在有效期内,无需更新" >> /var/log/ssl-renew.log
fi
}
12. HTTPS 常见问题排查
openssl x509 -in /etc/nginx/ssl/example.com.crt -text -noout
openssl rsa -in /etc/nginx/ssl/example.com.key -check
openssl x509 -noout -modulus -in example.com.crt | openssl md5
openssl rsa -noout -modulus -in example.com.key | openssl md5
openssl s_client -connect example.com:443 -servername example.com
openssl s_client -connect example.com:443 -tls1_2
openssl s_client -connect example.com:443 -tls1_3
openssl s_client -connect example.com:443 -showcerts
openssl s_client -connect example.com:443 -status
curl -vI https://example.com
curl --http2 -I https://example.com
nginx -t
tail -f /var/log/nginx/error.log
tail -f /var/log/nginx/access.log | grep SSL
四、综合安全配置示例
# /etc/nginx/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 {
use epoll;
worker_connections 10240;
multi_accept on;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# 隐藏版本号
server_tokens off;
# 日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
log_format security '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$request_time $upstream_response_time';
access_log /var/log/nginx/access.log main buffer=32k flush=5s;
# 基础优化
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 1k;
large_client_header_buffers 4 8k;
# 超时设置
client_body_timeout 10s;
client_header_timeout 10s;
send_timeout 10s;
# 限制区域
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;
# 代理设置
proxy_connect_timeout 30s;
proxy_send_timeout 30s;
proxy_read_timeout 30s;
proxy_buffer_size 4k;
proxy_buffers 8 8k;
proxy_busy_buffers_size 16k;
# Gzip 压缩
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_min_length 1000;
gzip_types text/plain text/css text/xml application/json application/javascript application/xml+rss application/atom+xml image/svg+xml;
# SSL 配置
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 1d;
ssl_session_tickets off;
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';
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
ssl_stapling on;
ssl_stapling_verify on;
# 安全头
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
# 包含站点配置
include /etc/nginx/conf.d/*.conf;
}
微信扫一扫,关注极客日志
微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
相关免费在线工具
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
- Base64 文件转换器
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
- Markdown 转 HTML
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML 转 Markdown 互为补充。 在线工具,Markdown 转 HTML在线工具,online
- HTML 转 Markdown
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML 转 Markdown在线工具,online
- JSON 压缩
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online
- JSON美化和格式化
将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online