XTLS / Xray-core

Xray, Penetrates Everything. Also the best v2ray-core, with XTLS support. Fully compatible configuration.
https://t.me/projectXray
Mozilla Public License 2.0
25.86k stars 3.98k forks source link

XHTTP: The real upload / download splitting #3955

Closed RPRX closed 4 weeks ago

RPRX commented 1 month ago

本来以为需要一天,结果两个小时就写好了

合并 https://github.com/XTLS/Xray-core/pull/3816 时想到的,如果只是 SplitHTTP in REALITY 的话比 H2 in REALITY 就只是多了 header padding 和 XMUX,但如果利用 SplitHTTP 天生的特性实现真正的上下行分离,事情就会比较有意思了

比如,你可以 XHTTP-H3-CDN 上行,结合 XHTTP-H2-REALITY 下行,给 GFW 整点麻烦 🎃,这下又开启了一个崭新的时代

客户端注意:目前下行无多路复用 https://github.com/XTLS/Xray-core/pull/3965下行 path 直接取自上行 path,所以需要一致 https://github.com/XTLS/Xray-core/pull/3977 服务端注意:目前需要用 VLESS fallbacks 把内层明文流量导至同一 XHTTP 入站

但我还没有测试,主要是懒得写配置,可能存在 bug,大家测试一下,尤其是 @yuhan6665 @Fangliding @mmmray

未来可能会把 address 和 port 加到 streamSettings,覆盖写在出站协议里的值,这个 PR 也只需要加一项配置了 已经做了

别忘了支持一下 Project X NFT:Announcement of NFTs by Project X #3633


服务端 inbounds 示例,一个明文 XHTTP,两个 REALITY(可换成 Nginx),443 为 example.com,8443 为 example.net:

    "inbounds": [
        {
            "listen": "@xhttp",
            "protocol": "vless",
            "settings": {
                "decryption": "none",
                "clients": [
                    {
                        "id": "" // your uuid
                    }
                ]
            },
            "streamSettings": {
                "network": "xhttp",
                "xhttpSettings": {
                    "path": "/yourpath"
                }
            }
        },
        {
            "listen": "0.0.0.0",
            "port": 443,
            "protocol": "vless",
            "settings": {
                "decryption": "none",
                "fallbacks": [
                    {
                        "dest": "@xhttp"
                    }
                ]
            },
            "streamSettings": {
                "network": "raw",
                "security": "reality",
                "realitySettings": {
                    "target": "example.com:443",
                    "serverNames": [
                        "example.com"
                    ],
                    "privateKey": "", // private key A
                    "shortIds": [
                        ""
                    ]
                }
            }
        },
        {
            "listen": "0.0.0.0",
            "port": 8443,
            "protocol": "vless",
            "settings": {
                "decryption": "none",
                "fallbacks": [
                    {
                        "dest": "@xhttp"
                    }
                ]
            },
            "streamSettings": {
                "network": "raw",
                "security": "reality",
                "realitySettings": {
                    "target": "example.net:443",
                    "serverNames": [
                        "example.net"
                    ],
                    "privateKey": "", // private key B
                    "shortIds": [
                        ""
                    ]
                }
            }
        }
    ]

客户端 outbounds 示例,多填一项 downloadSettings 即可:

    "outbounds": [
        {
            "protocol": "vless",
            "settings": {
                "vnext": [
                    {
                        "address": "", // your server's ip
                        "port": 443,
                        "users": [
                            {
                                "id": "", // your uuid
                                "encryption": "none"
                            }
                        ]
                    }
                ]
            },
            "streamSettings": {
                "network": "xhttp",
                "xhttpSettings": {
                    "path": "/yourpath", // must be the same
                    "downloadSettings": {
                        "address": "", // your server's ip
                        "port": 8443,
                        "network": "xhttp",
                        "xhttpSettings": {
                            "path": "/yourpath" // must be the same
                        },
                        "security": "reality",
                        "realitySettings": {
                            "fingerprint": "chrome",
                            "serverName": "example.net",
                            "publicKey": "" // public key B
                        }
                    }
                },
                "security": "reality",
                "realitySettings": {
                    "fingerprint": "chrome",
                    "serverName": "example.com",
                    "publicKey": "" // public key A
                }
            }
        }
    ]
