207 lines
9.4 KiB
Plaintext
207 lines
9.4 KiB
Plaintext
|
|
# ═══════════════════════════════════════════════════════════
|
|||
|
|
# 语言保护罩 · 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 端口 — HTTPS(SSL 由 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 端口
|