目录
第一步:配置监听端口443:
listen 443 ssl http2;
第二步:生成新证书
第三步:将生成的新证书配置到nginx里:
ssl_certificate /www/server/panel/vhost/cert/abc.com/a.pem;
ssl_certificate_key /www/server/panel/vhost/cert/abc.com/b.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
第一版:
# ==================== http 块内 ====================
# 【可选】前面有 CDN / 负载均衡时才启用,网段换成实际值,绝不写 0.0.0.0/0
# set_real_ip_from 203.0.113.0/24;
# real_ip_header X-Forwarded-For;
# real_ip_recursive on;
# 限流 zone 已全部移除:对漏洞扫描无效,正常用户反而被误伤
# 扫描防护交给下面的 403/404 规则 + 后端鉴权(验证码30次/分、登录10次/分、错5次锁10分钟)
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
# ==================== server 块 ====================
# ===== 80:只做 301 跳转 + 证书验证 =====
# ===== `listen 80` 和`listen 443 ssl` 写在 同一个 server 块 里,nginx 收到 http 请求就原地处理,不会跳 https。80 直接出内容",属于明文传输,安全头(HSTS)也失效。正确做法是 把 80 拆成独立 =====server,只做跳转 。
server {
listen 80;
server_name rzlssgtl.com www.abc.com;
server_tokens off;
# 证书续期验证必须放行,否则证书无法自动续
location /.well-known/acme-challenge/ {
root /www/wwwroot/java_node_ssl;
}
# 其余全部跳 https
location / {
return 301 https://$host$request_uri;
}
access_log /www/wwwlogs/abc.com_new.log;
error_log /www/wwwlogs/abc.com_new.error.log;
}
server
{
charset utf-8;
listen 443 ssl http2;
ssl_certificate /www/server/panel/vhost/cert/abc.com/a.pem;
ssl_certificate_key /www/server/panel/vhost/cert/abc.com/b.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
server_name abc.com www.abc.com;
server_tokens off;
# 全站 55m:文章保存的 JSON(含 base64 图片正文)可能很大,与 Spring 层 multipart 硬顶对齐
client_max_body_size 55m;
# 只接受本域名访问,不能用 IP 直连访问。不能用未知域名绑定(444 = 直接断开不回包)
# 如果平时用 IP 直连访问,把这行注释掉
if ($host !~* ^(abc\.com|www\.abc\.com)$ ) { return 444; }
# 禁用 TRACE,防 XST
if ($request_method = TRACE) { return 405; }
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header X-Frame-Options "SAMEORIGIN" always;
#收紧版CSP 比较严格,如果若依后台图标、静态资源加载失败,可以用下面的适度版 放宽版 CSP
add_header Content-Security-Policy "default-src 'self' 'unsafe-inline' data: blob: https: http:; img-src 'self' data: blob: https: http:; style-src 'self' 'unsafe-inline' https: http:; script-src 'self' 'unsafe-inline' 'unsafe-eval' https: http:; frame-src 'self' https: http:; media-src 'self' https: http: blob:;" always;
#适度版 放宽版:- 允许 `https:` 所有域名的图片、字体、样式、脚本
- 允许 iframe 嵌入外部链接(文件预览、pdf 预览常用)
add_header Content-Security-Policy "default-src 'self'; img-src 'self' data: blob: https:; font-src 'self' https:; style-src 'self' 'unsafe-inline' https:; script-src 'self' 'unsafe-inline' 'unsafe-eval' https:; frame-src 'self' https:; media-src 'self' blob: https:;" always;
#调试版:(快速调试,上线稳定后建议换回上面适度版)适合你现在排查页面空白、图标丢失、预览功能异常,**不建议长期生产使用**
add_header Content-Security-Policy "default-src 'self' https:; img-src 'self' data: blob: https:; font-src 'self' https:; style-src 'self' 'unsafe-inline' https:; script-src 'self' 'unsafe-inline' 'unsafe-eval' https:; frame-src *; media-src 'self' blob: https:;" always;
index index.html index.htm default.htm default.html;
root /www/wwwroot/www.abc.com_new;
include /www/server/panel/vhost/nginx/extension/abc.com_new/*.conf;
#CERT-APPLY-CHECK--START
include /www/server/panel/vhost/nginx/well-known/abc.com_new.conf;
#CERT-APPLY-CHECK--END
#REWRITE-START
include /www/server/panel/vhost/rewrite/java_abc_com_new_jar.conf;
#REWRITE-END
# ===== 安全扫描封禁 =====
location ~* \.(zip|7z|tar|gz|sql|bak|env|php|jsp|asp|aspx|exe|dll|sh|py|class|jar)$ { return 404; }
location ~* ^/(actuator|admin-actuator).* { return 403; }
location ~* ^/swagger.* { return 403; }
location ~* ^/v3/api-docs.* { return 403; }
location ~* ^/druid.* { return 403; }
location ~* ^/(status|server-status|server-info|phpinfo)\b { return 404; }
location ~* ^/error$ { return 404; }
# 上面的规则锚定在路径开头,挡不住 /api/ 前缀的同类请求,这里补一层
location ~* ^/api/(druid|swagger|v3/api-docs|actuator) { return 403; }
# ===== 敏感文件 =====
location ~* (\.user.ini|\.htaccess|\.htpasswd|\.env.*|\.project|\.bashrc|\.bash_profile|\.bash_logout|\.DS_Store|\.gitignore|\.gitattributes|LICENSE|README\.md|CLAUDE\.md|CHANGELOG\.md|CHANGELOG|CONTRIBUTING\.md|TODO\.md|FAQ\.md|composer\.json|composer\.lock|package(-lock)?\.json|yarn\.lock|pnpm-lock\.yaml|\.\w+~|\.swp|\.swo|\.bak(up)?|\.old|\.tmp|\.temp|\.log|\.sql(\.gz)?|docker-compose\.yml|docker\.env|Dockerfile|\.csproj|\.sln|Cargo\.toml|Cargo\.lock|go\.mod|go\.sum|phpunit\.xml|pom\.xml|build\.gradl|pyproject\.toml|requirements\.txt|application(-\w+)?\.(ya?ml|properties))$
{
return 404;
}
# ===== 敏感目录 =====
location ~* /(\.git|\.svn|\.bzr|\.vscode|\.claude|\.idea|\.ssh|\.github|\.npm|\.yarn|\.pnpm|\.cache|\.husky|\.turbo|\.next|\.nuxt|node_modules|runtime)/ {
return 404;
}
# ===== SSL 证书验证 =====
location /.well-known/ {
root /www/wwwroot/java_node_ssl;
}
if ( $uri ~ "^/\.well-known/.*\.(php|jsp|py|js|css|lua|ts|go|zip|tar\.gz|rar|7z|sql|bak)$" ) {
return 403;
}
# ===== STATIC =====
# 入口页禁缓存:每次部署后浏览器必须拉取新 index.html,避免引用已删除的旧 chunk
location = /index.html {
root /www/wwwroot/www.abc.com_new/web;
expires -1;
}
location / {
root /www/wwwroot/www.abc.com_new/web;
index index.html;
try_files $uri $uri/ /index.html;
# 注意:本层出现 add_header 后不再继承父级安全头,必须重写
location ~* \.(js|css|woff2?|ttf|eot|otf|png|jpg|jpeg|gif|webp|ico|svg|avif)$ {
expires 1y;
add_header Cache-Control "public, immutable" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header X-Frame-Options "SAMEORIGIN" always;
access_log off;
}
}
# ===== 上传目录(静态直出) =====
# ^~ 会让上面的正则黑名单失效(原本 /profile/x.jar 可以被直接下载),这里单独兜一层
location ^~ /profile/ {
alias /www/wwwroot/www.abc.com_new/uploadPath/;
expires 7d;
autoindex off;
location ~* \.(jar|class|sh|py|sql|bak|env|zip|tar|gz|7z|jsp|php|html|htm)$ {
return 404;
}
}
location = /admin/index.html {
root /www/wwwroot/www.abc.com_new;
expires -1;
}
location /admin/ {
root /www/wwwroot/www.abc.com_new;
# 整站最大的暴露面,建议至少做一项:IP 白名单 或 basic auth
# allow 1.2.3.4; # 办公出口公网 IP
# deny all;
# auth_basic "Restricted";
# auth_basic_user_file /www/server/panel/vhost/nginx/.htpasswd;
index index.html;
try_files $uri $uri/ /admin/index.html;
}
# ===== UPLOAD 代理(富文本传图 + 文章附件上传,共用 50m) =====
# 覆盖两个上传口:
# /api/common/upload → 富文本图片
# /api/cms/article/attachment/upload → 文章附件
location ~* ^/api/(common/upload(s)?|cms/article/attachment/upload)$ {
# 剥掉 /api 前缀,原样转发后端真实路径
rewrite ^/api/(.*)$ /$1 break;
proxy_pass http://127.0.0.1:8081;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_hide_header X-Powered-By;
proxy_hide_header Server;
proxy_request_buffering off;
proxy_buffering off;
proxy_connect_timeout 30s;
proxy_send_timeout 300s;
proxy_read_timeout 60s;
# 与字典 cms_attachment_max / Spring 50MB 对齐
client_max_body_size 50m;
}
# ===== API 代理 =====
location /api/ {
proxy_pass http://127.0.0.1:8081/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Host $host:$server_port;
proxy_set_header X-Scheme $scheme;
proxy_hide_header X-Powered-By;
proxy_hide_header Server;
proxy_connect_timeout 30s;
proxy_send_timeout 30s;
proxy_read_timeout 60s;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
# 413 统一返回 JSON,前端弹明确提示
error_page 413 = @413;
location @413 {
default_type application/json;
return 413 '{"code":413,"msg":"请求内容超过大小限制"}';
}
access_log /www/wwwlogs/abc.com_new.log;
error_log /www/wwwlogs/abc.com_new.error.log;
}
第二版加强版:
# ==============================================
# 变更总说明:本次一共9项修改,所有修改点都标记【变更【N】】,并且注释写明【修改前】【修改后】,方便对比回滚
# 变更【1】:拆分独立80端口server,不再和443合并,解决http直接返回明文、HSTS失效
# 变更【2】:Host校验规则,从固定匹配www.abc.com → 正则同时放行 abc.com、www.abc.com,拦截IP/其他域名返回444
# 变更【3】:顶层新增HSTS安全头、收紧CSP策略,保留unsafe-inline适配若依Vue
# 变更【4】:location = /index.html 补充全套安全头+HSTS(子location不继承外层add_header)
# 变更【5】:静态资源子location补充全套安全头+HSTS
# 变更【6】:/profile 上传目录补充全套安全头+HSTS
# 变更【7】:location = /admin/index.html 补充全套安全头+HSTS
# 变更【8】:location /admin/ 后台路由补充全套安全头+HSTS
# 变更【9】:@413 自定义超限返回块补充HSTS与安全头
# ==============================================
# ==================== http 块内 ====================
# 【可选】前面有 CDN / 负载均衡时才启用,网段换成实际值,绝不写 0.0.0.0/0
# set_real_ip_from 203.0.113.0/24;
# real_ip_header X-Forwarded-For;
# real_ip_recursive on;
# 限流 zone 已全部移除:对漏洞扫描无效,正常用户反而被误伤
# 扫描防护交给下面的 403/404 规则 + 后端鉴权(验证码30次/分、登录10次/分、错5次锁10分钟)
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
# ==================== server 块 ====================
# ===== 80:只做 301 跳转 + 证书验证 =====
# 【变更【1】】
# 修改前:listen 80 与 listen 443 ssl 写在同一个server{},http请求直接返回页面明文,HSTS失效
# 修改后:独立新建80的server块,只负责acme验证 + 301跳转https
server {
listen 80;
server_name abc.com www.abc.com;
server_tokens off;
# 证书续期验证必须放行,否则证书无法自动续
location /.well-known/acme-challenge/ {
root /www/wwwroot/java_node_ssl;
}
# 其余全部跳 https
location / {
return 301 https://$host$request_uri;
}
access_log /www/wwwlogs/abc.com_new.log;
error_log /www/wwwlogs/abc.com_new.error.log;
}
server {
charset utf-8;
listen 443 ssl http2;
ssl_certificate /www/server/panel/vhost/cert/abc.com/a.pem;
ssl_certificate_key /www/server/panel/vhost/cert/abc.com/b.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
server_name abc.com www.abc.com;
server_tokens off;
# 全站 55m:文章保存的 JSON(含 base64 图片正文)可能很大,与 Spring 层 multipart 硬顶对齐
client_max_body_size 55m;
# 【变更【2】】
# 修改前:if ($host != "www.abc.dadata.cc") { return 444; } 仅放行www子域名,裸域名abc.com会被拦截
# 修改后:正则白名单同时放行 abc.com / www.abc.com,IP、其他未知域名直接断开444
if ($host !~* ^(abc\.com|www\.abc\.com)$ ) { return 444; }
# 禁用 TRACE,防 XST
if ($request_method = TRACE) { return 405; }
# 【变更【3】】
# 修改前:无 Strict-Transport-Security,CSP策略宽泛
# 修改后:新增HSTS头(max-age=180天,未开includeSubDomains避免子域名翻车),收紧CSP,保留unsafe-inline适配若依
add_header Strict-Transport-Security "max-age=15552000" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Content-Security-Policy "default-src 'self'; img-src 'self' data: blob: https:; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; frame-src 'self'; media-src 'self' blob:;" always;
index index.html index.htm default.htm default.html;
root /www/wwwroot/www.abc.com_new;
include /www/server/panel/vhost/nginx/extension/abc.com_new/*.conf;
#CERT-APPLY-CHECK--START
include /www/server/panel/vhost/nginx/well-known/abc.com_new.conf;
#CERT-APPLY-CHECK--END
#REWRITE-START
include /www/server/panel/vhost/rewrite/java_abc_com_new_jar.conf;
#REWRITE-END
# ===== 安全扫描封禁 =====
location ~* \.(zip|7z|tar|gz|sql|bak|env|php|jsp|asp|aspx|exe|dll|sh|py|class|jar)$ { return 404; }
location ~* ^/(actuator|admin-actuator).* { return 403; }
location ~* ^/swagger.* { return 403; }
location ~* ^/v3/api-docs.* { return 403; }
location ~* ^/druid.* { return 403; }
location ~* ^/(status|server-status|server-info|phpinfo)\b { return 404; }
location ~* ^/error$ { return 404; }
# 上面的规则锚定在路径开头,挡不住 /api/ 前缀的同类请求,这里补一层
location ~* ^/api/(druid|swagger|v3/api-docs|actuator) { return 403; }
# ===== 敏感文件 =====
location ~* (\.user.ini|\.htaccess|\.htpasswd|\.env.*|\.project|\.bashrc|\.bash_profile|\.bash_logout|\.DS_Store|\.gitignore|\.gitattributes|LICENSE|README\.md|CLAUDE\.md|CHANGELOG\.md|CHANGELOG|CONTRIBUTING\.md|TODO\.md|FAQ\.md|composer\.json|composer\.lock|package(-lock)?\.json|yarn\.lock|pnpm-lock\.yaml|\.\w+~|\.swp|\.swo|\.bak(up)?|\.old|\.tmp|\.temp|\.log|\.sql(\.gz)?|docker-compose\.yml|docker\.env|Dockerfile|\.csproj|\.sln|Cargo\.toml|Cargo\.lock|go\.mod|go\.sum|phpunit\.xml|pom\.xml|build\.gradl|pyproject\.toml|requirements\.txt|application(-\w+)?\.(ya?ml|properties))$
{
return 404;
}
# ===== 敏感目录 =====
location ~* /(\.git|\.svn|\.bzr|\.vscode|\.claude|\.idea|\.ssh|\.github|\.npm|\.yarn|\.pnpm|\.cache|\.husky|\.turbo|\.next|\.nuxt|node_modules|runtime)/ {
return 404;
}
# ===== SSL 证书验证 =====
location /.well-known/ {
root /www/wwwroot/java_node_ssl;
}
if ( $uri ~ "^/\.well-known/.*\.(php|jsp|py|js|css|lua|ts|go|zip|tar\.gz|rar|7z|sql|bak)$" ) {
return 403;
}
# ===== STATIC =====
# 入口页禁缓存:每次部署后浏览器必须拉取新 index.html,避免引用已删除的旧 chunk
# 【变更【4】】
# 修改前:只有expires -1,没有安全头(子location不会继承外层add_header)
# 修改后:追加全套安全头+HSTS
location = /index.html {
root /www/wwwroot/www.abc.com_new/web;
expires -1;
add_header Strict-Transport-Security "max-age=15552000" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header X-Frame-Options "SAMEORIGIN" always;
}
location / {
root /www/wwwroot/www.abc.com_new/web;
index index.html;
try_files $uri $uri/ /index.html;
# 子location会脱离外层add_header继承,静态资源单独补安全头
# 【变更【5】】
# 修改前:只有缓存过期配置,缺少HSTS与安全响应头
# 修改后:静态资源子location追加全套安全头+HSTS
location ~* \.(js|css|woff2?|ttf|eot|otf|png|jpg|jpeg|gif|webp|ico|svg|avif)$ {
expires 1y;
add_header Cache-Control "public, immutable" always;
add_header Strict-Transport-Security "max-age=15552000" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header X-Frame-Options "SAMEORIGIN" always;
access_log off;
}
}
# ===== 上传目录(静态直出) =====
# ^~ 会让上面的正则黑名单失效(原本 /profile/x.jar 可以被直接下载),这里单独兜一层
# 【变更【6】】
# 修改前:只有alias、expires、autoindex,缺少HSTS与安全响应头
# 修改后:/profile上传目录追加全套安全头+HSTS
location ^~ /profile/ {
alias /www/wwwroot/www.abc.com_new/uploadPath/;
expires 7d;
autoindex off;
add_header Strict-Transport-Security "max-age=15552000" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header X-Frame-Options "SAMEORIGIN" always;
location ~* \.(jar|class|sh|py|sql|bak|env|zip|tar|gz|7z|jsp|php|html|htm)$ {
return 404;
}
}
# 【变更【7】】
# 修改前:只有expires -1,没有安全头
# 修改后:admin入口html追加全套安全头+HSTS
location = /admin/index.html {
root /www/wwwroot/www.abc.com_new;
expires -1;
add_header Strict-Transport-Security "max-age=15552000" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header X-Frame-Options "SAMEORIGIN" always;
}
# 【变更【8】】
# 修改前:只有前端路由try_files逻辑,缺少HSTS与安全响应头
# 修改后:/admin/后台路由块追加全套安全头+HSTS
location /admin/ {
root /www/wwwroot/www.abc.com_new;
# 整站最大的暴露面,建议至少做一项:IP 白名单 或 basic auth
# allow 1.2.3.4; # 办公出口公网 IP
# deny all;
# auth_basic "Restricted";
# auth_basic_user_file /www/server/panel/vhost/nginx/.htpasswd;
index index.html;
try_files $uri $uri/ /admin/index.html;
add_header Strict-Transport-Security "max-age=15552000" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header X-Frame-Options "SAMEORIGIN" always;
}
# ===== UPLOAD 代理(富文本传图 + 文章附件上传,共用 50m) =====
# 覆盖两个上传口:
# /api/common/upload → 富文本图片
# /api/cms/article/attachment/upload → 文章附件
location ~* ^/api/(common/upload(s)?|cms/article/attachment/upload)$ {
# 剥掉 /api 前缀,原样转发后端真实路径
rewrite ^/api/(.*)$ /$1 break;
proxy_pass http://127.0.0.1:8081;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_hide_header X-Powered-By;
proxy_hide_header Server;
proxy_request_buffering off;
proxy_buffering off;
proxy_connect_timeout 30s;
proxy_send_timeout 300s;
proxy_read_timeout 60s;
# 与字典 cms_attachment_max / Spring 50MB 对齐
client_max_body_size 50m;
}
# ===== API 代理 =====
location /api/ {
proxy_pass http://127.0.0.1:8081/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Host $host:$server_port;
proxy_set_header X-Scheme $scheme;
proxy_hide_header X-Powered-By;
proxy_hide_header Server;
proxy_connect_timeout 30s;
proxy_send_timeout 300s;
proxy_read_timeout 60s;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
# 413 统一返回 JSON,前端弹明确提示
# 【变更【9】】
# 修改前:只有json返回,缺少安全头
# 修改后:413自定义响应块补充HSTS与安全头
error_page 413 = @413;
location @413 {
default_type application/json;
add_header Strict-Transport-Security "max-age=15552000" always;
add_header X-Content-Type-Options "nosniff" always;
return 413 '{"code":413,"msg":"请求内容超过大小限制"}';
}
access_log /www/wwwlogs/abc.com_new.log;
error_log /www/wwwlogs/abc.com_new.error.log;
}
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/qq_22905801/article/details/170193556



