mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-16 04:32:21 +08:00
Migrate multiplex and UoT server to inbound & Add tcp-brutal support for multiplex
This commit is contained in:
parent
6d24be23da
commit
1b71e52e90
104
adapter/conn_router.go
Normal file
104
adapter/conn_router.go
Normal file
|
@ -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)
|
||||||
|
}
|
|
@ -2,14 +2,12 @@ package adapter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net"
|
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/common/geoip"
|
"github.com/sagernet/sing-box/common/geoip"
|
||||||
"github.com/sagernet/sing-dns"
|
"github.com/sagernet/sing-dns"
|
||||||
"github.com/sagernet/sing-tun"
|
"github.com/sagernet/sing-tun"
|
||||||
"github.com/sagernet/sing/common/control"
|
"github.com/sagernet/sing/common/control"
|
||||||
N "github.com/sagernet/sing/common/network"
|
|
||||||
"github.com/sagernet/sing/service"
|
"github.com/sagernet/sing/service"
|
||||||
|
|
||||||
mdns "github.com/miekg/dns"
|
mdns "github.com/miekg/dns"
|
||||||
|
@ -24,8 +22,7 @@ type Router interface {
|
||||||
|
|
||||||
FakeIPStore() FakeIPStore
|
FakeIPStore() FakeIPStore
|
||||||
|
|
||||||
RouteConnection(ctx context.Context, conn net.Conn, metadata InboundContext) error
|
ConnectionRouter
|
||||||
RoutePacketConnection(ctx context.Context, conn N.PacketConn, metadata InboundContext) error
|
|
||||||
|
|
||||||
GeoIPReader() *geoip.Reader
|
GeoIPReader() *geoip.Reader
|
||||||
LoadGeosite(code string) (Rule, error)
|
LoadGeosite(code string) (Rule, error)
|
||||||
|
|
|
@ -1,21 +1,42 @@
|
||||||
package mux
|
package mux
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
"github.com/sagernet/sing-mux"
|
"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"
|
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 {
|
if !options.Enabled {
|
||||||
return nil, nil
|
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{
|
return mux.NewClient(mux.Options{
|
||||||
Dialer: dialer,
|
Dialer: dialer,
|
||||||
|
Logger: logger,
|
||||||
Protocol: options.Protocol,
|
Protocol: options.Protocol,
|
||||||
MaxConnections: options.MaxConnections,
|
MaxConnections: options.MaxConnections,
|
||||||
MinStreams: options.MinStreams,
|
MinStreams: options.MinStreams,
|
||||||
MaxStreams: options.MaxStreams,
|
MaxStreams: options.MaxStreams,
|
||||||
Padding: options.Padding,
|
Padding: options.Padding,
|
||||||
|
Brutal: brutalOptions,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
package mux
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/sagernet/sing-mux"
|
|
||||||
)
|
|
||||||
|
|
||||||
type (
|
|
||||||
Client = mux.Client
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
Destination = mux.Destination
|
|
||||||
HandleConnection = mux.HandleConnection
|
|
||||||
)
|
|
65
common/mux/router.go
Normal file
65
common/mux/router.go
Normal file
|
@ -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
common/mux/v2ray_legacy.go
Normal file
32
common/mux/v2ray_legacy.go
Normal file
|
@ -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
common/uot/router.go
Normal file
53
common/uot/router.go
Normal file
|
@ -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
constant/speed.go
Normal file
3
constant/speed.go
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
package constant
|
||||||
|
|
||||||
|
const MbpsToBps = 125000
|
|
@ -62,7 +62,7 @@ Hysteria 用户
|
||||||
|
|
||||||
#### ignore_client_bandwidth
|
#### ignore_client_bandwidth
|
||||||
|
|
||||||
命令客户端使用 BBR 流量控制算法而不是 Hysteria CC。
|
命令客户端使用 BBR 拥塞控制算法而不是 Hysteria CC。
|
||||||
|
|
||||||
与 `up_mbps` 和 `down_mbps` 冲突。
|
与 `up_mbps` 和 `down_mbps` 冲突。
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,8 @@
|
||||||
... // Listen Fields
|
... // Listen Fields
|
||||||
|
|
||||||
"method": "2022-blake3-aes-128-gcm",
|
"method": "2022-blake3-aes-128-gcm",
|
||||||
"password": "8JCsPssfgS8tiRwiMlhARg=="
|
"password": "8JCsPssfgS8tiRwiMlhARg==",
|
||||||
|
"multiplex": {}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -23,7 +24,8 @@
|
||||||
"name": "sekai",
|
"name": "sekai",
|
||||||
"password": "PCD2Z4o12bKUoFa3cC97Hw=="
|
"password": "PCD2Z4o12bKUoFa3cC97Hw=="
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"multiplex": {}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -41,7 +43,8 @@
|
||||||
"server_port": 8080,
|
"server_port": 8080,
|
||||||
"password": "PCD2Z4o12bKUoFa3cC97Hw=="
|
"password": "PCD2Z4o12bKUoFa3cC97Hw=="
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"multiplex": {}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -82,3 +85,7 @@ Both if empty.
|
||||||
| none | / |
|
| none | / |
|
||||||
| 2022 methods | `sing-box generate rand --base64 <Key Length>` |
|
| 2022 methods | `sing-box generate rand --base64 <Key Length>` |
|
||||||
| other methods | any string |
|
| other methods | any string |
|
||||||
|
|
||||||
|
#### multiplex
|
||||||
|
|
||||||
|
See [Multiplex](/configuration/shared/multiplex#inbound) for details.
|
||||||
|
|
|
@ -8,7 +8,8 @@
|
||||||
... // 监听字段
|
... // 监听字段
|
||||||
|
|
||||||
"method": "2022-blake3-aes-128-gcm",
|
"method": "2022-blake3-aes-128-gcm",
|
||||||
"password": "8JCsPssfgS8tiRwiMlhARg=="
|
"password": "8JCsPssfgS8tiRwiMlhARg==",
|
||||||
|
"multiplex": {}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -23,7 +24,8 @@
|
||||||
"name": "sekai",
|
"name": "sekai",
|
||||||
"password": "PCD2Z4o12bKUoFa3cC97Hw=="
|
"password": "PCD2Z4o12bKUoFa3cC97Hw=="
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"multiplex": {}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -41,7 +43,8 @@
|
||||||
"server_port": 8080,
|
"server_port": 8080,
|
||||||
"password": "PCD2Z4o12bKUoFa3cC97Hw=="
|
"password": "PCD2Z4o12bKUoFa3cC97Hw=="
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"multiplex": {}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -82,3 +85,7 @@ See [Listen Fields](/configuration/shared/listen) for details.
|
||||||
| none | / |
|
| none | / |
|
||||||
| 2022 methods | `sing-box generate rand --base64 <密钥长度>` |
|
| 2022 methods | `sing-box generate rand --base64 <密钥长度>` |
|
||||||
| other methods | 任意字符串 |
|
| other methods | 任意字符串 |
|
||||||
|
|
||||||
|
#### multiplex
|
||||||
|
|
||||||
|
参阅 [多路复用](/zh/configuration/shared/multiplex#inbound)。
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
"server_port": 8081
|
"server_port": 8081
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"multiplex": {},
|
||||||
"transport": {}
|
"transport": {}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -58,6 +59,10 @@ Fallback server configuration for specified ALPN.
|
||||||
|
|
||||||
If not empty, TLS fallback requests with ALPN not in this table will be rejected.
|
If not empty, TLS fallback requests with ALPN not in this table will be rejected.
|
||||||
|
|
||||||
|
#### multiplex
|
||||||
|
|
||||||
|
See [Multiplex](/configuration/shared/multiplex#inbound) for details.
|
||||||
|
|
||||||
#### transport
|
#### transport
|
||||||
|
|
||||||
V2Ray Transport configuration, see [V2Ray Transport](/configuration/shared/v2ray-transport).
|
V2Ray Transport configuration, see [V2Ray Transport](/configuration/shared/v2ray-transport).
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
"server_port": 8081
|
"server_port": 8081
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"multiplex": {},
|
||||||
"transport": {}
|
"transport": {}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -60,6 +61,10 @@ TLS 配置, 参阅 [TLS](/zh/configuration/shared/tls/#inbound)。
|
||||||
|
|
||||||
如果不为空,ALPN 不在此列表中的 TLS 回退请求将被拒绝。
|
如果不为空,ALPN 不在此列表中的 TLS 回退请求将被拒绝。
|
||||||
|
|
||||||
|
#### multiplex
|
||||||
|
|
||||||
|
参阅 [多路复用](/zh/configuration/shared/multiplex#inbound)。
|
||||||
|
|
||||||
#### transport
|
#### transport
|
||||||
|
|
||||||
V2Ray 传输配置,参阅 [V2Ray 传输层](/zh/configuration/shared/v2ray-transport)。
|
V2Ray 传输配置,参阅 [V2Ray 传输层](/zh/configuration/shared/v2ray-transport)。
|
|
@ -48,7 +48,7 @@ TUIC 用户密码
|
||||||
|
|
||||||
#### congestion_control
|
#### congestion_control
|
||||||
|
|
||||||
QUIC 流量控制算法
|
QUIC 拥塞控制算法
|
||||||
|
|
||||||
可选值: `cubic`, `new_reno`, `bbr`
|
可选值: `cubic`, `new_reno`, `bbr`
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"tls": {},
|
"tls": {},
|
||||||
|
"multiplex": {},
|
||||||
"transport": {}
|
"transport": {}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -49,6 +50,10 @@ Available values:
|
||||||
|
|
||||||
TLS configuration, see [TLS](/configuration/shared/tls/#inbound).
|
TLS configuration, see [TLS](/configuration/shared/tls/#inbound).
|
||||||
|
|
||||||
|
#### multiplex
|
||||||
|
|
||||||
|
See [Multiplex](/configuration/shared/multiplex#inbound) for details.
|
||||||
|
|
||||||
#### transport
|
#### transport
|
||||||
|
|
||||||
V2Ray Transport configuration, see [V2Ray Transport](/configuration/shared/v2ray-transport).
|
V2Ray Transport configuration, see [V2Ray Transport](/configuration/shared/v2ray-transport).
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"tls": {},
|
"tls": {},
|
||||||
|
"multiplex": {},
|
||||||
"transport": {}
|
"transport": {}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -49,6 +50,10 @@ VLESS 子协议。
|
||||||
|
|
||||||
TLS 配置, 参阅 [TLS](/zh/configuration/shared/tls/#inbound)。
|
TLS 配置, 参阅 [TLS](/zh/configuration/shared/tls/#inbound)。
|
||||||
|
|
||||||
|
#### multiplex
|
||||||
|
|
||||||
|
参阅 [多路复用](/zh/configuration/shared/multiplex#inbound)。
|
||||||
|
|
||||||
#### transport
|
#### transport
|
||||||
|
|
||||||
V2Ray 传输配置,参阅 [V2Ray 传输层](/zh/configuration/shared/v2ray-transport)。
|
V2Ray 传输配置,参阅 [V2Ray 传输层](/zh/configuration/shared/v2ray-transport)。
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"tls": {},
|
"tls": {},
|
||||||
|
"multiplex": {},
|
||||||
"transport": {}
|
"transport": {}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -44,6 +45,10 @@ VMess users.
|
||||||
|
|
||||||
TLS configuration, see [TLS](/configuration/shared/tls/#inbound).
|
TLS configuration, see [TLS](/configuration/shared/tls/#inbound).
|
||||||
|
|
||||||
|
#### multiplex
|
||||||
|
|
||||||
|
See [Multiplex](/configuration/shared/multiplex#inbound) for details.
|
||||||
|
|
||||||
#### transport
|
#### transport
|
||||||
|
|
||||||
V2Ray Transport configuration, see [V2Ray Transport](/configuration/shared/v2ray-transport).
|
V2Ray Transport configuration, see [V2Ray Transport](/configuration/shared/v2ray-transport).
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"tls": {},
|
"tls": {},
|
||||||
|
"multiplex": {},
|
||||||
"transport": {}
|
"transport": {}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -44,6 +45,10 @@ VMess 用户。
|
||||||
|
|
||||||
TLS 配置, 参阅 [TLS](/zh/configuration/shared/tls/#inbound)。
|
TLS 配置, 参阅 [TLS](/zh/configuration/shared/tls/#inbound)。
|
||||||
|
|
||||||
|
#### multiplex
|
||||||
|
|
||||||
|
参阅 [多路复用](/zh/configuration/shared/multiplex#inbound)。
|
||||||
|
|
||||||
#### transport
|
#### transport
|
||||||
|
|
||||||
V2Ray 传输配置,参阅 [V2Ray 传输层](/zh/configuration/shared/v2ray-transport)。
|
V2Ray 传输配置,参阅 [V2Ray 传输层](/zh/configuration/shared/v2ray-transport)。
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
|
|
||||||
最大带宽。
|
最大带宽。
|
||||||
|
|
||||||
如果为空,将使用 BBR 流量控制算法而不是 Hysteria CC。
|
如果为空,将使用 BBR 拥塞控制算法而不是 Hysteria CC。
|
||||||
|
|
||||||
#### obfs.type
|
#### obfs.type
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,7 @@ Conflict with `multiplex`.
|
||||||
|
|
||||||
#### multiplex
|
#### multiplex
|
||||||
|
|
||||||
Multiplex configuration, see [Multiplex](/configuration/shared/multiplex).
|
See [Multiplex](/configuration/shared/multiplex#outbound) for details.
|
||||||
|
|
||||||
### Dial Fields
|
### Dial Fields
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,7 @@ UDP over TCP 配置。
|
||||||
|
|
||||||
#### multiplex
|
#### multiplex
|
||||||
|
|
||||||
多路复用配置, 参阅 [多路复用](/zh/configuration/shared/multiplex)。
|
参阅 [多路复用](/zh/configuration/shared/multiplex#outbound)。
|
||||||
|
|
||||||
### 拨号字段
|
### 拨号字段
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ TLS configuration, see [TLS](/configuration/shared/tls/#outbound).
|
||||||
|
|
||||||
#### multiplex
|
#### multiplex
|
||||||
|
|
||||||
Multiplex configuration, see [Multiplex](/configuration/shared/multiplex).
|
See [Multiplex](/configuration/shared/multiplex#outbound) for details.
|
||||||
|
|
||||||
#### transport
|
#### transport
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ TLS 配置, 参阅 [TLS](/zh/configuration/shared/tls/#outbound)。
|
||||||
|
|
||||||
#### multiplex
|
#### multiplex
|
||||||
|
|
||||||
多路复用配置, 参阅 [多路复用](/zh/configuration/shared/multiplex)。
|
参阅 [多路复用](/zh/configuration/shared/multiplex#outbound)。
|
||||||
|
|
||||||
#### transport
|
#### transport
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ TUIC 用户密码
|
||||||
|
|
||||||
#### congestion_control
|
#### congestion_control
|
||||||
|
|
||||||
QUIC 流量控制算法
|
QUIC 拥塞控制算法
|
||||||
|
|
||||||
可选值: `cubic`, `new_reno`, `bbr`
|
可选值: `cubic`, `new_reno`, `bbr`
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
"network": "tcp",
|
"network": "tcp",
|
||||||
"tls": {},
|
"tls": {},
|
||||||
"packet_encoding": "",
|
"packet_encoding": "",
|
||||||
|
"multiplex": {},
|
||||||
"transport": {},
|
"transport": {},
|
||||||
|
|
||||||
... // Dial Fields
|
... // Dial Fields
|
||||||
|
@ -68,6 +69,10 @@ UDP packet encoding, xudp is used by default.
|
||||||
| packetaddr | Supported by v2ray 5+ |
|
| packetaddr | Supported by v2ray 5+ |
|
||||||
| xudp | Supported by xray |
|
| xudp | Supported by xray |
|
||||||
|
|
||||||
|
#### multiplex
|
||||||
|
|
||||||
|
See [Multiplex](/configuration/shared/multiplex#outbound) for details.
|
||||||
|
|
||||||
#### transport
|
#### transport
|
||||||
|
|
||||||
V2Ray Transport configuration, see [V2Ray Transport](/configuration/shared/v2ray-transport).
|
V2Ray Transport configuration, see [V2Ray Transport](/configuration/shared/v2ray-transport).
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
"network": "tcp",
|
"network": "tcp",
|
||||||
"tls": {},
|
"tls": {},
|
||||||
"packet_encoding": "",
|
"packet_encoding": "",
|
||||||
|
"multiplex": {},
|
||||||
"transport": {},
|
"transport": {},
|
||||||
|
|
||||||
... // 拨号字段
|
... // 拨号字段
|
||||||
|
@ -68,6 +69,10 @@ UDP 包编码,默认使用 xudp。
|
||||||
| packetaddr | 由 v2ray 5+ 支持 |
|
| packetaddr | 由 v2ray 5+ 支持 |
|
||||||
| xudp | 由 xray 支持 |
|
| xudp | 由 xray 支持 |
|
||||||
|
|
||||||
|
#### multiplex
|
||||||
|
|
||||||
|
参阅 [多路复用](/zh/configuration/shared/multiplex#outbound)。
|
||||||
|
|
||||||
#### transport
|
#### transport
|
||||||
|
|
||||||
V2Ray 传输配置,参阅 [V2Ray 传输层](/zh/configuration/shared/v2ray-transport)。
|
V2Ray 传输配置,参阅 [V2Ray 传输层](/zh/configuration/shared/v2ray-transport)。
|
||||||
|
|
|
@ -15,8 +15,8 @@
|
||||||
"network": "tcp",
|
"network": "tcp",
|
||||||
"tls": {},
|
"tls": {},
|
||||||
"packet_encoding": "",
|
"packet_encoding": "",
|
||||||
"multiplex": {},
|
|
||||||
"transport": {},
|
"transport": {},
|
||||||
|
"multiplex": {},
|
||||||
|
|
||||||
... // Dial Fields
|
... // Dial Fields
|
||||||
}
|
}
|
||||||
|
@ -96,7 +96,7 @@ UDP packet encoding.
|
||||||
|
|
||||||
#### multiplex
|
#### multiplex
|
||||||
|
|
||||||
Multiplex configuration, see [Multiplex](/configuration/shared/multiplex).
|
See [Multiplex](/configuration/shared/multiplex#outbound) for details.
|
||||||
|
|
||||||
#### transport
|
#### transport
|
||||||
|
|
||||||
|
|
|
@ -96,7 +96,7 @@ UDP 包编码。
|
||||||
|
|
||||||
#### multiplex
|
#### multiplex
|
||||||
|
|
||||||
多路复用配置, 参阅 [多路复用](/zh/configuration/shared/multiplex)。
|
参阅 [多路复用](/zh/configuration/shared/multiplex#outbound)。
|
||||||
|
|
||||||
#### transport
|
#### transport
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,14 @@
|
||||||
### Server Requirements
|
### Inbound
|
||||||
|
|
||||||
`sing-box` :)
|
```json
|
||||||
|
{
|
||||||
|
"enabled": true,
|
||||||
|
"padding": false,
|
||||||
|
"brutal": {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Structure
|
### Outbound
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
@ -11,11 +17,27 @@
|
||||||
"max_connections": 4,
|
"max_connections": 4,
|
||||||
"min_streams": 4,
|
"min_streams": 4,
|
||||||
"max_streams": 0,
|
"max_streams": 0,
|
||||||
"padding": false
|
"padding": false,
|
||||||
|
"brutal": {}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Fields
|
|
||||||
|
### Inbound Fields
|
||||||
|
|
||||||
|
#### enabled
|
||||||
|
|
||||||
|
Enable multiplex support.
|
||||||
|
|
||||||
|
#### padding
|
||||||
|
|
||||||
|
If enabled, non-padded connections will be rejected.
|
||||||
|
|
||||||
|
#### brutal
|
||||||
|
|
||||||
|
See [TCP Brutal](/configuration/shared/tcp-brutal) for details.
|
||||||
|
|
||||||
|
### Outbound Fields
|
||||||
|
|
||||||
#### enabled
|
#### enabled
|
||||||
|
|
||||||
|
@ -59,3 +81,6 @@ Conflict with `max_connections` and `min_streams`.
|
||||||
|
|
||||||
Enable padding.
|
Enable padding.
|
||||||
|
|
||||||
|
#### brutal
|
||||||
|
|
||||||
|
See [TCP Brutal](/configuration/shared/tcp-brutal) for details.
|
||||||
|
|
|
@ -1,8 +1,14 @@
|
||||||
### 服务器要求
|
### 入站
|
||||||
|
|
||||||
`sing-box` :)
|
```json
|
||||||
|
{
|
||||||
|
"enabled": true,
|
||||||
|
"padding": false,
|
||||||
|
"brutal": {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### 结构
|
### 出站
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
@ -10,11 +16,27 @@
|
||||||
"protocol": "smux",
|
"protocol": "smux",
|
||||||
"max_connections": 4,
|
"max_connections": 4,
|
||||||
"min_streams": 4,
|
"min_streams": 4,
|
||||||
"max_streams": 0
|
"max_streams": 0,
|
||||||
|
"padding": false,
|
||||||
|
"brutal": {}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 字段
|
### 入站字段
|
||||||
|
|
||||||
|
#### enabled
|
||||||
|
|
||||||
|
启用多路复用支持。
|
||||||
|
|
||||||
|
#### padding
|
||||||
|
|
||||||
|
如果启用,将拒绝非填充连接。
|
||||||
|
|
||||||
|
#### brutal
|
||||||
|
|
||||||
|
参阅 [TCP Brutal](/zh/configuration/shared/tcp-brutal)。
|
||||||
|
|
||||||
|
### 出站字段
|
||||||
|
|
||||||
#### enabled
|
#### enabled
|
||||||
|
|
||||||
|
@ -58,3 +80,6 @@
|
||||||
|
|
||||||
启用填充。
|
启用填充。
|
||||||
|
|
||||||
|
#### brutal
|
||||||
|
|
||||||
|
参阅 [TCP Brutal](/zh/configuration/shared/tcp-brutal)。
|
28
docs/configuration/shared/tcp-brutal.md
Normal file
28
docs/configuration/shared/tcp-brutal.md
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
### Server Requirements
|
||||||
|
|
||||||
|
* Linux
|
||||||
|
* `brutal` congestion control algorithm kernel module installed
|
||||||
|
|
||||||
|
See [tcp-brutal](https://github.com/apernet/tcp-brutal) for details.
|
||||||
|
|
||||||
|
### Structure
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"enabled": true,
|
||||||
|
"up_mbps": 100,
|
||||||
|
"down_mbps": 100
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Fields
|
||||||
|
|
||||||
|
#### enabled
|
||||||
|
|
||||||
|
Enable TCP Brutal congestion control algorithm。
|
||||||
|
|
||||||
|
#### up_mbps, down_mbps
|
||||||
|
|
||||||
|
==Required==
|
||||||
|
|
||||||
|
Upload and download bandwidth, in Mbps.
|
28
docs/configuration/shared/tcp-brutal.zh.md
Normal file
28
docs/configuration/shared/tcp-brutal.zh.md
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
### 服务器要求
|
||||||
|
|
||||||
|
* Linux
|
||||||
|
* `brutal` 拥塞控制算法内核模块已安装
|
||||||
|
|
||||||
|
参阅 [tcp-brutal](https://github.com/apernet/tcp-brutal)。
|
||||||
|
|
||||||
|
### 结构
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"enabled": true,
|
||||||
|
"up_mbps": 100,
|
||||||
|
"down_mbps": 100
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 字段
|
||||||
|
|
||||||
|
#### enabled
|
||||||
|
|
||||||
|
启用 TCP Brutal 拥塞控制算法。
|
||||||
|
|
||||||
|
#### up_mbps, down_mbps
|
||||||
|
|
||||||
|
==必填==
|
||||||
|
|
||||||
|
上传和下载带宽,以 Mbps 为单位。
|
2
go.mod
2
go.mod
|
@ -28,7 +28,7 @@ require (
|
||||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
|
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
|
||||||
github.com/sagernet/sing v0.2.18-0.20231124125253-2dcabf4bfcbc
|
github.com/sagernet/sing v0.2.18-0.20231124125253-2dcabf4bfcbc
|
||||||
github.com/sagernet/sing-dns v0.1.11
|
github.com/sagernet/sing-dns v0.1.11
|
||||||
github.com/sagernet/sing-mux v0.1.4
|
github.com/sagernet/sing-mux v0.1.5-0.20231109075101-6b086ed6bb07
|
||||||
github.com/sagernet/sing-quic v0.1.5-0.20231123150204-077075e9b6ad
|
github.com/sagernet/sing-quic v0.1.5-0.20231123150204-077075e9b6ad
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.5
|
github.com/sagernet/sing-shadowsocks v0.2.5
|
||||||
github.com/sagernet/sing-shadowsocks2 v0.1.5
|
github.com/sagernet/sing-shadowsocks2 v0.1.5
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -118,8 +118,8 @@ github.com/sagernet/sing v0.2.18-0.20231124125253-2dcabf4bfcbc h1:vESVuxHgbd2EzH
|
||||||
github.com/sagernet/sing v0.2.18-0.20231124125253-2dcabf4bfcbc/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo=
|
github.com/sagernet/sing v0.2.18-0.20231124125253-2dcabf4bfcbc/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo=
|
||||||
github.com/sagernet/sing-dns v0.1.11 h1:PPrMCVVrAeR3f5X23I+cmvacXJ+kzuyAsBiWyUKhGSE=
|
github.com/sagernet/sing-dns v0.1.11 h1:PPrMCVVrAeR3f5X23I+cmvacXJ+kzuyAsBiWyUKhGSE=
|
||||||
github.com/sagernet/sing-dns v0.1.11/go.mod h1:zJ/YjnYB61SYE+ubMcMqVdpaSvsyQ2iShQGO3vuLvvE=
|
github.com/sagernet/sing-dns v0.1.11/go.mod h1:zJ/YjnYB61SYE+ubMcMqVdpaSvsyQ2iShQGO3vuLvvE=
|
||||||
github.com/sagernet/sing-mux v0.1.4 h1:BPNPOQr6HkXG3iY/BrfvUKUl+A7gYsGKVSxvoR3PO50=
|
github.com/sagernet/sing-mux v0.1.5-0.20231109075101-6b086ed6bb07 h1:ncKb5tVOsCQgCsv6UpsA0jinbNb5OQ5GMPJlyQP3EHM=
|
||||||
github.com/sagernet/sing-mux v0.1.4/go.mod h1:dKvcu/sb3fZ88uGv9vzAqUej6J4W+pHu5GqjRuFwAWs=
|
github.com/sagernet/sing-mux v0.1.5-0.20231109075101-6b086ed6bb07/go.mod h1:u/MZf32xPG8jEKe3t+xUV67EBnKtDtCaPhsJQOQGUYU=
|
||||||
github.com/sagernet/sing-quic v0.1.5-0.20231123150204-077075e9b6ad h1:PyMeM7c5xbrMbqGkIOMo6m2ip8o7TP0JONfDWs17rzg=
|
github.com/sagernet/sing-quic v0.1.5-0.20231123150204-077075e9b6ad h1:PyMeM7c5xbrMbqGkIOMo6m2ip8o7TP0JONfDWs17rzg=
|
||||||
github.com/sagernet/sing-quic v0.1.5-0.20231123150204-077075e9b6ad/go.mod h1:aXHVP+osF3w5wJzoWZbJSrX3ceJiU9QMd0KPnKV6C/o=
|
github.com/sagernet/sing-quic v0.1.5-0.20231123150204-077075e9b6ad/go.mod h1:aXHVP+osF3w5wJzoWZbJSrX3ceJiU9QMd0KPnKV6C/o=
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.5 h1:qxIttos4xu6ii7MTVJYA8EFQR7Q3KG6xMqmLJIFtBaY=
|
github.com/sagernet/sing-shadowsocks v0.2.5 h1:qxIttos4xu6ii7MTVJYA8EFQR7Q3KG6xMqmLJIFtBaY=
|
||||||
|
|
|
@ -22,7 +22,7 @@ type myInboundAdapter struct {
|
||||||
protocol string
|
protocol string
|
||||||
network []string
|
network []string
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
router adapter.Router
|
router adapter.ConnectionRouter
|
||||||
logger log.ContextLogger
|
logger log.ContextLogger
|
||||||
tag string
|
tag string
|
||||||
listenOptions option.ListenOptions
|
listenOptions option.ListenOptions
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
"github.com/sagernet/sing-box/common/tls"
|
"github.com/sagernet/sing-box/common/tls"
|
||||||
|
"github.com/sagernet/sing-box/common/uot"
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
|
@ -35,7 +36,7 @@ func NewHTTP(ctx context.Context, router adapter.Router, logger log.ContextLogge
|
||||||
protocol: C.TypeHTTP,
|
protocol: C.TypeHTTP,
|
||||||
network: []string{N.NetworkTCP},
|
network: []string{N.NetworkTCP},
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
router: router,
|
router: uot.NewRouter(router, logger),
|
||||||
logger: logger,
|
logger: logger,
|
||||||
tag: tag,
|
tag: tag,
|
||||||
listenOptions: options.ListenOptions,
|
listenOptions: options.ListenOptions,
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
"github.com/sagernet/sing-box/common/uot"
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
|
@ -37,7 +38,7 @@ func NewMixed(ctx context.Context, router adapter.Router, logger log.ContextLogg
|
||||||
protocol: C.TypeMixed,
|
protocol: C.TypeMixed,
|
||||||
network: []string{N.NetworkTCP},
|
network: []string{N.NetworkTCP},
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
router: router,
|
router: uot.NewRouter(router, logger),
|
||||||
logger: logger,
|
logger: logger,
|
||||||
tag: tag,
|
tag: tag,
|
||||||
listenOptions: options.ListenOptions,
|
listenOptions: options.ListenOptions,
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
"github.com/sagernet/sing-box/common/tls"
|
"github.com/sagernet/sing-box/common/tls"
|
||||||
|
"github.com/sagernet/sing-box/common/uot"
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/include"
|
"github.com/sagernet/sing-box/include"
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
|
@ -43,7 +44,7 @@ func NewNaive(ctx context.Context, router adapter.Router, logger log.ContextLogg
|
||||||
protocol: C.TypeNaive,
|
protocol: C.TypeNaive,
|
||||||
network: options.Network.Build(),
|
network: options.Network.Build(),
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
router: router,
|
router: uot.NewRouter(router, logger),
|
||||||
logger: logger,
|
logger: logger,
|
||||||
tag: tag,
|
tag: tag,
|
||||||
listenOptions: options.ListenOptions,
|
listenOptions: options.ListenOptions,
|
||||||
|
|
|
@ -6,6 +6,8 @@ import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
"github.com/sagernet/sing-box/common/mux"
|
||||||
|
"github.com/sagernet/sing-box/common/uot"
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
|
@ -48,21 +50,27 @@ func newShadowsocks(ctx context.Context, router adapter.Router, logger log.Conte
|
||||||
protocol: C.TypeShadowsocks,
|
protocol: C.TypeShadowsocks,
|
||||||
network: options.Network.Build(),
|
network: options.Network.Build(),
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
router: router,
|
router: uot.NewRouter(router, logger),
|
||||||
logger: logger,
|
logger: logger,
|
||||||
tag: tag,
|
tag: tag,
|
||||||
listenOptions: options.ListenOptions,
|
listenOptions: options.ListenOptions,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
inbound.connHandler = inbound
|
inbound.connHandler = inbound
|
||||||
inbound.packetHandler = inbound
|
inbound.packetHandler = inbound
|
||||||
|
var err error
|
||||||
|
inbound.router, err = mux.NewRouterWithOptions(inbound.router, logger, common.PtrValueOrDefault(options.Multiplex))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
var udpTimeout int64
|
var udpTimeout int64
|
||||||
if options.UDPTimeout != 0 {
|
if options.UDPTimeout != 0 {
|
||||||
udpTimeout = options.UDPTimeout
|
udpTimeout = options.UDPTimeout
|
||||||
} else {
|
} else {
|
||||||
udpTimeout = int64(C.UDPTimeout.Seconds())
|
udpTimeout = int64(C.UDPTimeout.Seconds())
|
||||||
}
|
}
|
||||||
var err error
|
|
||||||
switch {
|
switch {
|
||||||
case options.Method == shadowsocks.MethodNone:
|
case options.Method == shadowsocks.MethodNone:
|
||||||
inbound.service = shadowsocks.NewNoneService(options.UDPTimeout, inbound.upstreamContextHandler())
|
inbound.service = shadowsocks.NewNoneService(options.UDPTimeout, inbound.upstreamContextHandler())
|
||||||
|
|
|
@ -6,6 +6,8 @@ import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
"github.com/sagernet/sing-box/common/mux"
|
||||||
|
"github.com/sagernet/sing-box/common/uot"
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
|
@ -38,7 +40,7 @@ func newShadowsocksMulti(ctx context.Context, router adapter.Router, logger log.
|
||||||
protocol: C.TypeShadowsocks,
|
protocol: C.TypeShadowsocks,
|
||||||
network: options.Network.Build(),
|
network: options.Network.Build(),
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
router: router,
|
router: uot.NewRouter(router, logger),
|
||||||
logger: logger,
|
logger: logger,
|
||||||
tag: tag,
|
tag: tag,
|
||||||
listenOptions: options.ListenOptions,
|
listenOptions: options.ListenOptions,
|
||||||
|
@ -46,16 +48,18 @@ func newShadowsocksMulti(ctx context.Context, router adapter.Router, logger log.
|
||||||
}
|
}
|
||||||
inbound.connHandler = inbound
|
inbound.connHandler = inbound
|
||||||
inbound.packetHandler = inbound
|
inbound.packetHandler = inbound
|
||||||
|
var err error
|
||||||
|
inbound.router, err = mux.NewRouterWithOptions(inbound.router, logger, common.PtrValueOrDefault(options.Multiplex))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
var udpTimeout int64
|
var udpTimeout int64
|
||||||
if options.UDPTimeout != 0 {
|
if options.UDPTimeout != 0 {
|
||||||
udpTimeout = options.UDPTimeout
|
udpTimeout = options.UDPTimeout
|
||||||
} else {
|
} else {
|
||||||
udpTimeout = int64(C.UDPTimeout.Seconds())
|
udpTimeout = int64(C.UDPTimeout.Seconds())
|
||||||
}
|
}
|
||||||
var (
|
var service shadowsocks.MultiService[int]
|
||||||
service shadowsocks.MultiService[int]
|
|
||||||
err error
|
|
||||||
)
|
|
||||||
if common.Contains(shadowaead_2022.List, options.Method) {
|
if common.Contains(shadowaead_2022.List, options.Method) {
|
||||||
service, err = shadowaead_2022.NewMultiServiceWithPassword[int](
|
service, err = shadowaead_2022.NewMultiServiceWithPassword[int](
|
||||||
options.Method,
|
options.Method,
|
||||||
|
|
|
@ -6,6 +6,8 @@ import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
"github.com/sagernet/sing-box/common/mux"
|
||||||
|
"github.com/sagernet/sing-box/common/uot"
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
|
@ -34,7 +36,7 @@ func newShadowsocksRelay(ctx context.Context, router adapter.Router, logger log.
|
||||||
protocol: C.TypeShadowsocks,
|
protocol: C.TypeShadowsocks,
|
||||||
network: options.Network.Build(),
|
network: options.Network.Build(),
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
router: router,
|
router: uot.NewRouter(router, logger),
|
||||||
logger: logger,
|
logger: logger,
|
||||||
tag: tag,
|
tag: tag,
|
||||||
listenOptions: options.ListenOptions,
|
listenOptions: options.ListenOptions,
|
||||||
|
@ -43,6 +45,11 @@ func newShadowsocksRelay(ctx context.Context, router adapter.Router, logger log.
|
||||||
}
|
}
|
||||||
inbound.connHandler = inbound
|
inbound.connHandler = inbound
|
||||||
inbound.packetHandler = inbound
|
inbound.packetHandler = inbound
|
||||||
|
var err error
|
||||||
|
inbound.router, err = mux.NewRouterWithOptions(inbound.router, logger, common.PtrValueOrDefault(options.Multiplex))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
var udpTimeout int64
|
var udpTimeout int64
|
||||||
if options.UDPTimeout != 0 {
|
if options.UDPTimeout != 0 {
|
||||||
udpTimeout = options.UDPTimeout
|
udpTimeout = options.UDPTimeout
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
"github.com/sagernet/sing-box/common/uot"
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
|
@ -30,7 +31,7 @@ func NewSocks(ctx context.Context, router adapter.Router, logger log.ContextLogg
|
||||||
protocol: C.TypeSOCKS,
|
protocol: C.TypeSOCKS,
|
||||||
network: []string{N.NetworkTCP},
|
network: []string{N.NetworkTCP},
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
router: router,
|
router: uot.NewRouter(router, logger),
|
||||||
logger: logger,
|
logger: logger,
|
||||||
tag: tag,
|
tag: tag,
|
||||||
listenOptions: options.ListenOptions,
|
listenOptions: options.ListenOptions,
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
"github.com/sagernet/sing-box/common/mux"
|
||||||
"github.com/sagernet/sing-box/common/tls"
|
"github.com/sagernet/sing-box/common/tls"
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
|
@ -94,6 +95,10 @@ func NewTrojan(ctx context.Context, router adapter.Router, logger log.ContextLog
|
||||||
return nil, E.Cause(err, "create server transport: ", options.Transport.Type)
|
return nil, E.Cause(err, "create server transport: ", options.Transport.Type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
inbound.router, err = mux.NewRouterWithOptions(inbound.router, logger, common.PtrValueOrDefault(options.Multiplex))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
inbound.service = service
|
inbound.service = service
|
||||||
inbound.connHandler = inbound
|
inbound.connHandler = inbound
|
||||||
return inbound, nil
|
return inbound, nil
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
"github.com/sagernet/sing-box/common/tls"
|
"github.com/sagernet/sing-box/common/tls"
|
||||||
|
"github.com/sagernet/sing-box/common/uot"
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
|
@ -44,7 +45,7 @@ func NewTUIC(ctx context.Context, router adapter.Router, logger log.ContextLogge
|
||||||
protocol: C.TypeTUIC,
|
protocol: C.TypeTUIC,
|
||||||
network: []string{N.NetworkUDP},
|
network: []string{N.NetworkUDP},
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
router: router,
|
router: uot.NewRouter(router, logger),
|
||||||
logger: logger,
|
logger: logger,
|
||||||
tag: tag,
|
tag: tag,
|
||||||
listenOptions: options.ListenOptions,
|
listenOptions: options.ListenOptions,
|
||||||
|
|
|
@ -6,7 +6,9 @@ import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
"github.com/sagernet/sing-box/common/mux"
|
||||||
"github.com/sagernet/sing-box/common/tls"
|
"github.com/sagernet/sing-box/common/tls"
|
||||||
|
"github.com/sagernet/sing-box/common/uot"
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
|
@ -42,7 +44,7 @@ func NewVLESS(ctx context.Context, router adapter.Router, logger log.ContextLogg
|
||||||
protocol: C.TypeVLESS,
|
protocol: C.TypeVLESS,
|
||||||
network: []string{N.NetworkTCP},
|
network: []string{N.NetworkTCP},
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
router: router,
|
router: uot.NewRouter(router, logger),
|
||||||
logger: logger,
|
logger: logger,
|
||||||
tag: tag,
|
tag: tag,
|
||||||
listenOptions: options.ListenOptions,
|
listenOptions: options.ListenOptions,
|
||||||
|
@ -50,6 +52,11 @@ func NewVLESS(ctx context.Context, router adapter.Router, logger log.ContextLogg
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
users: options.Users,
|
users: options.Users,
|
||||||
}
|
}
|
||||||
|
var err error
|
||||||
|
inbound.router, err = mux.NewRouterWithOptions(inbound.router, logger, common.PtrValueOrDefault(options.Multiplex))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
service := vless.NewService[int](logger, adapter.NewUpstreamContextHandler(inbound.newConnection, inbound.newPacketConnection, inbound))
|
service := vless.NewService[int](logger, adapter.NewUpstreamContextHandler(inbound.newConnection, inbound.newPacketConnection, inbound))
|
||||||
service.UpdateUsers(common.MapIndexed(inbound.users, func(index int, _ option.VLESSUser) int {
|
service.UpdateUsers(common.MapIndexed(inbound.users, func(index int, _ option.VLESSUser) int {
|
||||||
return index
|
return index
|
||||||
|
@ -59,7 +66,6 @@ func NewVLESS(ctx context.Context, router adapter.Router, logger log.ContextLogg
|
||||||
return it.Flow
|
return it.Flow
|
||||||
}))
|
}))
|
||||||
inbound.service = service
|
inbound.service = service
|
||||||
var err error
|
|
||||||
if options.TLS != nil {
|
if options.TLS != nil {
|
||||||
inbound.tlsConfig, err = tls.NewServer(ctx, logger, common.PtrValueOrDefault(options.TLS))
|
inbound.tlsConfig, err = tls.NewServer(ctx, logger, common.PtrValueOrDefault(options.TLS))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -6,7 +6,9 @@ import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
"github.com/sagernet/sing-box/common/mux"
|
||||||
"github.com/sagernet/sing-box/common/tls"
|
"github.com/sagernet/sing-box/common/tls"
|
||||||
|
"github.com/sagernet/sing-box/common/uot"
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
|
@ -42,7 +44,7 @@ func NewVMess(ctx context.Context, router adapter.Router, logger log.ContextLogg
|
||||||
protocol: C.TypeVMess,
|
protocol: C.TypeVMess,
|
||||||
network: []string{N.NetworkTCP},
|
network: []string{N.NetworkTCP},
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
router: router,
|
router: uot.NewRouter(router, logger),
|
||||||
logger: logger,
|
logger: logger,
|
||||||
tag: tag,
|
tag: tag,
|
||||||
listenOptions: options.ListenOptions,
|
listenOptions: options.ListenOptions,
|
||||||
|
@ -50,6 +52,11 @@ func NewVMess(ctx context.Context, router adapter.Router, logger log.ContextLogg
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
users: options.Users,
|
users: options.Users,
|
||||||
}
|
}
|
||||||
|
var err error
|
||||||
|
inbound.router, err = mux.NewRouterWithOptions(inbound.router, logger, common.PtrValueOrDefault(options.Multiplex))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
var serviceOptions []vmess.ServiceOption
|
var serviceOptions []vmess.ServiceOption
|
||||||
if timeFunc := ntp.TimeFuncFromContext(ctx); timeFunc != nil {
|
if timeFunc := ntp.TimeFuncFromContext(ctx); timeFunc != nil {
|
||||||
serviceOptions = append(serviceOptions, vmess.ServiceWithTimeFunc(timeFunc))
|
serviceOptions = append(serviceOptions, vmess.ServiceWithTimeFunc(timeFunc))
|
||||||
|
@ -59,7 +66,7 @@ func NewVMess(ctx context.Context, router adapter.Router, logger log.ContextLogg
|
||||||
}
|
}
|
||||||
service := vmess.NewService[int](adapter.NewUpstreamContextHandler(inbound.newConnection, inbound.newPacketConnection, inbound), serviceOptions...)
|
service := vmess.NewService[int](adapter.NewUpstreamContextHandler(inbound.newConnection, inbound.newPacketConnection, inbound), serviceOptions...)
|
||||||
inbound.service = service
|
inbound.service = service
|
||||||
err := service.UpdateUsers(common.MapIndexed(options.Users, func(index int, it option.VMessUser) int {
|
err = service.UpdateUsers(common.MapIndexed(options.Users, func(index int, it option.VMessUser) int {
|
||||||
return index
|
return index
|
||||||
}), common.Map(options.Users, func(it option.VMessUser) string {
|
}), common.Map(options.Users, func(it option.VMessUser) string {
|
||||||
return it.UUID
|
return it.UUID
|
||||||
|
|
|
@ -75,6 +75,7 @@ nav:
|
||||||
- Multiplex: configuration/shared/multiplex.md
|
- Multiplex: configuration/shared/multiplex.md
|
||||||
- V2Ray Transport: configuration/shared/v2ray-transport.md
|
- V2Ray Transport: configuration/shared/v2ray-transport.md
|
||||||
- UDP over TCP: configuration/shared/udp-over-tcp.md
|
- UDP over TCP: configuration/shared/udp-over-tcp.md
|
||||||
|
- TCP Brutal: configuration/shared/tcp-brutal.md
|
||||||
- Inbound:
|
- Inbound:
|
||||||
- configuration/inbound/index.md
|
- configuration/inbound/index.md
|
||||||
- Direct: configuration/inbound/direct.md
|
- Direct: configuration/inbound/direct.md
|
||||||
|
|
23
option/multiplex.go
Normal file
23
option/multiplex.go
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
package option
|
||||||
|
|
||||||
|
type InboundMultiplexOptions struct {
|
||||||
|
Enabled bool `json:"enabled,omitempty"`
|
||||||
|
Padding bool `json:"padding,omitempty"`
|
||||||
|
Brutal *BrutalOptions `json:"brutal,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type OutboundMultiplexOptions struct {
|
||||||
|
Enabled bool `json:"enabled,omitempty"`
|
||||||
|
Protocol string `json:"protocol,omitempty"`
|
||||||
|
MaxConnections int `json:"max_connections,omitempty"`
|
||||||
|
MinStreams int `json:"min_streams,omitempty"`
|
||||||
|
MaxStreams int `json:"max_streams,omitempty"`
|
||||||
|
Padding bool `json:"padding,omitempty"`
|
||||||
|
Brutal *BrutalOptions `json:"brutal,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type BrutalOptions struct {
|
||||||
|
Enabled bool `json:"enabled,omitempty"`
|
||||||
|
UpMbps int `json:"up_mbps,omitempty"`
|
||||||
|
DownMbps int `json:"down_mbps,omitempty"`
|
||||||
|
}
|
|
@ -154,12 +154,3 @@ type ServerOptions struct {
|
||||||
func (o ServerOptions) Build() M.Socksaddr {
|
func (o ServerOptions) Build() M.Socksaddr {
|
||||||
return M.ParseSocksaddrHostPort(o.Server, o.ServerPort)
|
return M.ParseSocksaddrHostPort(o.Server, o.ServerPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
type MultiplexOptions struct {
|
|
||||||
Enabled bool `json:"enabled,omitempty"`
|
|
||||||
Protocol string `json:"protocol,omitempty"`
|
|
||||||
MaxConnections int `json:"max_connections,omitempty"`
|
|
||||||
MinStreams int `json:"min_streams,omitempty"`
|
|
||||||
MaxStreams int `json:"max_streams,omitempty"`
|
|
||||||
Padding bool `json:"padding,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ type ShadowsocksInboundOptions struct {
|
||||||
Password string `json:"password,omitempty"`
|
Password string `json:"password,omitempty"`
|
||||||
Users []ShadowsocksUser `json:"users,omitempty"`
|
Users []ShadowsocksUser `json:"users,omitempty"`
|
||||||
Destinations []ShadowsocksDestination `json:"destinations,omitempty"`
|
Destinations []ShadowsocksDestination `json:"destinations,omitempty"`
|
||||||
|
Multiplex *InboundMultiplexOptions `json:"multiplex,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ShadowsocksUser struct {
|
type ShadowsocksUser struct {
|
||||||
|
@ -23,11 +24,11 @@ type ShadowsocksDestination struct {
|
||||||
type ShadowsocksOutboundOptions struct {
|
type ShadowsocksOutboundOptions struct {
|
||||||
DialerOptions
|
DialerOptions
|
||||||
ServerOptions
|
ServerOptions
|
||||||
Method string `json:"method"`
|
Method string `json:"method"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
Plugin string `json:"plugin,omitempty"`
|
Plugin string `json:"plugin,omitempty"`
|
||||||
PluginOptions string `json:"plugin_opts,omitempty"`
|
PluginOptions string `json:"plugin_opts,omitempty"`
|
||||||
Network NetworkList `json:"network,omitempty"`
|
Network NetworkList `json:"network,omitempty"`
|
||||||
UDPOverTCPOptions *UDPOverTCPOptions `json:"udp_over_tcp,omitempty"`
|
UDPOverTCP *UDPOverTCPOptions `json:"udp_over_tcp,omitempty"`
|
||||||
MultiplexOptions *MultiplexOptions `json:"multiplex,omitempty"`
|
Multiplex *OutboundMultiplexOptions `json:"multiplex,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,11 +17,11 @@ type HTTPMixedInboundOptions struct {
|
||||||
type SocksOutboundOptions struct {
|
type SocksOutboundOptions struct {
|
||||||
DialerOptions
|
DialerOptions
|
||||||
ServerOptions
|
ServerOptions
|
||||||
Version string `json:"version,omitempty"`
|
Version string `json:"version,omitempty"`
|
||||||
Username string `json:"username,omitempty"`
|
Username string `json:"username,omitempty"`
|
||||||
Password string `json:"password,omitempty"`
|
Password string `json:"password,omitempty"`
|
||||||
Network NetworkList `json:"network,omitempty"`
|
Network NetworkList `json:"network,omitempty"`
|
||||||
UDPOverTCPOptions *UDPOverTCPOptions `json:"udp_over_tcp,omitempty"`
|
UDPOverTCP *UDPOverTCPOptions `json:"udp_over_tcp,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type HTTPOutboundOptions struct {
|
type HTTPOutboundOptions struct {
|
||||||
|
|
|
@ -6,6 +6,7 @@ type TrojanInboundOptions struct {
|
||||||
TLS *InboundTLSOptions `json:"tls,omitempty"`
|
TLS *InboundTLSOptions `json:"tls,omitempty"`
|
||||||
Fallback *ServerOptions `json:"fallback,omitempty"`
|
Fallback *ServerOptions `json:"fallback,omitempty"`
|
||||||
FallbackForALPN map[string]*ServerOptions `json:"fallback_for_alpn,omitempty"`
|
FallbackForALPN map[string]*ServerOptions `json:"fallback_for_alpn,omitempty"`
|
||||||
|
Multiplex *InboundMultiplexOptions `json:"multiplex,omitempty"`
|
||||||
Transport *V2RayTransportOptions `json:"transport,omitempty"`
|
Transport *V2RayTransportOptions `json:"transport,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,9 +18,9 @@ type TrojanUser struct {
|
||||||
type TrojanOutboundOptions struct {
|
type TrojanOutboundOptions struct {
|
||||||
DialerOptions
|
DialerOptions
|
||||||
ServerOptions
|
ServerOptions
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
Network NetworkList `json:"network,omitempty"`
|
Network NetworkList `json:"network,omitempty"`
|
||||||
TLS *OutboundTLSOptions `json:"tls,omitempty"`
|
TLS *OutboundTLSOptions `json:"tls,omitempty"`
|
||||||
Multiplex *MultiplexOptions `json:"multiplex,omitempty"`
|
Multiplex *OutboundMultiplexOptions `json:"multiplex,omitempty"`
|
||||||
Transport *V2RayTransportOptions `json:"transport,omitempty"`
|
Transport *V2RayTransportOptions `json:"transport,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,10 @@ package option
|
||||||
|
|
||||||
type VLESSInboundOptions struct {
|
type VLESSInboundOptions struct {
|
||||||
ListenOptions
|
ListenOptions
|
||||||
Users []VLESSUser `json:"users,omitempty"`
|
Users []VLESSUser `json:"users,omitempty"`
|
||||||
TLS *InboundTLSOptions `json:"tls,omitempty"`
|
TLS *InboundTLSOptions `json:"tls,omitempty"`
|
||||||
Transport *V2RayTransportOptions `json:"transport,omitempty"`
|
Multiplex *InboundMultiplexOptions `json:"multiplex,omitempty"`
|
||||||
|
Transport *V2RayTransportOptions `json:"transport,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type VLESSUser struct {
|
type VLESSUser struct {
|
||||||
|
@ -16,11 +17,11 @@ type VLESSUser struct {
|
||||||
type VLESSOutboundOptions struct {
|
type VLESSOutboundOptions struct {
|
||||||
DialerOptions
|
DialerOptions
|
||||||
ServerOptions
|
ServerOptions
|
||||||
UUID string `json:"uuid"`
|
UUID string `json:"uuid"`
|
||||||
Flow string `json:"flow,omitempty"`
|
Flow string `json:"flow,omitempty"`
|
||||||
Network NetworkList `json:"network,omitempty"`
|
Network NetworkList `json:"network,omitempty"`
|
||||||
TLS *OutboundTLSOptions `json:"tls,omitempty"`
|
TLS *OutboundTLSOptions `json:"tls,omitempty"`
|
||||||
Multiplex *MultiplexOptions `json:"multiplex,omitempty"`
|
Multiplex *OutboundMultiplexOptions `json:"multiplex,omitempty"`
|
||||||
Transport *V2RayTransportOptions `json:"transport,omitempty"`
|
Transport *V2RayTransportOptions `json:"transport,omitempty"`
|
||||||
PacketEncoding *string `json:"packet_encoding,omitempty"`
|
PacketEncoding *string `json:"packet_encoding,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,10 @@ package option
|
||||||
|
|
||||||
type VMessInboundOptions struct {
|
type VMessInboundOptions struct {
|
||||||
ListenOptions
|
ListenOptions
|
||||||
Users []VMessUser `json:"users,omitempty"`
|
Users []VMessUser `json:"users,omitempty"`
|
||||||
TLS *InboundTLSOptions `json:"tls,omitempty"`
|
TLS *InboundTLSOptions `json:"tls,omitempty"`
|
||||||
Transport *V2RayTransportOptions `json:"transport,omitempty"`
|
Multiplex *InboundMultiplexOptions `json:"multiplex,omitempty"`
|
||||||
|
Transport *V2RayTransportOptions `json:"transport,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type VMessUser struct {
|
type VMessUser struct {
|
||||||
|
@ -16,14 +17,14 @@ type VMessUser struct {
|
||||||
type VMessOutboundOptions struct {
|
type VMessOutboundOptions struct {
|
||||||
DialerOptions
|
DialerOptions
|
||||||
ServerOptions
|
ServerOptions
|
||||||
UUID string `json:"uuid"`
|
UUID string `json:"uuid"`
|
||||||
Security string `json:"security"`
|
Security string `json:"security"`
|
||||||
AlterId int `json:"alter_id,omitempty"`
|
AlterId int `json:"alter_id,omitempty"`
|
||||||
GlobalPadding bool `json:"global_padding,omitempty"`
|
GlobalPadding bool `json:"global_padding,omitempty"`
|
||||||
AuthenticatedLength bool `json:"authenticated_length,omitempty"`
|
AuthenticatedLength bool `json:"authenticated_length,omitempty"`
|
||||||
Network NetworkList `json:"network,omitempty"`
|
Network NetworkList `json:"network,omitempty"`
|
||||||
TLS *OutboundTLSOptions `json:"tls,omitempty"`
|
TLS *OutboundTLSOptions `json:"tls,omitempty"`
|
||||||
PacketEncoding string `json:"packet_encoding,omitempty"`
|
PacketEncoding string `json:"packet_encoding,omitempty"`
|
||||||
Multiplex *MultiplexOptions `json:"multiplex,omitempty"`
|
Multiplex *OutboundMultiplexOptions `json:"multiplex,omitempty"`
|
||||||
Transport *V2RayTransportOptions `json:"transport,omitempty"`
|
Transport *V2RayTransportOptions `json:"transport,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,9 +62,9 @@ func NewShadowsocks(ctx context.Context, router adapter.Router, logger log.Conte
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
uotOptions := common.PtrValueOrDefault(options.UDPOverTCPOptions)
|
uotOptions := common.PtrValueOrDefault(options.UDPOverTCP)
|
||||||
if !uotOptions.Enabled {
|
if !uotOptions.Enabled {
|
||||||
outbound.multiplexDialer, err = mux.NewClientWithOptions((*shadowsocksDialer)(outbound), common.PtrValueOrDefault(options.MultiplexOptions))
|
outbound.multiplexDialer, err = mux.NewClientWithOptions((*shadowsocksDialer)(outbound), logger, common.PtrValueOrDefault(options.Multiplex))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ func NewSocks(router adapter.Router, logger log.ContextLogger, tag string, optio
|
||||||
client: socks.NewClient(outboundDialer, options.ServerOptions.Build(), version, options.Username, options.Password),
|
client: socks.NewClient(outboundDialer, options.ServerOptions.Build(), version, options.Username, options.Password),
|
||||||
resolve: version == socks.Version4,
|
resolve: version == socks.Version4,
|
||||||
}
|
}
|
||||||
uotOptions := common.PtrValueOrDefault(options.UDPOverTCPOptions)
|
uotOptions := common.PtrValueOrDefault(options.UDPOverTCP)
|
||||||
if uotOptions.Enabled {
|
if uotOptions.Enabled {
|
||||||
outbound.uotClient = &uot.Client{
|
outbound.uotClient = &uot.Client{
|
||||||
Dialer: outbound.client,
|
Dialer: outbound.client,
|
||||||
|
|
|
@ -62,7 +62,7 @@ func NewTrojan(ctx context.Context, router adapter.Router, logger log.ContextLog
|
||||||
return nil, E.Cause(err, "create client transport: ", options.Transport.Type)
|
return nil, E.Cause(err, "create client transport: ", options.Transport.Type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
outbound.multiplexDialer, err = mux.NewClientWithOptions((*trojanDialer)(outbound), common.PtrValueOrDefault(options.Multiplex))
|
outbound.multiplexDialer, err = mux.NewClientWithOptions((*trojanDialer)(outbound), logger, common.PtrValueOrDefault(options.Multiplex))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,7 @@ func NewVLESS(ctx context.Context, router adapter.Router, logger log.ContextLogg
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
outbound.multiplexDialer, err = mux.NewClientWithOptions((*vlessDialer)(outbound), common.PtrValueOrDefault(options.Multiplex))
|
outbound.multiplexDialer, err = mux.NewClientWithOptions((*vlessDialer)(outbound), logger, common.PtrValueOrDefault(options.Multiplex))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@ func NewVMess(ctx context.Context, router adapter.Router, logger log.ContextLogg
|
||||||
return nil, E.Cause(err, "create client transport: ", options.Transport.Type)
|
return nil, E.Cause(err, "create client transport: ", options.Transport.Type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
outbound.multiplexDialer, err = mux.NewClientWithOptions((*vmessDialer)(outbound), common.PtrValueOrDefault(options.Multiplex))
|
outbound.multiplexDialer, err = mux.NewClientWithOptions((*vmessDialer)(outbound), logger, common.PtrValueOrDefault(options.Multiplex))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@ import (
|
||||||
"github.com/sagernet/sing-box/common/dialer"
|
"github.com/sagernet/sing-box/common/dialer"
|
||||||
"github.com/sagernet/sing-box/common/geoip"
|
"github.com/sagernet/sing-box/common/geoip"
|
||||||
"github.com/sagernet/sing-box/common/geosite"
|
"github.com/sagernet/sing-box/common/geosite"
|
||||||
"github.com/sagernet/sing-box/common/mux"
|
|
||||||
"github.com/sagernet/sing-box/common/process"
|
"github.com/sagernet/sing-box/common/process"
|
||||||
"github.com/sagernet/sing-box/common/sniff"
|
"github.com/sagernet/sing-box/common/sniff"
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
|
@ -27,6 +26,7 @@ import (
|
||||||
"github.com/sagernet/sing-box/outbound"
|
"github.com/sagernet/sing-box/outbound"
|
||||||
"github.com/sagernet/sing-box/transport/fakeip"
|
"github.com/sagernet/sing-box/transport/fakeip"
|
||||||
"github.com/sagernet/sing-dns"
|
"github.com/sagernet/sing-dns"
|
||||||
|
mux "github.com/sagernet/sing-mux"
|
||||||
"github.com/sagernet/sing-tun"
|
"github.com/sagernet/sing-tun"
|
||||||
"github.com/sagernet/sing-vmess"
|
"github.com/sagernet/sing-vmess"
|
||||||
"github.com/sagernet/sing/common"
|
"github.com/sagernet/sing/common"
|
||||||
|
@ -606,30 +606,13 @@ func (r *Router) RouteConnection(ctx context.Context, conn net.Conn, metadata ad
|
||||||
metadata.Network = N.NetworkTCP
|
metadata.Network = N.NetworkTCP
|
||||||
switch metadata.Destination.Fqdn {
|
switch metadata.Destination.Fqdn {
|
||||||
case mux.Destination.Fqdn:
|
case mux.Destination.Fqdn:
|
||||||
r.logger.InfoContext(ctx, "inbound multiplex connection")
|
return E.New("global multiplex is deprecated since sing-box v1.7.0, enable multiplex in inbound options instead.")
|
||||||
handler := adapter.NewUpstreamHandler(metadata, r.RouteConnection, r.RoutePacketConnection, r)
|
|
||||||
return mux.HandleConnection(ctx, handler, r.logger, conn, adapter.UpstreamMetadata(metadata))
|
|
||||||
case vmess.MuxDestination.Fqdn:
|
case vmess.MuxDestination.Fqdn:
|
||||||
r.logger.InfoContext(ctx, "inbound legacy multiplex connection")
|
return E.New("global multiplex (v2ray legacy) not supported since sing-box v1.7.0.")
|
||||||
return vmess.HandleMuxConnection(ctx, conn, adapter.NewUpstreamHandler(metadata, r.RouteConnection, r.RoutePacketConnection, r))
|
|
||||||
case uot.MagicAddress:
|
case uot.MagicAddress:
|
||||||
request, err := uot.ReadRequest(conn)
|
return E.New("global UoT not supported since sing-box v1.7.0.")
|
||||||
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.RoutePacketConnection(ctx, uot.NewConn(conn, *request), metadata)
|
|
||||||
case uot.LegacyMagicAddress:
|
case uot.LegacyMagicAddress:
|
||||||
r.logger.InfoContext(ctx, "inbound legacy UoT connection")
|
return E.New("global UoT (legacy) not supported since sing-box v1.7.0.")
|
||||||
metadata.Domain = metadata.Destination.Fqdn
|
|
||||||
metadata.Destination = M.Socksaddr{Addr: netip.IPv4Unspecified()}
|
|
||||||
return r.RoutePacketConnection(ctx, uot.NewConn(conn, uot.Request{}), metadata)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.fakeIPStore != nil && r.fakeIPStore.Contains(metadata.Destination.Addr) {
|
if r.fakeIPStore != nil && r.fakeIPStore.Contains(metadata.Destination.Addr) {
|
||||||
|
|
346
test/brutal_test.go
Normal file
346
test/brutal_test.go
Normal file
|
@ -0,0 +1,346 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/netip"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
C "github.com/sagernet/sing-box/constant"
|
||||||
|
"github.com/sagernet/sing-box/option"
|
||||||
|
"github.com/sagernet/sing-shadowsocks/shadowaead_2022"
|
||||||
|
|
||||||
|
"github.com/gofrs/uuid/v5"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestBrutalShadowsocks(t *testing.T) {
|
||||||
|
method := shadowaead_2022.List[0]
|
||||||
|
password := mkBase64(t, 16)
|
||||||
|
startInstance(t, option.Options{
|
||||||
|
Inbounds: []option.Inbound{
|
||||||
|
{
|
||||||
|
Type: C.TypeMixed,
|
||||||
|
Tag: "mixed-in",
|
||||||
|
MixedOptions: option.HTTPMixedInboundOptions{
|
||||||
|
ListenOptions: option.ListenOptions{
|
||||||
|
Listen: option.NewListenAddress(netip.IPv4Unspecified()),
|
||||||
|
ListenPort: clientPort,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: C.TypeShadowsocks,
|
||||||
|
ShadowsocksOptions: option.ShadowsocksInboundOptions{
|
||||||
|
ListenOptions: option.ListenOptions{
|
||||||
|
Listen: option.NewListenAddress(netip.IPv4Unspecified()),
|
||||||
|
ListenPort: serverPort,
|
||||||
|
},
|
||||||
|
Method: method,
|
||||||
|
Password: password,
|
||||||
|
Multiplex: &option.InboundMultiplexOptions{
|
||||||
|
Enabled: true,
|
||||||
|
Brutal: &option.BrutalOptions{
|
||||||
|
Enabled: true,
|
||||||
|
UpMbps: 100,
|
||||||
|
DownMbps: 100,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Outbounds: []option.Outbound{
|
||||||
|
{
|
||||||
|
Type: C.TypeDirect,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: C.TypeShadowsocks,
|
||||||
|
Tag: "ss-out",
|
||||||
|
ShadowsocksOptions: option.ShadowsocksOutboundOptions{
|
||||||
|
ServerOptions: option.ServerOptions{
|
||||||
|
Server: "127.0.0.1",
|
||||||
|
ServerPort: serverPort,
|
||||||
|
},
|
||||||
|
Method: method,
|
||||||
|
Password: password,
|
||||||
|
Multiplex: &option.OutboundMultiplexOptions{
|
||||||
|
Enabled: true,
|
||||||
|
Protocol: "smux",
|
||||||
|
Padding: true,
|
||||||
|
Brutal: &option.BrutalOptions{
|
||||||
|
Enabled: true,
|
||||||
|
UpMbps: 100,
|
||||||
|
DownMbps: 100,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Route: &option.RouteOptions{
|
||||||
|
Rules: []option.Rule{
|
||||||
|
{
|
||||||
|
DefaultOptions: option.DefaultRule{
|
||||||
|
Inbound: []string{"mixed-in"},
|
||||||
|
Outbound: "ss-out",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
testSuit(t, clientPort, testPort)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBrutalTrojan(t *testing.T) {
|
||||||
|
_, certPem, keyPem := createSelfSignedCertificate(t, "example.org")
|
||||||
|
password := mkBase64(t, 16)
|
||||||
|
startInstance(t, option.Options{
|
||||||
|
Inbounds: []option.Inbound{
|
||||||
|
{
|
||||||
|
Type: C.TypeMixed,
|
||||||
|
Tag: "mixed-in",
|
||||||
|
MixedOptions: option.HTTPMixedInboundOptions{
|
||||||
|
ListenOptions: option.ListenOptions{
|
||||||
|
Listen: option.NewListenAddress(netip.IPv4Unspecified()),
|
||||||
|
ListenPort: clientPort,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: C.TypeTrojan,
|
||||||
|
TrojanOptions: option.TrojanInboundOptions{
|
||||||
|
ListenOptions: option.ListenOptions{
|
||||||
|
Listen: option.NewListenAddress(netip.IPv4Unspecified()),
|
||||||
|
ListenPort: serverPort,
|
||||||
|
},
|
||||||
|
Users: []option.TrojanUser{{Password: password}},
|
||||||
|
Multiplex: &option.InboundMultiplexOptions{
|
||||||
|
Enabled: true,
|
||||||
|
Brutal: &option.BrutalOptions{
|
||||||
|
Enabled: true,
|
||||||
|
UpMbps: 100,
|
||||||
|
DownMbps: 100,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TLS: &option.InboundTLSOptions{
|
||||||
|
Enabled: true,
|
||||||
|
ServerName: "example.org",
|
||||||
|
CertificatePath: certPem,
|
||||||
|
KeyPath: keyPem,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Outbounds: []option.Outbound{
|
||||||
|
{
|
||||||
|
Type: C.TypeDirect,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: C.TypeTrojan,
|
||||||
|
Tag: "ss-out",
|
||||||
|
TrojanOptions: option.TrojanOutboundOptions{
|
||||||
|
ServerOptions: option.ServerOptions{
|
||||||
|
Server: "127.0.0.1",
|
||||||
|
ServerPort: serverPort,
|
||||||
|
},
|
||||||
|
Password: password,
|
||||||
|
Multiplex: &option.OutboundMultiplexOptions{
|
||||||
|
Enabled: true,
|
||||||
|
Protocol: "yamux",
|
||||||
|
Padding: true,
|
||||||
|
Brutal: &option.BrutalOptions{
|
||||||
|
Enabled: true,
|
||||||
|
UpMbps: 100,
|
||||||
|
DownMbps: 100,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TLS: &option.OutboundTLSOptions{
|
||||||
|
Enabled: true,
|
||||||
|
ServerName: "example.org",
|
||||||
|
CertificatePath: certPem,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Route: &option.RouteOptions{
|
||||||
|
Rules: []option.Rule{
|
||||||
|
{
|
||||||
|
DefaultOptions: option.DefaultRule{
|
||||||
|
Inbound: []string{"mixed-in"},
|
||||||
|
Outbound: "ss-out",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
testSuit(t, clientPort, testPort)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBrutalVMess(t *testing.T) {
|
||||||
|
user, _ := uuid.NewV4()
|
||||||
|
startInstance(t, option.Options{
|
||||||
|
Inbounds: []option.Inbound{
|
||||||
|
{
|
||||||
|
Type: C.TypeMixed,
|
||||||
|
Tag: "mixed-in",
|
||||||
|
MixedOptions: option.HTTPMixedInboundOptions{
|
||||||
|
ListenOptions: option.ListenOptions{
|
||||||
|
Listen: option.NewListenAddress(netip.IPv4Unspecified()),
|
||||||
|
ListenPort: clientPort,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: C.TypeVMess,
|
||||||
|
VMessOptions: option.VMessInboundOptions{
|
||||||
|
ListenOptions: option.ListenOptions{
|
||||||
|
Listen: option.NewListenAddress(netip.IPv4Unspecified()),
|
||||||
|
ListenPort: serverPort,
|
||||||
|
},
|
||||||
|
Users: []option.VMessUser{{UUID: user.String()}},
|
||||||
|
Multiplex: &option.InboundMultiplexOptions{
|
||||||
|
Enabled: true,
|
||||||
|
Brutal: &option.BrutalOptions{
|
||||||
|
Enabled: true,
|
||||||
|
UpMbps: 100,
|
||||||
|
DownMbps: 100,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Outbounds: []option.Outbound{
|
||||||
|
{
|
||||||
|
Type: C.TypeDirect,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: C.TypeVMess,
|
||||||
|
Tag: "ss-out",
|
||||||
|
VMessOptions: option.VMessOutboundOptions{
|
||||||
|
ServerOptions: option.ServerOptions{
|
||||||
|
Server: "127.0.0.1",
|
||||||
|
ServerPort: serverPort,
|
||||||
|
},
|
||||||
|
UUID: user.String(),
|
||||||
|
Multiplex: &option.OutboundMultiplexOptions{
|
||||||
|
Enabled: true,
|
||||||
|
Protocol: "h2mux",
|
||||||
|
Padding: true,
|
||||||
|
Brutal: &option.BrutalOptions{
|
||||||
|
Enabled: true,
|
||||||
|
UpMbps: 100,
|
||||||
|
DownMbps: 100,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Route: &option.RouteOptions{
|
||||||
|
Rules: []option.Rule{
|
||||||
|
{
|
||||||
|
DefaultOptions: option.DefaultRule{
|
||||||
|
Inbound: []string{"mixed-in"},
|
||||||
|
Outbound: "ss-out",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
testSuit(t, clientPort, testPort)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBrutalVLESS(t *testing.T) {
|
||||||
|
user, _ := uuid.NewV4()
|
||||||
|
startInstance(t, option.Options{
|
||||||
|
Inbounds: []option.Inbound{
|
||||||
|
{
|
||||||
|
Type: C.TypeMixed,
|
||||||
|
Tag: "mixed-in",
|
||||||
|
MixedOptions: option.HTTPMixedInboundOptions{
|
||||||
|
ListenOptions: option.ListenOptions{
|
||||||
|
Listen: option.NewListenAddress(netip.IPv4Unspecified()),
|
||||||
|
ListenPort: clientPort,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: C.TypeVLESS,
|
||||||
|
VLESSOptions: option.VLESSInboundOptions{
|
||||||
|
ListenOptions: option.ListenOptions{
|
||||||
|
Listen: option.NewListenAddress(netip.IPv4Unspecified()),
|
||||||
|
ListenPort: serverPort,
|
||||||
|
},
|
||||||
|
Users: []option.VLESSUser{{UUID: user.String()}},
|
||||||
|
Multiplex: &option.InboundMultiplexOptions{
|
||||||
|
Enabled: true,
|
||||||
|
Brutal: &option.BrutalOptions{
|
||||||
|
Enabled: true,
|
||||||
|
UpMbps: 100,
|
||||||
|
DownMbps: 100,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TLS: &option.InboundTLSOptions{
|
||||||
|
Enabled: true,
|
||||||
|
ServerName: "google.com",
|
||||||
|
Reality: &option.InboundRealityOptions{
|
||||||
|
Enabled: true,
|
||||||
|
Handshake: option.InboundRealityHandshakeOptions{
|
||||||
|
ServerOptions: option.ServerOptions{
|
||||||
|
Server: "google.com",
|
||||||
|
ServerPort: 443,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ShortID: []string{"0123456789abcdef"},
|
||||||
|
PrivateKey: "UuMBgl7MXTPx9inmQp2UC7Jcnwc6XYbwDNebonM-FCc",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Outbounds: []option.Outbound{
|
||||||
|
{
|
||||||
|
Type: C.TypeDirect,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: C.TypeVLESS,
|
||||||
|
Tag: "ss-out",
|
||||||
|
VLESSOptions: option.VLESSOutboundOptions{
|
||||||
|
ServerOptions: option.ServerOptions{
|
||||||
|
Server: "127.0.0.1",
|
||||||
|
ServerPort: serverPort,
|
||||||
|
},
|
||||||
|
UUID: user.String(),
|
||||||
|
TLS: &option.OutboundTLSOptions{
|
||||||
|
Enabled: true,
|
||||||
|
ServerName: "google.com",
|
||||||
|
Reality: &option.OutboundRealityOptions{
|
||||||
|
Enabled: true,
|
||||||
|
ShortID: "0123456789abcdef",
|
||||||
|
PublicKey: "jNXHt1yRo0vDuchQlIP6Z0ZvjT3KtzVI-T4E7RoLJS0",
|
||||||
|
},
|
||||||
|
UTLS: &option.OutboundUTLSOptions{
|
||||||
|
Enabled: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Multiplex: &option.OutboundMultiplexOptions{
|
||||||
|
Enabled: true,
|
||||||
|
Protocol: "h2mux",
|
||||||
|
Padding: true,
|
||||||
|
Brutal: &option.BrutalOptions{
|
||||||
|
Enabled: true,
|
||||||
|
UpMbps: 100,
|
||||||
|
DownMbps: 100,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Route: &option.RouteOptions{
|
||||||
|
Rules: []option.Rule{
|
||||||
|
{
|
||||||
|
DefaultOptions: option.DefaultRule{
|
||||||
|
Inbound: []string{"mixed-in"},
|
||||||
|
Outbound: "ss-out",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
testSuit(t, clientPort, testPort)
|
||||||
|
}
|
16
test/go.mod
16
test/go.mod
|
@ -11,11 +11,11 @@ require (
|
||||||
github.com/docker/go-connections v0.4.0
|
github.com/docker/go-connections v0.4.0
|
||||||
github.com/gofrs/uuid/v5 v5.0.0
|
github.com/gofrs/uuid/v5 v5.0.0
|
||||||
github.com/sagernet/quic-go v0.0.0-20231008035953-32727fef9460
|
github.com/sagernet/quic-go v0.0.0-20231008035953-32727fef9460
|
||||||
github.com/sagernet/sing v0.2.17
|
github.com/sagernet/sing v0.2.18-0.20231119032432-6a556bfa50cc
|
||||||
github.com/sagernet/sing-dns v0.1.11
|
github.com/sagernet/sing-dns v0.1.11
|
||||||
github.com/sagernet/sing-quic v0.1.4
|
github.com/sagernet/sing-quic v0.1.4
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.5
|
github.com/sagernet/sing-shadowsocks v0.2.5
|
||||||
github.com/sagernet/sing-shadowsocks2 v0.1.4
|
github.com/sagernet/sing-shadowsocks2 v0.1.5
|
||||||
github.com/spyzhov/ajson v0.9.0
|
github.com/spyzhov/ajson v0.9.0
|
||||||
github.com/stretchr/testify v1.8.4
|
github.com/stretchr/testify v1.8.4
|
||||||
go.uber.org/goleak v1.3.0
|
go.uber.org/goleak v1.3.0
|
||||||
|
@ -40,6 +40,8 @@ require (
|
||||||
github.com/go-chi/render v1.0.3 // indirect
|
github.com/go-chi/render v1.0.3 // indirect
|
||||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||||
|
github.com/gobwas/httphead v0.1.0 // indirect
|
||||||
|
github.com/gobwas/pool v0.2.1 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/golang/protobuf v1.5.3 // indirect
|
github.com/golang/protobuf v1.5.3 // indirect
|
||||||
github.com/google/btree v1.1.2 // indirect
|
github.com/google/btree v1.1.2 // indirect
|
||||||
|
@ -70,18 +72,18 @@ require (
|
||||||
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a // indirect
|
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a // indirect
|
||||||
github.com/sagernet/cloudflare-tls v0.0.0-20230829051644-4a68352d0c4a // indirect
|
github.com/sagernet/cloudflare-tls v0.0.0-20230829051644-4a68352d0c4a // indirect
|
||||||
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 // indirect
|
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 // indirect
|
||||||
github.com/sagernet/gvisor v0.0.0-20230930141345-5fef6f2e17ab // indirect
|
github.com/sagernet/gvisor v0.0.0-20231119034329-07cfb6aaf930 // indirect
|
||||||
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 // indirect
|
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 // indirect
|
||||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 // indirect
|
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 // indirect
|
||||||
github.com/sagernet/sing-mux v0.1.4 // indirect
|
github.com/sagernet/sing-mux v0.1.5-0.20231109075101-6b086ed6bb07 // indirect
|
||||||
github.com/sagernet/sing-shadowtls v0.1.4 // indirect
|
github.com/sagernet/sing-shadowtls v0.1.4 // indirect
|
||||||
github.com/sagernet/sing-tun v0.1.20 // indirect
|
github.com/sagernet/sing-tun v0.1.21-0.20231119035513-f6ea97c5af71 // indirect
|
||||||
github.com/sagernet/sing-vmess v0.1.8 // indirect
|
github.com/sagernet/sing-vmess v0.1.8 // indirect
|
||||||
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 // indirect
|
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 // indirect
|
||||||
github.com/sagernet/tfo-go v0.0.0-20230816093905-5a5c285d44a6 // indirect
|
github.com/sagernet/tfo-go v0.0.0-20230816093905-5a5c285d44a6 // indirect
|
||||||
github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2 // indirect
|
github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2 // indirect
|
||||||
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e // indirect
|
|
||||||
github.com/sagernet/wireguard-go v0.0.0-20230807125731-5d4a7ef2dc5f // indirect
|
github.com/sagernet/wireguard-go v0.0.0-20230807125731-5d4a7ef2dc5f // indirect
|
||||||
|
github.com/sagernet/ws v0.0.0-20231030053741-7d481eb31bed // indirect
|
||||||
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 // indirect
|
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 // indirect
|
||||||
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 // indirect
|
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 // indirect
|
||||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
|
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
|
||||||
|
@ -94,7 +96,7 @@ require (
|
||||||
golang.org/x/mod v0.14.0 // indirect
|
golang.org/x/mod v0.14.0 // indirect
|
||||||
golang.org/x/sys v0.14.0 // indirect
|
golang.org/x/sys v0.14.0 // indirect
|
||||||
golang.org/x/text v0.14.0 // indirect
|
golang.org/x/text v0.14.0 // indirect
|
||||||
golang.org/x/time v0.3.0 // indirect
|
golang.org/x/time v0.4.0 // indirect
|
||||||
golang.org/x/tools v0.15.0 // indirect
|
golang.org/x/tools v0.15.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
|
||||||
google.golang.org/grpc v1.59.0 // indirect
|
google.golang.org/grpc v1.59.0 // indirect
|
||||||
|
|
33
test/go.sum
33
test/go.sum
|
@ -43,6 +43,10 @@ github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
||||||
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
||||||
|
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
|
||||||
|
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
|
||||||
|
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
|
||||||
|
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
||||||
github.com/gofrs/uuid/v5 v5.0.0 h1:p544++a97kEL+svbcFbCQVM9KFu0Yo25UoISXGNNH9M=
|
github.com/gofrs/uuid/v5 v5.0.0 h1:p544++a97kEL+svbcFbCQVM9KFu0Yo25UoISXGNNH9M=
|
||||||
github.com/gofrs/uuid/v5 v5.0.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
|
github.com/gofrs/uuid/v5 v5.0.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
|
||||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||||
|
@ -117,8 +121,8 @@ github.com/sagernet/cloudflare-tls v0.0.0-20230829051644-4a68352d0c4a h1:wZHruBx
|
||||||
github.com/sagernet/cloudflare-tls v0.0.0-20230829051644-4a68352d0c4a/go.mod h1:dNV1ZP9y3qx5ltULeKaQZTZWTLHflgW5DES+Ses7cMI=
|
github.com/sagernet/cloudflare-tls v0.0.0-20230829051644-4a68352d0c4a/go.mod h1:dNV1ZP9y3qx5ltULeKaQZTZWTLHflgW5DES+Ses7cMI=
|
||||||
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 h1:5+m7c6AkmAylhauulqN/c5dnh8/KssrE9c93TQrXldA=
|
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 h1:5+m7c6AkmAylhauulqN/c5dnh8/KssrE9c93TQrXldA=
|
||||||
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61/go.mod h1:QUQ4RRHD6hGGHdFMEtR8T2P6GS6R3D/CXKdaYHKKXms=
|
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61/go.mod h1:QUQ4RRHD6hGGHdFMEtR8T2P6GS6R3D/CXKdaYHKKXms=
|
||||||
github.com/sagernet/gvisor v0.0.0-20230930141345-5fef6f2e17ab h1:u+xQoi/Yc6bNUvTfrDD6HhGRybn2lzrhf5vmS+wb4Ho=
|
github.com/sagernet/gvisor v0.0.0-20231119034329-07cfb6aaf930 h1:dSPgjIw0CT6ISLeEh8Q20dZMBMFCcEceo23+LncRcNQ=
|
||||||
github.com/sagernet/gvisor v0.0.0-20230930141345-5fef6f2e17ab/go.mod h1:3akUhSHSVtLuJaYcW5JPepUraBOW06Ibz2HKwaK5rOk=
|
github.com/sagernet/gvisor v0.0.0-20231119034329-07cfb6aaf930/go.mod h1:JpKHkOYgh4wLwrX2BhH3ZIvCvazCkTnPeEcmigZJfHY=
|
||||||
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE=
|
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE=
|
||||||
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
|
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
|
||||||
github.com/sagernet/quic-go v0.0.0-20231008035953-32727fef9460 h1:dAe4OIJAtE0nHOzTHhAReQteh3+sa63rvXbuIpbeOTY=
|
github.com/sagernet/quic-go v0.0.0-20231008035953-32727fef9460 h1:dAe4OIJAtE0nHOzTHhAReQteh3+sa63rvXbuIpbeOTY=
|
||||||
|
@ -127,22 +131,22 @@ github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byL
|
||||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
|
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
|
||||||
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
||||||
github.com/sagernet/sing v0.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk=
|
github.com/sagernet/sing v0.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk=
|
||||||
github.com/sagernet/sing v0.2.17 h1:vMPKb3MV0Aa5ws4dCJkRI8XEjrsUcDn810czd0FwmzI=
|
github.com/sagernet/sing v0.2.18-0.20231119032432-6a556bfa50cc h1:dmU0chO0QrBpARo8sqyOc+mvPLW+qux4ca16kb2WIc8=
|
||||||
github.com/sagernet/sing v0.2.17/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo=
|
github.com/sagernet/sing v0.2.18-0.20231119032432-6a556bfa50cc/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo=
|
||||||
github.com/sagernet/sing-dns v0.1.11 h1:PPrMCVVrAeR3f5X23I+cmvacXJ+kzuyAsBiWyUKhGSE=
|
github.com/sagernet/sing-dns v0.1.11 h1:PPrMCVVrAeR3f5X23I+cmvacXJ+kzuyAsBiWyUKhGSE=
|
||||||
github.com/sagernet/sing-dns v0.1.11/go.mod h1:zJ/YjnYB61SYE+ubMcMqVdpaSvsyQ2iShQGO3vuLvvE=
|
github.com/sagernet/sing-dns v0.1.11/go.mod h1:zJ/YjnYB61SYE+ubMcMqVdpaSvsyQ2iShQGO3vuLvvE=
|
||||||
github.com/sagernet/sing-mux v0.1.4 h1:BPNPOQr6HkXG3iY/BrfvUKUl+A7gYsGKVSxvoR3PO50=
|
github.com/sagernet/sing-mux v0.1.5-0.20231109075101-6b086ed6bb07 h1:ncKb5tVOsCQgCsv6UpsA0jinbNb5OQ5GMPJlyQP3EHM=
|
||||||
github.com/sagernet/sing-mux v0.1.4/go.mod h1:dKvcu/sb3fZ88uGv9vzAqUej6J4W+pHu5GqjRuFwAWs=
|
github.com/sagernet/sing-mux v0.1.5-0.20231109075101-6b086ed6bb07/go.mod h1:u/MZf32xPG8jEKe3t+xUV67EBnKtDtCaPhsJQOQGUYU=
|
||||||
github.com/sagernet/sing-quic v0.1.4 h1:F5KRGXMXKQEmP8VrzVollf9HWcRqggcuG9nRCL+5IJ8=
|
github.com/sagernet/sing-quic v0.1.4 h1:F5KRGXMXKQEmP8VrzVollf9HWcRqggcuG9nRCL+5IJ8=
|
||||||
github.com/sagernet/sing-quic v0.1.4/go.mod h1:aXHVP+osF3w5wJzoWZbJSrX3ceJiU9QMd0KPnKV6C/o=
|
github.com/sagernet/sing-quic v0.1.4/go.mod h1:aXHVP+osF3w5wJzoWZbJSrX3ceJiU9QMd0KPnKV6C/o=
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.5 h1:qxIttos4xu6ii7MTVJYA8EFQR7Q3KG6xMqmLJIFtBaY=
|
github.com/sagernet/sing-shadowsocks v0.2.5 h1:qxIttos4xu6ii7MTVJYA8EFQR7Q3KG6xMqmLJIFtBaY=
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.5/go.mod h1:MGWGkcU2xW2G2mfArT9/QqpVLOGU+dBaahZCtPHdt7A=
|
github.com/sagernet/sing-shadowsocks v0.2.5/go.mod h1:MGWGkcU2xW2G2mfArT9/QqpVLOGU+dBaahZCtPHdt7A=
|
||||||
github.com/sagernet/sing-shadowsocks2 v0.1.4 h1:vht2M8t3m5DTgXR2j24KbYOygG5aOp+MUhpQnAux728=
|
github.com/sagernet/sing-shadowsocks2 v0.1.5 h1:JDeAJ4ZWlYZ7F6qEVdDKPhQEangxKw/JtmU+i/YfCYE=
|
||||||
github.com/sagernet/sing-shadowsocks2 v0.1.4/go.mod h1:Mgdee99NxxNd5Zld3ixIs18yVs4x2dI2VTDDE1N14Wc=
|
github.com/sagernet/sing-shadowsocks2 v0.1.5/go.mod h1:KF65y8lI5PGHyMgRZGYXYsH9ilgRc/yr+NYbSNGuBm4=
|
||||||
github.com/sagernet/sing-shadowtls v0.1.4 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k=
|
github.com/sagernet/sing-shadowtls v0.1.4 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k=
|
||||||
github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4=
|
github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4=
|
||||||
github.com/sagernet/sing-tun v0.1.20 h1:vYWo/w6fkKc8I1WP/IB8eBWZVsGIC6eoEoNR6XqEDlY=
|
github.com/sagernet/sing-tun v0.1.21-0.20231119035513-f6ea97c5af71 h1:WQi0TwhjbSNFFbxybIgAUSjVvo7uWSsLD28ldoM2avY=
|
||||||
github.com/sagernet/sing-tun v0.1.20/go.mod h1:6kkPL/u9tWcLFfu55VbwMDnO++17cUihSmImkZjdZro=
|
github.com/sagernet/sing-tun v0.1.21-0.20231119035513-f6ea97c5af71/go.mod h1:hyzA4gDWbeg2SXklqPDswBKa//QcjlZqKw9aPcNdQ9A=
|
||||||
github.com/sagernet/sing-vmess v0.1.8 h1:XVWad1RpTy9b5tPxdm5MCU8cGfrTGdR8qCq6HV2aCNc=
|
github.com/sagernet/sing-vmess v0.1.8 h1:XVWad1RpTy9b5tPxdm5MCU8cGfrTGdR8qCq6HV2aCNc=
|
||||||
github.com/sagernet/sing-vmess v0.1.8/go.mod h1:vhx32UNzTDUkNwOyIjcZQohre1CaytquC5mPplId8uA=
|
github.com/sagernet/sing-vmess v0.1.8/go.mod h1:vhx32UNzTDUkNwOyIjcZQohre1CaytquC5mPplId8uA=
|
||||||
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 h1:HuE6xSwco/Xed8ajZ+coeYLmioq0Qp1/Z2zczFaV8as=
|
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 h1:HuE6xSwco/Xed8ajZ+coeYLmioq0Qp1/Z2zczFaV8as=
|
||||||
|
@ -151,10 +155,10 @@ github.com/sagernet/tfo-go v0.0.0-20230816093905-5a5c285d44a6 h1:Px+hN4Vzgx+iCGV
|
||||||
github.com/sagernet/tfo-go v0.0.0-20230816093905-5a5c285d44a6/go.mod h1:zovq6vTvEM6ECiqE3Eeb9rpIylPpamPcmrJ9tv0Bt0M=
|
github.com/sagernet/tfo-go v0.0.0-20230816093905-5a5c285d44a6/go.mod h1:zovq6vTvEM6ECiqE3Eeb9rpIylPpamPcmrJ9tv0Bt0M=
|
||||||
github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2 h1:kDUqhc9Vsk5HJuhfIATJ8oQwBmpOZJuozQG7Vk88lL4=
|
github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2 h1:kDUqhc9Vsk5HJuhfIATJ8oQwBmpOZJuozQG7Vk88lL4=
|
||||||
github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2/go.mod h1:JKQMZq/O2qnZjdrt+B57olmfgEmLtY9iiSIEYtWvoSM=
|
github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2/go.mod h1:JKQMZq/O2qnZjdrt+B57olmfgEmLtY9iiSIEYtWvoSM=
|
||||||
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e h1:7uw2njHFGE+VpWamge6o56j2RWk4omF6uLKKxMmcWvs=
|
|
||||||
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e/go.mod h1:45TUl8+gH4SIKr4ykREbxKWTxkDlSzFENzctB1dVRRY=
|
|
||||||
github.com/sagernet/wireguard-go v0.0.0-20230807125731-5d4a7ef2dc5f h1:Kvo8w8Y9lzFGB/7z09MJ3TR99TFtfI/IuY87Ygcycho=
|
github.com/sagernet/wireguard-go v0.0.0-20230807125731-5d4a7ef2dc5f h1:Kvo8w8Y9lzFGB/7z09MJ3TR99TFtfI/IuY87Ygcycho=
|
||||||
github.com/sagernet/wireguard-go v0.0.0-20230807125731-5d4a7ef2dc5f/go.mod h1:mySs0abhpc/gLlvhoq7HP1RzOaRmIXVeZGCh++zoApk=
|
github.com/sagernet/wireguard-go v0.0.0-20230807125731-5d4a7ef2dc5f/go.mod h1:mySs0abhpc/gLlvhoq7HP1RzOaRmIXVeZGCh++zoApk=
|
||||||
|
github.com/sagernet/ws v0.0.0-20231030053741-7d481eb31bed h1:90a510OeE9siSJoYsI8nSjPmA+u5ROMDts/ZkdNsuXY=
|
||||||
|
github.com/sagernet/ws v0.0.0-20231030053741-7d481eb31bed/go.mod h1:LtfoSK3+NG57tvnVEHgcuBW9ujgE8enPSgzgwStwCAA=
|
||||||
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 h1:rc/CcqLH3lh8n+csdOuDfP+NuykE0U6AeYSJJHKDgSg=
|
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 h1:rc/CcqLH3lh8n+csdOuDfP+NuykE0U6AeYSJJHKDgSg=
|
||||||
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9/go.mod h1:a/83NAfUXvEuLpmxDssAXxgUgrEy12MId3Wd7OTs76s=
|
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9/go.mod h1:a/83NAfUXvEuLpmxDssAXxgUgrEy12MId3Wd7OTs76s=
|
||||||
github.com/spyzhov/ajson v0.9.0 h1:tF46gJGOenYVj+k9K1U1XpCxVWhmiyY5PsVCAs1+OJ0=
|
github.com/spyzhov/ajson v0.9.0 h1:tF46gJGOenYVj+k9K1U1XpCxVWhmiyY5PsVCAs1+OJ0=
|
||||||
|
@ -222,6 +226,7 @@ golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||||
golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
|
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
|
||||||
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
@ -231,8 +236,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
golang.org/x/time v0.4.0 h1:Z81tqI5ddIoXDPvVQ7/7CC9TnLM7ubaFG2qXYd5BbYY=
|
||||||
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.4.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
|
|
@ -18,7 +18,7 @@ var muxProtocols = []string{
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVMessSMux(t *testing.T) {
|
func TestVMessSMux(t *testing.T) {
|
||||||
testVMessMux(t, option.MultiplexOptions{
|
testVMessMux(t, option.OutboundMultiplexOptions{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
Protocol: "smux",
|
Protocol: "smux",
|
||||||
})
|
})
|
||||||
|
@ -27,7 +27,7 @@ func TestVMessSMux(t *testing.T) {
|
||||||
func TestShadowsocksMux(t *testing.T) {
|
func TestShadowsocksMux(t *testing.T) {
|
||||||
for _, protocol := range muxProtocols {
|
for _, protocol := range muxProtocols {
|
||||||
t.Run(protocol, func(t *testing.T) {
|
t.Run(protocol, func(t *testing.T) {
|
||||||
testShadowsocksMux(t, option.MultiplexOptions{
|
testShadowsocksMux(t, option.OutboundMultiplexOptions{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
Protocol: protocol,
|
Protocol: protocol,
|
||||||
})
|
})
|
||||||
|
@ -36,7 +36,7 @@ func TestShadowsocksMux(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestShadowsockH2Mux(t *testing.T) {
|
func TestShadowsockH2Mux(t *testing.T) {
|
||||||
testShadowsocksMux(t, option.MultiplexOptions{
|
testShadowsocksMux(t, option.OutboundMultiplexOptions{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
Protocol: "h2mux",
|
Protocol: "h2mux",
|
||||||
Padding: true,
|
Padding: true,
|
||||||
|
@ -44,14 +44,14 @@ func TestShadowsockH2Mux(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestShadowsockSMuxPadding(t *testing.T) {
|
func TestShadowsockSMuxPadding(t *testing.T) {
|
||||||
testShadowsocksMux(t, option.MultiplexOptions{
|
testShadowsocksMux(t, option.OutboundMultiplexOptions{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
Protocol: "smux",
|
Protocol: "smux",
|
||||||
Padding: true,
|
Padding: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func testShadowsocksMux(t *testing.T, options option.MultiplexOptions) {
|
func testShadowsocksMux(t *testing.T, options option.OutboundMultiplexOptions) {
|
||||||
method := shadowaead_2022.List[0]
|
method := shadowaead_2022.List[0]
|
||||||
password := mkBase64(t, 16)
|
password := mkBase64(t, 16)
|
||||||
startInstance(t, option.Options{
|
startInstance(t, option.Options{
|
||||||
|
@ -90,9 +90,9 @@ func testShadowsocksMux(t *testing.T, options option.MultiplexOptions) {
|
||||||
Server: "127.0.0.1",
|
Server: "127.0.0.1",
|
||||||
ServerPort: serverPort,
|
ServerPort: serverPort,
|
||||||
},
|
},
|
||||||
Method: method,
|
Method: method,
|
||||||
Password: password,
|
Password: password,
|
||||||
MultiplexOptions: &options,
|
Multiplex: &options,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -110,7 +110,7 @@ func testShadowsocksMux(t *testing.T, options option.MultiplexOptions) {
|
||||||
testSuit(t, clientPort, testPort)
|
testSuit(t, clientPort, testPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testVMessMux(t *testing.T, options option.MultiplexOptions) {
|
func testVMessMux(t *testing.T, options option.OutboundMultiplexOptions) {
|
||||||
user, _ := uuid.NewV4()
|
user, _ := uuid.NewV4()
|
||||||
startInstance(t, option.Options{
|
startInstance(t, option.Options{
|
||||||
Inbounds: []option.Inbound{
|
Inbounds: []option.Inbound{
|
||||||
|
@ -136,6 +136,9 @@ func testVMessMux(t *testing.T, options option.MultiplexOptions) {
|
||||||
UUID: user.String(),
|
UUID: user.String(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Multiplex: &option.InboundMultiplexOptions{
|
||||||
|
Enabled: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -249,7 +249,7 @@ func TestShadowsocksUoT(t *testing.T) {
|
||||||
},
|
},
|
||||||
Method: method,
|
Method: method,
|
||||||
Password: password,
|
Password: password,
|
||||||
UDPOverTCPOptions: &option.UDPOverTCPOptions{
|
UDPOverTCP: &option.UDPOverTCPOptions{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue
Block a user