Compare commits

...

29 Commits

Author SHA1 Message Date
世界
ffd54eef6c Update documentation 2022-11-21 21:20:44 +08:00
世界
c16e4316d6 Fix shadowtls server 2022-11-21 21:20:44 +08:00
世界
8b7fe20b7f Include uTLS in release 2022-11-21 15:25:49 +08:00
世界
696c1065b6 Update stable documentation 2022-11-21 14:57:22 +08:00
世界
5d690f4147 Update documentation 2022-11-21 13:18:04 +08:00
世界
f906641a82 Add uTLS to makefile default tags 2022-11-21 13:18:04 +08:00
世界
89913dfa8c Improve shadowtls server 2022-11-21 13:18:04 +08:00
世界
468778f67f Update dependencies 2022-11-21 13:18:04 +08:00
世界
22a22aebe2 Fix default dns transport strategy 2022-11-21 13:18:04 +08:00
世界
a2d2ec9b45 Update documentation 2022-11-15 17:36:42 +08:00
世界
2695b3516e Update issue template 2022-11-13 11:45:24 +08:00
世界
3a9ef8fac0 Remove unused 2022-11-13 11:30:48 +08:00
世界
ebad363201 Fix create TLS config 2022-11-13 11:24:37 +08:00
世界
11076d52cd Fix dns buffer & quic retry 2022-11-13 11:16:10 +08:00
世界
5eb132063e Fix connect packet connection for mux client 2022-11-12 03:53:42 +08:00
世界
13ab5d3348 Remove follow in update script 2022-11-11 22:32:24 +08:00
世界
ce1ddc400f Support x/h2 v0.2.0 deadline 2022-11-11 22:08:20 +08:00
arm64v8a
2c9d25e853 Fix websocket alpn 2022-11-11 20:01:49 +08:00
世界
3d76777760 Fix tor geoip 2022-11-10 22:42:05 +08:00
世界
24f4dfea04 Fix hysteria test 2022-11-10 21:10:18 +08:00
世界
2fc1a0a9dd Update documentation 2022-11-10 16:33:10 +08:00
世界
617aba84e4 Add multi user support for hysteria inbound 2022-11-09 21:00:08 +08:00
世界
5510c474c7 Fix h2c transport 2022-11-09 12:15:14 +08:00
世界
eb2e8a0b40 Add custom tls client support for std grpc 2022-11-09 11:46:29 +08:00
世界
972491c19d Fix default local DNS server behavior 2022-11-09 10:35:16 +08:00
世界
7358ca4a52 Fix vmess request buffer 2022-11-09 10:16:22 +08:00
世界
61c274045a Update install go script 2022-11-08 23:19:53 +08:00
世界
f205140b04 Fix smux keep alive 2022-11-08 16:45:38 +08:00
世界
1db8e03c86 Fix format 2022-11-08 14:54:19 +08:00
64 changed files with 963 additions and 591 deletions

View File

@@ -12,7 +12,7 @@ body:
required: true
- label: Yes, I've searched similar issues on GitHub and didn't find any.
required: true
- label: Yes, I've included all information below (version, config, log, etc).
- label: Yes, I've included all information below (version, **FULL** config, **FULL** log, etc).
required: true
- type: textarea

View File

@@ -14,6 +14,7 @@ builds:
- with_gvisor
- with_quic
- with_wireguard
- with_utls
- with_clash_api
env:
- CGO_ENABLED=0

View File

@@ -1,6 +1,6 @@
NAME = sing-box
COMMIT = $(shell git rev-parse --short HEAD)
TAGS ?= with_gvisor,with_quic,with_wireguard,with_clash_api
TAGS ?= with_gvisor,with_quic,with_wireguard,with_utls,with_clash_api
TAGS_TEST ?= with_gvisor,with_quic,with_wireguard,with_grpc,with_ech,with_utls,with_shadowsocksr
PARAMS = -v -trimpath -tags "$(TAGS)" -ldflags "-s -w -buildid="
MAIN = ./cmd/sing-box

View File