RPRX commented 1 month ago

@decorativefamily 如果这东西经测试能用,合了这个 PR 就发新版

junx964 commented 1 month ago

会不会“上传流量到cdn, 下传流量从server -> client” 是一个独有的特征嘞😂 GFW直接一刀切

RPRX commented 1 month ago

@junx964 你不会反过来组合出上行 VPS 下行 CDN 吗,不会用两个 CDN 或 CDN 用两个 IP 吗,不会 VPS 整两个 IP 吗,多想

RPRX commented 1 month ago

To Q. E.:去程回程当然能使用不同的服务器啊,你甚至能叠上去程使用流量、回程使用家宽,这够不够有强度

RPRX commented 1 month ago

总之就是,在此之前的代理,上下行的源 IP、目标 IP 都不变,GFW 可以直接逮着狠狠分析,比如分析下有没有 TLS in TLS

但是你把上行多路复用了下行却没有,叠加上下行目标 IP 不同,甚至再叠加上下行连源 IP 都不同,GFW 就没那么舒服了

kingskill commented 1 month ago

总之就是,在此之前的代理,上下行的源 IP、目标 IP 都不变,GFW 可以直接逮着狠狠分析,比如分析下有没有 TLS in TLS

但是你把上行多路复用了下行却没有,叠加上下行目标 IP 不同,甚至再叠加上下行连源 IP 都不同,GFW 就没那么舒服了

不晓得实际各种网络场景里,上下分离后的包丢弃会怎样,响应会怎样,类似流媒体效能的降低是否在可承受范围。。

RPRX commented 1 month ago

@kingskill 你的两条线路原本是怎么样就还是怎么样,你看视频的话就取决于下行线路,没有什么流媒体效能降低

RPRX commented 1 month ago

To Lampadu Ao:你想上行移动家宽、下行联通家宽的话配置不同的 sockopt interface 就行了,这就是 https://github.com/XTLS/Xray-core/pull/3955#issuecomment-2445929622 所指的

tomxiang1 commented 1 month ago

H3长连接被Qos严重,请问定时随机换客户端udp端口在路上了吗?

RPRX commented 1 month ago

@tomxiang1 XMUX 就相当于会随机换客户端 UDP 端口,现在还有默认值,不用任何设置就有“定时随机换客户端udp端口”

RPRX commented 1 month ago

To 6:XMUX 是相当于是为一部分新的子连接使用新的客户端 UDP 端口,而不是影响旧的子连接,后者虽然也很简单但有特征

RPRX commented 1 month ago

To 073a8af9cfe4:如果 sockopt interface 是坏的请发个 issue,我觉得这个挺重要的,在 GFW 看来就像是两个不相干的连接

RPRX commented 1 month ago

这东西怎么配置不用我写了吧,我还等着你们写呢 @chika0801

客户端在原有的 splithttpSettings 里加个 "downloadAddrPort": "addr:port",同级再加个 downloadStreamConfig,内容就是一份新的、完整的 streamingSettings,把 SplitHTTP、TLS、REALITY、sockopt 什么的都写里面就行,下行会用这两项配置

服务端比如你有一个 TLS 有一个 REALITY,就配置 VLESS RAW,然后用 fallbacks 把内层明文流量导至同一明文 SplitHTTP 入站

RPRX commented 4 weeks ago

@dragonbreath2000 需要把这样的能力加给 VLESS,https://github.com/XTLS/Xray-core/pull/3816#issuecomment-2408843461 有提到,但 SplitHTTP 的兼容性特别强,直连、过 CDN 都能用,且现在只有 TLS 类、QUIC 类能过墙,所以 SplitHTTP 事实上已经覆盖了所有过墙场景,再加给 VLESS 的好处有限

下一步可以做上下行都预设多个线路,随机取用之类的

tomxiang1 commented 4 weeks ago

