Files
wecom_it_smart_desk/deploy-server/nginx/nginx.conf
T

249 lines
11 KiB
Nginx Configuration File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# =============================================================================
# 企微智能IT支持服务台 — Nginx 配置(公司内网服务器版)
# =============================================================================
# 适用场景:独立域名 itsupport.servyou.com.cn,公司内网 DNS 解析
# 与 NAS 版的区别:
# 1. 移除 Cloudflare 相关头(X-Forwarded-Proto https 等)
# 2. server_name 改为正式域名
# 3. 真实 IP 直接从 $remote_addr 获取(无 CF 代理层)
# 4. 预留 HTTPS 配置注释(如公司有统一 SSL 终端)
# =============================================================================
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# ------------------------------------------------------------------
# 日志格式
# ------------------------------------------------------------------
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent"';
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log warn;
# ------------------------------------------------------------------
# 真实 IP 还原(2026-06-15 v0.5.1 修复)
# ------------------------------------------------------------------
# 问题:公司有 WAF/堡垒机/反向代理,nginx 看到的 $remote_addr
# 是代理 IP(不在白名单),allow/deny 因此误判 403
# 修法:信任内网段代理透传的 X-Forwarded-For 头,用真实 IP 做白名单
# 注意:set_real_ip_from 是"我信任的代理",不是"我允许的客户端"
# 必须精确,否则攻击者可伪造 X-Forwarded-For 绕过白名单
set_real_ip_from 10.0.0.0/8; # 内网 A 类(代理/WAF 出口)
set_real_ip_from 172.16.0.0/12; # 内网 B 类
set_real_ip_from 192.168.0.0/16; # 内网 C 类
set_real_ip_from 10.212.0.0/16; # VPN 网段
real_ip_header X-Forwarded-For; # 从 X-Forwarded-For 取最后一个非信任 IP
real_ip_recursive on; # 递归剥离已信任代理 IP
# ------------------------------------------------------------------
# 基础配置
# ------------------------------------------------------------------
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
client_max_body_size 50m; # 支持文件上传(企微媒体文件)
# ------------------------------------------------------------------
# Gzip 压缩(前端静态资源)
# ------------------------------------------------------------------
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css text/xml text/javascript
application/javascript application/xml+rss
application/json application/ld+json;
# =================================================================
# 上游服务定义(Docker 内部网络)
# =================================================================
upstream backend_api {
server backend:8000;
}
# =================================================================
# HTTP 服务(监听 80 端口)
# =================================================================
# 如果公司有统一 SSL 终端(如 F5/Nginx 反代),此服务器只需监听 80
# 如果需要本机 HTTPS,取消下方 server 块注释,并配置证书路径
# =================================================================
# HTTP — 80 端口强制 301 跳 HTTPS
# =================================================================
server {
listen 80;
server_name itsupport.servyou.com.cn;
# ACME http-01 验证用(如果以后用 Let's Encrypt
location /.well-known/acme-challenge/ {
root /usr/share/nginx/html;
}
# 其他全部 301 跳 https
location / {
return 301 https://$host$request_uri;
}
}
# =================================================================
# HTTPS — 443 端口(主服务)
# =================================================================
server {
listen 443 ssl;
http2 on;
server_name itsupport.servyou.com.cn;
# SSL 证书(通配符 *.servyou.com.cn,fullchain 含 leaf+intermediate+root)
ssl_certificate /etc/nginx/ssl/itsupport.servyou.com.cn.crt;
ssl_certificate_key /etc/nginx/ssl/itsupport.servyou.com.cn.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
# ------------------------------------------------------------------
# 安全头
# ------------------------------------------------------------------
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# CSP 收紧: 去掉 unsafe-inline(生产不需要,只有 dev HMR 需要)
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-eval' https://res.wx.qq.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: https: http:; connect-src 'self' https://qyapi.weixin.qq.com wss://*; font-src 'self' data:;" always;
# 隐私与跨域控制
add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=()" always;
add_header Cross-Origin-Opener-Policy "same-origin" always;
add_header Cross-Origin-Embedder-Policy "require-corp" always;
add_header Cross-Origin-Resource-Policy "same-origin" always;
# 隐藏服务器版本
server_tokens off;
# ------------------------------------------------------------------
# 健康检查端点
# ------------------------------------------------------------------
location = /health {
access_log off;
return 200 "healthy\n";
add_header Content-Type text/plain;
}
# ------------------------------------------------------------------
# H5 员工端 — /itdesk/
# ------------------------------------------------------------------
location /itdesk/ {
alias /usr/share/nginx/html/itdesk/;
index index.html;
try_files $uri /itdesk/index.html;
}
# ------------------------------------------------------------------
# 坐席工作台 — /itagent/
# ------------------------------------------------------------------
location /itagent/ {
alias /usr/share/nginx/html/itagent/;
index index.html;
try_files $uri /itagent/index.html;
}
# ------------------------------------------------------------------
# 管理后台 — /itadmin/(仅限内网/VPN 访问)
# ------------------------------------------------------------------
location /itadmin/ {
# IP 白名单:仅允许内网网段
allow 10.0.0.0/8;
allow 172.16.0.0/12;
allow 192.168.0.0/16;
allow 10.212.0.0/16; # VPN 网段
deny all;
alias /usr/share/nginx/html/itadmin/;
index index.html;
try_files $uri /itadmin/index.html;
}
# ------------------------------------------------------------------
# 统一入口 Portal — /itportal/
# ------------------------------------------------------------------
location /itportal/ {
alias /usr/share/nginx/html/itportal/;
index index.html;
try_files $uri /itportal/index.html;
}
# ------------------------------------------------------------------
# 后端 API — /api/(管理端 API 仅限内网/VPN
# ------------------------------------------------------------------
location /api/ {
# 管理端 API 路径需要 IP 白名单
location ~ ^/api/admin/ {
allow 10.0.0.0/8;
allow 172.16.0.0/12;
allow 192.168.0.0/16;
allow 10.212.0.0/16;
deny all;
proxy_pass http://backend_api;
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_connect_timeout 60s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
}
# 其他 API 路径
proxy_pass http://backend_api/;
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;
# 超时设置(AI 回复可能较慢)
proxy_connect_timeout 60s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
}
# ------------------------------------------------------------------
# WebSocket — /ws/(坐席端实时通信)
# ------------------------------------------------------------------
location /ws/ {
access_log off; # P0-#4: 关闭 WS 路径日志,避免 token 泄露
proxy_pass http://backend_api;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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_read_timeout 86400s; # WebSocket 长连接
}
# ------------------------------------------------------------------
# 企微回调 — /api/wecom/callback(接收企微消息推送)
# ------------------------------------------------------------------
# 企微验证回调 URL 时使用 GET,后续消息推送使用 POST
# 此路径已包含在 /api/ 的代理规则中,无需单独配置
# ------------------------------------------------------------------
# 默认路径 — 重定向到统一入口
# ------------------------------------------------------------------
location = / {
return 302 /itportal/;
}
}
}