Skip to content

Commit

Permalink
Migrate multiplex and UoT server to inbound & Add tcp-brutal support …
Browse files Browse the repository at this point in the history
…for multiplex
  • Loading branch information
nekohasekai committed Nov 24, 2023
1 parent c9aa599 commit 615e93b
Show file tree
Hide file tree
Showing 65 changed files with 997 additions and 176 deletions.
104 changes: 104 additions & 0 deletions adapter/conn_router.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package adapter

import (
"context"
"net"

"github.com/sagernet/sing/common/logger"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
)

type ConnectionRouter interface {
RouteConnection(ctx context.Context, conn net.Conn, metadata InboundContext) error
RoutePacketConnection(ctx context.Context, conn N.PacketConn, metadata InboundContext) error
}

func NewRouteHandler(
metadata InboundContext,
router ConnectionRouter,
logger logger.ContextLogger,
) UpstreamHandlerAdapter {
return &routeHandlerWrapper{
metadata: metadata,
router: router,
logger: logger,
}
}

func NewRouteContextHandler(
router ConnectionRouter,
logger logger.ContextLogger,
) UpstreamHandlerAdapter {
return &routeContextHandlerWrapper{
router: router,
logger: logger,
}
}

var _ UpstreamHandlerAdapter = (*routeHandlerWrapper)(nil)

type routeHandlerWrapper struct {
metadata InboundContext
router ConnectionRouter
logger logger.ContextLogger
}

func (w *routeHandlerWrapper) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error {
myMetadata := w.metadata
if metadata.Source.IsValid() {
myMetadata.Source = metadata.Source
}
if metadata.Destination.IsValid() {
myMetadata.Destination = metadata.Destination
}
return w.router.RouteConnection(ctx, conn, myMetadata)
}

func (w *routeHandlerWrapper) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
myMetadata := w.metadata
if metadata.Source.IsValid() {
myMetadata.Source = metadata.Source
}
if metadata.Destination.IsValid() {
myMetadata.Destination = metadata.Destination
}
return w.router.RoutePacketConnection(ctx, conn, myMetadata)
}

func (w *routeHandlerWrapper) NewError(ctx context.Context, err error) {
w.logger.ErrorContext(ctx, err)
}

var _ UpstreamHandlerAdapter = (*routeContextHandlerWrapper)(nil)

type routeContextHandlerWrapper struct {
router ConnectionRouter
logger logger.ContextLogger
}

func (w *routeContextHandlerWrapper) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error {
myMetadata := ContextFrom(ctx)
if metadata.Source.IsValid() {
myMetadata.Source = metadata.Source
}
if metadata.Destination.IsValid() {
myMetadata.Destination = metadata.Destination
}
return w.router.RouteConnection(ctx, conn, *myMetadata)
}

func (w *routeContextHandlerWrapper) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
myMetadata := ContextFrom(ctx)
if metadata.Source.IsValid() {
myMetadata.Source = metadata.Source
}
if metadata.Destination.IsValid() {
myMetadata.Destination = metadata.Destination
}
return w.router.RoutePacketConnection(ctx, conn, *myMetadata)
}

func (w *routeContextHandlerWrapper) NewError(ctx context.Context, err error) {
w.logger.ErrorContext(ctx, err)
}
5 changes: 1 addition & 4 deletions adapter/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,12 @@ package adapter

