Files
Private-Proxy/server_config/nginx/nginx.conf
T
RRRosmontis 3e29012d9c server_config: CONNECT 出站超时 60s→10s,并补充排障口径
实测(2026-09):目标为黑洞 IP 时,nginx 出站超时 60s > lite 客户端 15s,
表现为客户端 'read operation timed out' 而非 502,形似代理卡死,实为超时错配。
改为 10s 后黑洞目标 10.2s 返回、正常目标 0.4-0.7s 不受影响(五节点已生效)。

README 新增 5.6 节:三个超时的口径 + 'CONNECT 502' 的排查顺序
(先判断目标是否本身不可达 → 再看 nginx 错误类型 → 最后才怀疑 CONNECT 模块),
并建议客户端日志记录原始域名(案例:Dropbox 旧 IP 失效导致误判)。
2026-09-19 01:23:38 +08:00

171 lines
6.6 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.
worker_processes auto;
worker_rlimit_nofile 65535;
events {
worker_connections 8192;
multi_accept on;
}
http {
server_tokens off;
resolver 8.8.8.8 ipv6=off valid=300s;
resolver_timeout 10s;
# 默认站点分流:本机/私网直连返回伪装页;其余 Host(正向代理目标)走 /__proxy 转发
# 公网 IP 无需手改:cron(sync-nginx-local-ips.sh)自动写入 local_ip_rules.conf;
# 另有 /__proxy 自代理环保护兜底,即使公网 IP 变更也不会死循环。
map $host $is_local {
default 0;
"~^(10\.|127\.|169\.254\.|192\.168\.|172\.(1[6-9]|2[0-9]|3[01])\.)" 1;
}
# UoT v2(UDP over TCP):CONNECT 目标为 sing-box UoT v2 magic 地址
# (sp.v2.udp-over-tcp.arpa)时转发到本机 UoT relay(127.0.0.1:15201),
# 其余 CONNECT 走默认解析($connect_addr)。
# 注意(实测结论,勿踩坑):
# 1. 必须用 $request 匹配——此模块版本未注册 $connect_host 变量;
# 2. proxy_connect_address 必须放在 default_server 块——nginx 按 Host 头
# 选虚拟主机,CONNECT 的 Host 是目标域名,永远落在 default_server;
# 3. 客户端 CONNECT magic 地址时端口必须非 0(模块拒绝 port<1,返回 400)。
map $request $rrpp_uot_connect_address {
default $connect_addr;
"~^CONNECT sp\.v2\.udp-over-tcp\.arpa" 127.0.0.1:15201;
}
include mime.types;
default_type application/octet-stream;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
keepalive_requests 100;
# <nginx端口>:主域名 HTTPS 站点 + 认证 CONNECT 代理
server {
listen <nginx端口> ssl;
http2 on;
server_name <节点域名>;
root /var/www/html;
ssl_certificate /etc/nginx/ssl/<节点域名>/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/<节点域名>/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# 仅 CONNECT/正向代理需要认证,普通页面不需要
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_connect;
proxy_connect_allow all;
proxy_connect_address $rrpp_uot_connect_address;
# 出站连接超时须小于客户端超时(lite 客户端 15s):
# 目标黑洞时快速返回 502,避免客户端"read operation timed out"干等
proxy_connect_connect_timeout 10s;
# 注:此模块版本 proxy_connect_data_timeout 与 proxy_connect_read_timeout
# 写同一字段(同时配置报 duplicate),长连接超时用 read/send timeout 设置
proxy_connect_read_timeout 10m;
proxy_connect_send_timeout 10m;
location / {
auth_basic off;
if ($host != "<节点域名>") {
rewrite ^ /__proxy last;
}
index index.html;
try_files $uri $uri/ =404;
}
location /__proxy {
internal;
proxy_intercept_errors on;
error_page 502 503 504 =444 @drop;
resolver 8.8.8.8 ipv6=off valid=300s;
proxy_pass $scheme://$host$request_uri;
proxy_set_header Host $host;
proxy_ssl_name $host;
proxy_ssl_server_name on;
}
location @drop {
return 444;
}
}
# <nginx端口> fallback:其他 SNI 也可用 CONNECT 代理;普通 GET 只返回伪装页
server {
listen <nginx端口> ssl default_server;
http2 on;
server_name _;
ssl_certificate /etc/nginx/ssl/<节点域名>/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/<节点域名>/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# 仅 CONNECT/正向代理需要认证,普通页面不需要
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_connect;
proxy_connect_allow all;
proxy_connect_address $rrpp_uot_connect_address;
# 出站连接超时须小于客户端超时(lite 客户端 15s):
# 目标黑洞时快速返回 502,避免客户端"read operation timed out"干等
proxy_connect_connect_timeout 10s;
# 注:此模块版本 proxy_connect_data_timeout 与 proxy_connect_read_timeout
# 写同一字段(同时配置报 duplicate),长连接超时用 read/send timeout 设置
proxy_connect_read_timeout 10m;
proxy_connect_send_timeout 10m;
location / {
auth_basic off;
# 自动判定本机:连接本地地址 / 无 Host / 私网回环 / cron 维护的公网 IP 规则
# 命中则 rewrite 到 /__local<原路径>(保留 $uri),其余走 /__proxy 转发
if ($host = $server_addr) { rewrite ^(.*)$ /__local$1 last; }
if ($host = "_") { rewrite ^(.*)$ /__local$1 last; }
if ($is_local) { rewrite ^(.*)$ /__local$1 last; }
include /etc/nginx/local_ip_rules.conf;
rewrite ^ /__proxy last;
}
# 本机 IP/域名直连:剥掉前缀后按原路径服务伪装页(保持原有行为)
location /__local {
internal;
auth_basic off;
rewrite ^/__local(.*)$ $1 break;
root /var/www/html;
index index.html;
try_files $uri $uri/ =404;
}
# 明文 HTTP 正向代理:绝对形式请求(Host=目标域名)在此转发
location /__proxy {
internal;
# 自代理环保护:转发请求带标记头,二次进入说明代理目标指向本机(未知/新公网 IP),
# 返回 508 Loop Detected 而非死循环
if ($http_x_proxy_loop_guard = "1") {
return 508;
}
proxy_set_header X-Proxy-Loop-Guard "1";
resolver 8.8.8.8 ipv6=off valid=300s;
proxy_pass http://$http_host$request_uri;
proxy_set_header Host $http_host;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_connect_timeout 10s;
proxy_read_timeout 120s;
proxy_intercept_errors on;
# 目标不可达/无法解析:直接断开连接(444),不返回任何页面
error_page 502 503 504 =444 @drop;
}
location @drop {
return 444;
}
}
include /etc/nginx/conf.d/*.conf;
}