Skip to content

Commit

Permalink
add support for uot on hysteria2
Browse files Browse the repository at this point in the history
  • Loading branch information
Mahdi-zarei committed Dec 5, 2023
1 parent e839711 commit ec84ce0
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 16 deletions.
10 changes: 10 additions & 0 deletions docs/configuration/outbound/hysteria2.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
},
"password": "goofy_ahh_password",
"network": "tcp",
"udp_over_stream": false,
"tls": {},
"brutal_debug": false,

Expand Down Expand Up @@ -72,6 +73,15 @@ One of `tcp` `udp`.

Both is enabled by default.

#### udp_over_stream

This is the Hysteria2 port of the [UDP over TCP protocol](/configuration/shared/udp-over-tcp), designed to provide a QUIC
stream based UDP relay mode that Hysteria2 does not provide. Since it is an add-on protocol, you will need to use sing-box or
another program compatible with the protocol as a server.

This mode can improve reliability in proxying UDP traffic in lossy networks, as it supports retransmitting lost packets using
QUIC's loss detection mechanisms.

#### tls

==Required==
Expand Down
3 changes: 2 additions & 1 deletion inbound/hysteria2.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package inbound

import (
"context"
"github.com/sagernet/sing-box/common/uot"
"net"
"net/http"
"net/http/httputil"
Expand Down Expand Up @@ -80,7 +81,7 @@ func NewHysteria2(ctx context.Context, router adapter.Router, logger log.Context
protocol: C.TypeHysteria2,
network: []string{N.NetworkUDP},
ctx: ctx,
router: router,
router: uot.NewRouter(router, logger),
logger: logger,
tag: tag,
listenOptions: options.ListenOptions,
Expand Down
15 changes: 8 additions & 7 deletions option/hysteria2.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@ type Hysteria2User struct {
type Hysteria2OutboundOptions struct {
DialerOptions
ServerOptions
UpMbps int `json:"up_mbps,omitempty"`
DownMbps int `json:"down_mbps,omitempty"`
Obfs *Hysteria2Obfs `json:"obfs,omitempty"`
Password string `json:"password,omitempty"`
Network NetworkList `json:"network,omitempty"`
TLS *OutboundTLSOptions `json:"tls,omitempty"`
BrutalDebug bool `json:"brutal_debug,omitempty"`
UpMbps int `json:"up_mbps,omitempty"`
DownMbps int `json:"down_mbps,omitempty"`
Obfs *Hysteria2Obfs `json:"obfs,omitempty"`
Password string `json:"password,omitempty"`
Network NetworkList `json:"network,omitempty"`
TLS *OutboundTLSOptions `json:"tls,omitempty"`
UDPOverStream bool `json:"udp_over_stream,omitempty"`
BrutalDebug bool `json:"brutal_debug,omitempty"`
}
43 changes: 35 additions & 8 deletions outbound/hysteria2.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package outbound

import (
"context"
"github.com/sagernet/sing/common/uot"
"net"
"os"

Expand All @@ -29,7 +30,8 @@ var (

type Hysteria2 struct {
myOutboundAdapter
client *hysteria2.Client
client *hysteria2.Client
udpStream bool
}

func NewHysteria2(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.Hysteria2OutboundOptions) (*Hysteria2, error) {
Expand Down Expand Up @@ -83,7 +85,8 @@ func NewHysteria2(ctx context.Context, router adapter.Router, logger log.Context
tag: tag,
dependencies: withDialerDependency(options.DialerOptions),
},
client: client,
client: client,
udpStream: options.UDPOverStream,
}, nil
}

Expand All @@ -93,19 +96,43 @@ func (h *Hysteria2) DialContext(ctx context.Context, network string, destination
h.logger.InfoContext(ctx, "outbound connection to ", destination)
return h.client.DialConn(ctx, destination)
case N.NetworkUDP:
conn, err := h.ListenPacket(ctx, destination)
if err != nil {
return nil, err
if h.udpStream {
h.logger.InfoContext(ctx, "outbound stream packet connection to ", destination)
streamConn, err := h.client.DialConn(ctx, uot.RequestDestination(uot.Version))
if err != nil {
return nil, err
}
return uot.NewLazyConn(streamConn, uot.Request{
IsConnect: true,
Destination: destination,
}), nil
} else {
conn, err := h.ListenPacket(ctx, destination)
if err != nil {
return nil, err
}
return bufio.NewBindPacketConn(conn, destination), nil
}
return bufio.NewBindPacketConn(conn, destination), nil
default:
return nil, E.New("unsupported network: ", network)
}
}

func (h *Hysteria2) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
h.logger.InfoContext(ctx, "outbound packet connection to ", destination)
return h.client.ListenPacket(ctx)
if h.udpStream {
h.logger.InfoContext(ctx, "outbound stream packet connection to ", destination)
streamConn, err := h.client.DialConn(ctx, uot.RequestDestination(uot.Version))
if err != nil {
return nil, err
}
return uot.NewLazyConn(streamConn, uot.Request{
IsConnect: false,
Destination: destination,
}), nil
} else {
h.logger.InfoContext(ctx, "outbound packet connection to ", destination)
return h.client.ListenPacket(ctx)
}
}

func (h *Hysteria2) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
Expand Down

0 comments on commit ec84ce0

Please sign in to comment.