import (
"context"
"net"
"net/netip"

"github.com/sagernet/sing-box/common/geoip"
"github.com/sagernet/sing-dns"
"github.com/sagernet/sing-tun"
"github.com/sagernet/sing/common/control"
N "github.com/sagernet/sing/common/network"
"github.com/sagernet/sing/service"

mdns "github.com/miekg/dns"
Expand All @@ -24,8 +22,7 @@ type Router interface {

FakeIPStore() FakeIPStore

RouteConnection(ctx context.Context, conn net.Conn, metadata InboundContext) error
RoutePacketConnection(ctx context.Context, conn N.PacketConn, metadata InboundContext) error
ConnectionRouter

GeoIPReader() *geoip.Reader
LoadGeosite(code string) (Rule, error)
Expand Down
23 changes: 22 additions & 1 deletion common/mux/client.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,42 @@
package mux

import (
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing-mux"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/logger"
N "github.com/sagernet/sing/common/network"
)

func NewClientWithOptions(dialer N.Dialer, options option.MultiplexOptions) (*Client, error) {
type Client = mux.Client

func NewClientWithOptions(dialer N.Dialer, logger logger.Logger, options option.OutboundMultiplexOptions) (*Client, error) {
if !options.Enabled {
return nil, nil
}
var brutalOptions mux.BrutalOptions
if options.Brutal != nil && options.Brutal.Enabled {
brutalOptions = mux.BrutalOptions{
Enabled: true,
SendBPS: uint64(options.Brutal.UpMbps * C.MbpsToBps),
ReceiveBPS: uint64(options.Brutal.DownMbps * C.MbpsToBps),
}
if brutalOptions.SendBPS < mux.BrutalMinSpeedBPS {
return nil, E.New("brutal: invalid upload speed")
}
if brutalOptions.ReceiveBPS < mux.BrutalMinSpeedBPS {
return nil, E.New("brutal: invalid download speed")
}
}
return mux.NewClient(mux.Options{
Dialer: dialer,
Logger: logger,
Protocol: options.Protocol,
MaxConnections: options.MaxConnections,
MinStreams: options.MinStreams,
MaxStreams: options.MaxStreams,
Padding: options.Padding,
Brutal: brutalOptions,
})
}
14 changes: 0 additions & 14 deletions common/mux/protocol.go

This file was deleted.

65 changes: 65 additions & 0 deletions common/mux/router.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package mux

import (
"context"
"net"

"github.com/sagernet/sing-box/adapter"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing-mux"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/logger"
N "github.com/sagernet/sing/common/network"
)

type Router struct {
router adapter.ConnectionRouter
service *mux.Service
}

func NewRouterWithOptions(router adapter.ConnectionRouter, logger logger.ContextLogger, options option.InboundMultiplexOptions) (adapter.ConnectionRouter, error) {
if !options.Enabled {
return router, nil
}
var brutalOptions mux.BrutalOptions
if options.Brutal != nil && options.Brutal.Enabled {
brutalOptions = mux.BrutalOptions{
Enabled: true,
SendBPS: uint64(options.Brutal.UpMbps * C.MbpsToBps),
ReceiveBPS: uint64(options.Brutal.DownMbps * C.MbpsToBps),
}
if brutalOptions.SendBPS < mux.BrutalMinSpeedBPS {
return nil, E.New("brutal: invalid upload speed")
}
if brutalOptions.ReceiveBPS < mux.BrutalMinSpeedBPS {
return nil, E.New("brutal: invalid download speed")
}
}
service, err := mux.NewService(mux.ServiceOptions{
NewStreamContext: func(ctx context.Context, conn net.Conn) context.Context {
return log.ContextWithNewID(ctx)
},
Logger: logger,
Handler: adapter.NewRouteContextHandler(router, logger),
Padding: options.Padding,
Brutal: brutalOptions,
})
if err != nil {
return nil, err
}
return &Router{router, service}, nil
}

func (r *Router) RouteConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
if metadata.Destination == mux.Destination {
return r.service.NewConnection(adapter.WithContext(ctx, &metadata), conn, adapter.UpstreamMetadata(metadata))
} else {
return r.router.RouteConnection(ctx, conn, metadata)
}
}

func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
return r.router.RoutePacketConnection(ctx, conn, metadata)
}
32 changes: 32 additions & 0 deletions common/mux/v2ray_legacy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package mux

import (
"context"
"net"

"github.com/sagernet/sing-box/adapter"
vmess "github.com/sagernet/sing-vmess"
"github.com/sagernet/sing/common/logger"
N "github.com/sagernet/sing/common/network"
)

type V2RayLegacyRouter struct {
router adapter.ConnectionRouter
logger logger.ContextLogger
}

func NewV2RayLegacyRouter(router adapter.ConnectionRouter, logger logger.ContextLogger) adapter.ConnectionRouter {
return &V2RayLegacyRouter{router, logger}
}

func (r *V2RayLegacyRouter) RouteConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
if metadata.Destination.Fqdn == vmess.MuxDestination.Fqdn {
r.logger.InfoContext(ctx, "inbound legacy multiplex connection")
return vmess.HandleMuxConnection(ctx, conn, adapter.NewRouteHandler(metadata, r.router, r.logger))
}
return r.router.RouteConnection(ctx, conn, metadata)
}

