Compare commits

..
Author SHA1 Message Date
世界 331d16a279 documentation: Bump version 2023-10-30 21:47:03 +08:00
世界 b217fedc21 Add exclude route support for tun 2023-10-30 21:46:57 +08:00
世界 c67c4a54d7 Add udp_disable_domain_unmapping inbound listen option 2023-10-30 21:41:36 +08:00
世界 3711534823 Migrate to gobwas/ws 2023-10-30 21:41:27 +08:00
世界 126f72d9a6 docs: Remove obsolete fields 2023-10-30 21:41:21 +08:00
80 changed files with 203 additions and 1194 deletions
-3
View File
@@ -84,9 +84,6 @@ upload_android:
release_android: lib_android update_android_version build_android upload_android
publish_android:
cd ../sing-box-for-android && ./gradlew :app:publishReleaseBundle
publish_android_appcenter:
cd ../sing-box-for-android && ./gradlew :app:appCenterAssembleAndUploadRelease
build_ios:
-104
View File
@@ -1,104 +0,0 @@
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)
}
+4 -1
View File
@@ -2,12 +2,14 @@ package adapter
import (
"context"
"net"
"net/netip"
"github.com/sagernet/sing-box/common/geoip"
"github.com/sagernet/sing-dns"
"github.com/sagernet/sing-tun"
"github.com/sagernet/sing/common/control"
N "github.com/sagernet/sing/common/network"
"github.com/sagernet/sing/service"
mdns "github.com/miekg/dns"
@@ -22,7 +24,8 @@ type Router interface {
FakeIPStore() FakeIPStore
ConnectionRouter
RouteConnection(ctx context.Context, conn net.Conn, metadata InboundContext) error
RoutePacketConnection(ctx context.Context, conn N.PacketConn, metadata InboundContext) error
GeoIPReader() *geoip.Reader
LoadGeosite(code string) (Rule, error)
+1 -22
View File
@@ -1,42 +1,21 @@
package mux
import (
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing-mux"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/logger"
N "github.com/sagernet/sing/common/network"
)
type Client = mux.Client
func NewClientWithOptions(dialer N.Dialer, logger logger.Logger, options option.OutboundMultiplexOptions) (*Client, error) {
func NewClientWithOptions(dialer N.Dialer, options option.MultiplexOptions) (*Client, error) {
if !options.Enabled {
return nil, nil
}
var brutalOptions mux.BrutalOptions
if options.Brutal != nil && options.Brutal.Enabled {
brutalOptions = mux.BrutalOptions{
Enabled: true,
SendBPS: uint64(options.Brutal.UpMbps * C.MbpsToBps),
ReceiveBPS: uint64(options.Brutal.DownMbps * C.MbpsToBps),
}
if brutalOptions.SendBPS < mux.BrutalMinSpeedBPS {
return nil, E.New("brutal: invalid upload speed")
}
if brutalOptions.ReceiveBPS < mux.BrutalMinSpeedBPS {
return nil, E.New("brutal: invalid download speed")
}
}
return mux.NewClient(mux.Options{
Dialer: dialer,
Logger: logger,
Protocol: options.Protocol,
MaxConnections: options.MaxConnections,
MinStreams: options.MinStreams,
MaxStreams: options.MaxStreams,
Padding: options.Padding,
Brutal: brutalOptions,
})
}
+14
View File
@@ -0,0 +1,14 @@
package mux
import (
"github.com/sagernet/sing-mux"
)
type (
Client = mux.Client
)
var (
Destination = mux.Destination
HandleConnection = mux.HandleConnection
)
-65
View File
@@ -1,65 +0,0 @@
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
View File
@@ -1,32 +0,0 @@
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
View File
@@ -1,53 +0,0 @@
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
View File
@@ -1,3 +0,0 @@
package constant
const MbpsToBps = 125000
+4 -5
View File
@@ -1,9 +1,8 @@
package constant
const (
V2RayTransportTypeHTTP = "http"
V2RayTransportTypeWebsocket = "ws"
V2RayTransportTypeQUIC = "quic"
V2RayTransportTypeGRPC = "grpc"
V2RayTransportTypeHTTPUpgrade = "httpupgrade"
V2RayTransportTypeHTTP = "http"
V2RayTransportTypeWebsocket = "ws"
V2RayTransportTypeQUIC = "quic"
V2RayTransportTypeGRPC = "grpc"
)
-70
View File
@@ -1,55 +1,3 @@
#### 1.7.0-alpha.6
* Fixes and improvements
#### 1.7.0-alpha.4
* Migrate multiplex and UoT server to inbound **1**
* Add TCP Brutal support for multiplex **2**
**1**:
Starting in 1.7.0, multiplexing support is no longer enabled by default and needs to be turned on explicitly in inbound options.
**2**
Hysteria Brutal Congestion Control Algorithm in TCP. A kernel module needs to be installed on the Linux server, see [TCP Brutal](/configuration/shared/tcp-brutal) for details.
#### 1.7.0-alpha.3
* Add [HTTPUpgrade V2Ray transport](/configuration/shared/v2ray-transport#HTTPUpgrade) support **1**
* Fixes and improvements
**1**:
Introduced in V2Ray 5.10.0.
The new HTTPUpgrade transport has better performance than WebSocket and is better suited for CDN abuse.
#### 1.6.0
* Fixes and improvements
Important changes since 1.5:
* Our [Apple tvOS client](/installation/clients/sft) is now available in the App Store 🍎
* Update BBR congestion control for TUIC and Hysteria2 **1**
* Update brutal congestion control for Hysteria2
* Add `brutal_debug` option for Hysteria2
* Update legacy Hysteria protocol **2**
* Add TLS self sign key pair generate command
* Remove [Deprecated Features](/deprecated) by agreement
**1**:
None of the existing Golang BBR congestion control implementations have been reviewed or unit tested.
This update is intended to address the multi-send defects of the old implementation and may introduce new issues.
**2**
Based on discussions with the original author, the brutal CC and QUIC protocol parameters of
the old protocol (Hysteria 1) have been updated to be consistent with Hysteria 2
#### 1.7.0-alpha.2
* Fix bugs introduced in 1.7.0-alpha.1
@@ -128,24 +76,6 @@ the old protocol (Hysteria 1) have been updated to be consistent with Hysteria 2
* Update golang.org/x/net to v0.17.0
* Fixes and improvements
#### 1.6.0-beta.3
* Update the legacy Hysteria protocol **1**
* Fixes and improvements
**1**
Based on discussions with the original author, the brutal CC and QUIC protocol parameters of
the old protocol (Hysteria 1) have been updated to be consistent with Hysteria 2
#### 1.6.0-beta.2
* Add TLS self sign key pair generate command
* Update brutal congestion control for Hysteria2
* Fix Clash cache crash on arm32 devices
* Update golang.org/x/net to v0.17.0
* Fixes and improvements
#### 1.5.3
* Fix compatibility with Android 14
+1 -1
View File
@@ -62,7 +62,7 @@ Hysteria 用户
#### ignore_client_bandwidth
命令客户端使用 BBR 拥塞控制算法而不是 Hysteria CC。
命令客户端使用 BBR 流量控制算法而不是 Hysteria CC。
与 `up_mbps` 和 `down_mbps` 冲突。
+3 -10
View File
@@ -8,8 +8,7 @@
... // Listen Fields
"method": "2022-blake3-aes-128-gcm",
"password": "8JCsPssfgS8tiRwiMlhARg==",
"multiplex": {}
"password": "8JCsPssfgS8tiRwiMlhARg=="
}
```
@@ -24,8 +23,7 @@
"name": "sekai",
"password": "PCD2Z4o12bKUoFa3cC97Hw=="
}
],
"multiplex": {}
]
}
```
@@ -43,8 +41,7 @@
"server_port": 8080,
"password": "PCD2Z4o12bKUoFa3cC97Hw=="
}
],
"multiplex": {}
]
}
```
@@ -85,7 +82,3 @@ Both if empty.
| none | / |
| 2022 methods | `sing-box generate rand --base64 <Key Length>` |
| other methods | any string |
#### multiplex
See [Multiplex](/configuration/shared/multiplex#inbound) for details.
+4 -11
View File
@@ -8,8 +8,7 @@
... // 监听字段
"method": "2022-blake3-aes-128-gcm",
"password": "8JCsPssfgS8tiRwiMlhARg==",
"multiplex": {}
"password": "8JCsPssfgS8tiRwiMlhARg=="
}
```
@@ -24,8 +23,7 @@
"name": "sekai",
"password": "PCD2Z4o12bKUoFa3cC97Hw=="
}
],
"multiplex": {}
]
}
```
@@ -43,8 +41,7 @@
"server_port": 8080,
"password": "PCD2Z4o12bKUoFa3cC97Hw=="
}
],
"multiplex": {}
]
}
```
@@ -84,8 +81,4 @@ See [Listen Fields](/configuration/shared/listen) for details.
|---------------|------------------------------------------|
| none | / |
| 2022 methods | `sing-box generate rand --base64 <密钥长度>` |
| other methods | 任意字符串 |
#### multiplex
参阅 [多路复用](/zh/configuration/shared/multiplex#inbound)。
| other methods | 任意字符串 |
-5
View File
@@ -24,7 +24,6 @@
"server_port": 8081
}
},
"multiplex": {},
"transport": {}
}
```
@@ -59,10 +58,6 @@ Fallback server configuration for specified ALPN.
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
V2Ray Transport configuration, see [V2Ray Transport](/configuration/shared/v2ray-transport).
-5
View File
@@ -24,7 +24,6 @@
"server_port": 8081
}
},
"multiplex": {},
"transport": {}
}
```
@@ -61,10 +60,6 @@ TLS 配置, 参阅 [TLS](/zh/configuration/shared/tls/#inbound)。
如果不为空,ALPN 不在此列表中的 TLS 回退请求将被拒绝。
#### multiplex
参阅 [多路复用](/zh/configuration/shared/multiplex#inbound)。
#### transport
V2Ray 传输配置,参阅 [V2Ray 传输层](/zh/configuration/shared/v2ray-transport)。
+1 -1
View File
@@ -48,7 +48,7 @@ TUIC 用户密码
#### congestion_control
QUIC 拥塞控制算法
QUIC 流量控制算法
可选值: `cubic`, `new_reno`, `bbr`
-5
View File
@@ -15,7 +15,6 @@
}
],
"tls": {},
"multiplex": {},
"transport": {}
}
```
@@ -50,10 +49,6 @@ Available values:
TLS configuration, see [TLS](/configuration/shared/tls/#inbound).
#### multiplex
See [Multiplex](/configuration/shared/multiplex#inbound) for details.
#### transport
V2Ray Transport configuration, see [V2Ray Transport](/configuration/shared/v2ray-transport).
-5
View File
@@ -15,7 +15,6 @@
}
],
"tls": {},
"multiplex": {},
"transport": {}
}
```
@@ -50,10 +49,6 @@ VLESS 子协议。
TLS 配置, 参阅 [TLS](/zh/configuration/shared/tls/#inbound)。
#### multiplex
参阅 [多路复用](/zh/configuration/shared/multiplex#inbound)。
#### transport
V2Ray 传输配置,参阅 [V2Ray 传输层](/zh/configuration/shared/v2ray-transport)。
-5
View File
@@ -15,7 +15,6 @@
}
],
"tls": {},
"multiplex": {},
"transport": {}
}
```
@@ -45,10 +44,6 @@ VMess users.
TLS configuration, see [TLS](/configuration/shared/tls/#inbound).
#### multiplex
See [Multiplex](/configuration/shared/multiplex#inbound) for details.
#### transport
V2Ray Transport configuration, see [V2Ray Transport](/configuration/shared/v2ray-transport).
-5
View File
@@ -15,7 +15,6 @@
}
],
"tls": {},
"multiplex": {},
"transport": {}
}
```
@@ -45,10 +44,6 @@ VMess 用户。
TLS 配置, 参阅 [TLS](/zh/configuration/shared/tls/#inbound)。
#### multiplex
参阅 [多路复用](/zh/configuration/shared/multiplex#inbound)。
#### transport
V2Ray 传输配置,参阅 [V2Ray 传输层](/zh/configuration/shared/v2ray-transport)。
+1 -1
View File
@@ -44,7 +44,7 @@
最大带宽。
如果为空,将使用 BBR 拥塞控制算法而不是 Hysteria CC。
如果为空,将使用 BBR 流量控制算法而不是 Hysteria CC。
#### obfs.type
+1 -1
View File
@@ -95,7 +95,7 @@ Conflict with `multiplex`.
#### multiplex
See [Multiplex](/configuration/shared/multiplex#outbound) for details.
Multiplex configuration, see [Multiplex](/configuration/shared/multiplex).
### Dial Fields
@@ -95,7 +95,7 @@ UDP over TCP 配置。
#### multiplex
参阅 [多路复用](/zh/configuration/shared/multiplex#outbound)。
多路复用配置, 参阅 [多路复用](/zh/configuration/shared/multiplex)。
### 拨号字段
+1 -1
View File
@@ -51,7 +51,7 @@ TLS configuration, see [TLS](/configuration/shared/tls/#outbound).
#### multiplex
See [Multiplex](/configuration/shared/multiplex#outbound) for details.
Multiplex configuration, see [Multiplex](/configuration/shared/multiplex).
#### transport
+1 -1
View File
@@ -51,7 +51,7 @@ TLS 配置, 参阅 [TLS](/zh/configuration/shared/tls/#outbound)。
#### multiplex
参阅 [多路复用](/zh/configuration/shared/multiplex#outbound)。
多路复用配置, 参阅 [多路复用](/zh/configuration/shared/multiplex)。
#### transport
+1 -1
View File
@@ -51,7 +51,7 @@ TUIC 用户密码
#### congestion_control
QUIC 拥塞控制算法
QUIC 流量控制算法
可选值: `cubic`, `new_reno`, `bbr`
-5
View File
@@ -12,7 +12,6 @@
"network": "tcp",
"tls": {},
"packet_encoding": "",
"multiplex": {},
"transport": {},
... // Dial Fields
@@ -69,10 +68,6 @@ UDP packet encoding, xudp is used by default.
| packetaddr | Supported by v2ray 5+ |
| xudp | Supported by xray |
#### multiplex
See [Multiplex](/configuration/shared/multiplex#outbound) for details.
#### transport
V2Ray Transport configuration, see [V2Ray Transport](/configuration/shared/v2ray-transport).
-5
View File
@@ -12,7 +12,6 @@
"network": "tcp",
"tls": {},
"packet_encoding": "",
"multiplex": {},
"transport": {},
... // 拨号字段
@@ -69,10 +68,6 @@ UDP 包编码,默认使用 xudp。
| packetaddr | 由 v2ray 5+ 支持 |
| xudp | 由 xray 支持 |
#### multiplex
参阅 [多路复用](/zh/configuration/shared/multiplex#outbound)。
#### transport
V2Ray 传输配置,参阅 [V2Ray 传输层](/zh/configuration/shared/v2ray-transport)。
+2 -2
View File
@@ -15,8 +15,8 @@
"network": "tcp",
"tls": {},
"packet_encoding": "",
"transport": {},
"multiplex": {},
"transport": {},
... // Dial Fields
}
@@ -96,7 +96,7 @@ UDP packet encoding.
#### multiplex
See [Multiplex](/configuration/shared/multiplex#outbound) for details.
Multiplex configuration, see [Multiplex](/configuration/shared/multiplex).
#### transport
+1 -1
View File
@@ -96,7 +96,7 @@ UDP 包编码。
#### multiplex
参阅 [多路复用](/zh/configuration/shared/multiplex#outbound)。
多路复用配置, 参阅 [多路复用](/zh/configuration/shared/multiplex)。
#### transport
+5 -30
View File
@@ -1,14 +1,8 @@
### Inbound
### Server Requirements
```json
{
"enabled": true,
"padding": false,
"brutal": {}
}
```
`sing-box` :)
### Outbound
### Structure
```json
{
@@ -17,27 +11,11 @@
"max_connections": 4,
"min_streams": 4,
"max_streams": 0,
"padding": false,
"brutal": {}
"padding": false
}
```
### 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
### Fields
#### enabled
@@ -81,6 +59,3 @@ Conflict with `max_connections` and `min_streams`.
Enable padding.
#### brutal
See [TCP Brutal](/configuration/shared/tcp-brutal) for details.
+5 -30
View File
@@ -1,14 +1,8 @@
### 入站
### 服务器要求
```json
{
"enabled": true,
"padding": false,
"brutal": {}
}
```
`sing-box` :)
### 出站
### 结构
```json
{
@@ -16,27 +10,11 @@
"protocol": "smux",
"max_connections": 4,
"min_streams": 4,
"max_streams": 0,
"padding": false,
"brutal": {}
"max_streams": 0
}
```
### 入站字段
#### enabled
启用多路复用支持。
#### padding
如果启用,将拒绝非填充连接。
#### brutal
参阅 [TCP Brutal](/zh/configuration/shared/tcp-brutal)。
### 出站字段
### 字段
#### enabled
@@ -80,6 +58,3 @@
启用填充。
#### brutal
参阅 [TCP Brutal](/zh/configuration/shared/tcp-brutal)。
-28
View File
@@ -1,28 +0,0 @@
### 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.
@@ -1,28 +0,0 @@
### 服务器要求
* 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 为单位。
@@ -15,7 +15,6 @@ Available transports:
* WebSocket
* QUIC
* gRPC
* HTTPUpgrade
!!! warning "Difference from v2ray-core"
@@ -185,32 +184,3 @@ In standard gRPC client:
If enabled, the client transport sends keepalive pings even with no active connections. If disabled, when there are no active connections, `idle_timeout` and `ping_timeout` will be ignored and no keepalive pings will be sent.
Disabled by default.
### HTTPUpgrade
```json
{
"type": "httpupgrade",
"host": "",
"path": "",
"headers": {}
}
```
#### host
Host domain.
The server will verify if not empty.
#### path
Path of HTTP request.
The server will verify if not empty.
#### headers
Extra headers of HTTP request.
The server will write in response if not empty.
@@ -14,7 +14,6 @@ V2Ray Transport 是 v2ray 发明的一组私有协议,并污染了其他协议
* WebSocket
* QUIC
* gRPC
* HTTPUpgrade
!!! warning "与 v2ray-core 的区别"
@@ -184,32 +183,3 @@ gRPC 服务名称。
如果启用,客户端传输即使没有活动连接也会发送 keepalive ping。如果禁用,则在没有活动连接时,将忽略 `idle_timeout` 和 `ping_timeout`,并且不会发送 keepalive ping。
默认禁用。
### HTTPUpgrade
```json
{
"type": "httpupgrade",
"host": "",
"path": "",
"headers": {}
}
```
#### host
主机域名。
默认服务器将验证。
#### path
HTTP 请求路径
默认服务器将验证。
#### headers
HTTP 请求的额外标头。
默认服务器将写入响应。
-5
View File
@@ -16,8 +16,3 @@ Experimental Android client for sing-box.
* User Agent in remote profile request is `SFA/$version ($version_code; sing-box $sing_box_version)`
* The working directory is located at `/sdcard/Android/data/io.nekohasekai.sfa/files` (External files directory)
* Crash logs is located in `$working_directory/stderr.log`
#### Privacy policy
* SFA did not collect or share personal data.
* The data generated by the software is always on your device.
-5
View File
@@ -16,8 +16,3 @@
* 远程配置文件请求中的 User Agent 为 `SFA/$version ($version_code; sing-box $sing_box_version)`
* 工作目录位于 `/sdcard/Android/data/io.nekohasekai.sfa/files` (外部文件目录)
* 崩溃日志位于 `$working_directory/stderr.log`
#### 隐私政策
* SFA 不收集或共享个人数据。
* 软件生成的数据始终在您的设备上。
+3 -3
View File
@@ -5,7 +5,7 @@ go 1.20
require (
berty.tech/go-libtor v1.0.385
github.com/caddyserver/certmagic v0.19.2
github.com/cloudflare/circl v1.3.6
github.com/cloudflare/circl v1.3.5
github.com/cretz/bine v0.2.0
github.com/fsnotify/fsnotify v1.7.0
github.com/go-chi/chi/v5 v5.0.10
@@ -28,12 +28,12 @@ require (
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
github.com/sagernet/sing v0.2.16-0.20231028125948-afcc9cb766c2
github.com/sagernet/sing-dns v0.1.10
github.com/sagernet/sing-mux v0.1.4-0.20231105044304-ae2745a33479
github.com/sagernet/sing-mux v0.1.3
github.com/sagernet/sing-quic v0.1.3-0.20231026034240-fa3d997246b6
github.com/sagernet/sing-shadowsocks v0.2.5
github.com/sagernet/sing-shadowsocks2 v0.1.4
github.com/sagernet/sing-shadowtls v0.1.4
github.com/sagernet/sing-tun v0.1.17-0.20231104000158-fb98efb75ca7
github.com/sagernet/sing-tun v0.1.17-0.20231030120513-2e85725657c1
github.com/sagernet/sing-vmess v0.1.8
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37
github.com/sagernet/tfo-go v0.0.0-20230816093905-5a5c285d44a6
+6 -6
View File
@@ -9,8 +9,8 @@ github.com/caddyserver/certmagic v0.19.2/go.mod h1:fsL01NomQ6N+kE2j37ZCnig2MFosG
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/cloudflare/circl v1.3.6 h1:/xbKIqSHbZXHwkhbrhrt2YOHIwYJlXH94E3tI/gDlUg=
github.com/cloudflare/circl v1.3.6/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
github.com/cloudflare/circl v1.3.5 h1:g+wWynZqVALYAlpSQFAa7TscDnUK8mKYtrxMpw6AUKo=
github.com/cloudflare/circl v1.3.5/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cretz/bine v0.1.0/go.mod h1:6PF6fWAvYtwjRGkAuDEJeWNOv3a2hUouSP/yRYXmvHw=
github.com/cretz/bine v0.2.0 h1:8GiDRGlTgz+o8H9DSnsl+5MeBK4HsExxgl6WgzOCuZo=
@@ -118,8 +118,8 @@ github.com/sagernet/sing v0.2.16-0.20231028125948-afcc9cb766c2 h1:PW18IgRodvppd0
github.com/sagernet/sing v0.2.16-0.20231028125948-afcc9cb766c2/go.mod h1:AhNEHu0GXrpqkuzvTwvC8+j2cQUU/dh+zLEmq4C99pg=
github.com/sagernet/sing-dns v0.1.10 h1:iIU7nRBlUYj+fF2TaktGIvRiTFFrHwSMedLQsvlTZCI=
github.com/sagernet/sing-dns v0.1.10/go.mod h1:vtUimtf7Nq9EdvD5WTpfCr69KL1M7bcgOVKiYBiAY/c=
github.com/sagernet/sing-mux v0.1.4-0.20231105044304-ae2745a33479 h1:h6ANTA5wbP5BSqbjOT7s1OKLZgdsLqiXO564KQqY2i4=
github.com/sagernet/sing-mux v0.1.4-0.20231105044304-ae2745a33479/go.mod h1:wGeIeiiFLx4HUM5LAg65wrNZ/X1muOimqK0PEhNbPi0=
github.com/sagernet/sing-mux v0.1.3 h1:fAf7PZa2A55mCeh0KKM02f1k2Y4vEmxuZZ/51ahkkLA=
github.com/sagernet/sing-mux v0.1.3/go.mod h1:wGeIeiiFLx4HUM5LAg65wrNZ/X1muOimqK0PEhNbPi0=
github.com/sagernet/sing-quic v0.1.3-0.20231026034240-fa3d997246b6 h1:w+TUbIZKZFSdf/AUa/y33kY9xaLeNGz/tBNcNhqpqfg=
github.com/sagernet/sing-quic v0.1.3-0.20231026034240-fa3d997246b6/go.mod h1:1M7xP4802K9Kz6BQ7LlA7UeCapWvWlH1Htmk2bAqkWc=
github.com/sagernet/sing-shadowsocks v0.2.5 h1:qxIttos4xu6ii7MTVJYA8EFQR7Q3KG6xMqmLJIFtBaY=
@@ -128,8 +128,8 @@ github.com/sagernet/sing-shadowsocks2 v0.1.4 h1:vht2M8t3m5DTgXR2j24KbYOygG5aOp+M
github.com/sagernet/sing-shadowsocks2 v0.1.4/go.mod h1:Mgdee99NxxNd5Zld3ixIs18yVs4x2dI2VTDDE1N14Wc=
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-tun v0.1.17-0.20231104000158-fb98efb75ca7 h1:nrjFCUNEsDZSZlxmE+tq8OuInjXI08vNfcSJ66gTbCs=
github.com/sagernet/sing-tun v0.1.17-0.20231104000158-fb98efb75ca7/go.mod h1:4ACZp3C6TDSy1rsMrfwtSyLrKPtm9Wm2eKHwhYIojbU=
github.com/sagernet/sing-tun v0.1.17-0.20231030120513-2e85725657c1 h1:QxC+myHDZ0BnkIEqXE0lWUzfYEVlhhQdSCo7mOMm7x4=
github.com/sagernet/sing-tun v0.1.17-0.20231030120513-2e85725657c1/go.mod h1:4ACZp3C6TDSy1rsMrfwtSyLrKPtm9Wm2eKHwhYIojbU=
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/smux v0.0.0-20230312102458-337ec2a5af37 h1:HuE6xSwco/Xed8ajZ+coeYLmioq0Qp1/Z2zczFaV8as=
+1 -1
View File
@@ -22,7 +22,7 @@ type myInboundAdapter struct {
protocol string
network []string
ctx context.Context
router adapter.ConnectionRouter
router adapter.Router
logger log.ContextLogger
tag string
listenOptions option.ListenOptions
+1 -2
View File
@@ -8,7 +8,6 @@ import (
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/tls"
"github.com/sagernet/sing-box/common/uot"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
@@ -36,7 +35,7 @@ func NewHTTP(ctx context.Context, router adapter.Router, logger log.ContextLogge
protocol: C.TypeHTTP,
network: []string{N.NetworkTCP},
ctx: ctx,
router: uot.NewRouter(router, logger),
router: router,
logger: logger,
tag: tag,
listenOptions: options.ListenOptions,
+1 -2
View File
@@ -7,7 +7,6 @@ import (
"os"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/uot"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
@@ -38,7 +37,7 @@ func NewMixed(ctx context.Context, router adapter.Router, logger log.ContextLogg
protocol: C.TypeMixed,
network: []string{N.NetworkTCP},
ctx: ctx,
router: uot.NewRouter(router, logger),
router: router,
logger: logger,
tag: tag,
listenOptions: options.ListenOptions,
+1 -2
View File
@@ -13,7 +13,6 @@ import (
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/tls"
"github.com/sagernet/sing-box/common/uot"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/include"
"github.com/sagernet/sing-box/log"
@@ -44,7 +43,7 @@ func NewNaive(ctx context.Context, router adapter.Router, logger log.ContextLogg
protocol: C.TypeNaive,
network: options.Network.Build(),
ctx: ctx,
router: uot.NewRouter(router, logger),
router: router,
logger: logger,
tag: tag,
listenOptions: options.ListenOptions,
+2 -10
View File
@@ -6,8 +6,6 @@ import (
"os"
"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"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
@@ -50,27 +48,21 @@ func newShadowsocks(ctx context.Context, router adapter.Router, logger log.Conte
protocol: C.TypeShadowsocks,
network: options.Network.Build(),
ctx: ctx,
router: uot.NewRouter(router, logger),
router: router,
logger: logger,
tag: tag,
listenOptions: options.ListenOptions,
},
}
inbound.connHandler = 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
if options.UDPTimeout != 0 {
udpTimeout = options.UDPTimeout
} else {
udpTimeout = int64(C.UDPTimeout.Seconds())
}
var err error
switch {
case options.Method == shadowsocks.MethodNone:
inbound.service = shadowsocks.NewNoneService(options.UDPTimeout, inbound.upstreamContextHandler())
+5 -9
View File
@@ -6,8 +6,6 @@ import (
"os"
"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"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
@@ -40,7 +38,7 @@ func newShadowsocksMulti(ctx context.Context, router adapter.Router, logger log.
protocol: C.TypeShadowsocks,
network: options.Network.Build(),
ctx: ctx,
router: uot.NewRouter(router, logger),
router: router,
logger: logger,
tag: tag,
listenOptions: options.ListenOptions,
@@ -48,18 +46,16 @@ func newShadowsocksMulti(ctx context.Context, router adapter.Router, logger log.
}
inbound.connHandler = 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
if options.UDPTimeout != 0 {
udpTimeout = options.UDPTimeout
} else {
udpTimeout = int64(C.UDPTimeout.Seconds())
}
var service shadowsocks.MultiService[int]
var (
service shadowsocks.MultiService[int]
err error
)
if common.Contains(shadowaead_2022.List, options.Method) {
service, err = shadowaead_2022.NewMultiServiceWithPassword[int](
options.Method,
+1 -8
View File
@@ -6,8 +6,6 @@ import (
"os"
"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"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
@@ -36,7 +34,7 @@ func newShadowsocksRelay(ctx context.Context, router adapter.Router, logger log.
protocol: C.TypeShadowsocks,
network: options.Network.Build(),
ctx: ctx,
router: uot.NewRouter(router, logger),
router: router,
logger: logger,
tag: tag,
listenOptions: options.ListenOptions,
@@ -45,11 +43,6 @@ func newShadowsocksRelay(ctx context.Context, router adapter.Router, logger log.
}
inbound.connHandler = 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
if options.UDPTimeout != 0 {
udpTimeout = options.UDPTimeout
+1 -2
View File
@@ -6,7 +6,6 @@ import (
"os"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/uot"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
@@ -31,7 +30,7 @@ func NewSocks(ctx context.Context, router adapter.Router, logger log.ContextLogg
protocol: C.TypeSOCKS,
network: []string{N.NetworkTCP},
ctx: ctx,
router: uot.NewRouter(router, logger),
router: router,
logger: logger,
tag: tag,
listenOptions: options.ListenOptions,
+2 -8
View File
@@ -6,9 +6,7 @@ import (
"os"
"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/uot"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
@@ -44,7 +42,7 @@ func NewVLESS(ctx context.Context, router adapter.Router, logger log.ContextLogg
protocol: C.TypeVLESS,
network: []string{N.NetworkTCP},
ctx: ctx,
router: uot.NewRouter(router, logger),
router: router,
logger: logger,
tag: tag,
listenOptions: options.ListenOptions,
@@ -52,11 +50,6 @@ func NewVLESS(ctx context.Context, router adapter.Router, logger log.ContextLogg
ctx: ctx,
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.UpdateUsers(common.MapIndexed(inbound.users, func(index int, _ option.VLESSUser) int {
return index
@@ -66,6 +59,7 @@ func NewVLESS(ctx context.Context, router adapter.Router, logger log.ContextLogg
return it.Flow
}))
inbound.service = service
var err error
if options.TLS != nil {
inbound.tlsConfig, err = tls.NewServer(ctx, logger, common.PtrValueOrDefault(options.TLS))
if err != nil {
+2 -9
View File
@@ -6,9 +6,7 @@ import (
"os"
"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/uot"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
@@ -44,7 +42,7 @@ func NewVMess(ctx context.Context, router adapter.Router, logger log.ContextLogg
protocol: C.TypeVMess,
network: []string{N.NetworkTCP},
ctx: ctx,
router: uot.NewRouter(router, logger),
router: router,
logger: logger,
tag: tag,
listenOptions: options.ListenOptions,
@@ -52,11 +50,6 @@ func NewVMess(ctx context.Context, router adapter.Router, logger log.ContextLogg
ctx: ctx,
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
if timeFunc := ntp.TimeFuncFromContext(ctx); timeFunc != nil {
serviceOptions = append(serviceOptions, vmess.ServiceWithTimeFunc(timeFunc))
@@ -66,7 +59,7 @@ func NewVMess(ctx context.Context, router adapter.Router, logger log.ContextLogg
}
service := vmess.NewService[int](adapter.NewUpstreamContextHandler(inbound.newConnection, inbound.newPacketConnection, inbound), serviceOptions...)
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
}), common.Map(options.Users, func(it option.VMessUser) string {
return it.UUID
-1
View File
@@ -75,7 +75,6 @@ nav:
- Multiplex: configuration/shared/multiplex.md
- V2Ray Transport: configuration/shared/v2ray-transport.md
- UDP over TCP: configuration/shared/udp-over-tcp.md
- TCP Brutal: configuration/shared/tcp-brutal.md
- Inbound:
- configuration/inbound/index.md
- Direct: configuration/inbound/direct.md
-23
View File
@@ -1,23 +0,0 @@
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"`
}
+9
View File
@@ -154,3 +154,12 @@ type ServerOptions struct {
func (o ServerOptions) Build() M.Socksaddr {
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 -8
View File
@@ -7,7 +7,6 @@ type ShadowsocksInboundOptions struct {
Password string `json:"password,omitempty"`
Users []ShadowsocksUser `json:"users,omitempty"`
Destinations []ShadowsocksDestination `json:"destinations,omitempty"`
Multiplex *InboundMultiplexOptions `json:"multiplex,omitempty"`
}
type ShadowsocksUser struct {
@@ -24,11 +23,11 @@ type ShadowsocksDestination struct {
type ShadowsocksOutboundOptions struct {
DialerOptions
ServerOptions
Method string `json:"method"`
Password string `json:"password"`
Plugin string `json:"plugin,omitempty"`
PluginOptions string `json:"plugin_opts,omitempty"`
Network NetworkList `json:"network,omitempty"`
UDPOverTCP *UDPOverTCPOptions `json:"udp_over_tcp,omitempty"`
Multiplex *OutboundMultiplexOptions `json:"multiplex,omitempty"`
Method string `json:"method"`
Password string `json:"password"`
Plugin string `json:"plugin,omitempty"`
PluginOptions string `json:"plugin_opts,omitempty"`
Network NetworkList `json:"network,omitempty"`
UDPOverTCPOptions *UDPOverTCPOptions `json:"udp_over_tcp,omitempty"`
MultiplexOptions *MultiplexOptions `json:"multiplex,omitempty"`
}
+5 -5
View File
@@ -17,11 +17,11 @@ type HTTPMixedInboundOptions struct {
type SocksOutboundOptions struct {
DialerOptions
ServerOptions
Version string `json:"version,omitempty"`
Username string `json:"username,omitempty"`
Password string `json:"password,omitempty"`
Network NetworkList `json:"network,omitempty"`
UDPOverTCP *UDPOverTCPOptions `json:"udp_over_tcp,omitempty"`
Version string `json:"version,omitempty"`
Username string `json:"username,omitempty"`
Password string `json:"password,omitempty"`
Network NetworkList `json:"network,omitempty"`
UDPOverTCPOptions *UDPOverTCPOptions `json:"udp_over_tcp,omitempty"`
}
type HTTPOutboundOptions struct {
+5 -6
View File
@@ -6,7 +6,6 @@ type TrojanInboundOptions struct {
TLS *InboundTLSOptions `json:"tls,omitempty"`
Fallback *ServerOptions `json:"fallback,omitempty"`
FallbackForALPN map[string]*ServerOptions `json:"fallback_for_alpn,omitempty"`
Multiplex *InboundMultiplexOptions `json:"multiplex,omitempty"`
Transport *V2RayTransportOptions `json:"transport,omitempty"`
}
@@ -18,9 +17,9 @@ type TrojanUser struct {
type TrojanOutboundOptions struct {
DialerOptions
ServerOptions
Password string `json:"password"`
Network NetworkList `json:"network,omitempty"`
TLS *OutboundTLSOptions `json:"tls,omitempty"`
Multiplex *OutboundMultiplexOptions `json:"multiplex,omitempty"`
Transport *V2RayTransportOptions `json:"transport,omitempty"`
Password string `json:"password"`
Network NetworkList `json:"network,omitempty"`
TLS *OutboundTLSOptions `json:"tls,omitempty"`
Multiplex *MultiplexOptions `json:"multiplex,omitempty"`
Transport *V2RayTransportOptions `json:"transport,omitempty"`
}
+5 -16
View File
@@ -7,12 +7,11 @@ import (
)
type _V2RayTransportOptions struct {
Type string `json:"type,omitempty"`
HTTPOptions V2RayHTTPOptions `json:"-"`
WebsocketOptions V2RayWebsocketOptions `json:"-"`
QUICOptions V2RayQUICOptions `json:"-"`
GRPCOptions V2RayGRPCOptions `json:"-"`
HTTPUpgradeOptions V2RayHTTPUpgradeOptions `json:"-"`
Type string `json:"type,omitempty"`
HTTPOptions V2RayHTTPOptions `json:"-"`
WebsocketOptions V2RayWebsocketOptions `json:"-"`
QUICOptions V2RayQUICOptions `json:"-"`
GRPCOptions V2RayGRPCOptions `json:"-"`
}
type V2RayTransportOptions _V2RayTransportOptions
@@ -30,8 +29,6 @@ func (o V2RayTransportOptions) MarshalJSON() ([]byte, error) {
v = o.QUICOptions
case C.V2RayTransportTypeGRPC:
v = o.GRPCOptions
case C.V2RayTransportTypeHTTPUpgrade:
v = o.HTTPUpgradeOptions
default:
return nil, E.New("unknown transport type: " + o.Type)
}
@@ -53,8 +50,6 @@ func (o *V2RayTransportOptions) UnmarshalJSON(bytes []byte) error {
v = &o.QUICOptions
case C.V2RayTransportTypeGRPC:
v = &o.GRPCOptions
case C.V2RayTransportTypeHTTPUpgrade:
v = &o.HTTPUpgradeOptions
default:
return E.New("unknown transport type: " + o.Type)
}
@@ -90,9 +85,3 @@ type V2RayGRPCOptions struct {
PermitWithoutStream bool `json:"permit_without_stream,omitempty"`
ForceLite bool `json:"-"` // for test
}
type V2RayHTTPUpgradeOptions struct {
Host string `json:"host,omitempty"`
Path string `json:"path,omitempty"`
Headers HTTPHeader `json:"headers,omitempty"`
}
+10 -11
View File
@@ -2,10 +2,9 @@ package option
type VLESSInboundOptions struct {
ListenOptions
Users []VLESSUser `json:"users,omitempty"`
TLS *InboundTLSOptions `json:"tls,omitempty"`
Multiplex *InboundMultiplexOptions `json:"multiplex,omitempty"`
Transport *V2RayTransportOptions `json:"transport,omitempty"`
Users []VLESSUser `json:"users,omitempty"`
TLS *InboundTLSOptions `json:"tls,omitempty"`
Transport *V2RayTransportOptions `json:"transport,omitempty"`
}
type VLESSUser struct {
@@ -17,11 +16,11 @@ type VLESSUser struct {
type VLESSOutboundOptions struct {
DialerOptions
ServerOptions
UUID string `json:"uuid"`
Flow string `json:"flow,omitempty"`
Network NetworkList `json:"network,omitempty"`
TLS *OutboundTLSOptions `json:"tls,omitempty"`
Multiplex *OutboundMultiplexOptions `json:"multiplex,omitempty"`
Transport *V2RayTransportOptions `json:"transport,omitempty"`
PacketEncoding *string `json:"packet_encoding,omitempty"`
UUID string `json:"uuid"`
Flow string `json:"flow,omitempty"`
Network NetworkList `json:"network,omitempty"`
TLS *OutboundTLSOptions `json:"tls,omitempty"`
Multiplex *MultiplexOptions `json:"multiplex,omitempty"`
Transport *V2RayTransportOptions `json:"transport,omitempty"`
PacketEncoding *string `json:"packet_encoding,omitempty"`
}
+13 -14
View File
@@ -2,10 +2,9 @@ package option
type VMessInboundOptions struct {
ListenOptions
Users []VMessUser `json:"users,omitempty"`
TLS *InboundTLSOptions `json:"tls,omitempty"`
Multiplex *InboundMultiplexOptions `json:"multiplex,omitempty"`
Transport *V2RayTransportOptions `json:"transport,omitempty"`
Users []VMessUser `json:"users,omitempty"`
TLS *InboundTLSOptions `json:"tls,omitempty"`
Transport *V2RayTransportOptions `json:"transport,omitempty"`
}
type VMessUser struct {
@@ -17,14 +16,14 @@ type VMessUser struct {
type VMessOutboundOptions struct {
DialerOptions
ServerOptions
UUID string `json:"uuid"`
Security string `json:"security"`
AlterId int `json:"alter_id,omitempty"`
GlobalPadding bool `json:"global_padding,omitempty"`
AuthenticatedLength bool `json:"authenticated_length,omitempty"`
Network NetworkList `json:"network,omitempty"`
TLS *OutboundTLSOptions `json:"tls,omitempty"`
PacketEncoding string `json:"packet_encoding,omitempty"`
Multiplex *OutboundMultiplexOptions `json:"multiplex,omitempty"`
Transport *V2RayTransportOptions `json:"transport,omitempty"`
UUID string `json:"uuid"`
Security string `json:"security"`
AlterId int `json:"alter_id,omitempty"`
GlobalPadding bool `json:"global_padding,omitempty"`
AuthenticatedLength bool `json:"authenticated_length,omitempty"`
Network NetworkList `json:"network,omitempty"`
TLS *OutboundTLSOptions `json:"tls,omitempty"`
PacketEncoding string `json:"packet_encoding,omitempty"`
Multiplex *MultiplexOptions `json:"multiplex,omitempty"`
Transport *V2RayTransportOptions `json:"transport,omitempty"`
}
+2 -2
View File
@@ -62,9 +62,9 @@ func NewShadowsocks(ctx context.Context, router adapter.Router, logger log.Conte
return nil, err
}
}
uotOptions := common.PtrValueOrDefault(options.UDPOverTCP)
uotOptions := common.PtrValueOrDefault(options.UDPOverTCPOptions)
if !uotOptions.Enabled {
outbound.multiplexDialer, err = mux.NewClientWithOptions((*shadowsocksDialer)(outbound), logger, common.PtrValueOrDefault(options.Multiplex))
outbound.multiplexDialer, err = mux.NewClientWithOptions((*shadowsocksDialer)(outbound), common.PtrValueOrDefault(options.MultiplexOptions))
if err != nil {
return nil, err
}
+1 -1
View File
@@ -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),
resolve: version == socks.Version4,
}
uotOptions := common.PtrValueOrDefault(options.UDPOverTCP)
uotOptions := common.PtrValueOrDefault(options.UDPOverTCPOptions)
if uotOptions.Enabled {
outbound.uotClient = &uot.Client{
Dialer: outbound.client,
+1 -1
View File
@@ -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)
}
}
outbound.multiplexDialer, err = mux.NewClientWithOptions((*trojanDialer)(outbound), logger, common.PtrValueOrDefault(options.Multiplex))
outbound.multiplexDialer, err = mux.NewClientWithOptions((*trojanDialer)(outbound), common.PtrValueOrDefault(options.Multiplex))
if err != nil {
return nil, err
}
+1 -1
View File
@@ -81,7 +81,7 @@ func NewVLESS(ctx context.Context, router adapter.Router, logger log.ContextLogg
if err != nil {
return nil, err
}
outbound.multiplexDialer, err = mux.NewClientWithOptions((*vlessDialer)(outbound), logger, common.PtrValueOrDefault(options.Multiplex))
outbound.multiplexDialer, err = mux.NewClientWithOptions((*vlessDialer)(outbound), common.PtrValueOrDefault(options.Multiplex))
if err != nil {
return nil, err
}
+1 -1
View File
@@ -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)
}
}
outbound.multiplexDialer, err = mux.NewClientWithOptions((*vmessDialer)(outbound), logger, common.PtrValueOrDefault(options.Multiplex))
outbound.multiplexDialer, err = mux.NewClientWithOptions((*vmessDialer)(outbound), common.PtrValueOrDefault(options.Multiplex))
if err != nil {
return nil, err
}
+22 -5
View File
@@ -16,6 +16,7 @@ import (
"github.com/sagernet/sing-box/common/dialer"
"github.com/sagernet/sing-box/common/geoip"
"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/sniff"
C "github.com/sagernet/sing-box/constant"
@@ -26,7 +27,6 @@ import (
"github.com/sagernet/sing-box/outbound"
"github.com/sagernet/sing-box/transport/fakeip"
"github.com/sagernet/sing-dns"
mux "github.com/sagernet/sing-mux"
"github.com/sagernet/sing-tun"
"github.com/sagernet/sing-vmess"
"github.com/sagernet/sing/common"
@@ -606,13 +606,30 @@ func (r *Router) RouteConnection(ctx context.Context, conn net.Conn, metadata ad
metadata.Network = N.NetworkTCP
switch metadata.Destination.Fqdn {
case mux.Destination.Fqdn:
return E.New("global multiplex is deprecated since sing-box v1.7.0, enable multiplex in inbound options instead.")
r.logger.InfoContext(ctx, "inbound multiplex connection")
handler := adapter.NewUpstreamHandler(metadata, r.RouteConnection, r.RoutePacketConnection, r)
return mux.HandleConnection(ctx, handler, r.logger, conn, adapter.UpstreamMetadata(metadata))
case vmess.MuxDestination.Fqdn:
return E.New("global multiplex (v2ray legacy) not supported since sing-box v1.7.0.")
r.logger.InfoContext(ctx, "inbound legacy multiplex connection")
return vmess.HandleMuxConnection(ctx, conn, adapter.NewUpstreamHandler(metadata, r.RouteConnection, r.RoutePacketConnection, r))
case uot.MagicAddress:
return E.New("global UoT not supported since sing-box v1.7.0.")
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.RoutePacketConnection(ctx, uot.NewConn(conn, *request), metadata)
case uot.LegacyMagicAddress:
return E.New("global UoT (legacy) not supported since sing-box v1.7.0.")
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)
}
if r.fakeIPStore != nil && r.fakeIPStore.Contains(metadata.Destination.Addr) {
-86
View File
@@ -1,86 +0,0 @@
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"
)
func TestMuxBrutal(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)
}
+6 -8
View File
@@ -7,11 +7,11 @@ require github.com/sagernet/sing-box v0.0.0
replace github.com/sagernet/sing-box => ../
require (
github.com/docker/docker v24.0.7+incompatible
github.com/docker/docker v24.0.6+incompatible
github.com/docker/go-connections v0.4.0
github.com/gofrs/uuid/v5 v5.0.0
github.com/sagernet/quic-go v0.0.0-20231008035953-32727fef9460
github.com/sagernet/sing v0.2.16-0.20231028125948-afcc9cb766c2
github.com/sagernet/sing v0.2.16-0.20231021090846-8002db54c028
github.com/sagernet/sing-dns v0.1.10
github.com/sagernet/sing-quic v0.1.3-0.20231026034240-fa3d997246b6
github.com/sagernet/sing-shadowsocks v0.2.5
@@ -28,7 +28,7 @@ require (
github.com/ajg/form v1.5.1 // indirect
github.com/andybalholm/brotli v1.0.5 // indirect
github.com/caddyserver/certmagic v0.19.2 // indirect
github.com/cloudflare/circl v1.3.6 // indirect
github.com/cloudflare/circl v1.3.5 // indirect
github.com/cretz/bine v0.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/distribution/reference v0.5.0 // indirect
@@ -40,8 +40,6 @@ require (
github.com/go-chi/render v1.0.3 // 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/gobwas/httphead v0.1.0 // indirect
github.com/gobwas/pool v0.2.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/btree v1.1.2 // indirect
@@ -75,15 +73,15 @@ require (
github.com/sagernet/gvisor v0.0.0-20230930141345-5fef6f2e17ab // indirect
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 // indirect
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 // indirect
github.com/sagernet/sing-mux v0.1.4-0.20231105044304-ae2745a33479 // indirect
github.com/sagernet/sing-mux v0.1.3 // indirect
github.com/sagernet/sing-shadowtls v0.1.4 // indirect
github.com/sagernet/sing-tun v0.1.17-0.20231104000158-fb98efb75ca7 // indirect
github.com/sagernet/sing-tun v0.1.17-0.20231026060825-efd9884154a6 // indirect
github.com/sagernet/sing-vmess v0.1.8 // 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/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/ws v0.0.0-20231030053741-7d481eb31bed // indirect
github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 // indirect
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 // indirect
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
+12 -17
View File
@@ -12,8 +12,8 @@ github.com/caddyserver/certmagic v0.19.2/go.mod h1:fsL01NomQ6N+kE2j37ZCnig2MFosG
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/cloudflare/circl v1.3.6 h1:/xbKIqSHbZXHwkhbrhrt2YOHIwYJlXH94E3tI/gDlUg=
github.com/cloudflare/circl v1.3.6/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
github.com/cloudflare/circl v1.3.5 h1:g+wWynZqVALYAlpSQFAa7TscDnUK8mKYtrxMpw6AUKo=
github.com/cloudflare/circl v1.3.5/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
github.com/cretz/bine v0.1.0/go.mod h1:6PF6fWAvYtwjRGkAuDEJeWNOv3a2hUouSP/yRYXmvHw=
github.com/cretz/bine v0.2.0 h1:8GiDRGlTgz+o8H9DSnsl+5MeBK4HsExxgl6WgzOCuZo=
github.com/cretz/bine v0.2.0/go.mod h1:WU4o9QR9wWp8AVKtTM1XD5vUHkEqnf2vVSo6dBqbetI=
@@ -24,8 +24,8 @@ github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK
github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM=
github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v24.0.6+incompatible h1:hceabKCtUgDqPu+qm0NgsaXf28Ljf4/pWFL7xjWWDgE=
github.com/docker/docker v24.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
@@ -43,10 +43,6 @@ 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-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/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/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
@@ -131,12 +127,12 @@ 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/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.2.16-0.20231028125948-afcc9cb766c2 h1:PW18IgRodvppd09d4mewYM3Hedu3PtFERN8yOqkTVk0=
github.com/sagernet/sing v0.2.16-0.20231028125948-afcc9cb766c2/go.mod h1:AhNEHu0GXrpqkuzvTwvC8+j2cQUU/dh+zLEmq4C99pg=
github.com/sagernet/sing v0.2.16-0.20231021090846-8002db54c028 h1:6GbQt7SC9y5Imrq5jDMbXDSaNiMhJ8KBjhjtQRuqQvE=
github.com/sagernet/sing v0.2.16-0.20231021090846-8002db54c028/go.mod h1:AhNEHu0GXrpqkuzvTwvC8+j2cQUU/dh+zLEmq4C99pg=
github.com/sagernet/sing-dns v0.1.10 h1:iIU7nRBlUYj+fF2TaktGIvRiTFFrHwSMedLQsvlTZCI=
github.com/sagernet/sing-dns v0.1.10/go.mod h1:vtUimtf7Nq9EdvD5WTpfCr69KL1M7bcgOVKiYBiAY/c=
github.com/sagernet/sing-mux v0.1.4-0.20231105044304-ae2745a33479 h1:h6ANTA5wbP5BSqbjOT7s1OKLZgdsLqiXO564KQqY2i4=
github.com/sagernet/sing-mux v0.1.4-0.20231105044304-ae2745a33479/go.mod h1:wGeIeiiFLx4HUM5LAg65wrNZ/X1muOimqK0PEhNbPi0=
github.com/sagernet/sing-mux v0.1.3 h1:fAf7PZa2A55mCeh0KKM02f1k2Y4vEmxuZZ/51ahkkLA=
github.com/sagernet/sing-mux v0.1.3/go.mod h1:wGeIeiiFLx4HUM5LAg65wrNZ/X1muOimqK0PEhNbPi0=
github.com/sagernet/sing-quic v0.1.3-0.20231026034240-fa3d997246b6 h1:w+TUbIZKZFSdf/AUa/y33kY9xaLeNGz/tBNcNhqpqfg=
github.com/sagernet/sing-quic v0.1.3-0.20231026034240-fa3d997246b6/go.mod h1:1M7xP4802K9Kz6BQ7LlA7UeCapWvWlH1Htmk2bAqkWc=
github.com/sagernet/sing-shadowsocks v0.2.5 h1:qxIttos4xu6ii7MTVJYA8EFQR7Q3KG6xMqmLJIFtBaY=
@@ -145,8 +141,8 @@ github.com/sagernet/sing-shadowsocks2 v0.1.4 h1:vht2M8t3m5DTgXR2j24KbYOygG5aOp+M
github.com/sagernet/sing-shadowsocks2 v0.1.4/go.mod h1:Mgdee99NxxNd5Zld3ixIs18yVs4x2dI2VTDDE1N14Wc=
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-tun v0.1.17-0.20231104000158-fb98efb75ca7 h1:nrjFCUNEsDZSZlxmE+tq8OuInjXI08vNfcSJ66gTbCs=
github.com/sagernet/sing-tun v0.1.17-0.20231104000158-fb98efb75ca7/go.mod h1:4ACZp3C6TDSy1rsMrfwtSyLrKPtm9Wm2eKHwhYIojbU=
github.com/sagernet/sing-tun v0.1.17-0.20231026060825-efd9884154a6 h1:4yEXBqQoUgXj7qPSLD6lr+z9/KfsvixO9JUA2i5xnM8=
github.com/sagernet/sing-tun v0.1.17-0.20231026060825-efd9884154a6/go.mod h1:w2+S+uWE94E/pQWSDdDdMIjwAEb645kuGPunr6ZllUg=
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/smux v0.0.0-20230312102458-337ec2a5af37 h1:HuE6xSwco/Xed8ajZ+coeYLmioq0Qp1/Z2zczFaV8as=
@@ -155,10 +151,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/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/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/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/go.mod h1:a/83NAfUXvEuLpmxDssAXxgUgrEy12MId3Wd7OTs76s=
github.com/spyzhov/ajson v0.9.0 h1:tF46gJGOenYVj+k9K1U1XpCxVWhmiyY5PsVCAs1+OJ0=
@@ -226,7 +222,6 @@ 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.1.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.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+9 -12
View File
@@ -18,7 +18,7 @@ var muxProtocols = []string{
}
func TestVMessSMux(t *testing.T) {
testVMessMux(t, option.OutboundMultiplexOptions{
testVMessMux(t, option.MultiplexOptions{
Enabled: true,
Protocol: "smux",
})
@@ -27,7 +27,7 @@ func TestVMessSMux(t *testing.T) {
func TestShadowsocksMux(t *testing.T) {
for _, protocol := range muxProtocols {
t.Run(protocol, func(t *testing.T) {
testShadowsocksMux(t, option.OutboundMultiplexOptions{
testShadowsocksMux(t, option.MultiplexOptions{
Enabled: true,
Protocol: protocol,
})
@@ -36,7 +36,7 @@ func TestShadowsocksMux(t *testing.T) {
}
func TestShadowsockH2Mux(t *testing.T) {
testShadowsocksMux(t, option.OutboundMultiplexOptions{
testShadowsocksMux(t, option.MultiplexOptions{
Enabled: true,
Protocol: "h2mux",
Padding: true,
@@ -44,14 +44,14 @@ func TestShadowsockH2Mux(t *testing.T) {
}
func TestShadowsockSMuxPadding(t *testing.T) {
testShadowsocksMux(t, option.OutboundMultiplexOptions{
testShadowsocksMux(t, option.MultiplexOptions{
Enabled: true,
Protocol: "smux",
Padding: true,
})
}
func testShadowsocksMux(t *testing.T, options option.OutboundMultiplexOptions) {
func testShadowsocksMux(t *testing.T, options option.MultiplexOptions) {
method := shadowaead_2022.List[0]
password := mkBase64(t, 16)
startInstance(t, option.Options{
@@ -90,9 +90,9 @@ func testShadowsocksMux(t *testing.T, options option.OutboundMultiplexOptions) {
Server: "127.0.0.1",
ServerPort: serverPort,
},
Method: method,
Password: password,
Multiplex: &options,
Method: method,
Password: password,
MultiplexOptions: &options,
},
},
},
@@ -110,7 +110,7 @@ func testShadowsocksMux(t *testing.T, options option.OutboundMultiplexOptions) {
testSuit(t, clientPort, testPort)
}
func testVMessMux(t *testing.T, options option.OutboundMultiplexOptions) {
func testVMessMux(t *testing.T, options option.MultiplexOptions) {
user, _ := uuid.NewV4()
startInstance(t, option.Options{
Inbounds: []option.Inbound{
@@ -136,9 +136,6 @@ func testVMessMux(t *testing.T, options option.OutboundMultiplexOptions) {
UUID: user.String(),
},
},
Multiplex: &option.InboundMultiplexOptions{
Enabled: true,
},
},
},
},
+1 -1
View File
@@ -232,7 +232,7 @@ func TestShadowsocksUoT(t *testing.T) {
},
Method: method,
Password: password,
UDPOverTCP: &option.UDPOverTCPOptions{
UDPOverTCPOptions: &option.UDPOverTCPOptions{
Enabled: true,
},
},
-16
View File
@@ -1,16 +0,0 @@
package main
import (
"testing"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/option"
)
func TestV2RayHTTPUpgrade(t *testing.T) {
t.Run("self", func(t *testing.T) {
testV2RayTransportSelf(t, &option.V2RayTransportOptions{
Type: C.V2RayTransportTypeHTTPUpgrade,
})
})
}
+2 -6
View File
@@ -8,7 +8,6 @@ import (
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing-box/transport/v2rayhttp"
"github.com/sagernet/sing-box/transport/v2rayhttpupgrade"
"github.com/sagernet/sing-box/transport/v2raywebsocket"
E "github.com/sagernet/sing/common/exceptions"
M "github.com/sagernet/sing/common/metadata"
@@ -36,8 +35,6 @@ func NewServerTransport(ctx context.Context, options option.V2RayTransportOption
return NewQUICServer(ctx, options.QUICOptions, tlsConfig, handler)
case C.V2RayTransportTypeGRPC:
return NewGRPCServer(ctx, options.GRPCOptions, tlsConfig, handler)
case C.V2RayTransportTypeHTTPUpgrade:
return v2rayhttpupgrade.NewServer(ctx, options.HTTPUpgradeOptions, tlsConfig, handler)
default:
return nil, E.New("unknown transport type: " + options.Type)
}
@@ -53,14 +50,13 @@ func NewClientTransport(ctx context.Context, dialer N.Dialer, serverAddr M.Socks
case C.V2RayTransportTypeGRPC:
return NewGRPCClient(ctx, dialer, serverAddr, options.GRPCOptions, tlsConfig)
case C.V2RayTransportTypeWebsocket:
return v2raywebsocket.NewClient(ctx, dialer, serverAddr, options.WebsocketOptions, tlsConfig)
return v2raywebsocket.NewClient(ctx, dialer, serverAddr, options.WebsocketOptions, tlsConfig), nil
case C.V2RayTransportTypeQUIC:
if tlsConfig == nil {
return nil, C.ErrTLSRequired
}
return NewQUICClient(ctx, dialer, serverAddr, options.QUICOptions, tlsConfig)
case C.V2RayTransportTypeHTTPUpgrade:
return v2rayhttpupgrade.NewClient(ctx, dialer, serverAddr, options.HTTPUpgradeOptions, tlsConfig)
default:
return nil, E.New("unknown transport type: " + options.Type)
}
+1 -1
View File
@@ -100,7 +100,7 @@ func (c *Client) DialContext(ctx context.Context) (net.Conn, error) {
conn.setup(nil, err)
} else if response.StatusCode != 200 {
response.Body.Close()
conn.setup(nil, E.New("unexpected status: ", response.Status))
conn.setup(nil, E.New("unexpected status: ", response.StatusCode, " ", response.Status))
} else {
conn.setup(response.Body, nil)
}
+4 -4
View File
@@ -35,6 +35,10 @@ type Server struct {
path string
}
func (s *Server) Network() []string {
return []string{N.NetworkTCP}
}
func NewServer(ctx context.Context, options option.V2RayGRPCOptions, tlsConfig tls.ServerConfig, handler adapter.V2RayServerTransportHandler) (*Server, error) {
server := &Server{
tlsConfig: tlsConfig,
@@ -88,10 +92,6 @@ func (s *Server) invalidRequest(writer http.ResponseWriter, request *http.Reques
s.handler.NewError(request.Context(), E.Cause(err, "process connection from ", request.RemoteAddr))
}
func (s *Server) Network() []string {
return []string{N.NetworkTCP}
}
func (s *Server) Serve(listener net.Listener) error {
if s.tlsConfig != nil {
if !common.Contains(s.tlsConfig.NextProtos(), http2.NextProtoTLS) {
+2 -2
View File
@@ -81,7 +81,7 @@ func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, opt
uri.Path = options.Path
err := sHTTP.URLSetPath(&uri, options.Path)
if err != nil {
return nil, E.New("parse path: " + err.Error())
return nil, E.New("failed to set path: " + err.Error())
}
client.url = &uri
return client, nil
@@ -143,7 +143,7 @@ func (c *Client) dialHTTP2(ctx context.Context) (net.Conn, error) {
conn.Setup(nil, err)
} else if response.StatusCode != 200 {
response.Body.Close()
conn.Setup(nil, E.New("unexpected status: ", response.Status))
conn.Setup(nil, E.New("unexpected status: ", response.StatusCode, " ", response.Status))
} else {
conn.Setup(response.Body, nil)
}
+4 -4
View File
@@ -40,6 +40,10 @@ type Server struct {
headers http.Header
}
func (s *Server) Network() []string {
return []string{N.NetworkTCP}
}
func NewServer(ctx context.Context, options option.V2RayHTTPOptions, tlsConfig tls.ServerConfig, handler adapter.V2RayServerTransportHandler) (*Server, error) {
server := &Server{
ctx: ctx,
@@ -149,10 +153,6 @@ func (s *Server) invalidRequest(writer http.ResponseWriter, request *http.Reques
s.handler.NewError(request.Context(), E.Cause(err, "process connection from ", request.RemoteAddr))
}
func (s *Server) Network() []string {
return []string{N.NetworkTCP}
}
func (s *Server) Serve(listener net.Listener) error {
if s.tlsConfig != nil {
if len(s.tlsConfig.NextProtos()) == 0 {
-118
View File
@@ -1,118 +0,0 @@
package v2rayhttpupgrade
import (
std_bufio "bufio"
"context"
"net"
"net/http"
"net/url"
"strings"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/tls"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing/common/buf"
"github.com/sagernet/sing/common/bufio"
E "github.com/sagernet/sing/common/exceptions"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
sHTTP "github.com/sagernet/sing/protocol/http"
)
var _ adapter.V2RayClientTransport = (*Client)(nil)
type Client struct {
dialer N.Dialer
tlsConfig tls.Config
serverAddr M.Socksaddr
requestURL url.URL
headers http.Header
host string
}
func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, options option.V2RayHTTPUpgradeOptions, tlsConfig tls.Config) (*Client, error) {
if tlsConfig != nil {
if len(tlsConfig.NextProtos()) == 0 {
tlsConfig.SetNextProtos([]string{"http/1.1"})
}
}
var host string
if options.Host != "" {
host = options.Host
} else if tlsConfig != nil && tlsConfig.ServerName() != "" {
host = tlsConfig.ServerName()
} else {
host = serverAddr.String()
}
var requestURL url.URL
if tlsConfig == nil {
requestURL.Scheme = "http"
} else {
requestURL.Scheme = "https"
}
requestURL.Host = serverAddr.String()
requestURL.Path = options.Path
err := sHTTP.URLSetPath(&requestURL, options.Path)
if err != nil {
return nil, E.Cause(err, "parse path")
}
if !strings.HasPrefix(requestURL.Path, "/") {
requestURL.Path = "/" + requestURL.Path
}
headers := make(http.Header)
for key, value := range options.Headers {
headers[key] = value
}
return &Client{
dialer: dialer,
tlsConfig: tlsConfig,
serverAddr: serverAddr,
requestURL: requestURL,
headers: headers,
host: host,
}, nil
}
func (c *Client) DialContext(ctx context.Context) (net.Conn, error) {
conn, err := c.dialer.DialContext(ctx, N.NetworkTCP, c.serverAddr)
if err != nil {
return nil, err
}
if c.tlsConfig != nil {
conn, err = tls.ClientHandshake(ctx, conn, c.tlsConfig)
if err != nil {
return nil, err
}
}
request := &http.Request{
Method: http.MethodGet,
URL: &c.requestURL,
Header: c.headers.Clone(),
Host: c.host,
}
request.Header.Set("Connection", "Upgrade")
request.Header.Set("Upgrade", "websocket")
err = request.Write(conn)
if err != nil {
return nil, err
}
bufReader := std_bufio.NewReader(conn)
response, err := http.ReadResponse(bufReader, request)
if err != nil {
return nil, err
}
if response.StatusCode != 101 ||
!strings.EqualFold(response.Header.Get("Connection"), "upgrade") ||
!strings.EqualFold(response.Header.Get("Upgrade"), "websocket") {
return nil, E.New("unexpected status: ", response.Status)
}
if bufReader.Buffered() > 0 {
buffer := buf.NewSize(bufReader.Buffered())
_, err = buffer.ReadFullFrom(bufReader, buffer.Len())
if err != nil {
return nil, err
}
conn = bufio.NewCachedConn(conn, buffer)
}
return conn, nil
}
-139
View File
@@ -1,139 +0,0 @@
package v2rayhttpupgrade
import (
"context"
"net"
"net/http"
"os"
"strings"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/tls"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing/common"
E "github.com/sagernet/sing/common/exceptions"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
aTLS "github.com/sagernet/sing/common/tls"
sHttp "github.com/sagernet/sing/protocol/http"
)
var _ adapter.V2RayServerTransport = (*Server)(nil)
type Server struct {
ctx context.Context
tlsConfig tls.ServerConfig
handler adapter.V2RayServerTransportHandler
httpServer *http.Server
host string
path string
headers http.Header
}
func NewServer(ctx context.Context, options option.V2RayHTTPUpgradeOptions, tlsConfig tls.ServerConfig, handler adapter.V2RayServerTransportHandler) (*Server, error) {
server := &Server{
ctx: ctx,
tlsConfig: tlsConfig,
handler: handler,
host: options.Host,
path: options.Path,
headers: options.Headers.Build(),
}
if !strings.HasPrefix(server.path, "/") {
server.path = "/" + server.path
}
server.httpServer = &http.Server{
Handler: server,
ReadHeaderTimeout: C.TCPTimeout,
MaxHeaderBytes: http.DefaultMaxHeaderBytes,
BaseContext: func(net.Listener) context.Context {
return ctx
},
TLSNextProto: make(map[string]func(*http.Server, *tls.STDConn, http.Handler)),
}
return server, nil
}
type httpFlusher interface {
FlushError() error
}
func (s *Server) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
host := request.Host
if len(s.host) > 0 && host != s.host {
s.invalidRequest(writer, request, http.StatusBadRequest, E.New("bad host: ", host))
return
}
if !strings.HasPrefix(request.URL.Path, s.path) {
s.invalidRequest(writer, request, http.StatusNotFound, E.New("bad path: ", request.URL.Path))
return
}
if request.Method != http.MethodGet {
s.invalidRequest(writer, request, http.StatusNotFound, E.New("bad method: ", request.Method))
return
}
if !strings.EqualFold(request.Header.Get("Connection"), "upgrade") {
s.invalidRequest(writer, request, http.StatusNotFound, E.New("not a upgrade request"))
return
}
if !strings.EqualFold(request.Header.Get("Upgrade"), "websocket") {
s.invalidRequest(writer, request, http.StatusNotFound, E.New("not a websocket request"))
return
}
if request.Header.Get("Sec-WebSocket-Key") != "" {
s.invalidRequest(writer, request, http.StatusNotFound, E.New("real websocket request received"))
return
}
writer.Header().Set("Connection", "upgrade")
writer.Header().Set("Upgrade", "websocket")
writer.WriteHeader(http.StatusSwitchingProtocols)
if flusher, isFlusher := writer.(httpFlusher); isFlusher {
err := flusher.FlushError()
if err != nil {
s.invalidRequest(writer, request, http.StatusInternalServerError, E.New("flush response"))
}
}
hijacker, canHijack := writer.(http.Hijacker)
if !canHijack {
s.invalidRequest(writer, request, http.StatusInternalServerError, E.New("invalid connection, maybe HTTP/2"))
return
}
conn, _, err := hijacker.Hijack()
if err != nil {
s.invalidRequest(writer, request, http.StatusInternalServerError, E.Cause(err, "hijack failed"))
return
}
var metadata M.Metadata
metadata.Source = sHttp.SourceAddress(request)
s.handler.NewConnection(request.Context(), conn, metadata)
}
func (s *Server) invalidRequest(writer http.ResponseWriter, request *http.Request, statusCode int, err error) {
if statusCode > 0 {
writer.WriteHeader(statusCode)
}
s.handler.NewError(request.Context(), E.Cause(err, "process connection from ", request.RemoteAddr))
}
func (s *Server) Network() []string {
return []string{N.NetworkTCP}
}
func (s *Server) Serve(listener net.Listener) error {
if s.tlsConfig != nil {
if len(s.tlsConfig.NextProtos()) == 0 {
s.tlsConfig.SetNextProtos([]string{"http/1.1"})
}
listener = aTLS.NewListener(listener, s.tlsConfig)
}
return s.httpServer.Serve(listener)
}
func (s *Server) ServePacket(listener net.PacketConn) error {
return os.ErrInvalid
}
func (s *Server) Close() error {
return common.Close(common.PtrOrNil(s.httpServer))
}
+3 -7
View File
@@ -12,7 +12,6 @@ import (
"github.com/sagernet/sing-box/common/tls"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/option"
E "github.com/sagernet/sing/common/exceptions"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
sHTTP "github.com/sagernet/sing/protocol/http"
@@ -31,7 +30,7 @@ type Client struct {
earlyDataHeaderName string
}
func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, options option.V2RayWebsocketOptions, tlsConfig tls.Config) (*Client, error) {
func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, options option.V2RayWebsocketOptions, tlsConfig tls.Config) adapter.V2RayClientTransport {
if tlsConfig != nil {
if len(tlsConfig.NextProtos()) == 0 {
tlsConfig.SetNextProtos([]string{"http/1.1"})
@@ -47,7 +46,7 @@ func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, opt
requestURL.Path = options.Path
err := sHTTP.URLSetPath(&requestURL, options.Path)
if err != nil {
return nil, E.Cause(err, "parse path")
return nil
}
if !strings.HasPrefix(requestURL.Path, "/") {
requestURL.Path = "/" + requestURL.Path
@@ -56,9 +55,6 @@ func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, opt
for key, value := range options.Headers {
headers[key] = value
}
if headers.Get("User-Agent") == "" {
headers.Set("User-Agent", "Go-http-client/1.1")
}
return &Client{
dialer,
tlsConfig,
@@ -67,7 +63,7 @@ func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, opt
headers,
options.MaxEarlyData,
options.EarlyDataHeaderName,
}, nil
}
}
func (c *Client) dialContext(ctx context.Context, requestURL *url.URL, headers http.Header) (*WebsocketConn, error) {