目前测试感觉XMUX 没有迁移过期连接中的流到新连接中。 迁移流这个功能比较重要是因为,如果你在下载一个比较大的文件需要较长时间(长连接),为了不触发运营商Qos,"cMaxLifetimeMs"设置为30秒过期连接,但这时只有新开的流会用新的连接,在下载大文件的老流还在过期连接中,这样就顺理成章触发运营商Qos或阻断。 不知道能不能用上http3的天生特性 image

RPRX commented 4 weeks ago

@tomxiang1 https://github.com/XTLS/Xray-core/pull/3955#issuecomment-2447535019 已经说了没有迁移旧的子连接,但想迁移很简单因为换个本地端口就行了,我说它有特征是因为 CID 没变且是明文的、GFW 看得到的,而浏览器的 QUIC 大概不会在 CID 不变时没事换个端口,所以不一定会做迁移功能

tomxiang1 commented 4 weeks ago

移动设备已经很多了,在从一个wifi到另一个wifi切换很常见了吧,浏览器很大概率换端口。应该不会有明显特征吧。

RPRX commented 4 weeks ago

@tomxiang1 切换网络的话,浏览器不需要换端口,只是比如对外 IP 加端口变了,但不换对外 IP 却不停换端口就有点怪了

RPRX commented 4 weeks ago

今天心情好是因为早些时候我试了下,这两个小时写完、未经测试的代码竟然直接跑通了,一遍过,看来我还是一如既往的牛逼,看哪个 APT-ZERO 还敢说我写不了代码了,激动得我直接给它改名 XHTTP 了,并精简了配置,配置示例已补,可以开玩了

qwerttvv commented 4 weeks ago

此功能有点野,想象空间有点大

MiniKoro commented 4 weeks ago

这个上下行分离 那可以把流量路由到其他机器回来吗

dfldylan commented 4 weeks ago

学校上行ipv4免流量,下行计费。可以上行直连,下行挂代理吗

RPRX commented 4 weeks ago

@MiniKoro 举个例子,你可以用 VPS A 接收上行,用 VPS B 接收下行,然后均转发至 VPS C,最后由同一 XHTTP 入站处理即可

dcdebug commented 4 weeks ago

New Times Begin...

tianlichunhong commented 4 weeks ago

"listen": "@xhttp", 这个@xhttp 不需要改?还是需要改,比如改为127.0.0.1? 对应的 "dest": "@xhttp" 也要改?比如改为实际的vps的IP地址?

DE009 commented 4 weeks ago

@MiniKoro 举个例子,你可以用 VPS A 接收上行,用 VPS B 接收下行,然后均转发至 VPS C,最后由同一 XHTTP 入站处理即可

是可以做到fallback到其他IP的端口了吗?印象里fallback还是只能回落到本机的端口。

qwerttvv commented 4 weeks ago

Can this version solve the Iranian and Russian GFW problem?

伊朗和大毛在这方面和中国比起来只是弟弟啊

KobeArthurScofield commented 4 weeks ago

试用了几十分钟目前在配置正确的情况下没有发现什么 bug。 用的是 HTTP/2(TCP) 的话下行连接数会比较惊人 (某种意义上的达到目的?),上行连接数有 XMUX 控制所以影响不明显。(如果用的 XHTTP 但是没有做上下行分离的配置,下行也受 XMUX 控制,连接数不会变化很多) 实际体验上面和 TLS/REALITY + 任意裸协议/Vision 没有 mux 的情况下不会差太远,因为建立下行连接的 RTT 目前去不掉,除非给下行连接也加上 XMUX 控制(目前是没有的)。 如果是电池供电的小型设备(例如手机)可能会因为连接比较多导致数据包增多,用在无线电上面的耗电可能会有所增加,建议同时设置 sockopt 里面的 TCPKeepAliveInterval 和 TCPKeepAliveIdle。

KobeArthurScofield commented 4 weeks ago

用的是 HTTP/2(TCP) 的话下行连接数会比较惊人