func (r *V2RayLegacyRouter) RoutePacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
return r.router.RoutePacketConnection(ctx, conn, metadata)
}
53 changes: 53 additions & 0 deletions common/uot/router.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package uot

import (
"context"
"net"
"net/netip"

"github.com/sagernet/sing-box/adapter"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/logger"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"github.com/sagernet/sing/common/uot"
)

var _ adapter.ConnectionRouter = (*Router)(nil)

type Router struct {
router adapter.ConnectionRouter
logger logger.ContextLogger
}

func NewRouter(router adapter.ConnectionRouter, logger logger.ContextLogger) *Router {
return &Router{router, logger}
}

func (r *Router) RouteConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
switch metadata.Destination.Fqdn {
case uot.MagicAddress:
request, err := uot.ReadRequest(conn)
if err != nil {
return E.Cause(err, "read UoT request")
}
if request.IsConnect {
r.logger.InfoContext(ctx, "inbound UoT connect connection to ", request.Destination)
} else {
r.logger.InfoContext(ctx, "inbound UoT connection to ", request.Destination)
}
metadata.Domain = metadata.Destination.Fqdn
metadata.Destination = request.Destination
return r.router.RoutePacketConnection(ctx, uot.NewConn(conn, *request), metadata)
case uot.LegacyMagicAddress:
r.logger.InfoContext(ctx, "inbound legacy UoT connection")
metadata.Domain = metadata.Destination.Fqdn
metadata.Destination = M.Socksaddr{Addr: netip.IPv4Unspecified()}
return r.RoutePacketConnection(ctx, uot.NewConn(conn, uot.Request{}), metadata)
}
return r.router.RouteConnection(ctx, conn, metadata)
}

func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
return r.router.RoutePacketConnection(ctx, conn, metadata)
}
3 changes: 3 additions & 0 deletions constant/speed.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package constant

const MbpsToBps = 125000
2 changes: 1 addition & 1 deletion docs/configuration/inbound/hysteria2.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ Hysteria 用户

#### ignore_client_bandwidth

命令客户端使用 BBR 流量控制算法而不是 Hysteria CC。
命令客户端使用 BBR 拥塞控制算法而不是 Hysteria CC。

`up_mbps``down_mbps` 冲突。

Expand Down
13 changes: 10 additions & 3 deletions docs/configuration/inbound/shadowsocks.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
... // Listen Fields

"method": "2022-blake3-aes-128-gcm",
"password": "8JCsPssfgS8tiRwiMlhARg=="
"password": "8JCsPssfgS8tiRwiMlhARg==",
"multiplex": {}
}
```

Expand All @@ -23,7 +24,8 @@
"name": "sekai",
"password": "PCD2Z4o12bKUoFa3cC97Hw=="
}
]
],
"multiplex": {}
}
```

Expand All @@ -41,7 +43,8 @@
"server_port": 8080,
"password": "PCD2Z4o12bKUoFa3cC97Hw=="
}
]
],
"multiplex": {}
}
```

Expand Down Expand Up @@ -82,3 +85,7 @@ Both if empty.
| none | / |
| 2022 methods | `sing-box generate rand --base64 <Key Length>` |
| other methods | any string |

#### multiplex

See [Multiplex](/configuration/shared/multiplex#inbound) for details.
Loading

0 comments on commit 615e93b

Please sign in to comment.