sing-box/protocol/hysteria2/outbound.go

118 lines
3.6 KiB
Go
Raw Permalink Normal View History

2024-11-01 16:39:02 +00:00
package hysteria2
2023-08-31 12:07:32 +00:00
import (
"context"
"net"
"os"
"github.com/sagernet/sing-box/adapter"
2024-11-01 16:39:02 +00:00
"github.com/sagernet/sing-box/adapter/outbound"
2023-08-31 12:07:32 +00:00
"github.com/sagernet/sing-box/common/dialer"
"github.com/sagernet/sing-box/common/tls"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
2024-11-01 16:39:02 +00:00
"github.com/sagernet/sing-box/protocol/tuic"
"github.com/sagernet/sing-quic/hysteria"
"github.com/sagernet/sing-quic/hysteria2"
2023-08-31 12:07:32 +00:00
"github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/bufio"
E "github.com/sagernet/sing/common/exceptions"
2024-11-01 16:39:02 +00:00
"github.com/sagernet/sing/common/logger"
2023-08-31 12:07:32 +00:00
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
)
2024-11-01 16:39:02 +00:00
func RegisterOutbound(registry *outbound.Registry) {
outbound.Register[option.Hysteria2OutboundOptions](registry, C.TypeHysteria2, NewOutbound)
}
2023-08-31 12:07:32 +00:00
var (
2024-11-01 16:39:02 +00:00
_ adapter.Outbound = (*tuic.Outbound)(nil)
_ adapter.InterfaceUpdateListener = (*tuic.Outbound)(nil)
2023-08-31 12:07:32 +00:00
)
2024-11-01 16:39:02 +00:00
type Outbound struct {
outbound.Adapter
logger logger.ContextLogger
2023-08-31 12:07:32 +00:00
client *hysteria2.Client
}
2024-11-01 16:39:02 +00:00
func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.Hysteria2OutboundOptions) (adapter.Outbound, error) {
2023-08-31 12:07:32 +00:00
options.UDPFragmentDefault = true
if options.TLS == nil || !options.TLS.Enabled {
return nil, C.ErrTLSRequired
}
tlsConfig, err := tls.NewClient(ctx, options.Server, common.PtrValueOrDefault(options.TLS))
if err != nil {
return nil, err
}
var salamanderPassword string
if options.Obfs != nil {
if options.Obfs.Password == "" {
return nil, E.New("missing obfs password")
}
switch options.Obfs.Type {
case hysteria2.ObfsTypeSalamander:
salamanderPassword = options.Obfs.Password
default:
return nil, E.New("unknown obfs type: ", options.Obfs.Type)
}
}
outboundDialer, err := dialer.New(ctx, options.DialerOptions)
2023-08-31 12:07:32 +00:00
if err != nil {
return nil, err
}
networkList := options.Network.Build()
client, err := hysteria2.NewClient(hysteria2.ClientOptions{
Context: ctx,
Dialer: outboundDialer,
2023-10-21 04:00:00 +00:00
Logger: logger,
BrutalDebug: options.BrutalDebug,
2023-08-31 12:07:32 +00:00
ServerAddress: options.ServerOptions.Build(),
2023-09-16 16:25:53 +00:00
SendBPS: uint64(options.UpMbps * hysteria.MbpsToBps),
ReceiveBPS: uint64(options.DownMbps * hysteria.MbpsToBps),
2023-08-31 12:07:32 +00:00
SalamanderPassword: salamanderPassword,
Password: options.Password,
TLSConfig: tlsConfig,
UDPDisabled: !common.Contains(networkList, N.NetworkUDP),
})
if err != nil {
return nil, err
}
2024-11-01 16:39:02 +00:00
return &Outbound{
Adapter: outbound.NewAdapterWithDialerOptions(C.TypeHysteria2, networkList, tag, options.DialerOptions),
logger: logger,
client: client,
2023-08-31 12:07:32 +00:00
}, nil
}
2024-11-01 16:39:02 +00:00
func (h *Outbound) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
2023-08-31 12:07:32 +00:00
switch N.NetworkName(network) {
case N.NetworkTCP:
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
}
return bufio.NewBindPacketConn(conn, destination), nil
default:
return nil, E.New("unsupported network: ", network)
}
}
2024-11-01 16:39:02 +00:00
func (h *Outbound) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
2023-08-31 12:07:32 +00:00
h.logger.InfoContext(ctx, "outbound packet connection to ", destination)
return h.client.ListenPacket(ctx)
}
2024-11-01 16:39:02 +00:00
func (h *Outbound) InterfaceUpdated() {
2024-07-07 07:45:50 +00:00
h.client.CloseWithError(E.New("network changed"))
2023-08-31 12:07:32 +00:00
}
2024-11-01 16:39:02 +00:00
func (h *Outbound) Close() error {
2023-08-31 12:07:32 +00:00
return h.client.CloseWithError(os.ErrClosed)
}