Skip to content

Commit f78fccb

Browse files
committed
1 parent 0700e72 commit f78fccb

9 files changed

Lines changed: 925 additions & 7 deletions

File tree

.vitepress/menus/sidebar.en.mts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ export const sidebar: DefaultTheme.Config["sidebar"] = {
2020
{
2121
text: "Multiple Configurations",
2222
link: "/en/config/features/multiple.md"
23+
},
24+
{
25+
text: "Reverse Proxy / NAT Traversal",
26+
link: "/en/document/level-2/vless_reverse.md"
2327
}
2428
]
2529
},

.vitepress/menus/sidebar.mts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@ export const sidebar: DefaultTheme.Config["sidebar"] = {
1414
link: "/config/features/browser_dialer.md"
1515
},
1616
{ text: "环境变量", link: "/config/features/env.md" },
17-
{ text: "多文件配置", link: "/config/features/multiple.md" }
17+
{ text: "多文件配置", link: "/config/features/multiple.md" },
18+
{
19+
text: "反向代理 / 内网穿透",
20+
link: "/document/level-2/vless_reverse.md"
21+
}
1822
]
1923
},
2024
{

.vitepress/menus/sidebar.ru.mts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ export const sidebar: DefaultTheme.Config["sidebar"] = {
2626
{
2727
text: "Конфигурация из нескольких файлов",
2828
link: "/ru/config/features/multiple.md"
29+
},
30+
{
31+
text: "Обратный прокси / NAT Traversal",
32+
link: "/ru/document/level-2/vless_reverse.md"
2933
}
3034
]
3135
},

docs/config/reverse.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
# 反向代理
1+
# 旧版反向代理
22

33
::: danger
4-
此功能已废弃,请使用 VLESS 反向代理
4+
旧版反向代理已废弃,请改用 [VLESS 反向代理](/document/level-2/vless_reverse.md)
55
:::
66

7+
:::: details 旧版反向代理文档(已废弃)
78
反向代理可以把服务器端的流量向客户端转发,即逆向流量转发。
89

