# ═══════════════════════════════════════════════════════════
# 语言保护罩 · 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 端口