@@ -329,6 +329,23 @@ func (c *ClientPacketConn) Write(b []byte) (n int, err error) {
return c.ExtendedConn.Write(b)
}
func (c *ClientPacketConn) ReadBuffer(buffer *buf.Buffer) (err error) {
if !c.responseRead {
err = c.readResponse()
if err != nil {
return
}
c.responseRead = true
}
var length uint16
err = binary.Read(c.ExtendedConn, binary.BigEndian, &length)
if err != nil {
return
}
_, err = buffer.ReadFullFrom(c.ExtendedConn, int(length))
return
}
func (c *ClientPacketConn) WriteBuffer(buffer *buf.Buffer) error {
if !c.requestWrite {
defer buffer.Release()
@@ -343,6 +360,11 @@ func (c *ClientPacketConn) FrontHeadroom() int {
return 2
}
func (c *ClientPacketConn) ReadPacket(buffer *buf.Buffer) (destination M.Socksaddr, err error) {
err = c.ReadBuffer(buffer)
return
}
func (c *ClientPacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error {
return c.WriteBuffer(buffer)
}

View File

@@ -43,7 +43,7 @@ func ParseProtocol(name string) (Protocol, error) {
func (p Protocol) newServer(conn net.Conn) (abstractSession, error) {
switch p {
case ProtocolSMux:
session, err := smux.Server(conn, nil)
session, err := smux.Server(conn, smuxConfig())
if err != nil {
return nil, err
}
@@ -58,7 +58,7 @@ func (p Protocol) newServer(conn net.Conn) (abstractSession, error) {
func (p Protocol) newClient(conn net.Conn) (abstractSession, error) {
switch p {
case ProtocolSMux:
session, err := smux.Client(conn, nil)
session, err := smux.Client(conn, smuxConfig())
if err != nil {
return nil, err
}
@@ -70,6 +70,12 @@ func (p Protocol) newClient(conn net.Conn) (abstractSession, error) {
}
}
func smuxConfig() *smux.Config {
config := smux.DefaultConfig()
config.KeepAliveDisabled = true
return config
}
func yaMuxConfig() *yamux.Config {
config := yamux.DefaultConfig()
config.LogOutput = io.Discard

View File

@@ -15,6 +15,9 @@ import (
)
func NewDialerFromOptions(router adapter.Router, dialer N.Dialer, serverAddress string, options option.OutboundTLSOptions) (N.Dialer, error) {
if !options.Enabled {
return dialer, nil
}
config, err := NewClient(router, serverAddress, options)
if err != nil {
return nil, err
@@ -23,12 +26,15 @@ func NewDialerFromOptions(router adapter.Router, dialer N.Dialer, serverAddress
}
func NewClient(router adapter.Router, serverAddress string, options option.OutboundTLSOptions) (Config, error) {
if !options.Enabled {
return nil, nil
}
if options.ECH != nil && options.ECH.Enabled {
return newECHClient(router, serverAddress, options)
return NewECHClient(router, serverAddress, options)
} else if options.UTLS != nil && options.UTLS.Enabled {
return newUTLSClient(router, serverAddress, options)
return NewUTLSClient(router, serverAddress, options)
} else {
return newStdClient(serverAddress, options)
return NewSTDClient(serverAddress, options)
}
}

View File

@@ -15,10 +15,13 @@ type (
)
type Config interface {
ServerName() string
SetServerName(serverName string)
NextProtos() []string
SetNextProtos(nextProto []string)
Config() (*STDConfig, error)
Client(conn net.Conn) Conn
Clone() Config
}
type ServerConfig interface {

View File

@@ -20,26 +20,40 @@ import (
mDNS "github.com/miekg/dns"
)
type echClientConfig struct {
type ECHClientConfig struct {
config *cftls.Config
}
func (e *echClientConfig) NextProtos() []string {
func (e *ECHClientConfig) ServerName() string {
return e.config.ServerName
}
func (e *ECHClientConfig) SetServerName(serverName string) {
e.config.ServerName = serverName
}
func (e *ECHClientConfig) NextProtos() []string {
return e.config.NextProtos
}
func (e *echClientConfig) SetNextProtos(nextProto []string) {
func (e *ECHClientConfig) SetNextProtos(nextProto []string) {
e.config.NextProtos = nextProto
}
func (e *echClientConfig) Config() (*STDConfig, error) {
func (e *ECHClientConfig) Config() (*STDConfig, error) {
return nil, E.New("unsupported usage for ECH")
}
func (e *echClientConfig) Client(conn net.Conn) Conn {
func (e *ECHClientConfig) Client(conn net.Conn) Conn {
return &echConnWrapper{cftls.Client(conn, e.config)}
}
func (e *ECHClientConfig) Clone() Config {
return &ECHClientConfig{
config: e.config.Clone(),
}
}
type echConnWrapper struct {
*cftls.Conn
}
@@ -62,7 +76,7 @@ func (c *echConnWrapper) ConnectionState() tls.ConnectionState {
}
}
func newECHClient(router adapter.Router, serverAddress string, options option.OutboundTLSOptions) (Config, error) {
func NewECHClient(router adapter.Router, serverAddress string, options option.OutboundTLSOptions) (Config, error) {
var serverName string
if options.ServerName != "" {
serverName = options.ServerName
@@ -162,7 +176,7 @@ func newECHClient(router adapter.Router, serverAddress string, options option.Ou
} else {
tlsConfig.GetClientECHConfigs = fetchECHClientConfig(router)
}
return &echClientConfig{&tlsConfig}, nil
return &ECHClientConfig{&tlsConfig}, nil
}
func fetchECHClientConfig(router adapter.Router) func(ctx context.Context, serverName string) ([]cftls.ECHConfig, error) {

View File

@@ -8,6 +8,6 @@ import (
E "github.com/sagernet/sing/common/exceptions"
)
func newECHClient(router adapter.Router, serverAddress string, options option.OutboundTLSOptions) (Config, error) {
func NewECHClient(router adapter.Router, serverAddress string, options option.OutboundTLSOptions) (Config, error) {
return nil, E.New(`ECH is not included in this build, rebuild with -tags with_ech`)
}

View File

@@ -12,7 +12,10 @@ import (
)
func NewServer(ctx context.Context, logger log.Logger, options option.InboundTLSOptions) (ServerConfig, error) {
return newSTDServer(ctx, logger, options)
if !options.Enabled {
return nil, nil
}
return NewSTDServer(ctx, logger, options)
}
func ServerHandshake(ctx context.Context, conn net.Conn, config ServerConfig) (Conn, error) {

View File

@@ -11,11 +11,39 @@ import (
E "github.com/sagernet/sing/common/exceptions"
)
type stdClientConfig struct {
type STDClientConfig struct {
config *tls.Config
}
func newStdClient(serverAddress string, options option.OutboundTLSOptions) (Config, error) {
func (s *STDClientConfig) ServerName() string {
return s.config.ServerName
}
func (s *STDClientConfig) SetServerName(serverName string) {
s.config.ServerName = serverName
}
func (s *STDClientConfig) NextProtos() []string {
return s.config.NextProtos
}
func (s *STDClientConfig) SetNextProtos(nextProto []string) {
s.config.NextProtos = nextProto
}
func (s *STDClientConfig) Config() (*STDConfig, error) {
return s.config, nil
}
func (s *STDClientConfig) Client(conn net.Conn) Conn {
return tls.Client(conn, s.config)
}
func (s *STDClientConfig) Clone() Config {
return &STDClientConfig{s.config.Clone()}
}
func NewSTDClient(serverAddress string, options option.OutboundTLSOptions) (Config, error) {
var serverName string
if options.ServerName != "" {
serverName = options.ServerName
@@ -96,21 +124,5 @@ func newStdClient(serverAddress string, options option.OutboundTLSOptions) (Conf
}
tlsConfig.RootCAs = certPool
}
return &stdClientConfig{&tlsConfig}, nil
}
func (s *stdClientConfig) NextProtos() []string {
return s.config.NextProtos
}
func (s *stdClientConfig) SetNextProtos(nextProto []string) {
s.config.NextProtos = nextProto
}
func (s *stdClientConfig) Config() (*STDConfig, error) {
return s.config, nil
}
func (s *stdClientConfig) Client(conn net.Conn) Conn {
return tls.Client(conn, s.config)
return &STDClientConfig{&tlsConfig}, nil
}

View File

@@ -15,6 +15,8 @@ import (
"github.com/fsnotify/fsnotify"
)
var errInsecureUnused = E.New("tls: insecure unused")
type STDServerConfig struct {
config *tls.Config
logger log.Logger
@@ -26,6 +28,14 @@ type STDServerConfig struct {
watcher *fsnotify.Watcher
}
func (c *STDServerConfig) ServerName() string {
return c.config.ServerName
}
func (c *STDServerConfig) SetServerName(serverName string) {
c.config.ServerName = serverName
}
func (c *STDServerConfig) NextProtos() []string {
return c.config.NextProtos
}
@@ -34,9 +44,119 @@ func (c *STDServerConfig) SetNextProtos(nextProto []string) {
c.config.NextProtos = nextProto
}
var errInsecureUnused = E.New("tls: insecure unused")
func (c *STDServerConfig) Config() (*STDConfig, error) {
return c.config, nil
}
func newSTDServer(ctx context.Context, logger log.Logger, options option.InboundTLSOptions) (ServerConfig, error) {
func (c *STDServerConfig) Client(conn net.Conn) Conn {
return tls.Client(conn, c.config)
}
func (c *STDServerConfig) Server(conn net.Conn) Conn {
return tls.Server(conn, c.config)
}
func (c *STDServerConfig) Clone() Config {
return &STDServerConfig{
config: c.config.Clone(),
}
}
func (c *STDServerConfig) Start() error {
if c.acmeService != nil {
return c.acmeService.Start()
} else {
if c.certificatePath == "" && c.keyPath == "" {
return nil
}
err := c.startWatcher()
if err != nil {
c.logger.Warn("create fsnotify watcher: ", err)
}
return nil
}
}
func (c *STDServerConfig) startWatcher() error {
watcher, err := fsnotify.NewWatcher()
if err != nil {
return err
}
if c.certificatePath != "" {
err = watcher.Add(c.certificatePath)
if err != nil {
return err
}
}
if c.keyPath != "" {
err = watcher.Add(c.keyPath)
if err != nil {
return err
}
}
c.watcher = watcher
go c.loopUpdate()
return nil
}
func (c *STDServerConfig) loopUpdate() {
for {
select {
case event, ok := <-c.watcher.Events:
if !ok {
return
}
if event.Op&fsnotify.Write != fsnotify.Write {
continue
}
err := c.reloadKeyPair()
if err != nil {
c.logger.Error(E.Cause(err, "reload TLS key pair"))
}
case err, ok := <-c.watcher.Errors:
if !ok {
return
}
c.logger.Error(E.Cause(err, "fsnotify error"))
}
}
}
func (c *STDServerConfig) reloadKeyPair() error {
if c.certificatePath != "" {
certificate, err := os.ReadFile(c.certificatePath)
if err != nil {
return E.Cause(err, "reload certificate from ", c.certificatePath)
}
c.certificate = certificate
}
if c.keyPath != "" {
key, err := os.ReadFile(c.keyPath)
if err != nil {
return E.Cause(err, "reload key from ", c.keyPath)
}
c.key = key
}
keyPair, err := tls.X509KeyPair(c.certificate, c.key)
if err != nil {
return E.Cause(err, "reload key pair")
}
c.config.Certificates = []tls.Certificate{keyPair}
c.logger.Info("reloaded TLS certificate")
return nil
}
func (c *STDServerConfig) Close() error {
if c.acmeService != nil {
return c.acmeService.Close()
}
if c.watcher != nil {
return c.watcher.Close()
}
return nil
}
func NewSTDServer(ctx context.Context, logger log.Logger, options option.InboundTLSOptions) (ServerConfig, error) {
if !options.Enabled {
return nil, nil
}
@@ -136,109 +256,3 @@ func newSTDServer(ctx context.Context, logger log.Logger, options option.Inbound
keyPath: options.KeyPath,
}, nil
}
func (c *STDServerConfig) Config() (*STDConfig, error) {
return c.config, nil
}
func (c *STDServerConfig) Client(conn net.Conn) Conn {
return tls.Client(conn, c.config)
}
func (c *STDServerConfig) Server(conn net.Conn) Conn {
return tls.Server(conn, c.config)
}
func (c *STDServerConfig) Start() error {
if c.acmeService != nil {
return c.acmeService.Start()
} else {
if c.certificatePath == "" && c.keyPath == "" {
return nil
}
err := c.startWatcher()
if err != nil {
c.logger.Warn("create fsnotify watcher: ", err)
}
return nil
}
}
func (c *STDServerConfig) startWatcher() error {
watcher, err := fsnotify.NewWatcher()
if err != nil {
return err
}
if c.certificatePath != "" {
err = watcher.Add(c.certificatePath)
if err != nil {
return err
}
}
if c.keyPath != "" {
err = watcher.Add(c.keyPath)
if err != nil {
return err
}
}
c.watcher = watcher
go c.loopUpdate()
return nil
}
func (c *STDServerConfig) loopUpdate() {
for {
select {
case event, ok := <-c.watcher.Events:
if !ok {
return
}
if event.Op&fsnotify.Write != fsnotify.Write {
continue
}
err := c.reloadKeyPair()
if err != nil {
c.logger.Error(E.Cause(err, "reload TLS key pair"))
}
case err, ok := <-c.watcher.Errors:
if !ok {
return
}
c.logger.Error(E.Cause(err, "fsnotify error"))
}
}
}
func (c *STDServerConfig) reloadKeyPair() error {
if c.certificatePath != "" {
certificate, err := os.ReadFile(c.certificatePath)
if err != nil {
return E.Cause(err, "reload certificate from ", c.certificatePath)
}
c.certificate = certificate
}
if c.keyPath != "" {
key, err := os.ReadFile(c.keyPath)
if err != nil {
return E.Cause(err, "reload key from ", c.keyPath)
}
c.key = key
}
keyPair, err := tls.X509KeyPair(c.certificate, c.key)
if err != nil {
return E.Cause(err, "reload key pair")
}
c.config.Certificates = []tls.Certificate{keyPair}
c.logger.Info("reloaded TLS certificate")
return nil
}
func (c *STDServerConfig) Close() error {
if c.acmeService != nil {
return c.acmeService.Close()
}
if c.watcher != nil {
return c.watcher.Close()
}
return nil
}

View File

@@ -16,24 +16,32 @@ import (
utls "github.com/refraction-networking/utls"
)
type utlsClientConfig struct {
type UTLSClientConfig struct {
config *utls.Config
id utls.ClientHelloID
}
func (e *utlsClientConfig) NextProtos() []string {
func (e *UTLSClientConfig) ServerName() string {
return e.config.ServerName
}
func (e *UTLSClientConfig) SetServerName(serverName string) {
e.config.ServerName = serverName
}
func (e *UTLSClientConfig) NextProtos() []string {
return e.config.NextProtos
}
func (e *utlsClientConfig) SetNextProtos(nextProto []string) {
func (e *UTLSClientConfig) SetNextProtos(nextProto []string) {
e.config.NextProtos = nextProto
}
func (e *utlsClientConfig) Config() (*STDConfig, error) {
func (e *UTLSClientConfig) Config() (*STDConfig, error) {
return nil, E.New("unsupported usage for uTLS")
}
func (e *utlsClientConfig) Client(conn net.Conn) Conn {
func (e *UTLSClientConfig) Client(conn net.Conn) Conn {
return &utlsConnWrapper{utls.UClient(conn, e.config.Clone(), e.id)}
}
@@ -59,7 +67,14 @@ func (c *utlsConnWrapper) ConnectionState() tls.ConnectionState {
}
}
func newUTLSClient(router adapter.Router, serverAddress string, options option.OutboundTLSOptions) (Config, error) {
func (e *UTLSClientConfig) Clone() Config {
return &UTLSClientConfig{
config: e.config.Clone(),
id: e.id,
}
}
func NewUTLSClient(router adapter.Router, serverAddress string, options option.OutboundTLSOptions) (Config, error) {
var serverName string
if options.ServerName != "" {
serverName = options.ServerName
@@ -152,5 +167,5 @@ func newUTLSClient(router adapter.Router, serverAddress string, options option.O
default:
return nil, E.New("unknown uTLS fingerprint: ", options.UTLS.Fingerprint)
}
return &utlsClientConfig{&tlsConfig, id}, nil
return &UTLSClientConfig{&tlsConfig, id}, nil
}

View File

@@ -8,6 +8,6 @@ import (
E "github.com/sagernet/sing/common/exceptions"
)
func newUTLSClient(router adapter.Router, serverAddress string, options option.OutboundTLSOptions) (Config, error) {
func NewUTLSClient(router adapter.Router, serverAddress string, options option.OutboundTLSOptions) (Config, error) {
return nil, E.New(`uTLS is not included in this build, rebuild with -tags with_utls`)
}

View File

@@ -1,145 +0,0 @@
package trafficcontrol
import (
"io"
"net"
"sync"
"sync/atomic"
"github.com/sagernet/sing/common/buf"
"github.com/sagernet/sing/common/bufio"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
)
type Manager[U comparable] struct {
access sync.Mutex
users map[U]*Traffic
}
type Traffic struct {
Upload uint64
Download uint64
}
func NewManager[U comparable]() *Manager[U] {
return &Manager[U]{
users: make(map[U]*Traffic),
}
}
func (m *Manager[U]) Reset() {
m.users = make(map[U]*Traffic)
}
func (m *Manager[U]) TrackConnection(user U, conn net.Conn) net.Conn {
m.access.Lock()
defer m.access.Unlock()
var traffic *Traffic
if t, loaded := m.users[user]; loaded {
traffic = t
} else {
traffic = new(Traffic)
m.users[user] = traffic
}
return &TrackConn{conn, traffic}
}
func (m *Manager[U]) TrackPacketConnection(user U, conn N.PacketConn) N.PacketConn {
m.access.Lock()
defer m.access.Unlock()
var traffic *Traffic
if t, loaded := m.users[user]; loaded {
traffic = t
} else {
traffic = new(Traffic)
m.users[user] = traffic
}
return &TrackPacketConn{conn, traffic}
}
func (m *Manager[U]) ReadTraffics() map[U]Traffic {
m.access.Lock()
defer m.access.Unlock()
trafficMap := make(map[U]Traffic)
for user, traffic := range m.users {
upload := atomic.SwapUint64(&traffic.Upload, 0)
download := atomic.SwapUint64(&traffic.Download, 0)
if upload == 0 && download == 0 {
continue
}
trafficMap[user] = Traffic{
Upload: upload,
Download: download,
}
}
return trafficMap
}
type TrackConn struct {
net.Conn
*Traffic
}
func (c *TrackConn) Read(p []byte) (n int, err error) {
n, err = c.Conn.Read(p)
if n > 0 {
atomic.AddUint64(&c.Upload, uint64(n))
}
return
}
func (c *TrackConn) Write(p []byte) (n int, err error) {
n, err = c.Conn.Write(p)
if n > 0 {
atomic.AddUint64(&c.Download, uint64(n))
}
return
}
func (c *TrackConn) WriteTo(w io.Writer) (n int64, err error) {
n, err = bufio.Copy(w, c.Conn)
if n > 0 {
atomic.AddUint64(&c.Upload, uint64(n))
}
return
}
func (c *TrackConn) ReadFrom(r io.Reader) (n int64, err error) {
n, err = bufio.Copy(c.Conn, r)
if n > 0 {
atomic.AddUint64(&c.Download, uint64(n))
}
return
}
func (c *TrackConn) Upstream() any {
return c.Conn
}
type TrackPacketConn struct {
N.PacketConn
*Traffic
}
func (c *TrackPacketConn) ReadPacket(buffer *buf.Buffer) (M.Socksaddr, error) {
destination, err := c.PacketConn.ReadPacket(buffer)
if err == nil {
atomic.AddUint64(&c.Upload, uint64(buffer.Len()))
}
return destination, err
}
func (c *TrackPacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error {
n := buffer.Len()
err := c.PacketConn.WritePacket(buffer, destination)
if err == nil {
atomic.AddUint64(&c.Download, uint64(n))
}
return err
}
func (c *TrackPacketConn) Upstream() any {
return c.PacketConn
}

View File

@@ -1,3 +1,3 @@
package constant
var Version = "1.1-beta13"
var Version = "1.1-beta17"

View File

@@ -1,3 +1,53 @@
#### 1.1-beta17
* Fix shadowtls server **1**
*1*:
Added [fallback_after](/configuration/inbound/shadowtls#fallback_after) options.
#### 1.0.7
* Add support for new x/h2 deadline
* Fix copy pipe
* Fix decrypt xplus packet
* Fix macOS Ventura process name match
* Fix smux keepalive
* Fix vmess request buffer
* Fix h2c transport
* Fix tor geoip
* Fix udp connect for mux client
* Fix default dns transport strategy
#### 1.1-beta16
* Improve shadowtls server
* Fix default dns transport strategy
* Update uTLS to v1.2.0
#### 1.1-beta15
* Add support for new x/h2 deadline
* Fix udp connect for mux client
* Fix dns buffer
* Fix quic dns retry
* Fix create TLS config
* Fix websocket alpn
* Fix tor geoip
#### 1.1-beta14
* Add multi-user support for hysteria inbound **1**
* Add custom tls client support for std grpc
* Fix smux keep alive
* Fix vmess request buffer
* Fix default local DNS server behavior
* Fix h2c transport
*1*:
The `auth` and `auth_str` fields have been replaced by the `users` field.
#### 1.1-beta13
* Add custom worker count option for WireGuard outbound

View File

@@ -12,8 +12,15 @@
"down": "100 Mbps",
"down_mbps": 100,
"obfs": "fuck me till the daylight",
"auth": "",
"auth_str": "password",
"users": [
{
"name": "sekai",
"auth": "",
"auth_str": "password"
}
],
"recv_window_conn": 0,
"recv_window_client": 0,
"max_conn_client": 0,
@@ -61,11 +68,19 @@ Supported units (case sensitive, b = bits, B = bytes, 8b=1B):
Obfuscated password.
#### auth
#### users
Hysteria users
#### users.auth
==Required if `auth_str` is empty==
Authentication password, in base64.
#### auth_str
#### users.auth_str
==Required if `auth` is empty==
Authentication password.

View File

@@ -12,8 +12,15 @@
"down": "100 Mbps",
"down_mbps": 100,
"obfs": "fuck me till the daylight",
"auth": "",
"auth_str": "password",
"users": [
{
"name": "sekai",
"auth": "",
"auth_str": "password"
}
],
"recv_window_conn": 0,
"recv_window_client": 0,
"max_conn_client": 0,
@@ -61,11 +68,19 @@
混淆密码。
#### auth
#### users
Hysteria 用户
#### users.auth
==与 auth_str 必填一个==
base64 编码的认证密码。
#### auth_str
#### users.auth_str
==与 auth 必填一个==
认证密码。

View File

@@ -9,6 +9,7 @@
"version": 2,
"password": "fuck me till the daylight",
"fallback_after": 2,
"handshake": {
"server": "google.com",
"server_port": 443,
@@ -39,6 +40,15 @@ Set password.
Only available in the ShadowTLS v2 protocol.
#### fallback_after
Packet count before perform fallback.
Default is 2.
Lowering this may prevent TLS 1.3 connections, but reduces the risk of being actively probed.
#### handshake
==Required==

View File

@@ -9,6 +9,7 @@
"version": 2,
"password": "fuck me till the daylight",
"fallback_after": 2,
"handshake": {
"server": "google.com",
"server_port": 443,
@@ -39,6 +40,14 @@ ShadowTLS 协议版本。
仅在 ShadowTLS v2 协议中可用。
#### fallback_after
在执行回退之前的包计数。
默认值为 2。
降低此值可能会阻止 TLS 1.3 连接,但会降低被主动探测的风险。
#### handshake
==必填==

18
go.mod
View File

@@ -20,26 +20,27 @@ require (
github.com/miekg/dns v1.1.50
github.com/oschwald/maxminddb-golang v1.10.0
github.com/pires/go-proxyproto v0.6.2
github.com/refraction-networking/utls v1.1.5
github.com/refraction-networking/utls v1.2.0
github.com/sagernet/cloudflare-tls v0.0.0-20221031050923-d70792f4c3a0
github.com/sagernet/quic-go v0.0.0-20221108053023-645bcc4f9b15
github.com/sagernet/sing v0.0.0-20221008120626-60a9910eefe4
github.com/sagernet/sing-dns v0.0.0-20221031055845-7de76401d403
github.com/sagernet/sing-dns v0.0.0-20221113031420-c6aaf2ea4b10
github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6
github.com/sagernet/sing-tun v0.0.0-20221104121441-66c48a57776f
github.com/sagernet/sing-vmess v0.0.0-20220925083655-063bc85ea685
github.com/sagernet/sing-vmess v0.0.0-20221109021549-b446d5bdddf0
github.com/sagernet/smux v0.0.0-20220831015742-e0f1988e3195
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e
github.com/sagernet/wireguard-go v0.0.0-20221108054404-7c2acadba17c
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c
github.com/spf13/cobra v1.6.1
github.com/stretchr/testify v1.8.1
go.etcd.io/bbolt v1.3.6
go.uber.org/atomic v1.10.0
go4.org/netipx v0.0.0-20220925034521-797b0c90d8ab
golang.org/x/crypto v0.1.1-0.20221024173537-a3485e174077
golang.org/x/net v0.1.1-0.20221102181756-a1278a7f7ee0
golang.org/x/crypto v0.3.0
golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f
golang.org/x/net v0.2.0
golang.org/x/sys v0.2.0
google.golang.org/grpc v1.50.1
google.golang.org/grpc v1.51.0
google.golang.org/protobuf v1.28.1
gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c
)
@@ -54,7 +55,7 @@ require (
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/btree v1.0.1 // indirect
github.com/inconshreveable/mousetrap v1.0.1 // indirect
github.com/klauspost/compress v1.15.9 // indirect
github.com/klauspost/compress v1.15.12 // indirect
github.com/klauspost/cpuid/v2 v2.1.1 // indirect
github.com/libdns/libdns v0.2.1 // indirect
github.com/marten-seemann/qpack v0.3.0 // indirect
@@ -68,7 +69,6 @@ require (
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.23.0 // indirect
golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f // indirect
golang.org/x/mod v0.6.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect

38
go.sum
View File

@@ -81,8 +81,8 @@ github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY=
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
github.com/klauspost/compress v1.15.12 h1:YClS/PImqYbn+UILDnqxQCZ3RehC9N318SU3kElDUEM=
github.com/klauspost/compress v1.15.12/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.1.1 h1:t0wUqjowdm8ezddV5k0tLWVklVuvLJpoHeb4WBdydm0=
github.com/klauspost/cpuid/v2 v2.1.1/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
@@ -116,8 +116,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/refraction-networking/utls v1.1.5 h1:JtrojoNhbUQkBqEg05sP3gDgDj6hIEAAVKbI9lx4n6w=
github.com/refraction-networking/utls v1.1.5/go.mod h1:jRQxtYi7nkq1p28HF2lwOH5zQm9aC8rpK0O9lIIzGh8=
github.com/refraction-networking/utls v1.2.0 h1:U5f8wkij2NVinfLuJdFP3gCMwIHs+EzvhxmYdXgiapo=
github.com/refraction-networking/utls v1.2.0/go.mod h1:NPq+cVqzH7D1BeOkmOcb5O/8iVewAsiVt2x1/eO0hgQ=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sagernet/abx-go v0.0.0-20220819185957-dba1257d738e h1:5CFRo8FJbCuf5s/eTBdZpmMbn8Fe2eSMLNAYfKanA34=
@@ -134,20 +134,20 @@ github.com/sagernet/sing v0.0.0-20220812082120-05f9836bff8f/go.mod h1:QVsS5L/ZA2
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
github.com/sagernet/sing v0.0.0-20221008120626-60a9910eefe4 h1:LO7xMvMGhYmjQg2vjhTzsODyzs9/WLYu5Per+/8jIeo=
github.com/sagernet/sing v0.0.0-20221008120626-60a9910eefe4/go.mod h1:zvgDYKI+vCAW9RyfyrKTgleI+DOa8lzHMPC7VZo3OL4=
github.com/sagernet/sing-dns v0.0.0-20221031055845-7de76401d403 h1:kKDO97rx+JVJ4HI1hTWOnCCI6um5clK1LfnIto2DY4M=
github.com/sagernet/sing-dns v0.0.0-20221031055845-7de76401d403/go.mod h1:cyL9DHbBZ0Xlt/8VD0i6yeiDayH0KzWGNQb8MYhhz7g=
github.com/sagernet/sing-dns v0.0.0-20221113031420-c6aaf2ea4b10 h1:K84AY2TxNX37ePYXVO6QTD/kgn9kDo4oGpTIn9PF5bo=
github.com/sagernet/sing-dns v0.0.0-20221113031420-c6aaf2ea4b10/go.mod h1:VAvOT1pyryBIthTGRryFLXAsR1VRQZ05wolMYeQrr/E=
github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6 h1:JJfDeYYhWunvtxsU/mOVNTmFQmnzGx9dY034qG6G3g4=
github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6/go.mod h1:EX3RbZvrwAkPI2nuGa78T2iQXmrkT+/VQtskjou42xM=
github.com/sagernet/sing-tun v0.0.0-20221104121441-66c48a57776f h1:CXF+nErOb9f7qiHingSgTa2/lJAgmEFtAQ47oVwdRGU=
github.com/sagernet/sing-tun v0.0.0-20221104121441-66c48a57776f/go.mod h1:1u3pjXA9HmH7kRiBJqM3C/zPxrxnCLd3svmqtub/RFU=
github.com/sagernet/sing-vmess v0.0.0-20220925083655-063bc85ea685 h1:AZzFNRR/ZwMTceUQ1b/mxx6oyKqmFymdMn/yleJmoVM=
github.com/sagernet/sing-vmess v0.0.0-20220925083655-063bc85ea685/go.mod h1:bwhAdSNET1X+j9DOXGj9NIQR39xgcWIk1rOQ9lLD+gM=
github.com/sagernet/sing-vmess v0.0.0-20221109021549-b446d5bdddf0 h1:z3kuD3hPNdEq7/wVy5lwE21f+8ZTazBtR81qswxJoCc=
github.com/sagernet/sing-vmess v0.0.0-20221109021549-b446d5bdddf0/go.mod h1:bwhAdSNET1X+j9DOXGj9NIQR39xgcWIk1rOQ9lLD+gM=
github.com/sagernet/smux v0.0.0-20220831015742-e0f1988e3195 h1:5VBIbVw9q7aKbrFdT83mjkyvQ+VaRsQ6yflTepfln38=
github.com/sagernet/smux v0.0.0-20220831015742-e0f1988e3195/go.mod h1:yedWtra8nyGJ+SyI+ziwuaGMzBatbB10P1IOOZbbSK8=
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-20221108054404-7c2acadba17c h1:qP3ZOHnjZalvqbjundbXiv/YrNlo3HOgrKc+S1QGs0U=
github.com/sagernet/wireguard-go v0.0.0-20221108054404-7c2acadba17c/go.mod h1:euOmN6O5kk9dQmgSS8Df4psAl3TCjxOz0NW60EWkSaI=
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c h1:vK2wyt9aWYHHvNLWniwijBu/n4pySypiKRhN32u/JGo=
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c/go.mod h1:euOmN6O5kk9dQmgSS8Df4psAl3TCjxOz0NW60EWkSaI=
github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
@@ -185,9 +185,8 @@ golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaE
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.1.1-0.20221024173537-a3485e174077 h1:t5bjOfJPQfaG9NV1imLZM5E2uzaLGs5/NtyMtRNVjQ4=
golang.org/x/crypto v0.1.1-0.20221024173537-a3485e174077/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A=
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
@@ -212,11 +211,9 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220630215102-69896b714898/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.1.1-0.20221102181756-a1278a7f7ee0 h1:vZ44Ys50wUISbPd+jC8cRLSvhyfX9Ii/ZmDnn/aiJtM=
golang.org/x/net v0.1.1-0.20221102181756-a1278a7f7ee0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU=
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -240,14 +237,13 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw=
golang.org/x/term v0.2.0 h1:z85xZCsEl7bi/KwbNADeBYoOP0++7W1ipu+aGnpwzRM=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@@ -287,8 +283,8 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY=
google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U=
google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=

View File

@@ -3,7 +3,6 @@
package inbound
import (
"bytes"
"context"
"sync"
@@ -16,9 +15,13 @@ import (
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing-box/transport/hysteria"
"github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/auth"
E "github.com/sagernet/sing/common/exceptions"
F "github.com/sagernet/sing/common/format"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"golang.org/x/exp/slices"
)
var _ adapter.Inbound = (*Hysteria)(nil)
@@ -27,7 +30,8 @@ type Hysteria struct {
myInboundAdapter
quicConfig *quic.Config
tlsConfig tls.ServerConfig
authKey []byte
authKey []string
authUser []string
xplusKey []byte
sendBPS uint64
recvBPS uint64
@@ -60,12 +64,16 @@ func NewHysteria(ctx context.Context, router adapter.Router, logger log.ContextL
if quicConfig.MaxIncomingStreams == 0 {
quicConfig.MaxIncomingStreams = hysteria.DefaultMaxIncomingStreams
}
var auth []byte
if len(options.Auth) > 0 {
auth = options.Auth
} else {
auth = []byte(options.AuthString)
}
authKey := common.Map(options.Users, func(it option.HysteriaUser) string {
if len(it.Auth) > 0 {
return string(it.Auth)
} else {
return it.AuthString
}
})
authUser := common.Map(options.Users, func(it option.HysteriaUser) string {
return it.Name
})
var xplus []byte
if options.Obfs != "" {
xplus = []byte(options.Obfs)
@@ -104,7 +112,8 @@ func NewHysteria(ctx context.Context, router adapter.Router, logger log.ContextL
listenOptions: options.ListenOptions,
},
quicConfig: quicConfig,
authKey: auth,
authKey: authKey,
authUser: authUser,
xplusKey: xplus,
sendBPS: up,
recvBPS: down,
@@ -158,7 +167,6 @@ func (h *Hysteria) acceptLoop() {
if err != nil {
return
}
h.logger.InfoContext(ctx, "inbound connection from ", conn.RemoteAddr())
go func() {
hErr := h.accept(ctx, conn)
if hErr != nil {
@@ -178,12 +186,21 @@ func (h *Hysteria) accept(ctx context.Context, conn quic.Connection) error {
if err != nil {
return err
}
if !bytes.Equal(clientHello.Auth, h.authKey) {
userIndex := slices.Index(h.authKey, string(clientHello.Auth))
if userIndex == -1 {
err = hysteria.WriteServerHello(controlStream, hysteria.ServerHello{
Message: "wrong password",
})
return E.Errors(E.New("wrong password: ", string(clientHello.Auth)), err)
}
user := h.authUser[userIndex]
if user == "" {
user = F.ToString(userIndex)
} else {
ctx = auth.ContextWithUser(ctx, user)
}
h.logger.InfoContext(ctx, "[", user, "] inbound connection from ", conn.RemoteAddr())
h.logger.DebugContext(ctx, "peer send speed: ", clientHello.SendBPS/1024/1024, " MBps, peer recv speed: ", clientHello.RecvBPS/1024/1024, " MBps")
if clientHello.SendBPS == 0 || clientHello.RecvBPS == 0 {
return E.New("invalid rate from client")
}

View File

@@ -1,94 +0,0 @@
package inbound
import (
"encoding/json"
"io"
"net/http"
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"
F "github.com/sagernet/sing/common/format"
"github.com/go-chi/chi/v5"
"github.com/go-chi/render"
)
func (h *ShadowsocksMulti) createHandler() http.Handler {
router := chi.NewRouter()
router.Get("/", h.handleHello)
router.Put("/users", h.handleUpdateUsers)
router.Get("/traffics", h.handleReadTraffics)
return router
}
func (h *ShadowsocksMulti) handleHello(writer http.ResponseWriter, request *http.Request) {
render.JSON(writer, request, render.M{
"server": "sing-box",
"version": C.Version,
})
}
func (h *ShadowsocksMulti) handleUpdateUsers(writer http.ResponseWriter, request *http.Request) {
var users []option.ShadowsocksUser
err := readRequest(request, &users)
if err != nil {
h.newError(E.Cause(err, "controller: update users: parse request"))
writer.WriteHeader(http.StatusBadRequest)
writer.Write([]byte(F.ToString(err)))
return
}
users = append([]option.ShadowsocksUser{{
Name: "control",
Password: h.users[0].Password,
}}, users...)
err = h.service.UpdateUsersWithPasswords(common.MapIndexed(users, func(index int, user option.ShadowsocksUser) int {
return index
}), common.Map(users, func(user option.ShadowsocksUser) string {
return user.Password
}))
if err != nil {
h.newError(E.Cause(err, "controller: update users"))
writer.WriteHeader(http.StatusBadRequest)
writer.Write([]byte(F.ToString(err)))
return
}
h.users = users
h.trafficManager.Reset()
writer.WriteHeader(http.StatusNoContent)
h.logger.Info("controller: updated ", len(users)-1, " users")
}
type ShadowsocksUserTraffic struct {
Name string `json:"name,omitempty"`
Upload uint64 `json:"upload,omitempty"`
Download uint64 `json:"download,omitempty"`
}
func (h *ShadowsocksMulti) handleReadTraffics(writer http.ResponseWriter, request *http.Request) {
h.logger.Debug("controller: traffics sent")
trafficMap := h.trafficManager.ReadTraffics()
if len(trafficMap) == 0 {
writer.WriteHeader(http.StatusNoContent)
return
}
traffics := make([]ShadowsocksUserTraffic, 0, len(trafficMap))
for user, traffic := range trafficMap {
traffics = append(traffics, ShadowsocksUserTraffic{
Name: h.users[user].Name,
Upload: traffic.Upload,
Download: traffic.Download,
})
}
render.JSON(writer, request, traffics)
}
func readRequest(request *http.Request, v any) error {
defer request.Body.Close()
content, err := io.ReadAll(request.Body)
if err != nil {
return err
}
return json.Unmarshal(content, v)
}

View File

@@ -3,12 +3,9 @@ package inbound
import (
"context"
"net"
"net/http"
"os"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/pipelistener"
"github.com/sagernet/sing-box/common/trafficcontrol"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
@@ -16,7 +13,6 @@ import (
"github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/auth"
"github.com/sagernet/sing/common/buf"
E "github.com/sagernet/sing/common/exceptions"
F "github.com/sagernet/sing/common/format"
N "github.com/sagernet/sing/common/network"
)
@@ -28,12 +24,8 @@ var (
type ShadowsocksMulti struct {
myInboundAdapter
service *shadowaead_2022.MultiService[int]
users []option.ShadowsocksUser
controlEnabled bool
controller *http.Server
controllerPipe *pipelistener.Listener
trafficManager *trafficcontrol.Manager[int]
service *shadowaead_2022.MultiService[int]
users []option.ShadowsocksUser
}
func newShadowsocksMulti(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.ShadowsocksInboundOptions) (*ShadowsocksMulti, error) {
@@ -62,20 +54,7 @@ func newShadowsocksMulti(ctx context.Context, router adapter.Router, logger log.
udpTimeout,
adapter.NewUpstreamContextHandler(inbound.newConnection, inbound.newPacketConnection, inbound),
)
users := options.Users
if options.ControlPassword != "" {
inbound.controlEnabled = true
users = append([]option.ShadowsocksUser{{
Name: "control",
Password: options.ControlPassword,
}}, users...)
inbound.controller = &http.Server{Handler: inbound.createHandler()}
inbound.trafficManager = trafficcontrol.NewManager[int]()
}
if err != nil {
return nil, err
}
err = service.UpdateUsersWithPasswords(common.MapIndexed(users, func(index int, user option.ShadowsocksUser) int {
err = service.UpdateUsersWithPasswords(common.MapIndexed(options.Users, func(index int, user option.ShadowsocksUser) int {
return index
}), common.Map(options.Users, func(user option.ShadowsocksUser) string {
return user.Password
@@ -85,30 +64,10 @@ func newShadowsocksMulti(ctx context.Context, router adapter.Router, logger log.
}
inbound.service = service
inbound.packetUpstream = service
inbound.users = users
inbound.users = options.Users
return inbound, err
}
func (h *ShadowsocksMulti) Start() error {
if h.controlEnabled {
h.controllerPipe = pipelistener.New(16)
go func() {
err := h.controller.Serve(h.controllerPipe)
if err != nil {
h.newError(E.Cause(err, "controller serve error"))
}
}()
}
return h.myInboundAdapter.Start()
}
func (h *ShadowsocksMulti) Close() error {
if h.controlEnabled {
h.controllerPipe.Close()
}
return h.myInboundAdapter.Close()
}
func (h *ShadowsocksMulti) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
return h.service.NewConnection(adapter.WithContext(log.ContextWithNewID(ctx), &metadata), conn, adapter.UpstreamMetadata(metadata))
}
@@ -126,11 +85,6 @@ func (h *ShadowsocksMulti) newConnection(ctx context.Context, conn net.Conn, met
if !loaded {
return os.ErrInvalid
}
if userIndex == 0 && h.controlEnabled {
h.logger.InfoContext(ctx, "inbound control connection")
h.controllerPipe.Serve(conn)
return nil
}
user := h.users[userIndex].Name
if user == "" {
user = F.ToString(userIndex)

View File

@@ -29,6 +29,7 @@ type ShadowTLS struct {
handshakeAddr M.Socksaddr
v2 bool
password string
fallbackAfter int
}
func NewShadowTLS(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.ShadowTLSInboundOptions) (*ShadowTLS, error) {
@@ -52,6 +53,11 @@ func NewShadowTLS(ctx context.Context, router adapter.Router, logger log.Context
case 1:
case 2:
inbound.v2 = true
if options.FallbackAfter == nil {
inbound.fallbackAfter = 2
} else {
inbound.fallbackAfter = *options.FallbackAfter
}
default:
return nil, E.New("unknown shadowtls protocol version: ", options.Version)
}
@@ -85,7 +91,7 @@ func (s *ShadowTLS) NewConnection(ctx context.Context, conn net.Conn, metadata a
hashConn := shadowtls.NewHashWriteConn(conn, s.password)
go bufio.Copy(hashConn, handshakeConn)
var request *buf.Buffer
request, err = s.copyUntilHandshakeFinishedV2(handshakeConn, conn, hashConn)
request, err = s.copyUntilHandshakeFinishedV2(handshakeConn, conn, hashConn, s.fallbackAfter)
if err == nil {
handshakeConn.Close()
return s.newConnection(ctx, bufio.NewCachedConn(shadowtls.NewConn(conn), request), metadata)
@@ -129,7 +135,7 @@ func (s *ShadowTLS) copyUntilHandshakeFinished(dst io.Writer, src io.Reader) err
}
}
func (s *ShadowTLS) copyUntilHandshakeFinishedV2(dst net.Conn, src io.Reader, hash *shadowtls.HashWriteConn) (*buf.Buffer, error) {
func (s *ShadowTLS) copyUntilHandshakeFinishedV2(dst net.Conn, src io.Reader, hash *shadowtls.HashWriteConn, fallbackAfter int) (*buf.Buffer, error) {
const applicationData = 0x17
var tlsHdr [5]byte
var applicationDataCount int
@@ -159,7 +165,7 @@ func (s *ShadowTLS) copyUntilHandshakeFinishedV2(dst net.Conn, src io.Reader, ha
if err != nil {
return nil, err
}
if applicationDataCount > 3 {
if applicationDataCount > fallbackAfter {
return nil, os.ErrPermission
}
}

View File

@@ -23,7 +23,7 @@ func init() {
return nil, C.ErrQUICNotIncluded
})
v2ray.RegisterQUICConstructor(
func(ctx context.Context, options option.V2RayQUICOptions, tlsConfig tls.Config, handler N.TCPConnectionHandler, errorHandler E.Handler) (adapter.V2RayServerTransport, error) {
func(ctx context.Context, options option.V2RayQUICOptions, tlsConfig tls.ServerConfig, handler N.TCPConnectionHandler, errorHandler E.Handler) (adapter.V2RayServerTransport, error) {
return nil, C.ErrQUICNotIncluded
},
func(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, options option.V2RayQUICOptions, tlsConfig tls.Config) (adapter.V2RayClientTransport, error) {

View File

@@ -7,8 +7,7 @@ type HysteriaInboundOptions struct {
Down string `json:"down,omitempty"`
DownMbps int `json:"down_mbps,omitempty"`
Obfs string `json:"obfs,omitempty"`
Auth []byte `json:"auth,omitempty"`
AuthString string `json:"auth_str,omitempty"`
Users []HysteriaUser `json:"users,omitempty"`
ReceiveWindowConn uint64 `json:"recv_window_conn,omitempty"`
ReceiveWindowClient uint64 `json:"recv_window_client,omitempty"`
MaxConnClient int `json:"max_conn_client,omitempty"`
@@ -16,6 +15,12 @@ type HysteriaInboundOptions struct {
TLS *InboundTLSOptions `json:"tls,omitempty"`
}
type HysteriaUser struct {
Name string `json:"name,omitempty"`
Auth []byte `json:"auth,omitempty"`
AuthString string `json:"auth_str,omitempty"`
}
type HysteriaOutboundOptions struct {
DialerOptions
ServerOptions

View File

@@ -2,9 +2,10 @@ package option
type ShadowTLSInboundOptions struct {
ListenOptions
Version int `json:"version,omitempty"`
Password string `json:"password,omitempty"`
Handshake ShadowTLSHandshakeOptions `json:"handshake"`
Version int `json:"version,omitempty"`
Password string `json:"password,omitempty"`
FallbackAfter *int `json:"fallback_after,omitempty"`
Handshake ShadowTLSHandshakeOptions `json:"handshake"`
}
type ShadowTLSHandshakeOptions struct {

View File

@@ -41,9 +41,18 @@ func NewTor(ctx context.Context, router adapter.Router, logger log.ContextLogger
startConf := newConfig()
startConf.DataDir = os.ExpandEnv(options.DataDirectory)
startConf.TempDataDirBase = os.TempDir()
startConf.ExtraArgs = options.ExtraArgs
if options.DataDirectory != "" {
dataDirAbs, _ := filepath.Abs(startConf.DataDir)
if geoIPPath := filepath.Join(dataDirAbs, "geoip"); rw.FileExists(geoIPPath) && !common.Contains(options.ExtraArgs, "--GeoIPFile") {
options.ExtraArgs = append(options.ExtraArgs, "--GeoIPFile", geoIPPath)
}
if geoIP6Path := filepath.Join(dataDirAbs, "geoip6"); rw.FileExists(geoIP6Path) && !common.Contains(options.ExtraArgs, "--GeoIPv6File") {
options.ExtraArgs = append(options.ExtraArgs, "--GeoIPv6File", geoIP6Path)
}
}
if options.ExecutablePath != "" {
startConf.ExePath = options.ExecutablePath
startConf.ExtraArgs = options.ExtraArgs
startConf.ProcessCreator = nil
startConf.UseEmbeddedControlConn = false
}

View File

@@ -22,7 +22,6 @@ import (
E "github.com/sagernet/sing/common/exceptions"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"github.com/sagernet/wireguard-go/device"
)

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env bash
set -e -o pipefail
curl -Lo go.tar.gz https://go.dev/dl/go1.19.2.linux-amd64.tar.gz
curl -Lo go.tar.gz https://go.dev/dl/go1.19.3.linux-amd64.tar.gz
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf go.tar.gz
rm go.tar.gz

View File

@@ -16,4 +16,3 @@ popd
sudo systemctl stop sing-box
sudo cp $(go env GOPATH)/bin/sing-box /usr/local/bin/
sudo systemctl start sing-box
sudo journalctl -u sing-box --output cat -f

View File

@@ -234,7 +234,7 @@ func NewRouter(ctx context.Context, logger log.ContextLogger, dnsLogger log.Cont
}
if defaultTransport == nil {
if len(transports) == 0 {
transports = append(transports, dns.NewLocalTransport(dialer.NewRouter(router)))
transports = append(transports, dns.NewLocalTransport(N.SystemDialer))
}
defaultTransport = transports[0]
}

View File

@@ -37,7 +37,11 @@ func (r *Router) matchDNS(ctx context.Context) (context.Context, dns.Transport,
r.dnsLogger.ErrorContext(ctx, "transport not found: ", detour)
}
}
return ctx, r.defaultTransport, r.defaultDomainStrategy
if domainStrategy, dsLoaded := r.transportDomainStrategy[r.defaultTransport]; dsLoaded {
return ctx, r.defaultTransport, domainStrategy
} else {
return ctx, r.defaultTransport, r.defaultDomainStrategy
}
}
func (r *Router) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, error) {

View File

@@ -15,7 +15,7 @@ require (
github.com/spyzhov/ajson v0.7.1
github.com/stretchr/testify v1.8.1
go.uber.org/goleak v1.2.0
golang.org/x/net v0.1.1-0.20221102181756-a1278a7f7ee0
golang.org/x/net v0.2.0
)
require (
@@ -39,7 +39,7 @@ require (
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/btree v1.0.1 // indirect
github.com/hashicorp/yamux v0.1.1 // indirect
github.com/klauspost/compress v1.15.9 // indirect
github.com/klauspost/compress v1.15.12 // indirect
github.com/klauspost/cpuid/v2 v2.1.1 // indirect
github.com/libdns/libdns v0.2.1 // indirect
github.com/logrusorgru/aurora v2.0.3+incompatible // indirect
@@ -56,18 +56,18 @@ require (
github.com/pires/go-proxyproto v0.6.2 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/refraction-networking/utls v1.1.5 // indirect
github.com/refraction-networking/utls v1.2.0 // indirect
github.com/sagernet/abx-go v0.0.0-20220819185957-dba1257d738e // indirect
github.com/sagernet/cloudflare-tls v0.0.0-20221031050923-d70792f4c3a0 // indirect
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 // indirect
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 // indirect
github.com/sagernet/quic-go v0.0.0-20221031051350-29d8bb1c8127 // indirect
github.com/sagernet/sing-dns v0.0.0-20221031055845-7de76401d403 // indirect
github.com/sagernet/quic-go v0.0.0-20221108053023-645bcc4f9b15 // indirect
github.com/sagernet/sing-dns v0.0.0-20221113031420-c6aaf2ea4b10 // indirect
github.com/sagernet/sing-tun v0.0.0-20221104121441-66c48a57776f // indirect
github.com/sagernet/sing-vmess v0.0.0-20220925083655-063bc85ea685 // indirect
github.com/sagernet/sing-vmess v0.0.0-20221109021549-b446d5bdddf0 // indirect
github.com/sagernet/smux v0.0.0-20220831015742-e0f1988e3195 // indirect
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e // indirect
github.com/sagernet/wireguard-go v0.0.0-20221107074148-ffff5ffac938 // indirect
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c // indirect
github.com/sirupsen/logrus v1.9.0 // indirect
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
go.etcd.io/bbolt v1.3.6 // indirect
@@ -75,15 +75,15 @@ require (
go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.23.0 // indirect
go4.org/netipx v0.0.0-20220925034521-797b0c90d8ab // indirect
golang.org/x/crypto v0.1.1-0.20221024173537-a3485e174077 // indirect
golang.org/x/crypto v0.3.0 // indirect
golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f // indirect
golang.org/x/mod v0.6.0 // indirect
golang.org/x/sys v0.1.1-0.20221102194838-fc697a31fa06 // indirect
golang.org/x/sys v0.2.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
golang.org/x/tools v0.2.0 // indirect
google.golang.org/genproto v0.0.0-20210722135532-667f2b7c528f // indirect
google.golang.org/grpc v1.50.1 // indirect
google.golang.org/grpc v1.51.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gotest.tools/v3 v3.4.0 // indirect

View File

@@ -91,8 +91,8 @@ github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY=
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
github.com/klauspost/compress v1.15.12 h1:YClS/PImqYbn+UILDnqxQCZ3RehC9N318SU3kElDUEM=
github.com/klauspost/compress v1.15.12/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.1.1 h1:t0wUqjowdm8ezddV5k0tLWVklVuvLJpoHeb4WBdydm0=
github.com/klauspost/cpuid/v2 v2.1.1/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
@@ -135,8 +135,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/refraction-networking/utls v1.1.5 h1:JtrojoNhbUQkBqEg05sP3gDgDj6hIEAAVKbI9lx4n6w=
github.com/refraction-networking/utls v1.1.5/go.mod h1:jRQxtYi7nkq1p28HF2lwOH5zQm9aC8rpK0O9lIIzGh8=
github.com/refraction-networking/utls v1.2.0 h1:U5f8wkij2NVinfLuJdFP3gCMwIHs+EzvhxmYdXgiapo=
github.com/refraction-networking/utls v1.2.0/go.mod h1:NPq+cVqzH7D1BeOkmOcb5O/8iVewAsiVt2x1/eO0hgQ=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/sagernet/abx-go v0.0.0-20220819185957-dba1257d738e h1:5CFRo8FJbCuf5s/eTBdZpmMbn8Fe2eSMLNAYfKanA34=
github.com/sagernet/abx-go v0.0.0-20220819185957-dba1257d738e/go.mod h1:qbt0dWObotCfcjAJJ9AxtFPNSDUfZF+6dCpgKEOBn/g=
@@ -146,26 +146,26 @@ github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 h1:5+m7c
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61/go.mod h1:QUQ4RRHD6hGGHdFMEtR8T2P6GS6R3D/CXKdaYHKKXms=
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/quic-go v0.0.0-20221031051350-29d8bb1c8127 h1:rraPfWlUy2cdZ61FLXRCFbL0lb7oocScbr4Ac0rIzTU=
github.com/sagernet/quic-go v0.0.0-20221031051350-29d8bb1c8127/go.mod h1:oWFbojDMm85/Jbm/fyWoo8Pux6dIssxGi3q1r+5642A=
github.com/sagernet/quic-go v0.0.0-20221108053023-645bcc4f9b15 h1:l8RQTjz5LlGEFOc49dXAr14ORbj8mTW7nX88Rbm+FiY=
github.com/sagernet/quic-go v0.0.0-20221108053023-645bcc4f9b15/go.mod h1:oWFbojDMm85/Jbm/fyWoo8Pux6dIssxGi3q1r+5642A=
github.com/sagernet/sing v0.0.0-20220812082120-05f9836bff8f/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.0.0-20221008120626-60a9910eefe4 h1:LO7xMvMGhYmjQg2vjhTzsODyzs9/WLYu5Per+/8jIeo=
github.com/sagernet/sing v0.0.0-20221008120626-60a9910eefe4/go.mod h1:zvgDYKI+vCAW9RyfyrKTgleI+DOa8lzHMPC7VZo3OL4=
github.com/sagernet/sing-dns v0.0.0-20221031055845-7de76401d403 h1:kKDO97rx+JVJ4HI1hTWOnCCI6um5clK1LfnIto2DY4M=
github.com/sagernet/sing-dns v0.0.0-20221031055845-7de76401d403/go.mod h1:cyL9DHbBZ0Xlt/8VD0i6yeiDayH0KzWGNQb8MYhhz7g=
github.com/sagernet/sing-dns v0.0.0-20221113031420-c6aaf2ea4b10 h1:K84AY2TxNX37ePYXVO6QTD/kgn9kDo4oGpTIn9PF5bo=
github.com/sagernet/sing-dns v0.0.0-20221113031420-c6aaf2ea4b10/go.mod h1:VAvOT1pyryBIthTGRryFLXAsR1VRQZ05wolMYeQrr/E=
github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6 h1:JJfDeYYhWunvtxsU/mOVNTmFQmnzGx9dY034qG6G3g4=
github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6/go.mod h1:EX3RbZvrwAkPI2nuGa78T2iQXmrkT+/VQtskjou42xM=
github.com/sagernet/sing-tun v0.0.0-20221104121441-66c48a57776f h1:CXF+nErOb9f7qiHingSgTa2/lJAgmEFtAQ47oVwdRGU=
github.com/sagernet/sing-tun v0.0.0-20221104121441-66c48a57776f/go.mod h1:1u3pjXA9HmH7kRiBJqM3C/zPxrxnCLd3svmqtub/RFU=
github.com/sagernet/sing-vmess v0.0.0-20220925083655-063bc85ea685 h1:AZzFNRR/ZwMTceUQ1b/mxx6oyKqmFymdMn/yleJmoVM=
github.com/sagernet/sing-vmess v0.0.0-20220925083655-063bc85ea685/go.mod h1:bwhAdSNET1X+j9DOXGj9NIQR39xgcWIk1rOQ9lLD+gM=
github.com/sagernet/sing-vmess v0.0.0-20221109021549-b446d5bdddf0 h1:z3kuD3hPNdEq7/wVy5lwE21f+8ZTazBtR81qswxJoCc=
github.com/sagernet/sing-vmess v0.0.0-20221109021549-b446d5bdddf0/go.mod h1:bwhAdSNET1X+j9DOXGj9NIQR39xgcWIk1rOQ9lLD+gM=
github.com/sagernet/smux v0.0.0-20220831015742-e0f1988e3195 h1:5VBIbVw9q7aKbrFdT83mjkyvQ+VaRsQ6yflTepfln38=
github.com/sagernet/smux v0.0.0-20220831015742-e0f1988e3195/go.mod h1:yedWtra8nyGJ+SyI+ziwuaGMzBatbB10P1IOOZbbSK8=
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-20221107074148-ffff5ffac938 h1:QBeUPiA35gP6XqSUXCdwfDfWjhBRV2m0+mtXNUzLpZ0=
github.com/sagernet/wireguard-go v0.0.0-20221107074148-ffff5ffac938/go.mod h1:euOmN6O5kk9dQmgSS8Df4psAl3TCjxOz0NW60EWkSaI=
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c h1:vK2wyt9aWYHHvNLWniwijBu/n4pySypiKRhN32u/JGo=
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c/go.mod h1:euOmN6O5kk9dQmgSS8Df4psAl3TCjxOz0NW60EWkSaI=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
@@ -208,9 +208,8 @@ golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaE
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.1.1-0.20221024173537-a3485e174077 h1:t5bjOfJPQfaG9NV1imLZM5E2uzaLGs5/NtyMtRNVjQ4=
golang.org/x/crypto v0.1.1-0.20221024173537-a3485e174077/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A=
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
@@ -240,11 +239,9 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220630215102-69896b714898/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.1.1-0.20221102181756-a1278a7f7ee0 h1:vZ44Ys50wUISbPd+jC8cRLSvhyfX9Ii/ZmDnn/aiJtM=
golang.org/x/net v0.1.1-0.20221102181756-a1278a7f7ee0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU=
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -275,14 +272,13 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.1-0.20221102194838-fc697a31fa06 h1:E1pm64FqQa4v8dHd/bAneyMkR4hk8LTJhoSlc5mc1cM=
golang.org/x/sys v0.1.1-0.20221102194838-fc697a31fa06/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw=
golang.org/x/term v0.2.0 h1:z85xZCsEl7bi/KwbNADeBYoOP0++7W1ipu+aGnpwzRM=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@@ -325,8 +321,8 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY=
google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U=
google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=

61
test/http_test.go Normal file
View File

@@ -0,0 +1,61 @@
package main
import (
"net/netip"
"testing"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/option"
)
func TestHTTPSelf(t *testing.T) {
startInstance(t, option.Options{
Inbounds: []option.Inbound{
{
Type: C.TypeMixed,
Tag: "mixed-in",
MixedOptions: option.HTTPMixedInboundOptions{
ListenOptions: option.ListenOptions{
Listen: option.ListenAddress(netip.IPv4Unspecified()),
ListenPort: clientPort,
},
},
},
{
Type: C.TypeMixed,
MixedOptions: option.HTTPMixedInboundOptions{
ListenOptions: option.ListenOptions{
Listen: option.ListenAddress(netip.IPv4Unspecified()),
ListenPort: serverPort,
},
},
},
},
Outbounds: []option.Outbound{
{
Type: C.TypeDirect,
},
{
Type: C.TypeHTTP,
Tag: "http-out",
HTTPOptions: option.HTTPOutboundOptions{
ServerOptions: option.ServerOptions{
Server: "127.0.0.1",
ServerPort: serverPort,
},
},
},
},
Route: &option.RouteOptions{
Rules: []option.Rule{
{
DefaultOptions: option.DefaultRule{
Inbound: []string{"mixed-in"},
Outbound: "http-out",
},
},
},
},
})
testTCP(t, clientPort, testPort)
}

View File

@@ -29,10 +29,12 @@ func TestHysteriaSelf(t *testing.T) {
Listen: option.ListenAddress(netip.IPv4Unspecified()),
ListenPort: serverPort,
},
UpMbps: 100,
DownMbps: 100,
AuthString: "password",
Obfs: "fuck me till the daylight",
UpMbps: 100,
DownMbps: 100,
Users: []option.HysteriaUser{{
AuthString: "password",
}},
Obfs: "fuck me till the daylight",
TLS: &option.InboundTLSOptions{
Enabled: true,
ServerName: "example.org",
@@ -91,10 +93,12 @@ func TestHysteriaInbound(t *testing.T) {
Listen: option.ListenAddress(netip.IPv4Unspecified()),
ListenPort: serverPort,
},
UpMbps: 100,
DownMbps: 100,
AuthString: "password",
Obfs: "fuck me till the daylight",
UpMbps: 100,
DownMbps: 100,
Users: []option.HysteriaUser{{
AuthString: "password",
}},
Obfs: "fuck me till the daylight",
TLS: &option.InboundTLSOptions{
Enabled: true,
ServerName: "example.org",

View File

@@ -15,7 +15,7 @@ import (
N "github.com/sagernet/sing/common/network"
)
func NewGRPCServer(ctx context.Context, options option.V2RayGRPCOptions, tlsConfig tls.Config, handler N.TCPConnectionHandler, errorHandler E.Handler) (adapter.V2RayServerTransport, error) {
func NewGRPCServer(ctx context.Context, options option.V2RayGRPCOptions, tlsConfig tls.ServerConfig, handler N.TCPConnectionHandler, errorHandler E.Handler) (adapter.V2RayServerTransport, error) {
if options.ForceLite {
return v2raygrpclite.NewServer(ctx, options, tlsConfig, handler, errorHandler)
}

View File

@@ -14,7 +14,7 @@ import (
N "github.com/sagernet/sing/common/network"
)
func NewGRPCServer(ctx context.Context, options option.V2RayGRPCOptions, tlsConfig tls.Config, handler N.TCPConnectionHandler, errorHandler E.Handler) (adapter.V2RayServerTransport, error) {
func NewGRPCServer(ctx context.Context, options option.V2RayGRPCOptions, tlsConfig tls.ServerConfig, handler N.TCPConnectionHandler, errorHandler E.Handler) (adapter.V2RayServerTransport, error) {
return v2raygrpclite.NewServer(ctx, options, tlsConfig, handler, errorHandler)
}

View File

@@ -22,7 +22,7 @@ func RegisterQUICConstructor(server ServerConstructor[option.V2RayQUICOptions],
quicClientConstructor = client
}
func NewQUICServer(ctx context.Context, options option.V2RayQUICOptions, tlsConfig tls.Config, handler N.TCPConnectionHandler, errorHandler E.Handler) (adapter.V2RayServerTransport, error) {
func NewQUICServer(ctx context.Context, options option.V2RayQUICOptions, tlsConfig tls.ServerConfig, handler N.TCPConnectionHandler, errorHandler E.Handler) (adapter.V2RayServerTransport, error) {
if quicServerConstructor == nil {
return nil, os.ErrInvalid
}

View File

@@ -15,11 +15,11 @@ import (
)
type (
ServerConstructor[O any] func(ctx context.Context, options O, tlsConfig tls.Config, handler N.TCPConnectionHandler, errorHandler E.Handler) (adapter.V2RayServerTransport, error)
ServerConstructor[O any] func(ctx context.Context, options O, tlsConfig tls.ServerConfig, handler N.TCPConnectionHandler, errorHandler E.Handler) (adapter.V2RayServerTransport, error)
ClientConstructor[O any] func(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, options O, tlsConfig tls.Config) (adapter.V2RayClientTransport, error)
)
func NewServerTransport(ctx context.Context, options option.V2RayTransportOptions, tlsConfig tls.Config, handler N.TCPConnectionHandler, errorHandler E.Handler) (adapter.V2RayServerTransport, error) {
func NewServerTransport(ctx context.Context, options option.V2RayTransportOptions, tlsConfig tls.ServerConfig, handler N.TCPConnectionHandler, errorHandler E.Handler) (adapter.V2RayServerTransport, error) {
if options.Type == "" {
return nil, nil
}

View File

@@ -13,10 +13,10 @@ import (
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"golang.org/x/net/http2"
"google.golang.org/grpc"
"google.golang.org/grpc/backoff"
"google.golang.org/grpc/connectivity"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/insecure"
)
@@ -35,11 +35,8 @@ type Client struct {
func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, options option.V2RayGRPCOptions, tlsConfig tls.Config) (adapter.V2RayClientTransport, error) {
var dialOptions []grpc.DialOption
if tlsConfig != nil {
stdConfig, err := tlsConfig.Config()
if err != nil {
return nil, err
}
dialOptions = append(dialOptions, grpc.WithTransportCredentials(credentials.NewTLS(stdConfig)))
tlsConfig.SetNextProtos([]string{http2.NextProtoTLS})
dialOptions = append(dialOptions, grpc.WithTransportCredentials(NewTLSTransportCredentials(tlsConfig)))
} else {
dialOptions = append(dialOptions, grpc.WithTransportCredentials(insecure.NewCredentials()))
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright 2021 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package credentials
import (
"context"
)
// requestInfoKey is a struct to be used as the key to store RequestInfo in a
// context.
type requestInfoKey struct{}
// NewRequestInfoContext creates a context with ri.
func NewRequestInfoContext(ctx context.Context, ri interface{}) context.Context {
return context.WithValue(ctx, requestInfoKey{}, ri)
}
// RequestInfoFromContext extracts the RequestInfo from ctx.
func RequestInfoFromContext(ctx context.Context) interface{} {
return ctx.Value(requestInfoKey{})
}
// clientHandshakeInfoKey is a struct used as the key to store
// ClientHandshakeInfo in a context.
type clientHandshakeInfoKey struct{}
// ClientHandshakeInfoFromContext extracts the ClientHandshakeInfo from ctx.
func ClientHandshakeInfoFromContext(ctx context.Context) interface{} {
return ctx.Value(clientHandshakeInfoKey{})
}
// NewClientHandshakeInfoContext creates a context with chi.
func NewClientHandshakeInfoContext(ctx context.Context, chi interface{}) context.Context {
return context.WithValue(ctx, clientHandshakeInfoKey{}, chi)
}

View File

@@ -0,0 +1,75 @@
/*
*
* Copyright 2020 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
// Package credentials defines APIs for parsing SPIFFE ID.
//
// All APIs in this package are experimental.
package credentials
import (
"crypto/tls"
"crypto/x509"
"net/url"
"google.golang.org/grpc/grpclog"
)
var logger = grpclog.Component("credentials")
// SPIFFEIDFromState parses the SPIFFE ID from State. If the SPIFFE ID format
// is invalid, return nil with warning.
func SPIFFEIDFromState(state tls.ConnectionState) *url.URL {
if len(state.PeerCertificates) == 0 || len(state.PeerCertificates[0].URIs) == 0 {
return nil
}
return SPIFFEIDFromCert(state.PeerCertificates[0])
}
// SPIFFEIDFromCert parses the SPIFFE ID from x509.Certificate. If the SPIFFE
// ID format is invalid, return nil with warning.
func SPIFFEIDFromCert(cert *x509.Certificate) *url.URL {
if cert == nil || cert.URIs == nil {
return nil
}
var spiffeID *url.URL
for _, uri := range cert.URIs {
if uri == nil || uri.Scheme != "spiffe" || uri.Opaque != "" || (uri.User != nil && uri.User.Username() != "") {
continue
}
// From this point, we assume the uri is intended for a SPIFFE ID.
if len(uri.String()) > 2048 {
logger.Warning("invalid SPIFFE ID: total ID length larger than 2048 bytes")
return nil
}
if len(uri.Host) == 0 || len(uri.Path) == 0 {
logger.Warning("invalid SPIFFE ID: domain or workload ID is empty")
return nil
}
if len(uri.Host) > 255 {
logger.Warning("invalid SPIFFE ID: domain length larger than 255 characters")
return nil
}
// A valid SPIFFE certificate can only have exactly one URI SAN field.
if len(cert.URIs) > 1 {
logger.Warning("invalid SPIFFE ID: multiple URI SANs")
return nil
}
spiffeID = uri
}
return spiffeID
}

View File

@@ -0,0 +1,58 @@
/*
*
* Copyright 2018 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package credentials
import (
"net"
"syscall"
)
type sysConn = syscall.Conn
// syscallConn keeps reference of rawConn to support syscall.Conn for channelz.
// SyscallConn() (the method in interface syscall.Conn) is explicitly
// implemented on this type,
//
// Interface syscall.Conn is implemented by most net.Conn implementations (e.g.
// TCPConn, UnixConn), but is not part of net.Conn interface. So wrapper conns
// that embed net.Conn don't implement syscall.Conn. (Side note: tls.Conn
// doesn't embed net.Conn, so even if syscall.Conn is part of net.Conn, it won't
// help here).
type syscallConn struct {
net.Conn
// sysConn is a type alias of syscall.Conn. It's necessary because the name
// `Conn` collides with `net.Conn`.
sysConn
}
// WrapSyscallConn tries to wrap rawConn and newConn into a net.Conn that
// implements syscall.Conn. rawConn will be used to support syscall, and newConn
// will be used for read/write.
//
// This function returns newConn if rawConn doesn't implement syscall.Conn.
func WrapSyscallConn(rawConn, newConn net.Conn) net.Conn {
sysConn, ok := rawConn.(syscall.Conn)
if !ok {
return newConn
}
return &syscallConn{
Conn: newConn,
sysConn: sysConn,
}
}

View File

@@ -0,0 +1,52 @@
/*
*
* Copyright 2020 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package credentials
import (
"crypto/tls"
)
const alpnProtoStrH2 = "h2"
// AppendH2ToNextProtos appends h2 to next protos.
func AppendH2ToNextProtos(ps []string) []string {
for _, p := range ps {
if p == alpnProtoStrH2 {
return ps
}
}
ret := make([]string, 0, len(ps)+1)
ret = append(ret, ps...)
return append(ret, alpnProtoStrH2)
}
// CloneTLSConfig returns a shallow clone of the exported
// fields of cfg, ignoring the unexported sync.Once, which
// contains a mutex and must not be copied.
//
// If cfg is nil, a new zero tls.Config is returned.
//
// TODO: inline this function if possible.
func CloneTLSConfig(cfg *tls.Config) *tls.Config {
if cfg == nil {
return &tls.Config{}
}
return cfg.Clone()
}

View File

@@ -13,7 +13,6 @@ import (
N "github.com/sagernet/sing/common/network"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
gM "google.golang.org/grpc/metadata"
"google.golang.org/grpc/peer"
)
@@ -26,15 +25,11 @@ type Server struct {
server *grpc.Server
}
func NewServer(ctx context.Context, options option.V2RayGRPCOptions, tlsConfig tls.Config, handler N.TCPConnectionHandler) (*Server, error) {
func NewServer(ctx context.Context, options option.V2RayGRPCOptions, tlsConfig tls.ServerConfig, handler N.TCPConnectionHandler) (*Server, error) {
var serverOptions []grpc.ServerOption
if tlsConfig != nil {
stdConfig, err := tlsConfig.Config()
if err != nil {
return nil, err
}
stdConfig.NextProtos = []string{"h2"}
serverOptions = append(serverOptions, grpc.Creds(credentials.NewTLS(stdConfig)))
tlsConfig.SetNextProtos([]string{"h2"})
serverOptions = append(serverOptions, grpc.Creds(NewTLSTransportCredentials(tlsConfig)))
}
server := &Server{ctx, handler, grpc.NewServer(serverOptions...)}
RegisterGunServiceCustomNameServer(server.server, server, options.ServiceName)

View File

@@ -0,0 +1,86 @@
package v2raygrpc
import (
"context"
"net"
"os"
"github.com/sagernet/sing-box/common/tls"
internal_credentials "github.com/sagernet/sing-box/transport/v2raygrpc/credentials"
"google.golang.org/grpc/credentials"
)
type TLSTransportCredentials struct {
config tls.Config
}
func NewTLSTransportCredentials(config tls.Config) credentials.TransportCredentials {
return &TLSTransportCredentials{config}
}
func (c *TLSTransportCredentials) Info() credentials.ProtocolInfo {
return credentials.ProtocolInfo{
SecurityProtocol: "tls",
SecurityVersion: "1.2",
ServerName: c.config.ServerName(),
}
}
func (c *TLSTransportCredentials) ClientHandshake(ctx context.Context, authority string, rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) {
cfg := c.config.Clone()
if cfg.ServerName() == "" {
serverName, _, err := net.SplitHostPort(authority)
if err != nil {
serverName = authority
}
cfg.SetServerName(serverName)
}
conn, err := tls.ClientHandshake(ctx, rawConn, cfg)
if err != nil {
return nil, nil, err
}
tlsInfo := credentials.TLSInfo{
State: conn.ConnectionState(),
CommonAuthInfo: credentials.CommonAuthInfo{
SecurityLevel: credentials.PrivacyAndIntegrity,
},
}
id := internal_credentials.SPIFFEIDFromState(conn.ConnectionState())
if id != nil {
tlsInfo.SPIFFEID = id
}
return internal_credentials.WrapSyscallConn(rawConn, conn), tlsInfo, nil
}
func (c *TLSTransportCredentials) ServerHandshake(rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) {
serverConfig, isServer := c.config.(tls.ServerConfig)
if !isServer {
return nil, nil, os.ErrInvalid
}
conn, err := tls.ServerHandshake(context.Background(), rawConn, serverConfig)
if err != nil {
rawConn.Close()
return nil, nil, err
}
tlsInfo := credentials.TLSInfo{
State: conn.ConnectionState(),
CommonAuthInfo: credentials.CommonAuthInfo{
SecurityLevel: credentials.PrivacyAndIntegrity,
},
}
id := internal_credentials.SPIFFEIDFromState(conn.ConnectionState())
if id != nil {
tlsInfo.SPIFFEID = id
}
return internal_credentials.WrapSyscallConn(rawConn, conn), tlsInfo, nil
}
func (c *TLSTransportCredentials) Clone() credentials.TransportCredentials {
return NewTLSTransportCredentials(c.config)
}
func (c *TLSTransportCredentials) OverrideServerName(serverNameOverride string) error {
c.config.SetServerName(serverNameOverride)
return nil
}

View File

@@ -153,13 +153,31 @@ func (c *GunConn) RemoteAddr() net.Addr {
}
func (c *GunConn) SetDeadline(t time.Time) error {
return os.ErrInvalid
responseWriter, loaded := c.writer.(interface {
SetWriteDeadline(time.Time) error
})
if !loaded {
return os.ErrInvalid
}
return responseWriter.SetWriteDeadline(t)
}
func (c *GunConn) SetReadDeadline(t time.Time) error {
return os.ErrInvalid
responseWriter, loaded := c.writer.(interface {
SetReadDeadline(time.Time) error
})
if !loaded {
return os.ErrInvalid
}
return responseWriter.SetReadDeadline(t)
}
func (c *GunConn) SetWriteDeadline(t time.Time) error {
return os.ErrInvalid
responseWriter, loaded := c.writer.(interface {
SetWriteDeadline(time.Time) error
})
if !loaded {
return os.ErrInvalid
}
return responseWriter.SetWriteDeadline(t)
}

View File

@@ -19,6 +19,7 @@ import (
sHttp "github.com/sagernet/sing/protocol/http"
"golang.org/x/net/http2"
"golang.org/x/net/http2/h2c"
)
var _ adapter.V2RayServerTransport = (*Server)(nil)
@@ -27,6 +28,8 @@ type Server struct {
handler N.TCPConnectionHandler
errorHandler E.Handler
httpServer *http.Server
h2Server *http2.Server
h2cHandler http.Handler
path string
}
@@ -34,15 +37,17 @@ func (s *Server) Network() []string {
return []string{N.NetworkTCP}
}
func NewServer(ctx context.Context, options option.V2RayGRPCOptions, tlsConfig tls.Config, handler N.TCPConnectionHandler, errorHandler E.Handler) (*Server, error) {
func NewServer(ctx context.Context, options option.V2RayGRPCOptions, tlsConfig tls.ServerConfig, handler N.TCPConnectionHandler, errorHandler E.Handler) (*Server, error) {
server := &Server{
handler: handler,
errorHandler: errorHandler,
path: fmt.Sprintf("/%s/Tun", url.QueryEscape(options.ServiceName)),
h2Server: new(http2.Server),
}
server.httpServer = &http.Server{
Handler: server,
}
server.h2cHandler = h2c.NewHandler(server, server.h2Server)
if tlsConfig != nil {
stdConfig, err := tlsConfig.Config()
if err != nil {
@@ -57,7 +62,12 @@ func NewServer(ctx context.Context, options option.V2RayGRPCOptions, tlsConfig t
}
func (s *Server) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
if request.Method == "PRI" && len(request.Header) == 0 && request.URL.Path == "*" && request.Proto == "HTTP/2.0" {
s.h2cHandler.ServeHTTP(writer, request)
return
}
if request.URL.Path != s.path {
request.Write(os.Stdout)
writer.WriteHeader(http.StatusNotFound)
s.badRequest(request, E.New("bad path: ", request.URL.Path))
return
@@ -86,13 +96,13 @@ func (s *Server) badRequest(request *http.Request, err error) {
}
func (s *Server) Serve(listener net.Listener) error {
err := http2.ConfigureServer(s.httpServer, s.h2Server)
if err != nil {
return err
}
if s.httpServer.TLSConfig == nil {
return s.httpServer.Serve(listener)
} else {
err := http2.ConfigureServer(s.httpServer, &http2.Server{})
if err != nil {
return err
}
return s.httpServer.ServeTLS(listener, "", "")
}
}

View File

@@ -67,15 +67,33 @@ func (c *HTTPConn) RemoteAddr() net.Addr {
}
func (c *HTTPConn) SetDeadline(t time.Time) error {
return os.ErrInvalid
responseWriter, loaded := c.writer.(interface {
SetWriteDeadline(time.Time) error
})
if !loaded {
return os.ErrInvalid
}
return responseWriter.SetWriteDeadline(t)
}
func (c *HTTPConn) SetReadDeadline(t time.Time) error {
return os.ErrInvalid
responseWriter, loaded := c.writer.(interface {
SetReadDeadline(time.Time) error
})
if !loaded {
return os.ErrInvalid
}
return responseWriter.SetReadDeadline(t)
}
func (c *HTTPConn) SetWriteDeadline(t time.Time) error {
return os.ErrInvalid
responseWriter, loaded := c.writer.(interface {
SetWriteDeadline(time.Time) error
})
if !loaded {
return os.ErrInvalid
}
return responseWriter.SetWriteDeadline(t)
}
type ServerHTTPConn struct {

View File

@@ -18,6 +18,7 @@ import (
sHttp "github.com/sagernet/sing/protocol/http"
"golang.org/x/net/http2"
"golang.org/x/net/http2/h2c"
)
var _ adapter.V2RayServerTransport = (*Server)(nil)
@@ -27,6 +28,8 @@ type Server struct {
handler N.TCPConnectionHandler
errorHandler E.Handler
httpServer *http.Server
h2Server *http2.Server
h2cHandler http.Handler
host []string
path string
method string
@@ -37,11 +40,12 @@ func (s *Server) Network() []string {
return []string{N.NetworkTCP}
}
func NewServer(ctx context.Context, options option.V2RayHTTPOptions, tlsConfig tls.Config, handler N.TCPConnectionHandler, errorHandler E.Handler) (*Server, error) {
func NewServer(ctx context.Context, options option.V2RayHTTPOptions, tlsConfig tls.ServerConfig, handler N.TCPConnectionHandler, errorHandler E.Handler) (*Server, error) {
server := &Server{
ctx: ctx,
handler: handler,
errorHandler: errorHandler,
h2Server: new(http2.Server),
host: options.Host,
path: options.Path,
method: options.Method,
@@ -61,6 +65,7 @@ func NewServer(ctx context.Context, options option.V2RayHTTPOptions, tlsConfig t
ReadHeaderTimeout: C.TCPTimeout,
MaxHeaderBytes: http.DefaultMaxHeaderBytes,
}
server.h2cHandler = h2c.NewHandler(server, server.h2Server)
if tlsConfig != nil {
stdConfig, err := tlsConfig.Config()
if err != nil {
@@ -72,6 +77,10 @@ func NewServer(ctx context.Context, options option.V2RayHTTPOptions, tlsConfig t
}
func (s *Server) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
if request.Method == "PRI" && len(request.Header) == 0 && request.URL.Path == "*" && request.Proto == "HTTP/2.0" {
s.h2cHandler.ServeHTTP(writer, request)
return
}
host := request.Host
if len(s.host) > 0 && !common.Contains(s.host, host) {
writer.WriteHeader(http.StatusBadRequest)
@@ -124,13 +133,13 @@ func (s *Server) badRequest(request *http.Request, err error) {
}
func (s *Server) Serve(listener net.Listener) error {
err := http2.ConfigureServer(s.httpServer, s.h2Server)
if err != nil {
return err
}
if s.httpServer.TLSConfig == nil {
return s.httpServer.Serve(listener)
} else {
err := http2.ConfigureServer(s.httpServer, &http2.Server{})
if err != nil {
return err
}
return s.httpServer.ServeTLS(listener, "", "")
}
}

View File

@@ -29,7 +29,7 @@ type Server struct {
quicListener quic.Listener
}
func NewServer(ctx context.Context, options option.V2RayQUICOptions, tlsConfig tls.Config, handler N.TCPConnectionHandler, errorHandler E.Handler) (adapter.V2RayServerTransport, error) {
func NewServer(ctx context.Context, options option.V2RayQUICOptions, tlsConfig tls.ServerConfig, handler N.TCPConnectionHandler, errorHandler E.Handler) (adapter.V2RayServerTransport, error) {
quicConfig := &quic.Config{
DisablePathMTUDiscovery: !C.IsLinux && !C.IsWindows,
}

View File

@@ -34,6 +34,9 @@ func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, opt
HandshakeTimeout: time.Second * 8,
}
if tlsConfig != nil {
if len(tlsConfig.NextProtos()) == 0 {
tlsConfig.SetNextProtos([]string{"http/1.1"})
}
wsDialer.NetDialTLSContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
conn, err := dialer.DialContext(ctx, network, M.ParseSocksaddr(addr))
if err != nil {

View File

@@ -34,7 +34,7 @@ type Server struct {
earlyDataHeaderName string
}
func NewServer(ctx context.Context, options option.V2RayWebsocketOptions, tlsConfig tls.Config, handler N.TCPConnectionHandler, errorHandler E.Handler) (*Server, error) {
func NewServer(ctx context.Context, options option.V2RayWebsocketOptions, tlsConfig tls.ServerConfig, handler N.TCPConnectionHandler, errorHandler E.Handler) (*Server, error) {
server := &Server{
ctx: ctx,
handler: handler,

View File

@@ -8,7 +8,6 @@ import (
"github.com/sagernet/sing/common"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"github.com/sagernet/wireguard-go/conn"
)

View File

@@ -2,7 +2,6 @@ package wireguard
import (
N "github.com/sagernet/sing/common/network"
"github.com/sagernet/wireguard-go/tun"
)

View File

@@ -11,8 +11,8 @@ import (
E "github.com/sagernet/sing/common/exceptions"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"github.com/sagernet/wireguard-go/tun"
"gvisor.dev/gvisor/pkg/bufferv2"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/adapters/gonet"

View File

@@ -12,7 +12,6 @@ import (
"github.com/sagernet/sing-tun"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
wgTun "github.com/sagernet/wireguard-go/tun"
)

View File

@@ -4,7 +4,6 @@ import (
"net/netip"
M "github.com/sagernet/sing/common/metadata"
"github.com/sagernet/wireguard-go/conn"
)

View File

@@ -7,7 +7,6 @@ import (
E "github.com/sagernet/sing/common/exceptions"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"github.com/sagernet/wireguard-go/conn"
)