910
::: tip
@@ -260,3 +261,5 @@ inbound:
260261
]
261262
}
262263
```
264+
265+
::::

docs/document/level-2/vless_reverse.md

Lines changed: 299 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,3 +433,302 @@ VLESS 反向代理至少可以覆盖两类场景:
433433
- 让用户接入公网服务器后再通过反向通道漫游回家。
434434

435435
两者使用的是同一套反向连接机制,区别主要在公网侧如何路由流量,以及内网侧如何继续处理这些流量。理解这一点之后,就可以按自己的场景在“端口映射”和“远程漫游”之间自由扩展。
436+
437+
## 进阶技巧:高级负载均衡
438+
439+
如果公网端存在多个入站使用相同的 reverse tag,最终也只会对应产生一个出站;可以把它理解为多条线路同时挂在同一个可用池中,每次使用时随机选一路。
440+
441+
这种方式可以实现更灵活的多对多配置。假如某条线路暂时不可用,例如对应的内网端还没有连上来,那么它就不会进入当前可用池,后续流量会自动转发到其它仍然在线的线路上,无需手动切换。
442+
443+
不难看出,`reverse.tag` 在两侧都是“同 tag 合并为一个连接池”的语义:
444+
445+
- 公网侧多个 client 共用同一个 `reverse-out`,会收敛为同一个出站池;
446+
- 内网侧多个 VLESS 出站共用同一个 `reverse-in`,会收敛为同一个入口池。
447+
448+
所以它天然可以扩展成 N 对 N。更常见的实际部署是:对外只有一个业务域名,例如 `www.example.com`,再通过 GeoDNS 把访客就近分配到美西和东京两台公网服务器;而内网端则分别回连 `us-reverse.example.com``jp-reverse.example.com` 这两个公网节点。再部署两个内网端:家里和办公室。家里、办公室都分别连到美西和东京,于是每个公网端都会维护一个“家里 + 办公室”的可用池。实际转发时,会从当前已建立的连接里随机选一条可用线路;某一端离线后,它会自动从池里消失。
449+
450+
下面给一个极简片段,只保留 reverse 相关部分,继续沿用“公网入口端口映射到内网服务”的写法。
451+
452+
### 美西公网端
453+
454+
```json
455+
{
456+
"inbounds": [
457+
{
458+
"port": 8443,
459+
"protocol": "vless",
460+
"settings": {
461+
"clients": [
462+
{
463+
"id": "us-home-uuid",
464+
"reverse": {
465+
"tag": "reverse-out"
466+
}
467+
},
468+
{
469+
"id": "us-office-uuid",
470+
"reverse": {
471+
"tag": "reverse-out"
472+
}
473+
}
474+
]
475+
}
476+
},
477+
{
478+
"port": 443,
479+
"protocol": "tunnel",
480+
"tag": "portal"
481+
}
482+
],
483+
"routing": {
484+
"rules": [
485+
{
486+
"inboundTag": ["portal"],
487+
"outboundTag": "reverse-out"
488+
}
489+
]
490+
},
491+
"outbounds": [
492+
{
493+
"protocol": "freedom"
494+
}
495+
]
496+
}
497+
```
498+
499+
### 东京公网端
500+
501+
完全同理,只是把 UUID 换成 `jp-home-uuid``jp-office-uuid`
502+
503+
### 家里内网端
504+
505+
```json
506+
{
507+
"routing": {
508+
"rules": [
509+
{
510+
"inboundTag": ["reverse-in"],
511+
"outboundTag": "reverse-direct"
512+
}
513+
]
514+
},
515+
"outbounds": [
516+
{
517+
"protocol": "freedom",
518+
"tag": "reverse-direct",
519+
"settings": {
520+
"redirect": "192.168.1.123:80",
521+
"finalRules": [
522+
{
523+
"action": "allow",
524+
"network": "tcp",
525+
"ip": "192.168.1.123",
526+
"port": "80"
527+
}
528+
]
529+
}
530+
},
531+
{
532+
"protocol": "vless",
533+
"settings": {
534+
"address": "us-reverse.example.com",
535+
"port": 8443,
536+
"id": "us-home-uuid",
537+
"reverse": {
538+
"tag": "reverse-in"
539+
}
540+
}
541+
},
542+
{
543+
"protocol": "vless",
544+
"settings": {
545+
"address": "jp-reverse.example.com",
546+
"port": 8443,
547+
"id": "jp-home-uuid",
548+
"reverse": {
549+
"tag": "reverse-in"
550+
}
551+
}
552+
}
553+
]
554+
}
555+
```
556+
557+
### 办公室内网端
558+
559+
和家里内网端完全同理,只是把 UUID 换成 `us-office-uuid``jp-office-uuid`,并把 `redirect` 改成办公室要暴露的内网服务。
560+
561+
## 进阶技巧:透传真实访客 IP
562+
563+
如果你希望内网 Web 服务看到真实访客 IP,而不是把访问来源识别成内网侧 Xray 那台机器的 IP 地址,可以在内网侧的 `freedom` 出站里开启 `proxyProtocol`。不开启时,后端 WebServer 看到的源地址通常就是内网侧 Xray 的 IP;开启后,Xray 在把连接转发到 `redirect` 指定的后端时,会先发送一段 PROXY protocol 头,把真实源地址一并传给 WebServer。
564+
565+
例如:
566+
567+
```json
568+
{
569+
"outbounds": [
570+
{
571+
"protocol": "freedom",
572+
"tag": "reverse-direct",
573+
"settings": {
574+
"redirect": "192.168.1.123:80",
575+
"proxyProtocol": 1,
576+
"finalRules": [
577+
{
578+
"action": "allow",
579+
"network": "tcp",
580+
"ip": "192.168.1.123",
581+
"port": "80"
582+
}
583+
]
584+
}
585+
}
586+
]
587+
}
588+
```
589+
590+
此时 `redirect` 指向的后端不能只是普通的 HTTP 监听,而必须显式开启 PROXY protocol。假设 WebServer 就是 `192.168.1.123`,而内网侧 Xray 的地址是 `192.168.1.10`,以 `nginx` 为例可以这样配置:
591+
592+
```nginx
593+
server {
594+
listen 80 proxy_protocol;
595+
server_name _;
596+
597+
set_real_ip_from 192.168.1.10;
598+
real_ip_header proxy_protocol;
599+
600+
location / {
601+
root /srv/www/html;
602+
index index.html;
603+
}
604+
}
605+
```
606+
607+
上面的 `set_real_ip_from 192.168.1.10;` 表示只信任来自内网侧 Xray 的 PROXY protocol 头;这里的 `192.168.1.10` 只是示例,请改成你那台内网 Xray 的实际 IP。`proxyProtocol` 可选 `1``2`,只要后端支持,`nginx` 这一侧的写法保持不变。
608+
609+
## 进阶技巧:在内网侧按域名与访客 IP 精细分流
610+
611+
如果你希望外部能够访问到的内网站点不止一个,而且这些站点并不在同一台机器上,那么可以直接在反向代理入口上开启 `sniffing`,先从 HTTP Host 或 TLS SNI 中嗅探出域名,再按域名把流量送到不同的 `freedom` 出站。这样公网侧只需要保留一个入口,内网侧就能继续按站点拆分到不同主机。
612+
613+
同时,VLESS 反向代理会保留真实的访客源 IP,因此这些流量进入内网侧的路由系统后,还可以继续结合 `sourceIP` 做更细的控制,例如对某些来源直接 `blackhole`,或者把特定来源引导到另一组后端。下面给出一个组合示例:
614+
615+
```json
616+
{
617+
"routing": {
618+
"domainStrategy": "AsIs",
619+
"rules": [
620+
{
621+
"inboundTag": ["reverse-in"],
622+
"sourceIP": ["!geoip:cn"],
623+
"outboundTag": "reverse-block"
624+
},
625+
{
626+
"inboundTag": ["reverse-in"],
627+
"domain": ["full:admin.example.com"],
628+
"outboundTag": "reverse-admin"
629+
},
630+
{
631+
"inboundTag": ["reverse-in"],
632+
"domain": ["domain:blog.example.com"],
633+
"outboundTag": "reverse-blog"
634+
},
635+
{
636+
"inboundTag": ["reverse-in"],
637+
"outboundTag": "reverse-default"
638+
}
639+
]
640+
},
641+
"outbounds": [
642+
{
643+
"protocol": "freedom"
644+
},
645+
{
646+
"protocol": "blackhole",
647+
"tag": "reverse-block"
648+
},
649+
{
650+
"protocol": "freedom",
651+
"tag": "reverse-admin",
652+
"settings": {
653+
"redirect": "192.168.1.10:8443",
654+
"proxyProtocol": 1,
655+
"finalRules": [
656+
{
657+
"action": "allow",
658+
"network": "tcp",
659+
"ip": "192.168.1.10",
660+
"port": "8443"
661+
}
662+
]
663+
}
664+
},
665+
{
666+
"protocol": "freedom",
667+
"tag": "reverse-blog",
668+
"settings": {
669+
"redirect": "192.168.1.20:8080",
670+
"proxyProtocol": 1,
671+
"finalRules": [
672+
{
673+
"action": "allow",
674+
"network": "tcp",
675+
"ip": "192.168.1.20",
676+
"port": "8080"
677+
}
678+
]
679+
}
680+
},
681+
{
682+
"protocol": "freedom",
683+
"tag": "reverse-default",
684+
"settings": {
685+
"redirect": "192.168.1.30:80",
686+
"proxyProtocol": 1,
687+
"finalRules": [
688+
{
689+
"action": "allow",
690+
"network": "tcp",
691+
"ip": "192.168.1.30",
692+
"port": "80"
693+
}
694+
]
695+
}
696+
},
697+
{
698+
"protocol": "vless",
699+
"settings": {
700+
"address": "yourserver.com",
701+
"port": 8443,
702+
"id": "ac04551d-6ebf-4685-86e2-17c12491f7f4",
703+
"flow": "xtls-rprx-vision",
704+
"reverse": {
705+
"tag": "reverse-in",
706+
"sniffing": {
707+
"enabled": true,
708+
"destOverride": ["http", "tls"]
709+
}
710+
}
711+
}
712+
}
713+
]
714+
}
715+
```
716+
717+
这个例子的要点是:
718+
719+
- `reverse.sniffing` 开在内网侧 VLESS 出站的 `reverse` 下,表示对从反向代理入口进来的连接执行嗅探;
720+
- 路由规则有先后顺序,所以像 `sourceIP -> blackhole` 这样的限制规则应当放在前面;
721+
- `proxyProtocol` 只负责把真实访客 IP 继续传给后端应用,如果你只想在 Xray 路由里按 `sourceIP` 分流,也可以不启用它。
722+
723+
这样配置后,一个公网入口就可以同时承接多个内网站点,并且还能在内网侧根据访客来源地址继续做拒绝、分流、审计等更灵活的处理。
724+
725+
## 安全注意事项
726+
727+
下面这些点更偏部署安全与边界控制,建议在正式使用前通读一遍:
728+
729+
- 用于反向代理的 UUID 无法与正向代理(普通客户端)共用,只能单独新建。此外反向代理 UUID 要妥善保管,否则一旦客户端配置泄露,攻击者就可能尝试劫持你的反向代理通道。
730+
- 用于内网穿透的那条连接,即使开启了 `XTLS Vision`,当前主要获得的也是 `padding` 等收益,并不等同于常说的“裸奔”效果。至于面向最终用户的那条连接是否也要开启 XTLS,需要结合你的链路形态和威胁模型自行评估。
731+
- 承接反向代理流量的内网 `freedom`(也就是常说的 `direct`)出站,建议按最小权限原则配置。把默认出站设为 `blackhole`,只把允许访问的目标显式路由到专用 `freedom`。再通过 `finalRules` 只放行必要的地址和端口。
732+
- 如果你使用的是别人提供的穿透服务用于远程回家,或者你并不完全信任公网 VPS,建议不要让反向代理流量直接落到真实内网业务。可以在内网再部署一个带 `VLESS Encryption` 的服务端专门承接这部分流量,再由它转发给实际业务,以补上身份认证和数据保护,否则有权限接触到公网服务器的人可以漫游你的内网。
733+
- 通过 `VLESS` 等入站协议把流量送到内网端时,路由系统里看到的 `Source` / `Local` 所属协议,不一定与最终 `Target` 一致。涉及 `source``local``network` 等条件时,应以实际流量形态为准,不要想当然地把它们等同起来。
734+
- `XHTTP``WebSocket` 等基于 HTTP 的入站当前会默认读取 `X-Forwarded-For`。如果前面没有你自己信任的 HTTP 反向代理,这个头可以被客户端伪造,因此不要直接拿它做严格的安全判断,例如 IP 白名单、黑名单或审计归因。

docs/en/config/reverse.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
# Reverse Proxy
1+
# Legacy Reverse Proxy
22

33
::: danger
4-
This feature has been deprecated. Please use the VLESS reverse proxy.
4+
The legacy reverse proxy has been deprecated. Please use the [VLESS reverse proxy](/en/document/level-2/vless_reverse.md).
55
:::
66

7+
:::: details Legacy reverse proxy documentation (deprecated)
78
A reverse proxy can forward traffic from the server side to the client side, effectively performing reverse traffic forwarding.
89

910
::: tip
@@ -262,3 +263,5 @@ Routing Configuration:
262263
]
263264
}
264265
```
266+
267+
::::

0 commit comments

Comments
 (0)