应该是和被代理连接关闭后 XHTTP 需要过一段时间关闭下行连接有关,一段时间内打开的新连接比较多的话开启的下行连接会被累积直到连接因为不活跃被关闭。

如果是电池供电的小型设备(例如手机)可能会因为连接比较多导致数据包增多,用在无线电上面的耗电可能会有所增加

因为目前 Go 的默认 keepalive idle 和 interval 还是 15 秒,堆的连接越多 keepalive 包也就越多,发包耗电也会变多。

Yochee commented 4 weeks ago

xhttp支持reality了?能过cdn么 edit: 试了下应该是不行,套cdn时security只能用tls。不过上下行分流还是蛮好玩的,上行走cdn下行直连救了我一个被封的ip

amydesun commented 4 weeks ago

如果我使用cloudflare的worker用作vpsa与购买vpsb定义为两个服务器,上行发送给vpsa或b,此vps访问并接收到下行数据后发给另一个vps下行再传回,假设vpsb传回时流量太大也许vpsb可以再来一层cdn呢?也就是客户端同时连接这两个vps后的玩法,如果进阶可以在墙内用vpsc组合流量后客户端直接连接墙内的vpsc即可,或者用ipv6家宽与软路由承接也可当作vpsc来派上用场,不知这个思路是否可行?如果worker因ip等因素没办法被承接,那可能就只能去购买vpsa了。思路还是把大流量过墙路线转移给CDN菩萨。

egg1234 commented 4 weeks ago

想请教一下上面的客户端 outbounds 示例的 downloadSettings 配置项的意思是否就是通知服务器端使用8443端口发送返程流量给客户端?

谢谢!

liushengqi000 commented 4 weeks ago

曾经的设想被一步步实现了呢,真好。大佬真厉害。分流之后可操作空间就大多了。我甚至想过分流后,小流量的http上行套phproxy使用。

liushengqi000 commented 4 weeks ago

上传流量有没有可能共享一个入口(可以限制上传速度),然后再由入口转发给各自的下行VPS。

zzlinwq commented 4 weeks ago

今天心情好是因为早些时候我试了下,这两个小时写完、未经测试的代码竟然直接跑通了,一遍过,~看来我还是一如既往的牛逼,看哪个 APT-ZERO 还敢说我写不了代码了~,激动得我直接给它改名 XHTTP 了,并精简了配置,配置示例已补,可以开玩了

大佬真乃天下第一奇才。比起马斯克有过之而无不及!

zzlinwq commented 4 weeks ago

试用了几十分钟目前在配置正确的情况下没有发现什么 bug。 用的是 HTTP/2(TCP) 的话下行连接数会比较惊人 ~(某种意义上的达到目的?)~,上行连接数有 XMUX 控制所以影响不明显。(如果用的 XHTTP 但是没有做上下行分离的配置,下行也受 XMUX 控制,连接数不会变化很多) 实际体验上面和 TLS/REALITY + 任意裸协议/Vision 没有 mux 的情况下不会差太远,因为建立下行连接的 RTT 目前去不掉,除非给下行连接也加上 XMUX 控制(目前是没有的)。 如果是电池供电的小型设备(例如手机)可能会因为连接比较多导致数据包增多,用在无线电上面的耗电可能会有所增加,建议同时设置 sockopt 里面的 TCPKeepAliveInterval 和 TCPKeepAliveIdle。

试用后稳定吗?你是怎么用的?用了几个VPS?

KobeArthurScofield commented 4 weeks ago

试用后稳定吗?

看线路,本身比较稳定,但是因为上行采用 XMUX 实际会对线路有点要求。如果线路本来就稳体验还是可以的。 按照当前来看下行强烈建议用 h2。上行可以用 h2 或者 h3,但是使用 h3 的时候建议将 XMUX 复用次数(maxConcurrencycMaxReuseTimescMaxLifetimeMs)调高一些或者将总连接数(maxConnections)调低一些。

你是怎么用的?用了几个VPS?

