Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

XHTTP: The real upload / download splitting #3955

Merged
merged 3 commits into from
Oct 31, 2024
Merged

Conversation

RPRX
Copy link
Member

@RPRX RPRX commented Oct 30, 2024

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

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

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

客户端注意:目前下行无多路复用 #3965下行 path 直接取自上行 path,所以需要一致 #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 RPRX changed the title SplitHTTP client: Add upload / download splitting SplitHTTP client: Add real upload / download splitting Oct 30, 2024
@RPRX
Copy link
Member Author

RPRX commented Oct 30, 2024

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

@junx964
Copy link

junx964 commented Oct 30, 2024

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

@RPRX
Copy link
Member Author

RPRX commented Oct 30, 2024

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

@RPRX
Copy link
Member Author

RPRX commented Oct 30, 2024

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

@RPRX
Copy link
Member Author

RPRX commented Oct 30, 2024

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

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

@kingskill
Copy link

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

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

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

@RPRX
Copy link
Member Author

RPRX commented Oct 30, 2024

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

@RPRX
Copy link
Member Author

RPRX commented Oct 30, 2024

To Lampadu Ao:你想上行移动家宽、下行联通家宽的话配置不同的 sockopt interface 就行了,这就是 #3955 (comment) 所指的

@tomxiang1
Copy link

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

@RPRX
Copy link
Member Author

RPRX commented Oct 30, 2024

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

@RPRX
Copy link
Member Author

RPRX commented Oct 30, 2024

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

@RPRX
Copy link
Member Author

RPRX commented Oct 30, 2024

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

@RPRX
Copy link
Member Author

RPRX commented Oct 30, 2024

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

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

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

@RPRX
Copy link
Member Author

RPRX commented Oct 31, 2024

@dragonbreath2000 需要把这样的能力加给 VLESS,#3816 (comment) 有提到,但 SplitHTTP 的兼容性特别强,直连、过 CDN 都能用,且现在只有 TLS 类、QUIC 类能过墙,所以 SplitHTTP 事实上已经覆盖了所有过墙场景,再加给 VLESS 的好处有限

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

@tomxiang1
Copy link

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

@RPRX
Copy link
Member Author

RPRX commented Oct 31, 2024

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

@tomxiang1
Copy link

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

@RPRX
Copy link
Member Author

RPRX commented Oct 31, 2024

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

@RPRX RPRX changed the title SplitHTTP client: Add real upload / download splitting XHTTP: The real upload / download splitting Oct 31, 2024
@RPRX RPRX force-pushed the upload-download-splitting branch from aff354a to 5540b7a Compare October 31, 2024 06:44
@RPRX
Copy link
Member Author

RPRX commented Oct 31, 2024

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

@RPRX RPRX merged commit b30e05d into main Oct 31, 2024
36 checks passed
@qwerttvv
Copy link

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

@MiniKoro
Copy link

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

@dfldylan
Copy link

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

@RPRX
Copy link
Member Author

RPRX commented Oct 31, 2024

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

@egg1234
Copy link

egg1234 commented Oct 31, 2024

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

谢谢!

@liushengqi000
Copy link

liushengqi000 commented Nov 1, 2024

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

@liushengqi000
Copy link

liushengqi000 commented Nov 1, 2024

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

@zzlinwq
Copy link

zzlinwq commented Nov 1, 2024

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

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

@zzlinwq
Copy link

zzlinwq commented Nov 1, 2024

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

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

@KobeArthurScofield
Copy link
Contributor

试用后稳定吗?

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

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

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

@areyouokhaha
Copy link

areyouokhaha commented Nov 2, 2024

试用后稳定吗?

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

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

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

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

@areyouokhaha
Copy link

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

@emeryve
Copy link

emeryve commented Nov 2, 2024

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.

@RPRX RPRX deleted the upload-download-splitting branch November 3, 2024 05:51
@Alceatraz
Copy link

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

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

@TheLordOfTheKings
Copy link

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

@52709394
Copy link

52709394 commented Nov 8, 2024

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

@yuhan6665
Copy link
Member

@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
Copy link
Member

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

@RPRX
Copy link
Member Author

RPRX commented Nov 18, 2024

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

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

@yuhan6665
Copy link
Member

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

@RPRX
Copy link
Member Author

RPRX commented Nov 18, 2024

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

@RPRX
Copy link
Member Author

RPRX commented Nov 18, 2024

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

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

@TheLordOfTheKings
Copy link

Hi @RPRX,
Can you post an example of XHTTP-H3-CDN UPLINK combined with XHTTP-H2-REALITY DOWNLINK ?
Thanks a lot.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.