guanghulab/server/nginx/novel-mirror-shield.conf

207 lines
9.4 KiB
Plaintext
Raw Normal View History

# ═══════════════════════════════════════════════════════════
# 语言保护罩 · Novel智库节点入站保护配置
# ═══════════════════════════════════════════════════════════
#
# 编号: ZY-SVR-NGX-006-SHIELD
# 服务器: ZY-SVR-006 (43.153.203.105 · 新加坡 · 智库节点)
# 守护: 铸渊 · ICE-GL-ZY001
# 版权: 国作登字-2026-A-00037559
#
# 语言保护罩三层架构 (L2 + L3 由本配置实现):
#
# L1 · 出站伪装层 — 由 novel-api 的代理池模块负责
# L2 · 入站蜜罐层 — 本配置: 扫描者看到自己的镜像
# L3 · 自动封禁层 — fail2ban 监控 nginx 日志自动 ban
#
# 蜜罐原理:
# 未授权访问 → 返回 JSON 镜像,把扫描者的信息原样反射
# 服务器伪装为 CDN 静态节点,不暴露任何技术栈
# 真实应用 (4000/4001/4002) 只绑定 127.0.0.1,不直接暴露
#
# ═══════════════════════════════════════════════════════════
# ─── 全局:隐藏 Nginx 版本,伪装为 CDN ───
# 在 nginx.conf 主配置 http{} 块内设置:
# server_tokens off;
# more_set_headers 'Server: cloudfront'; # 需要 headers_more 模块
# 本配置通过 add_header 覆盖实现类似效果
# ─── 速率限制区域 (在 http{} 块定义,此处注释说明) ───
# limit_req_zone $binary_remote_addr zone=shield_limit:10m rate=10r/m;
# limit_conn_zone $binary_remote_addr zone=shield_conn:10m;
# ─── GeoIP 封锁区 (可选,需 ngx_http_geoip2_module) ───
# geo $blocked_country {
# default 0;
# # 如需按国家封锁,在此添加
# }
# ═══════════════════════════════════════════════════════════
# HTTP → HTTPS 重定向 · novel.guanghuyaoming.com
# ───────────────────────────────────────────────────────────
# 必须在 default_server (蜜罐) 之前定义,让合法域名流量
# 在到达蜜罐之前先被这个 server block 捕获并重定向到 HTTPS。
# Let's Encrypt ACME 挑战也在此处处理。
# ═══════════════════════════════════════════════════════════
server {
listen 80;
listen [::]:80;
server_name novel.guanghuyaoming.com;
server_tokens off;
# Let's Encrypt ACME 验证路径certbot 申请证书时需要)
location /.well-known/acme-challenge/ {
root /var/www/certbot;
try_files $uri =404;
}
# 所有其他请求重定向到 HTTPS
location / {
return 301 https://$host$request_uri;
}
}
# ═══════════════════════════════════════════════════════════
# 蜜罐 · 80 端口 — HTTP 入站捕获
# ═══════════════════════════════════════════════════════════
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
# 隐藏服务器信息,伪装为静态 CDN 节点
server_tokens off;
add_header Server "AmazonS3" always;
add_header X-Cache "Miss from cloudfront" always;
add_header Via "1.1 cloudfront.net (CloudFront)" always;
# 访问日志fail2ban 监控此日志)
access_log /var/log/nginx/shield-access.log;
error_log /var/log/nginx/shield-error.log warn;
# ─── 蜜罐路由:所有未知路径 ───
# 将扫描者的信息原样镜像反射回去
location / {
# 速率限制每分钟10次超出返回 429
limit_req zone=shield_limit burst=5 nodelay;
# 返回镜像响应 (纯静态 HTML不暴露后端)
default_type text/html;
return 200 '<!DOCTYPE html>
<html><head><meta charset="utf-8">
<title>Amazon S3</title>
<style>body{font-family:Arial,sans-serif;background:#f0f0f0;margin:40px;color:#333}
.container{max-width:600px;margin:0 auto;background:#fff;padding:40px;border-radius:4px;box-shadow:0 1px 3px rgba(0,0,0,.1)}
h1{color:#e47911;font-size:24px}p{line-height:1.6;color:#555}
.code{font-family:monospace;background:#f8f8f8;padding:12px;border-radius:3px;border-left:3px solid #e47911;font-size:13px}
</style></head>
<body><div class="container">
<h1>AccessDenied</h1>
<p>Access Denied</p>
<div class="code">RequestId: $request_id<br>
HostId: novel.guanghuyaoming.com</div>
</div></body></html>';
}
# ─── 健康检查(内部监控用,外部不知道此路径)───
location = /_shield_health {
allow 127.0.0.1;
deny all;
default_type application/json;
return 200 '{"status":"alive","shield":"active","layer":"L2"}';
}
}
# ═══════════════════════════════════════════════════════════
# 正式入口 · 443 端口 — HTTPSSSL 由 certbot 配置)
# ═══════════════════════════════════════════════════════════
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name novel.guanghuyaoming.com;
# SSL 证书certbot --nginx 自动填写)
ssl_certificate /etc/letsencrypt/live/novel.guanghuyaoming.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/novel.guanghuyaoming.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
# 强化 SSL隐藏版本伪装 CDN
server_tokens off;
add_header Server "cloudfront" 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 Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# 不暴露后端 IP
add_header X-Powered-By "" always;
# 访问日志
access_log /var/log/nginx/novel-access.log;
error_log /var/log/nginx/novel-error.log warn;
# ─── 小说 API 后端 (:4000) ───
location /api/ {
proxy_pass http://127.0.0.1:4000;
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_hide_header X-Powered-By;
proxy_hide_header Server;
proxy_read_timeout 120s;
}
# ─── Phase 1: 阅读器静态入口Phase 2 替换为 Node.js 阅读器)───
location / {
root /opt/novel-db/app/public;
try_files $uri $uri/ /index.html;
}
# ─── 成员 Agent API (:4002) ───
location /agent/ {
proxy_pass http://127.0.0.1:4002;
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_hide_header X-Powered-By;
proxy_hide_header Server;
# Agent 长连接支持
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 300s;
}
# ─── 保护罩状态 API供面板拉取仅已认证用户可访问───
location /shield/ {
proxy_pass http://127.0.0.1:4000/shield/;
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;
}
# ─── 蜜罐:未知路径扫描捕获 ───
location @honeypot {
default_type application/json;
add_header Server "cloudfront" always;
add_header X-Cache "Hit" always;
return 403 '{"error":"AccessDenied","requestId":"$request_id","message":"Access Denied"}';
}
}
# ═══════════════════════════════════════════════════════════
# 扫描捕获 · 非标准端口蜜罐(需 iptables 引流)
# ═══════════════════════════════════════════════════════════
# 在 stream{} 块配置(须在 nginx.conf 引入 stream 模块)
# 将常见扫描端口(8080/8443/3000/3001/3002)流量引入蜜罐
# 可通过 iptables REDIRECT 规则实现:
# iptables -t nat -A PREROUTING -p tcp --dport 8080 -j REDIRECT --to-port 80
# iptables -t nat -A PREROUTING -p tcp --dport 8443 -j REDIRECT --to-port 80
# iptables -t nat -A PREROUTING -p tcp --dport 3000 -j REDIRECT --to-port 80
# 这样所有扫描常用端口的流量都被引导到蜜罐 80 端口