其实单个 VPS 也可以用,拆端口或者同一个端口也可以用,就是在反流量分析上面不知道效果会不会差点。 路径上面用什么东西转发也可以,管他 NGINX 还是 caddy,管他 cf 还是 cft,只要转发路径指向的最后一个目标都是同一个用了 XHTTP 传输的入站就可以。

areyouokhaha commented 3 weeks ago

试用后稳定吗?

看线路,本身比较稳定,但是因为上行采用 XMUX 实际会对线路有点要求。如果线路本来就稳体验还是可以的。 按照当前来看下行强烈建议用 h2。上行可以用 h2 或者 h3,但是使用 h3 的时候建议将 XMUX 复用次数(maxConcurrencycMaxReuseTimescMaxLifetimeMs)调高一些或者将总连接数(maxConnections)调低一些。

你是怎么用的?用了几个VPS?

其实单个 VPS 也可以用,拆端口或者同一个端口也可以用,就是在反流量分析上面不知道效果会不会差点。 路径上面用什么东西转发也可以,管他 NGINX 还是 caddy,管他 cf 还是 cft,只要转发路径指向的最后一个目标都是同一个用了 XHTTP 传输的入站就可以。

反流量分析肯定差,这本身就类似于tor,如果只有一台小鸡,那么用这个简直是脱裤子放屁

areyouokhaha commented 3 weeks ago

gfw:凭尔几路来,吾只一路去

emeryve commented 3 weeks ago

Just make L3 splitter-out / joiner-in. Packets from all app connections must be (weighted)-randomly distributed between reality/cdn/ss/any-proxy connections, then sent to one place to be organized back in sequence to then send them to freedom.

image

Each proxy connection will have actually random payload with no other characteristic. Also if censor will try to precisely slow down or limit each proxy connection then it's not a big deal because your internet speed have already been split between proxy connections by load balancing effect from random splitting.

Alceatraz commented 3 weeks ago

这东西怎么配置不用我写了吧,~我还等着你们写呢~ @chika0801

这回是真看不懂了 大脑烧了🤣

TheLordOfTheKings commented 3 weeks ago

Quick question here, when we use Reality with XHTTP (like OP) then there is no CDN support, right?

52709394 commented 3 weeks ago

大佬,我想问,v2rayN 如何 使用 XHTTP-H2-REALITY 和 XHTTP-H2-TLS ?在 network 选择 http 还 SplitHTTP 订阅链接 type=什么 xhttp? http? splithttp?

yuhan6665 commented 1 week ago

@RPRX 例子里面的服务端能否简化为?

    "inbounds": [
        {
            "listen": "0.0.0.0",
            "port": “443,8443”,
            "protocol": "vless",
            "settings": {
                "decryption": "none",
                "clients": [
                    {
                        "id": "" // your uuid
                    }
                ]
            },
            "streamSettings": {
                "network": "xhttp",
                "xhttpSettings": {
                    "path": "/yourpath"
                }
                "security": "reality",
                "realitySettings": {
                    "target": "example.com:443",
                    "serverNames": [
                        "example.com"
                    ],
                    "privateKey": "", // private key A
                    "shortIds": [
                        ""
                    ]
                }
            }
        }
    ]
Fangliding commented 1 week ago

我觉得演示它可以拆开的属性重要一点 比如使用两个不同的dest

RPRX commented 1 week ago

@RPRX 例子里面的服务端能否简化为?

需要体现出是两套公私钥和 fallbacks,不适合简化

yuhan6665 commented 1 week ago

本来我想的是 如果不靠 CDN 上行下行分别走 ipv4 ipv6 (不同线路)或者一个tcp(H2)一个UDP(H3)(不同审查系统)就足够好了

RPRX commented 1 week ago

To cargoo:并非严格的“只发不收”或“只收不发”,比如分离上行仍有 HTTP response,分离下行仍有 HTTP request,还有心跳包等

RPRX commented 1 week ago

本来我想的是 如果不靠 CDN 上行下行分别走 ipv4 ipv6 (不同线路)或者一个tcp(H2)一个UDP(H3)(不同审查系统)就足够好了

那甚至不需要分端口,服务端几乎不用改,只改客户端配置就行