v2ray-core
v2ray-core copied to clipboard
Add Hysteria2 Protocol
Use hysteria's quic-go to support BBR and brutal congestion algorithm
Same as hysteria, BBR
and Brutal
congestion algorithm can improve performance.
Usage:
-
send_mbps
is needed when congestion'stype
isbrutal
, meaning the max bandwidth of current network can use to send.
{
"transport":"quic",
"transportSettings":{
"congestion": {"type":"brutal", "send_mbps": 200}
},
"security":"tls",
"securitySettings":{}
}
- If user don't know how to config
brutal
, it's just ok to usebbr
in both client and server side.
{
"transport":"quic",
"transportSettings":{
"congestion": {"type":"bbr"}
},
"security":"tls",
"securitySettings":{}
}
Fix vprotogen
bug and update all Protobuf data
vprotogen
can not work, because it failed to recognize new version of protoc
, so that we can not add new feature to v2ray.
Update go version to 1.21
fix #2701 #2644
Codecov Report
Attention: 1048 lines
in your changes are missing coverage. Please review.
Comparison is base (
cb84b28
) 37.79% compared to head (0b7f037
) 36.78%. Report is 5 commits behind head on master.
:exclamation: Your organization needs to install the Codecov GitHub app to enable full functionality.
Additional details and impacted files
@@ Coverage Diff @@
## master #2721 +/- ##
==========================================
- Coverage 37.79% 36.78% -1.01%
==========================================
Files 654 664 +10
Lines 38723 39771 +1048
==========================================
- Hits 14636 14631 -5
- Misses 22477 23524 +1047
- Partials 1610 1616 +6
Files | Coverage Δ | |
---|---|---|
app/dns/nameserver_quic.go | 70.94% <ø> (ø) |
|
common/protocol/quic/sniff.go | 44.87% <ø> (ø) |
|
config.pb.go | 29.34% <ø> (ø) |
|
transport/internet/quic/conn.go | 58.00% <ø> (ø) |
|
transport/internet/quic/hub.go | 75.34% <100.00%> (+2.61%) |
:arrow_up: |
...ransport/internet/quic/congestion/bbr/bandwidth.go | 0.00% <0.00%> (ø) |
|
transport/internet/quic/congestion/bbr/clock.go | 0.00% <0.00%> (ø) |
|
transport/internet/grpc/dial.go | 3.27% <0.00%> (-0.06%) |
:arrow_down: |
transport/internet/quic/congestion/utils.go | 0.00% <0.00%> (ø) |
|
transport/internet/quic/dialer.go | 55.72% <63.33%> (-2.40%) |
:arrow_down: |
... and 8 more |
:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.
I had merged newest commit and fixed go-lint.
Hi! Thanks for your contribution. Since this merge request includes switching the dependency, it will be a longer review process, however I will try my best to expatiate the process.
Hi, after some interal discuss, it seems there is no active maintainer within V2Ray could take over the maintaince of hysteria transport. Is it possible for you to refactor this code, so that the original quic transport is left as is, and make the necessary change to make hysteria a new transport that can be disabled when something goes wrong by removing the import line in https://github.com/v2fly/v2ray-core/blob/master/main/distro/all/all.go
.
I am happy to merge it after the usage of forked quic from hysteria is isolated from main quic.
I am happy to merge it after the usage of forked quic from hysteria is isolated from main quic.
Thanks. I will dig into it later. But I have been very busy lately, and I may reply very late. Anyway, I will try my best.
Hi, I tried to add a QUIC-based HTTP3 tranpsort which required by Hysteria, and it works. I use the code from here. So it's possible to add Hysteria proxy protocol to V2ray. I can take responsibility for maintenance if you want.
Assumed configuration:
- Compatible with the original hy2
{
"tag": "demo1",
"protocol": "hysteria2",
"settings": {},
"streamSettings": {
"transport": "hysteria2",
"transportSettings": {
"congestion": {
"type": "brutal",
"download_mbps": 200,
"upload_mbps": 200,
"password": "password"
}
},
"security": "tls",
"securitySettings": {}
}
}
- As a transport layer.
{
"tag": "demo2",
"protocol": "vmess",
"settings": {},
"streamSettings": {
"transport": "hysteria2",
"transportSettings": {
"congestion": {
"type": "bbr",
"password": "" // empty means no password.
}
},
"security": "tls",
"securitySettings": {}
}
}
What do you think? @xiaokangwang
Hi, I tried to add a QUIC-based HTTP3 tranpsort which required by Hysteria, and it works. I use the code from here. So it's possible to add Hysteria proxy protocol to V2ray. I can take responsibility for maintenance if you want.
Assumed configuration:
1. Compatible with the original hy2
{ "tag": "demo1", "protocol": "hysteria2", "settings": {}, "streamSettings": { "transport": "hysteria2", "transportSettings": { "congestion": { "type": "brutal", "download_mbps": 200, "upload_mbps": 200, "password": "password" } }, "security": "tls", "securitySettings": {} } }
2. As a transport layer.
{ "tag": "demo2", "protocol": "vmess", "settings": {}, "streamSettings": { "transport": "hysteria2", "transportSettings": { "congestion": { "type": "bbr", "password": "" // empty means no password. } }, "security": "tls", "securitySettings": {} } }
What do you think? @xiaokangwang
I think it should be fine so long it can be selectively compiled and don't interference with existing quic related features. This means it is expected that existing code rely on quic like dns or quic transports are not impacted by this change. So long as this requirement is satisfied, I am happy to merge it so long as there is someone ready to maintain Hysteria stack in the future.
Hi, I tried to add a QUIC-based HTTP3 tranpsort which required by Hysteria, and it works. I use the code from here. So it's possible to add Hysteria proxy protocol to V2ray. I can take responsibility for maintenance if you want. Assumed configuration:
1. Compatible with the original hy2
{ "tag": "demo1", "protocol": "hysteria2", "settings": {}, "streamSettings": { "transport": "hysteria2", "transportSettings": { "congestion": { "type": "brutal", "download_mbps": 200, "upload_mbps": 200, "password": "password" } }, "security": "tls", "securitySettings": {} } }
2. As a transport layer.
{ "tag": "demo2", "protocol": "vmess", "settings": {}, "streamSettings": { "transport": "hysteria2", "transportSettings": { "congestion": { "type": "bbr", "password": "" // empty means no password. } }, "security": "tls", "securitySettings": {} } }
What do you think? @xiaokangwang
I think it should be fine so long it can be selectively compiled and don't interference with existing quic related features. This means it is expected that existing code rely on quic like dns or quic transports are not impacted by this change. So long as this requirement is satisfied, I am happy to merge it so long as there is someone ready to maintain Hysteria stack in the future.
Thanks. I think make it separately and will not affect others existing features.
Hi, packages like dns, common/protocol are still depended on newly introduced package. Could you have a look and make sure the hy2 fork of quic is not used outside its own transport and proxy implementaion, or justify it?
Please let me know when you are ready for another review!
Please let me know when you are ready for another review!
Thanks. Currently, I had restored to original quic-go and added a http3 transport that based on hysteria quic, supports brutal
and bbr
congestion algorithm.
I will add a hysteria2 proxy protocol in later so that it can work with the offical one.
But I am busy on my daily job, I plan to complete this PR in the Lunar New Year. I Will request another code review when I finished.
Hi @xiaokangwang,
Apologies for the delay. I'm ready for the code review.
Here's what I've accomplished:
Added Hysteria2 transport to V2ray, utilizing QUIC and HTTP3
Now, any proxy protocol in V2ray can utilize Hy2 as a transport layer, such as trojan + hysteria2
. You can review some transport tests for further details.
Implemented Hysteria2 proxy compatible with the official version
It functions well with the ordinary server I use. However, UDP requires additional testing. You can also examine some proxy tests for more insight.
Provided some real configuration examples
I'm uncertain about the appropriate location for these examples. They're mainly for testing purposes, so they might be subject to change.
Added documentation
For more detailed information, including special features, you can refer to the documentation.
Can you let hy2 transport's client use v2ray system dialer? I think implementing a custom ConnFactory
with v2ray's function (internet.ListenSystemPacket
or internet.DialSystem
) is enough.
Can you let hy2 transport's client use v2ray system dialer? I think implementing a custom
ConnFactory
with v2ray's function (internet.ListenSystemPacket
orinternet.DialSystem
) is enough.
I don't really get you, please elaborate it. In my opinion, this PR will not use "net.ListenUDP()" in JimmyHuang454/hysteria, it will hijack all traffic into v2ray.
Android clients may use internet.UseAlternativeSystemDialer
to replace v2ray system dialer (internet.DialSystem
) to protect socket and prevent VPN traffic loopback. Currently hy2 does not comply with this.
~~(Nevermind I found QUIC transport doesn't comply with this too, see #1510. V2Ray just lacks a similar API for PacketConn. Maybe ignore this for now...)~~ QUIC transport uses internet.ListenSystemPacket
instead. It seems that internet.ListenSystemPacket
can be protected by internet.RegisterListenerController
.
I mean something like the below.
(I don't know why context.Background()
is used here, just copy from QUIC code as is.)
--- a/transport/internet/hysteria2/dialer.go
+++ b/transport/internet/hysteria2/dialer.go
@@ -52,6 +52,14 @@ func InitAddress(dest net.Destination) (net.Addr, error) {
return destAddr, nil
}
+type connFactory struct {
+ NewFunc func(addr net.Addr) (net.PacketConn, error)
+}
+
+func (f *connFactory) New(addr net.Addr) (net.PacketConn, error) {
+ return f.NewFunc(addr)
+}
+
func NewHyClient(dest net.Destination, streamSettings *internet.MemoryStreamConfig) (hy_client.Client, error) {
tlsConfig, err := InitTLSConifg(streamSettings)
if err != nil {
@@ -68,6 +76,18 @@ func NewHyClient(dest net.Destination, streamSettings *internet.MemoryStreamConf
TLSConfig: *tlsConfig,
Auth: config.GetPassword(),
ServerAddr: serverAddr,
+ ConnFactory: &connFactory{
+ NewFunc: func(addr net.Addr) (net.PacketConn, error) {
+ rawConn, err := internet.ListenSystemPacket(context.Background(), &net.UDPAddr{
+ IP: []byte{0, 0, 0, 0},
+ Port: 0,
+ }, streamSettings.SocketSettings)
+ if err != nil {
+ return nil, err
+ }
+ return rawConn.(*net.UDPConn), nil
+ },
+ },
})
if err != nil {
return nil, err
Android clients may use
internet.UseAlternativeSystemDialer
to replace v2ray system dialer (internet.DialSystem
) to protect socket and prevent VPN traffic loopback. Currently hy2 does not comply with this. ~(Nevermind I found QUIC transport doesn't comply with this too, see #1510. V2Ray just lacks a similar API for PacketConn. Maybe ignore this for now...)~ QUIC transport usesinternet.ListenSystemPacket
instead. It seems thatinternet.ListenSystemPacket
can be protected byinternet.RegisterListenerController
.I mean something like the below.
Thanks, you are right. I forgot to handle that on the client side.
建议保留brutal作为quic的一种流控算法选择,不必考虑它与hysteria的兼容性,反正hysteria已经被作为新的协议和传输层实现了。多一种选择不是坏事。
A lock is needed for RunningClient map[net.Destination](hyClient.Client)
(like those in quic
, grpc
and http
). I encountered some concurrent map writes
panics.
By the way, identifying clients only by net.Destination
is not enough. This will cause multiple outbounds with the same destination but different streamSettings using a wrong dialer. This is a common issue for quic
, grpc
and http
, not only this PR's hysteria
though.
A lock is needed for
RunningClient map[net.Destination](hyClient.Client)
(like those inquic
,grpc
andhttp
). I encountered someconcurrent map writes
panics.
Ofcourse.
By the way, identifying clients only by
net.Destination
is not enough. This will cause multiple outbounds with the same destination but different streamSettings using a wrong dialer. This is a common issue forquic
,grpc
andhttp
, not only this PR'shysteria
though.
I have switched to using IP addresses to differentiate between different outbound connections. At the moment, it is indeed difficult to reuse a single port for multiple inbound connections.
Hi, I found that the values of congestion type
, up_mbps
and down_mbps
are never used, so in fact it is always BBR no Brutal?
Hi, I found that the values of congestion
type
,up_mbps
anddown_mbps
are never used, so in fact it is always BBR no Brutal?
My bad. Use the Brutal congestion algorithm when both up_mbps
and down_mbps
are not zero.
Is that Mbps or MBps? The multiplier should be 1000*1000/8 not 1000*1000. Hysteria's case-insensitive conversation is confusing...
https://github.com/apernet/hysteria/blob/b563f3981fc63eadb6710f50eecb92922b8ae1ce/app/cmd/client.go#L317
https://github.com/apernet/hysteria/blob/master/app/internal/utils/bpsconv.go#L10-L53
Is that Mbps or MBps? The multiplier should be 10001000/8 not 10001000. Hysteria's case-insensitive conversation is confusing...
https://github.com/apernet/hysteria/blob/b563f3981fc63eadb6710f50eecb92922b8ae1ce/app/cmd/client.go#L317
https://github.com/apernet/hysteria/blob/master/app/internal/utils/bpsconv.go#L10-L53
My bad again. It should be 1000*1000/8
.
Hi! Is this merge request ready for another review?