Compare commits

..

9 Commits

Author SHA1 Message Date
世界
bc4545f2ef documentation: Bump version 2023-10-11 13:27:31 +08:00
世界
ffb9088526 Fix netip.Prefix usage 2023-10-11 12:47:24 +08:00
世界
6c15743931 Add brutal debug option for Hysteria2 2023-10-11 12:45:09 +08:00
世界
6aeb31a1e6 Update BBR and Hysteria congestion control 2023-10-11 12:45:09 +08:00
septs
7b6f9a3971 Improve HTTP headers option 2023-10-11 12:45:09 +08:00
septs
e5cc56cce4 Improve naive auth logical 2023-10-11 12:45:08 +08:00
世界
fde00ef21b Update gVisor to 20230814.0 2023-10-11 12:20:42 +08:00
世界
37360442a1 Improve linux bind interface 2023-10-11 12:20:39 +08:00
世界
b4505a9fd4 Remove deprecated features 2023-10-11 12:20:27 +08:00
66 changed files with 297 additions and 2785 deletions

View File

@@ -36,35 +36,6 @@ builds:
- darwin_amd64_v3
- darwin_arm64
mod_timestamp: '{{ .CommitTimestamp }}'
- id: legacy
main: ./cmd/sing-box
flags:
- -v
- -trimpath
asmflags:
- all=-trimpath={{.Env.GOPATH}}
gcflags:
- all=-trimpath={{.Env.GOPATH}}
ldflags:
- -X github.com/sagernet/sing-box/constant.Version={{ .Version }} -s -w -buildid=
tags:
- with_gvisor
- with_quic
- with_dhcp
- with_wireguard
- with_ech
- with_utls
- with_reality_server
- with_clash_api
env:
- CGO_ENABLED=0
- GOROOT=/nix/store/5h8gjl89zx8qxgc572wa3k81zplv8v4z-go-1.20.10/share/go
gobinary: /nix/store/5h8gjl89zx8qxgc572wa3k81zplv8v4z-go-1.20.10/bin/go
targets:
- windows_amd64_v1
- windows_386
- darwin_amd64_v1
mod_timestamp: '{{ .CommitTimestamp }}'
- id: android
main: ./cmd/sing-box
flags:
@@ -119,9 +90,6 @@ snapshot:
name_template: "{{ .Version }}.{{ .ShortCommit }}"
archives:
- id: archive
builds:
- main
- android
format: tar.gz
format_overrides:
- goos: windows
@@ -130,17 +98,6 @@ archives:
files:
- LICENSE
name_template: '{{ .ProjectName }}-{{ .Version }}-{{ .Os }}-{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}{{ with .Mips }}_{{ . }}{{ end }}{{ if not (eq .Amd64 "v1") }}{{ .Amd64 }}{{ end }}'
- id: archive-legacy
builds:
- legacy
format: tar.gz
format_overrides:
- goos: windows
format: zip
wrap_in_directory: true
files:
- LICENSE
name_template: '{{ .ProjectName }}-{{ .Version }}-{{ .Os }}-{{ .Arch }}-legacy'
nfpms:
- id: package
package_name: sing-box

View File

@@ -63,7 +63,7 @@ release:
mkdir dist/release
mv dist/*.tar.gz dist/*.zip dist/*.deb dist/*.rpm dist/release
ghr --replace --draft --prerelease -p 3 "v${VERSION}" dist/release
rm -r dist/release
rm -r dist
release_install:
go install -v github.com/goreleaser/goreleaser@latest
@@ -93,7 +93,7 @@ build_ios:
upload_ios_app_store:
cd ../sing-box-for-apple && \
xcodebuild -exportArchive -archivePath build/SFI.xcarchive -exportOptionsPlist SFI/Upload.plist -allowProvisioningUpdates
xcodebuild -exportArchive -archivePath build/SFI.xcarchive -exportOptionsPlist SFI/Upload.plist
release_ios: build_ios upload_ios_app_store
@@ -104,7 +104,7 @@ build_macos:
upload_macos_app_store:
cd ../sing-box-for-apple && \
xcodebuild -exportArchive -archivePath build/SFM.xcarchive -exportOptionsPlist SFI/Upload.plist -allowProvisioningUpdates
xcodebuild -exportArchive -archivePath build/SFM.xcarchive -exportOptionsPlist SFI/Upload.plist
release_macos: build_macos upload_macos_app_store
@@ -115,7 +115,7 @@ build_macos_independent:
notarize_macos_independent:
cd ../sing-box-for-apple && \
xcodebuild -exportArchive -archivePath "build/SFM.System.xcarchive" -exportOptionsPlist SFM.System/Upload.plist -allowProvisioningUpdates
xcodebuild -exportArchive -archivePath "build/SFM.System.xcarchive" -exportOptionsPlist SFM.System/Upload.plist
wait_notarize_macos_independent:
sleep 60
@@ -141,7 +141,7 @@ build_tvos:
upload_tvos_app_store:
cd ../sing-box-for-apple && \
xcodebuild -exportArchive -archivePath "build/SFT.xcarchive" -exportOptionsPlist SFI/Upload.plist -allowProvisioningUpdates
xcodebuild -exportArchive -archivePath "build/SFT.xcarchive" -exportOptionsPlist SFI/Upload.plist
release_tvos: build_tvos upload_tvos_app_store

View File

@@ -75,11 +75,3 @@ func AppendContext(ctx context.Context) (context.Context, *InboundContext) {
metadata = new(InboundContext)
return WithContext(ctx, metadata), metadata
}
func ExtendContext(ctx context.Context) (context.Context, *InboundContext) {
var newMetadata InboundContext
if metadata := ContextFrom(ctx); metadata != nil {
newMetadata = *metadata
}
return WithContext(ctx, &newMetadata), &newMetadata
}

View File

@@ -69,7 +69,7 @@ func (s *Box) startOutbounds() error {
}
problemOutbound := outbounds[problemOutboundTag]
if problemOutbound == nil {
return E.New("dependency[", problemOutboundTag, "] not found for outbound[", outboundTags[oCurrent], "]")
return E.New("dependency[", problemOutbound, "] not found for outbound[", outboundTags[oCurrent], "]")
}
return lintOutbound(append(oTree, problemOutboundTag), problemOutbound)
}

View File

@@ -36,7 +36,7 @@ func (d *ResolveDialer) DialContext(ctx context.Context, network string, destina
if !destination.IsFqdn() {
return d.dialer.DialContext(ctx, network, destination)
}
ctx, metadata := adapter.ExtendContext(ctx)
ctx, metadata := adapter.AppendContext(ctx)
ctx = log.ContextWithOverrideLevel(ctx, log.LevelDebug)
metadata.Destination = destination
metadata.Domain = ""
@@ -61,7 +61,7 @@ func (d *ResolveDialer) ListenPacket(ctx context.Context, destination M.Socksadd
if !destination.IsFqdn() {
return d.dialer.ListenPacket(ctx, destination)
}
ctx, metadata := adapter.ExtendContext(ctx)
ctx, metadata := adapter.AppendContext(ctx)
ctx = log.ContextWithOverrideLevel(ctx, log.LevelDebug)
metadata.Destination = destination
metadata.Domain = ""

View File

@@ -1,50 +0,0 @@
package proxyproto
import (
"context"
"net"
"net/netip"
"github.com/sagernet/sing-box/adapter"
E "github.com/sagernet/sing/common/exceptions"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"github.com/pires/go-proxyproto"
)
var _ N.Dialer = (*Dialer)(nil)
type Dialer struct {
N.Dialer
}
func (d *Dialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
switch N.NetworkName(network) {
case N.NetworkTCP:
conn, err := d.Dialer.DialContext(ctx, network, destination)
if err != nil {
return nil, err
}
var source M.Socksaddr
metadata := adapter.ContextFrom(ctx)
if metadata != nil {
source = metadata.Source
}
if !source.IsValid() {
source = M.SocksaddrFromNet(conn.LocalAddr())
}
if destination.Addr.Is6() {
source = M.SocksaddrFrom(netip.AddrFrom16(source.Addr.As16()), source.Port)
}
h := proxyproto.HeaderProxyFromAddrs(1, source.TCPAddr(), destination.TCPAddr())
_, err = h.WriteTo(conn)
if err != nil {
conn.Close()
return nil, E.Cause(err, "write proxy protocol header")
}
return conn, nil
default:
return d.Dialer.DialContext(ctx, network, destination)
}
}

View File

@@ -1,62 +0,0 @@
package proxyproto
import (
std_bufio "bufio"
"net"
"github.com/sagernet/sing/common/buf"
"github.com/sagernet/sing/common/bufio"
M "github.com/sagernet/sing/common/metadata"
"github.com/pires/go-proxyproto"
)
type Listener struct {
net.Listener
AcceptNoHeader bool
}
func (l *Listener) Accept() (net.Conn, error) {
conn, err := l.Listener.Accept()
if err != nil {
return nil, err
}
bufReader := std_bufio.NewReader(conn)
header, err := proxyproto.Read(bufReader)
if err != nil && !(l.AcceptNoHeader && err == proxyproto.ErrNoProxyProtocol) {
return nil, &Error{err}
}
if bufReader.Buffered() > 0 {
cache := buf.NewSize(bufReader.Buffered())
_, err = cache.ReadFullFrom(bufReader, cache.FreeLen())
if err != nil {
return nil, &Error{err}
}
conn = bufio.NewCachedConn(conn, cache)
}
if header != nil {
return &bufio.AddrConn{Conn: conn, Metadata: M.Metadata{
Source: M.SocksaddrFromNet(header.SourceAddr).Unwrap(),
Destination: M.SocksaddrFromNet(header.DestinationAddr).Unwrap(),
}}, nil
}
return conn, nil
}
var _ net.Error = (*Error)(nil)
type Error struct {
error
}
func (e *Error) Unwrap() error {
return e.error
}
func (e *Error) Timeout() bool {
return false
}
func (e *Error) Temporary() bool {
return true
}

View File

@@ -1,25 +1,21 @@
#### 1.5.5
#### 1.6.0-beta.1
* Fix IPv6 `auto_route` for Linux **1**
* Add legacy builds for old Windows and macOS systems **2**
* Fixes and improvements
#### 1.6.0-alpha.5
* Fix compatibility with Android 14
* Update BBR congestion control for TUIC and Hysteria2 **1**
* Fixes and improvements
**1**:
When `auto_route` is enabled and `strict_route` is disabled, the device can now be reached from external IPv6 addresses.
None of the existing Golang BBR congestion control implementations have been reviewed or unit tested.
This update is intended to fix a memory leak flaw in the new implementation introduced in 1.6.0-alpha.1 and may introduce new issues.
**2**:
#### 1.6.0-alpha.4
Built using Go 1.20, the last version that will run on Windows 7, 8, Server 2008, Server 2012 and macOS 10.13 High Sierra, 10.14 Mojave.
#### 1.5.4
* Fix Clash cache crash on arm32 devices
* Fixes and improvements
#### 1.5.3
* Fix compatibility with Android 14
* Add `brutal_debug` option for Hysteria2
* Fixes and improvements
#### 1.5.2
@@ -27,10 +23,31 @@ Built using Go 1.20, the last version that will run on Windows 7, 8, Server 2008
* Our [Apple tvOS client](/installation/clients/sft) is now available in the App Store 🍎
* Fixes and improvements
#### 1.6.0-alpha.3
* Fixes and improvements
#### 1.6.0-alpha.2
* Fixes and improvements
#### 1.5.1
* Fixes and improvements
#### 1.6.0-alpha.1
* Update BBR congestion control for TUIC and Hysteria2 **1**
* Update quic-go to v0.39.0
* Update gVisor to 20230814.0
* Remove [Deprecated Features](/deprecated) by agreement
* Fixes and improvements
**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.
#### 1.5.0
* Fixes and improvements

View File

@@ -20,8 +20,9 @@
}
],
"ignore_client_bandwidth": false,
"tls": {},
"masquerade": "",
"tls": {}
"brutal_debug": false
}
```
@@ -67,6 +68,12 @@ Commands the client to use the BBR flow control algorithm instead of Hysteria CC
Conflict with `up_mbps` and `down_mbps`.
#### tls
==Required==
TLS configuration, see [TLS](/configuration/shared/tls/#inbound).
#### masquerade
HTTP3 server behavior when authentication fails.
@@ -78,8 +85,6 @@ HTTP3 server behavior when authentication fails.
A 404 page will be returned if empty.
#### tls
#### brutal_debug
==Required==
TLS configuration, see [TLS](/configuration/shared/tls/#inbound).
Enable debug information logging for Hysteria Brutal CC.

View File

@@ -20,8 +20,9 @@
}
],
"ignore_client_bandwidth": false,
"tls": {},
"masquerade": "",
"tls": {}
"brutal_debug": false
}
```
@@ -65,6 +66,12 @@ Hysteria 用户
`up_mbps``down_mbps` 冲突。
#### tls
==必填==
TLS 配置, 参阅 [TLS](/zh/configuration/shared/tls/#inbound)。
#### masquerade
HTTP3 服务器认证失败时的行为。
@@ -76,8 +83,6 @@ HTTP3 服务器认证失败时的行为。
如果为空,则返回 404 页。
#### tls
#### brutal_debug
==必填==
TLS 配置, 参阅 [TLS](/zh/configuration/shared/tls/#inbound)。
启用 Hysteria Brutal CC 的调试信息日志记录。

View File

@@ -16,6 +16,7 @@
"password": "goofy_ahh_password",
"network": "tcp",
"tls": {},
"brutal_debug": false,
... // Dial Fields
}
@@ -73,6 +74,10 @@ Both is enabled by default.
TLS configuration, see [TLS](/configuration/shared/tls/#outbound).
#### brutal_debug
Enable debug information logging for Hysteria Brutal CC.
### Dial Fields
See [Dial Fields](/configuration/shared/dial) for details.

View File

@@ -16,6 +16,7 @@
"password": "goofy_ahh_password",
"network": "tcp",
"tls": {},
"brutal_debug": false,
... // 拨号字段
}
@@ -73,6 +74,9 @@ QUIC 流量混淆器密码.
TLS 配置, 参阅 [TLS](/zh/configuration/shared/tls/#outbound)。
#### brutal_debug
启用 Hysteria Brutal CC 的调试信息日志记录。
### 拨号字段

View File

@@ -1,7 +1,6 @@
package cachefile
import (
"errors"
"net/netip"
"os"
"strings"
@@ -12,7 +11,6 @@ import (
bboltErrors "github.com/sagernet/bbolt/errors"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing/common"
E "github.com/sagernet/sing/common/exceptions"
)
var (
@@ -44,25 +42,13 @@ type CacheFile struct {
func Open(path string, cacheID string) (*CacheFile, error) {
const fileMode = 0o666
options := bbolt.Options{Timeout: time.Second}
var (
db *bbolt.DB
err error
)
for i := 0; i < 10; i++ {
db, err = bbolt.Open(path, fileMode, &options)
if err == nil {
db, err := bbolt.Open(path, fileMode, &options)
switch err {
case bboltErrors.ErrInvalid, bboltErrors.ErrChecksum, bboltErrors.ErrVersionMismatch:
if err = os.Remove(path); err != nil {
break
}
if errors.Is(err, bboltErrors.ErrTimeout) {
continue
}
if E.IsMulti(err, bboltErrors.ErrInvalid, bboltErrors.ErrChecksum, bboltErrors.ErrVersionMismatch) {
rmErr := os.Remove(path)
if rmErr != nil {
return nil, err
}
}
time.Sleep(100 * time.Millisecond)
db, err = bbolt.Open(path, 0o666, &options)
}
if err != nil {
return nil, err

View File

@@ -65,6 +65,17 @@ func (m *platformDefaultInterfaceMonitor) DefaultInterfaceIndex(destination neti
return m.defaultInterfaceIndex
}
func (m *platformDefaultInterfaceMonitor) DefaultInterface(destination netip.Addr) (string, int) {
for _, address := range m.networkAddresses {
for _, prefix := range address.addresses {
if prefix.Contains(destination) {
return address.interfaceName, address.interfaceIndex
}
}
}
return m.defaultInterfaceName, m.defaultInterfaceIndex
}
func (m *platformDefaultInterfaceMonitor) OverrideAndroidVPN() bool {
return false
}

33
go.mod
View File

@@ -4,16 +4,15 @@ go 1.20
require (
berty.tech/go-libtor v1.0.385
github.com/Dreamacro/clash v1.17.0
github.com/caddyserver/certmagic v0.19.2
github.com/cloudflare/circl v1.3.5
github.com/cloudflare/circl v1.3.3
github.com/cretz/bine v0.2.0
github.com/fsnotify/fsnotify v1.7.0
github.com/fsnotify/fsnotify v1.6.0
github.com/go-chi/chi/v5 v5.0.10
github.com/go-chi/cors v1.2.1
github.com/go-chi/render v1.0.3
github.com/gofrs/uuid/v5 v5.0.0
github.com/insomniacslk/dhcp v0.0.0-20231016090811-6a2c8fbdcc1c
github.com/insomniacslk/dhcp v0.0.0-20230908212754-65c27093e38a
github.com/libdns/alidns v1.0.3
github.com/libdns/cloudflare v0.1.0
github.com/logrusorgru/aurora v2.0.3+incompatible
@@ -21,21 +20,20 @@ require (
github.com/miekg/dns v1.1.56
github.com/ooni/go-libtor v1.1.8
github.com/oschwald/maxminddb-golang v1.12.0
github.com/pires/go-proxyproto v0.7.0
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a
github.com/sagernet/bbolt v0.0.0-20231008142710-b2d6e2f20458
github.com/sagernet/cloudflare-tls v0.0.0-20230829051644-4a68352d0c4a
github.com/sagernet/gomobile v0.0.0-20230915142329-c6740b6d2950
github.com/sagernet/gvisor v0.0.0-20230627031050-1ab0276e0dd2
github.com/sagernet/quic-go v0.0.0-20230919101909-0cc6c5dcecee
github.com/sagernet/gvisor v0.0.0-20230930141345-5fef6f2e17ab
github.com/sagernet/quic-go v0.0.0-20231008035953-32727fef9460
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
github.com/sagernet/sing v0.2.15
github.com/sagernet/sing v0.2.14-0.20231011041941-e4d9384bcd84
github.com/sagernet/sing-dns v0.1.10
github.com/sagernet/sing-mux v0.1.3
github.com/sagernet/sing-quic v0.1.2
github.com/sagernet/sing-quic v0.1.3-0.20231011042217-13b8d0b8f74b
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.16
github.com/sagernet/sing-tun v0.1.16-0.20231006112722-19cc8b9e81aa
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
@@ -47,11 +45,11 @@ require (
go.uber.org/zap v1.26.0
go4.org/netipx v0.0.0-20230824141953-6213f710f925
golang.org/x/crypto v0.14.0
golang.org/x/exp v0.0.0-20231006140011-7918f672742d
golang.org/x/net v0.17.0
golang.org/x/exp v0.0.0-20231005195138-3e424a577f31
golang.org/x/net v0.16.0
golang.org/x/sys v0.13.0
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
google.golang.org/grpc v1.59.0
google.golang.org/grpc v1.58.2
google.golang.org/protobuf v1.31.0
howett.net/plist v1.0.0
)
@@ -59,7 +57,6 @@ require (
//replace github.com/sagernet/sing => ../sing
require (
github.com/Dreamacro/protobytes v0.0.0-20230617041236-6500a9f4f158 // indirect
github.com/ajg/form v1.5.1 // indirect
github.com/andybalholm/brotli v1.0.5 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
@@ -88,11 +85,11 @@ require (
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
github.com/zeebo/blake3 v0.2.3 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/mod v0.13.0 // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.14.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
golang.org/x/tools v0.13.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
lukechampine.com/blake3 v1.2.1 // indirect

69
go.sum
View File

@@ -1,9 +1,5 @@
berty.tech/go-libtor v1.0.385 h1:RWK94C3hZj6Z2GdvePpHJLnWYobFr3bY/OdUJ5aoEXw=
berty.tech/go-libtor v1.0.385/go.mod h1:9swOOQVb+kmvuAlsgWUK/4c52pm69AdbJsxLzk+fJEw=
github.com/Dreamacro/clash v1.17.0 h1:LWtp6KcnrCiujY58ufI8pylI+hbCBgSCsLI90EWhpi4=
github.com/Dreamacro/clash v1.17.0/go.mod h1:PtcAft7sdsK325BD6uwm8wvhOkMV3TCeED6dfZ/lnfE=
github.com/Dreamacro/protobytes v0.0.0-20230617041236-6500a9f4f158 h1:JFnwKplz9hj8ubqYjm8HkgZS1Rvz9yW+u/XCNNTxr0k=
github.com/Dreamacro/protobytes v0.0.0-20230617041236-6500a9f4f158/go.mod h1:QvmEZ/h6KXszPOr2wUFl7Zn3hfFNYdfbXwPVDTyZs6k=
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
@@ -13,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.5 h1:g+wWynZqVALYAlpSQFAa7TscDnUK8mKYtrxMpw6AUKo=
github.com/cloudflare/circl v1.3.5/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs=
github.com/cloudflare/circl v1.3.3/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=
@@ -22,8 +18,8 @@ github.com/cretz/bine v0.2.0/go.mod h1:WU4o9QR9wWp8AVKtTM1XD5vUHkEqnf2vVSo6dBqbe
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk=
github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
@@ -51,8 +47,8 @@ github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbg
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/insomniacslk/dhcp v0.0.0-20231016090811-6a2c8fbdcc1c h1:PgxFEySCI41sH0mB7/2XswdXbUykQsRUGod8Rn+NubM=
github.com/insomniacslk/dhcp v0.0.0-20231016090811-6a2c8fbdcc1c/go.mod h1:3A9PQ1cunSDF/1rbTq99Ts4pVnycWg+vlPkfeD2NLFI=
github.com/insomniacslk/dhcp v0.0.0-20230908212754-65c27093e38a h1:S33o3djA1nPRd+d/bf7jbbXytXuK/EoXow7+aa76grQ=
github.com/insomniacslk/dhcp v0.0.0-20230908212754-65c27093e38a/go.mod h1:zmdm3sTSDP3vOOX3CEWRkkRHtKr1DxBx+J1OQFoDQQs=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/josharian/native v1.0.1-0.20221213033349-c1e37c09b531/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
@@ -89,8 +85,6 @@ github.com/oschwald/maxminddb-golang v1.12.0 h1:9FnTOD0YOhP7DGxGsq4glzpGy5+w7pq5
github.com/oschwald/maxminddb-golang v1.12.0/go.mod h1:q0Nob5lTCqyQ8WT6FYgS1L7PXKVVbgiymefNwIjPzgY=
github.com/pierrec/lz4/v4 v4.1.14 h1:+fL8AQEZtz/ijeNnpduH0bROTu0O3NZAlPjQxGn8LwE=
github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pires/go-proxyproto v0.7.0 h1:IukmRewDQFWC7kfnb66CSomk2q/seBuilHBYFwyq0Hs=
github.com/pires/go-proxyproto v0.7.0/go.mod h1:Vz/1JPY/OACxWGQNIRY2BeyDmpoaWmEP40O9LbuiFR4=
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/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
@@ -98,40 +92,40 @@ github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1
github.com/quic-go/qtls-go1-20 v0.3.4 h1:MfFAPULvst4yoMgY9QmtpYmfij/em7O8UUi+bNVm7Cg=
github.com/quic-go/qtls-go1-20 v0.3.4/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a h1:+NkI2670SQpQWvkkD2QgdTuzQG263YZ+2emfpeyGqW0=
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a/go.mod h1:63s7jpZqcDAIpj8oI/1v4Izok+npJOHACFCU6+huCkM=
github.com/sagernet/bbolt v0.0.0-20231008142710-b2d6e2f20458 h1:7NXD6FUQucBklrw/TLCqeAARyFuoK9fD5iJ+Y/EHHBQ=
github.com/sagernet/bbolt v0.0.0-20231008142710-b2d6e2f20458/go.mod h1:63s7jpZqcDAIpj8oI/1v4Izok+npJOHACFCU6+huCkM=
github.com/sagernet/cloudflare-tls v0.0.0-20230829051644-4a68352d0c4a h1:wZHruBxZCsQLXHAozWpnJBL3wJ/XufDpz0qKtgpSnA4=
github.com/sagernet/cloudflare-tls v0.0.0-20230829051644-4a68352d0c4a/go.mod h1:dNV1ZP9y3qx5ltULeKaQZTZWTLHflgW5DES+Ses7cMI=
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 h1:5+m7c6AkmAylhauulqN/c5dnh8/KssrE9c93TQrXldA=
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61/go.mod h1:QUQ4RRHD6hGGHdFMEtR8T2P6GS6R3D/CXKdaYHKKXms=
github.com/sagernet/gomobile v0.0.0-20230915142329-c6740b6d2950 h1:hUz/2mJLgi7l2H36JGpDY+jou9FmI6kAm0ZkU+xPpgE=
github.com/sagernet/gomobile v0.0.0-20230915142329-c6740b6d2950/go.mod h1:5YE39YkJkCcMsfq1jMKkjsrM2GfBoF9JVWnvU89hmvU=
github.com/sagernet/gvisor v0.0.0-20230627031050-1ab0276e0dd2 h1:dnkKrzapqtAwjTSWt6hdPrARORfoYvuUczynvRLrueo=
github.com/sagernet/gvisor v0.0.0-20230627031050-1ab0276e0dd2/go.mod h1:1JUiV7nGuf++YFm9eWZ8q2lrwHmhcUGzptMl/vL1+LA=
github.com/sagernet/gvisor v0.0.0-20230930141345-5fef6f2e17ab h1:u+xQoi/Yc6bNUvTfrDD6HhGRybn2lzrhf5vmS+wb4Ho=
github.com/sagernet/gvisor v0.0.0-20230930141345-5fef6f2e17ab/go.mod h1:3akUhSHSVtLuJaYcW5JPepUraBOW06Ibz2HKwaK5rOk=
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-20230919101909-0cc6c5dcecee h1:ykuhl9jCS638N+jw1vC9AvT9bbQn6xRNScP2FWPV9dM=
github.com/sagernet/quic-go v0.0.0-20230919101909-0cc6c5dcecee/go.mod h1:0CfhWwZAeXGYM9+Nkkw1zcQtFHQC8KWjbpeDv7pu8iw=
github.com/sagernet/quic-go v0.0.0-20231008035953-32727fef9460 h1:dAe4OIJAtE0nHOzTHhAReQteh3+sa63rvXbuIpbeOTY=
github.com/sagernet/quic-go v0.0.0-20231008035953-32727fef9460/go.mod h1:uJGpmJCOcMQqMlHKc3P1Vz6uygmpz4bPeVIoOhdVQnM=
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc=
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.15 h1:PFwyiMzkyJkq+YGOVznJUsRVOT6EoVxRGIsllLuvHXA=
github.com/sagernet/sing v0.2.15/go.mod h1:AhNEHu0GXrpqkuzvTwvC8+j2cQUU/dh+zLEmq4C99pg=
github.com/sagernet/sing v0.2.14-0.20231011041941-e4d9384bcd84 h1:bPpV5QTOm6s9oJUCdfInImOgsWueoZWaJ7IpRkZuEsk=
github.com/sagernet/sing v0.2.14-0.20231011041941-e4d9384bcd84/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.3 h1:fAf7PZa2A55mCeh0KKM02f1k2Y4vEmxuZZ/51ahkkLA=
github.com/sagernet/sing-mux v0.1.3/go.mod h1:wGeIeiiFLx4HUM5LAg65wrNZ/X1muOimqK0PEhNbPi0=
github.com/sagernet/sing-quic v0.1.2 h1:+u9CRf0KHi5HgXmJ3eB0CtqpWXtF0lx2QlWq+ZFZ+XY=
github.com/sagernet/sing-quic v0.1.2/go.mod h1:H1TX0/y9UUM43wyaLQ+qjg2+o901ibYtwWX2rWG+a3o=
github.com/sagernet/sing-quic v0.1.3-0.20231011042217-13b8d0b8f74b h1:u95u1icfN2Ya7FTkuWfyNrC4llMn8AYwD+ZsGkVWkac=
github.com/sagernet/sing-quic v0.1.3-0.20231011042217-13b8d0b8f74b/go.mod h1:1M7xP4802K9Kz6BQ7LlA7UeCapWvWlH1Htmk2bAqkWc=
github.com/sagernet/sing-shadowsocks v0.2.5 h1:qxIttos4xu6ii7MTVJYA8EFQR7Q3KG6xMqmLJIFtBaY=
github.com/sagernet/sing-shadowsocks v0.2.5/go.mod h1:MGWGkcU2xW2G2mfArT9/QqpVLOGU+dBaahZCtPHdt7A=
github.com/sagernet/sing-shadowsocks2 v0.1.4 h1:vht2M8t3m5DTgXR2j24KbYOygG5aOp+MUhpQnAux728=
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.16 h1:RHXYIVg6uacvdfbYMiPEz9VX5uu6mNrvP7u9yAH3oNc=
github.com/sagernet/sing-tun v0.1.16/go.mod h1:S3q8GCjeyRniK+KLmo4XqKY0bS3x2UdKkKbqxT/Agl8=
github.com/sagernet/sing-tun v0.1.16-0.20231006112722-19cc8b9e81aa h1:lQVFeYJ916CXunKB3JrsOQqCtT16OAitMXw8Z0lRNvY=
github.com/sagernet/sing-tun v0.1.16-0.20231006112722-19cc8b9e81aa/go.mod h1:d5kKDDW3I8Tr1OSWNaHXzrnsg1LbOx9sYVx83cHPhm8=
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=
@@ -177,15 +171,15 @@ golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaE
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/exp v0.0.0-20231005195138-3e424a577f31 h1:9k5exFQKQglLo+RoP+4zMjOFE14P6+vyR0baDAi0Rcs=
golang.org/x/exp v0.0.0-20231005195138-3e424a577f31/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
golang.org/x/net v0.16.0 h1:7eBu7KsSvFDtSXUIDbh3aqlK4DPsZ1rByC8PFfBThos=
golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -193,6 +187,7 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/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.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
@@ -206,15 +201,15 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 h1:CawjfCvYQH2OU3/TnxLx97WDSUDRABfT18pCOYwc2GE=
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6/go.mod h1:3rxYc4HtVcSG9gVaTs2GEBdehh+sYPOwKtyUWEOTb80=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M=
google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk=
google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM=
google.golang.org/grpc v1.58.2 h1:SXUpjxeVF3FKrTYQI4f4KvbGD5u2xccdYdurwowix5I=
google.golang.org/grpc v1.58.2/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=

View File

@@ -5,7 +5,6 @@ import (
"net"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/proxyproto"
"github.com/sagernet/sing-box/log"
E "github.com/sagernet/sing/common/exceptions"
M "github.com/sagernet/sing/common/metadata"
@@ -34,9 +33,8 @@ func (a *myInboundAdapter) ListenTCP() (net.Listener, error) {
if err == nil {
a.logger.Info("tcp server started at ", tcpListener.Addr())
}
if a.listenOptions.ProxyProtocol {
a.logger.Warn("Proxy Protocol is deprecated, see https://sing-box.sagernet.org/deprecated")
tcpListener = &proxyproto.Listener{Listener: tcpListener, AcceptNoHeader: a.listenOptions.ProxyProtocolAcceptNoHeader}
if a.listenOptions.ProxyProtocol || a.listenOptions.ProxyProtocolAcceptNoHeader {
return nil, E.New("Proxy Protocol is deprecated and removed in sing-box 1.6.0")
}
a.tcpListener = tcpListener
return tcpListener, err

View File

@@ -221,7 +221,7 @@ func (h *Hysteria) accept(ctx context.Context, conn quic.Connection) error {
if err != nil {
return err
}
conn.SetCongestionControl(hyCC.NewBrutalSender(serverSendBPS))
conn.SetCongestionControl(hyCC.NewBrutalSender(serverSendBPS, false, nil))
go h.udpRecvLoop(conn)
for {
var stream quic.Stream

View File

@@ -89,6 +89,7 @@ func NewHysteria2(ctx context.Context, router adapter.Router, logger log.Context
service, err := hysteria2.NewService[int](hysteria2.ServiceOptions{
Context: ctx,
Logger: logger,
BrutalDebug: options.BrutalDebug,
SendBPS: uint64(options.UpMbps * hysteria.MbpsToBps),
ReceiveBPS: uint64(options.DownMbps * hysteria.MbpsToBps),
SalamanderPassword: salamanderPassword,

View File

@@ -2,7 +2,6 @@ package inbound
import (
"context"
"encoding/base64"
"encoding/binary"
"io"
"math/rand"
@@ -139,14 +138,9 @@ func (n *Naive) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
n.badRequest(ctx, request, E.New("missing naive padding"))
return
}
var authOk bool
var userName string
authorization := request.Header.Get("Proxy-Authorization")
if strings.HasPrefix(authorization, "BASIC ") || strings.HasPrefix(authorization, "Basic ") {
userPassword, _ := base64.URLEncoding.DecodeString(authorization[6:])
userPswdArr := strings.SplitN(string(userPassword), ":", 2)
userName = userPswdArr[0]
authOk = n.authenticator.Verify(userPswdArr[0], userPswdArr[1])
userName, password, authOk := sHttp.ParseBasicAuth(request.Header.Get("Proxy-Authorization"))
if authOk {
authOk = n.authenticator.Verify(userName, password)
}
if !authOk {
rejectHTTP(writer, http.StatusProxyAuthRequired)

View File

@@ -49,7 +49,6 @@ func NewTUIC(ctx context.Context, router adapter.Router, logger log.ContextLogge
tag: tag,
listenOptions: options.ListenOptions,
},
tlsConfig: tlsConfig,
}
service, err := tuic.NewService[int](tuic.ServiceOptions{
Context: ctx,

View File

@@ -73,14 +73,14 @@ func NewTun(ctx context.Context, router adapter.Router, logger log.ContextLogger
tunOptions: tun.Options{
Name: options.InterfaceName,
MTU: tunMTU,
Inet4Address: common.Map(options.Inet4Address, option.ListenPrefix.Build),
Inet6Address: common.Map(options.Inet6Address, option.ListenPrefix.Build),
Inet4Address: options.Inet4Address,
Inet6Address: options.Inet6Address,
AutoRoute: options.AutoRoute,
StrictRoute: options.StrictRoute,
IncludeInterface: options.IncludeInterface,
ExcludeInterface: options.ExcludeInterface,
Inet4RouteAddress: common.Map(options.Inet4RouteAddress, option.ListenPrefix.Build),
Inet6RouteAddress: common.Map(options.Inet6RouteAddress, option.ListenPrefix.Build),
Inet4RouteAddress: options.Inet4RouteAddress,
Inet6RouteAddress: options.Inet6RouteAddress,
IncludeUID: includeUID,
ExcludeUID: excludeUID,
IncludeAndroidUser: options.IncludeAndroidUser,

View File

@@ -1,5 +1,7 @@
package option
import "net/netip"
type DNSOptions struct {
Servers []DNSServerOptions `json:"servers,omitempty"`
Rules []DNSRule `json:"rules,omitempty"`
@@ -28,6 +30,6 @@ type DNSClientOptions struct {
type DNSFakeIPOptions struct {
Enabled bool `json:"enabled,omitempty"`
Inet4Range *ListenPrefix `json:"inet4_range,omitempty"`
Inet6Range *ListenPrefix `json:"inet6_range,omitempty"`
Inet4Range *netip.Prefix `json:"inet4_range,omitempty"`
Inet6Range *netip.Prefix `json:"inet6_range,omitempty"`
}

View File

@@ -9,6 +9,7 @@ type Hysteria2InboundOptions struct {
IgnoreClientBandwidth bool `json:"ignore_client_bandwidth,omitempty"`
TLS *InboundTLSOptions `json:"tls,omitempty"`
Masquerade string `json:"masquerade,omitempty"`
BrutalDebug bool `json:"brutal_debug,omitempty"`
}
type Hysteria2Obfs struct {
@@ -24,10 +25,11 @@ type Hysteria2User struct {
type Hysteria2OutboundOptions struct {
DialerOptions
ServerOptions
UpMbps int `json:"up_mbps,omitempty"`
DownMbps int `json:"down_mbps,omitempty"`
Obfs *Hysteria2Obfs `json:"obfs,omitempty"`
Password string `json:"password,omitempty"`
Network NetworkList `json:"network,omitempty"`
TLS *OutboundTLSOptions `json:"tls,omitempty"`
UpMbps int `json:"up_mbps,omitempty"`
DownMbps int `json:"down_mbps,omitempty"`
Obfs *Hysteria2Obfs `json:"obfs,omitempty"`
Password string `json:"password,omitempty"`
Network NetworkList `json:"network,omitempty"`
TLS *OutboundTLSOptions `json:"tls,omitempty"`
BrutalDebug bool `json:"brutal_debug,omitempty"`
}

View File

@@ -27,9 +27,9 @@ type SocksOutboundOptions struct {
type HTTPOutboundOptions struct {
DialerOptions
ServerOptions
Username string `json:"username,omitempty"`
Password string `json:"password,omitempty"`
TLS *OutboundTLSOptions `json:"tls,omitempty"`
Path string `json:"path,omitempty"`
Headers map[string]Listable[string] `json:"headers,omitempty"`
Username string `json:"username,omitempty"`
Password string `json:"password,omitempty"`
TLS *OutboundTLSOptions `json:"tls,omitempty"`
Path string `json:"path,omitempty"`
Headers HTTPHeader `json:"headers,omitempty"`
}

View File

@@ -1,14 +1,16 @@
package option
import "net/netip"
type TunInboundOptions struct {
InterfaceName string `json:"interface_name,omitempty"`
MTU uint32 `json:"mtu,omitempty"`
Inet4Address Listable[ListenPrefix] `json:"inet4_address,omitempty"`
Inet6Address Listable[ListenPrefix] `json:"inet6_address,omitempty"`
Inet4Address Listable[netip.Prefix] `json:"inet4_address,omitempty"`
Inet6Address Listable[netip.Prefix] `json:"inet6_address,omitempty"`
AutoRoute bool `json:"auto_route,omitempty"`
StrictRoute bool `json:"strict_route,omitempty"`
Inet4RouteAddress Listable[ListenPrefix] `json:"inet4_route_address,omitempty"`
Inet6RouteAddress Listable[ListenPrefix] `json:"inet6_route_address,omitempty"`
Inet4RouteAddress Listable[netip.Prefix] `json:"inet4_route_address,omitempty"`
Inet6RouteAddress Listable[netip.Prefix] `json:"inet6_route_address,omitempty"`
IncludeInterface Listable[string] `json:"include_interface,omitempty"`
ExcludeInterface Listable[string] `json:"exclude_interface,omitempty"`
IncludeUID Listable[uint32] `json:"include_uid,omitempty"`

View File

@@ -1,6 +1,7 @@
package option
import (
"net/http"
"net/netip"
"strings"
"time"
@@ -171,34 +172,6 @@ func (d *Duration) UnmarshalJSON(bytes []byte) error {
return nil
}
type ListenPrefix netip.Prefix
func (p ListenPrefix) MarshalJSON() ([]byte, error) {
prefix := netip.Prefix(p)
if !prefix.IsValid() {
return json.Marshal(nil)
}
return json.Marshal(prefix.String())
}
func (p *ListenPrefix) UnmarshalJSON(bytes []byte) error {
var value string
err := json.Unmarshal(bytes, &value)
if err != nil {
return err
}
prefix, err := netip.ParsePrefix(value)
if err != nil {
return err
}
*p = ListenPrefix(prefix)
return nil
}
func (p ListenPrefix) Build() netip.Prefix {
return netip.Prefix(p)
}
type DNSQueryType uint16
func (t DNSQueryType) MarshalJSON() ([]byte, error) {
@@ -235,3 +208,15 @@ func DNSQueryTypeToString(queryType uint16) string {
}
return F.ToString(queryType)
}
type HTTPHeader map[string]Listable[string]
func (h HTTPHeader) Build() http.Header {
header := make(http.Header)
for name, values := range h {
for _, value := range values {
header.Add(name, value)
}
}
return header
}

View File

@@ -61,19 +61,19 @@ func (o *V2RayTransportOptions) UnmarshalJSON(bytes []byte) error {
}
type V2RayHTTPOptions struct {
Host Listable[string] `json:"host,omitempty"`
Path string `json:"path,omitempty"`
Method string `json:"method,omitempty"`
Headers map[string]Listable[string] `json:"headers,omitempty"`
IdleTimeout Duration `json:"idle_timeout,omitempty"`
PingTimeout Duration `json:"ping_timeout,omitempty"`
Host Listable[string] `json:"host,omitempty"`
Path string `json:"path,omitempty"`
Method string `json:"method,omitempty"`
Headers HTTPHeader `json:"headers,omitempty"`
IdleTimeout Duration `json:"idle_timeout,omitempty"`
PingTimeout Duration `json:"ping_timeout,omitempty"`
}
type V2RayWebsocketOptions struct {
Path string `json:"path,omitempty"`
Headers map[string]Listable[string] `json:"headers,omitempty"`
MaxEarlyData uint32 `json:"max_early_data,omitempty"`
EarlyDataHeaderName string `json:"early_data_header_name,omitempty"`
Path string `json:"path,omitempty"`
Headers HTTPHeader `json:"headers,omitempty"`
MaxEarlyData uint32 `json:"max_early_data,omitempty"`
EarlyDataHeaderName string `json:"early_data_header_name,omitempty"`
}
type V2RayQUICOptions struct{}

View File

@@ -1,10 +1,12 @@
package option
import "net/netip"
type WireGuardOutboundOptions struct {
DialerOptions
SystemInterface bool `json:"system_interface,omitempty"`
InterfaceName string `json:"interface_name,omitempty"`
LocalAddress Listable[ListenPrefix] `json:"local_address"`
LocalAddress Listable[netip.Prefix] `json:"local_address"`
PrivateKey string `json:"private_key"`
Peers []WireGuardPeer `json:"peers,omitempty"`
ServerOptions

View File

@@ -17,7 +17,6 @@ import (
"github.com/sagernet/sing/common/bufio"
"github.com/sagernet/sing/common/canceler"
E "github.com/sagernet/sing/common/exceptions"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
)
@@ -120,10 +119,7 @@ func NewPacketConnection(ctx context.Context, this N.Dialer, conn N.PacketConn,
return err
}
if destinationAddress.IsValid() {
if metadata.Destination.IsFqdn() {
outConn = bufio.NewNATPacketConn(bufio.NewPacketConn(outConn), M.SocksaddrFrom(destinationAddress, metadata.Destination.Port), metadata.Destination)
}
if natConn, loaded := common.Cast[*bufio.NATPacketConn](conn); loaded {
if natConn, loaded := common.Cast[bufio.NATPacketConn](conn); loaded {
natConn.UpdateDestination(destinationAddress)
}
}
@@ -163,10 +159,7 @@ func NewDirectPacketConnection(ctx context.Context, router adapter.Router, this
return err
}
if destinationAddress.IsValid() {
if metadata.Destination.IsFqdn() {
outConn = bufio.NewNATPacketConn(bufio.NewPacketConn(outConn), M.SocksaddrFrom(destinationAddress, metadata.Destination.Port), metadata.Destination)
}
if natConn, loaded := common.Cast[*bufio.NATPacketConn](conn); loaded {
if natConn, loaded := common.Cast[bufio.NATPacketConn](conn); loaded {
natConn.UpdateDestination(destinationAddress)
}
}

View File

@@ -17,8 +17,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/pires/go-proxyproto"
)
var (
@@ -33,7 +31,6 @@ type Direct struct {
fallbackDelay time.Duration
overrideOption int
overrideDestination M.Socksaddr
proxyProto uint8
}
func NewDirect(router adapter.Router, logger log.ContextLogger, tag string, options option.DirectOutboundOptions) (*Direct, error) {
@@ -54,10 +51,9 @@ func NewDirect(router adapter.Router, logger log.ContextLogger, tag string, opti
domainStrategy: dns.DomainStrategy(options.DomainStrategy),
fallbackDelay: time.Duration(options.FallbackDelay),
dialer: outboundDialer,
proxyProto: options.ProxyProtocol,
}
if options.ProxyProtocol > 2 {
return nil, E.New("invalid proxy protocol option: ", options.ProxyProtocol)
if options.ProxyProtocol != 0 {
return nil, E.New("Proxy Protocol is deprecated and removed in sing-box 1.6.0")
}
if options.OverrideAddress != "" && options.OverridePort != 0 {
outbound.overrideOption = 1
@@ -74,7 +70,6 @@ func NewDirect(router adapter.Router, logger log.ContextLogger, tag string, opti
func (h *Direct) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
ctx, metadata := adapter.AppendContext(ctx)
originDestination := metadata.Destination
metadata.Outbound = h.tag
metadata.Destination = destination
switch h.overrideOption {
@@ -94,31 +89,11 @@ func (h *Direct) DialContext(ctx context.Context, network string, destination M.
case N.NetworkUDP:
h.logger.InfoContext(ctx, "outbound packet connection to ", destination)
}
conn, err := h.dialer.DialContext(ctx, network, destination)
if err != nil {
return nil, err
}
if h.proxyProto > 0 {
source := metadata.Source
if !source.IsValid() {
source = M.SocksaddrFromNet(conn.LocalAddr())
}
if originDestination.Addr.Is6() {
source = M.SocksaddrFrom(netip.AddrFrom16(source.Addr.As16()), source.Port)
}
header := proxyproto.HeaderProxyFromAddrs(h.proxyProto, source.TCPAddr(), originDestination.TCPAddr())
_, err = header.WriteTo(conn)
if err != nil {
conn.Close()
return nil, E.Cause(err, "write proxy protocol header")
}
}
return conn, nil
return h.dialer.DialContext(ctx, network, destination)
}
func (h *Direct) DialParallel(ctx context.Context, network string, destination M.Socksaddr, destinationAddresses []netip.Addr) (net.Conn, error) {
ctx, metadata := adapter.AppendContext(ctx)
originDestination := metadata.Destination
metadata.Outbound = h.tag
metadata.Destination = destination
switch h.overrideOption {
@@ -141,30 +116,11 @@ func (h *Direct) DialParallel(ctx context.Context, network string, destination M
} else {
domainStrategy = dns.DomainStrategy(metadata.InboundOptions.DomainStrategy)
}
conn, err := N.DialParallel(ctx, h.dialer, network, destination, destinationAddresses, domainStrategy == dns.DomainStrategyPreferIPv6, h.fallbackDelay)
if err != nil {
return nil, err
}
if h.proxyProto > 0 {
source := metadata.Source
if !source.IsValid() {
source = M.SocksaddrFromNet(conn.LocalAddr())
}
if originDestination.Addr.Is6() {
source = M.SocksaddrFrom(netip.AddrFrom16(source.Addr.As16()), source.Port)
}
header := proxyproto.HeaderProxyFromAddrs(h.proxyProto, source.TCPAddr(), originDestination.TCPAddr())
_, err = header.WriteTo(conn)
if err != nil {
conn.Close()
return nil, E.Cause(err, "write proxy protocol header")
}
}
return conn, nil
return N.DialParallel(ctx, h.dialer, network, destination, destinationAddresses, domainStrategy == dns.DomainStrategyPreferIPv6, h.fallbackDelay)
}
func (h *Direct) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
ctx, metadata := adapter.ExtendContext(ctx)
ctx, metadata := adapter.AppendContext(ctx)
metadata.Outbound = h.tag
metadata.Destination = destination
switch h.overrideOption {

View File

@@ -3,7 +3,6 @@ package outbound
import (
"context"
"net"
"net/http"
"os"
"github.com/sagernet/sing-box/adapter"
@@ -34,13 +33,6 @@ func NewHTTP(ctx context.Context, router adapter.Router, logger log.ContextLogge
if err != nil {
return nil, err
}
var headers http.Header
if options.Headers != nil {
headers = make(http.Header)
for key, values := range options.Headers {
headers[key] = values
}
}
return &HTTP{
myOutboundAdapter{
protocol: C.TypeHTTP,
@@ -56,7 +48,7 @@ func NewHTTP(ctx context.Context, router adapter.Router, logger log.ContextLogge
Username: options.Username,
Password: options.Password,
Path: options.Path,
Headers: headers,
Headers: options.Headers.Build(),
}),
}, nil
}

View File

@@ -206,7 +206,7 @@ func (h *Hysteria) offerNew(ctx context.Context) (quic.Connection, error) {
packetConn.Close()
return nil, E.New("remote error: ", serverHello.Message)
}
quicConn.SetCongestionControl(hyCC.NewBrutalSender(serverHello.RecvBPS))
quicConn.SetCongestionControl(hyCC.NewBrutalSender(serverHello.RecvBPS, false, nil))
h.conn = quicConn
h.rawConn = udpConn
return quicConn, nil

View File

@@ -61,6 +61,8 @@ func NewHysteria2(ctx context.Context, router adapter.Router, logger log.Context
client, err := hysteria2.NewClient(hysteria2.ClientOptions{
Context: ctx,
Dialer: outboundDialer,
Logger: logger,
BrutalDebug: options.BrutalDebug,
ServerAddress: options.ServerOptions.Build(),
SendBPS: uint64(options.UpMbps * hysteria.MbpsToBps),
ReceiveBPS: uint64(options.DownMbps * hysteria.MbpsToBps),

View File

@@ -4,192 +4,15 @@ package outbound
import (
"context"
"errors"
"fmt"
"net"
"os"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/dialer"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing-box/transport/clashssr/obfs"
"github.com/sagernet/sing-box/transport/clashssr/protocol"
"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"
"github.com/Dreamacro/clash/transport/shadowsocks/core"
"github.com/Dreamacro/clash/transport/shadowsocks/shadowstream"
"github.com/Dreamacro/clash/transport/socks5"
)
var _ adapter.Outbound = (*ShadowsocksR)(nil)
var _ int = "ShadowsocksR is deprecated and removed in sing-box 1.6.0"
type ShadowsocksR struct {
myOutboundAdapter
dialer N.Dialer
serverAddr M.Socksaddr
cipher core.Cipher
obfs obfs.Obfs
protocol protocol.Protocol
}
func NewShadowsocksR(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.ShadowsocksROutboundOptions) (*ShadowsocksR, error) {
logger.Warn("ShadowsocksR is deprecated, see https://sing-box.sagernet.org/deprecated")
outboundDialer, err := dialer.New(router, options.DialerOptions)
if err != nil {
return nil, err
}
outbound := &ShadowsocksR{
myOutboundAdapter: myOutboundAdapter{
protocol: C.TypeShadowsocksR,
network: options.Network.Build(),
router: router,
logger: logger,
tag: tag,
dependencies: withDialerDependency(options.DialerOptions),
},
dialer: outboundDialer,
serverAddr: options.ServerOptions.Build(),
}
var cipher string
switch options.Method {
case "none":
cipher = "dummy"
default:
cipher = options.Method
}
outbound.cipher, err = core.PickCipher(cipher, nil, options.Password)
if err != nil {
return nil, err
}
var (
ivSize int
key []byte
)
if cipher == "dummy" {
ivSize = 0
key = core.Kdf(options.Password, 16)
} else {
streamCipher, ok := outbound.cipher.(*core.StreamCipher)
if !ok {
return nil, fmt.Errorf("%s is not none or a supported stream cipher in ssr", cipher)
}
ivSize = streamCipher.IVSize()
key = streamCipher.Key
}
obfs, obfsOverhead, err := obfs.PickObfs(options.Obfs, &obfs.Base{
Host: options.Server,
Port: int(options.ServerPort),
Key: key,
IVSize: ivSize,
Param: options.ObfsParam,
})
if err != nil {
return nil, E.Cause(err, "initialize obfs")
}
protocol, err := protocol.PickProtocol(options.Protocol, &protocol.Base{
Key: key,
Overhead: obfsOverhead,
Param: options.ProtocolParam,
})
if err != nil {
return nil, E.Cause(err, "initialize protocol")
}
outbound.obfs = obfs
outbound.protocol = protocol
return outbound, nil
}
func (h *ShadowsocksR) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
ctx, metadata := adapter.AppendContext(ctx)
metadata.Outbound = h.tag
metadata.Destination = destination
switch network {
case N.NetworkTCP:
h.logger.InfoContext(ctx, "outbound connection to ", destination)
conn, err := h.dialer.DialContext(ctx, network, h.serverAddr)
if err != nil {
return nil, err
}
conn = h.cipher.StreamConn(h.obfs.StreamConn(conn))
writeIv, err := conn.(*shadowstream.Conn).ObtainWriteIV()
if err != nil {
conn.Close()
return nil, err
}
conn = h.protocol.StreamConn(conn, writeIv)
err = M.SocksaddrSerializer.WriteAddrPort(conn, destination)
if err != nil {
conn.Close()
return nil, E.Cause(err, "write request")
}
return conn, nil
case N.NetworkUDP:
conn, err := h.ListenPacket(ctx, destination)
if err != nil {
return nil, err
}
return bufio.NewBindPacketConn(conn, destination), nil
default:
return nil, E.Extend(N.ErrUnknownNetwork, network)
}
}
func (h *ShadowsocksR) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
ctx, metadata := adapter.AppendContext(ctx)
metadata.Outbound = h.tag
metadata.Destination = destination
h.logger.InfoContext(ctx, "outbound packet connection to ", destination)
outConn, err := h.dialer.DialContext(ctx, N.NetworkUDP, h.serverAddr)
if err != nil {
return nil, err
}
packetConn := h.cipher.PacketConn(bufio.NewUnbindPacketConn(outConn))
packetConn = h.protocol.PacketConn(packetConn)
packetConn = &ssPacketConn{packetConn, outConn.RemoteAddr()}
return packetConn, nil
}
func (h *ShadowsocksR) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
return NewConnection(ctx, h, conn, metadata)
}
func (h *ShadowsocksR) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
return NewPacketConnection(ctx, h, conn, metadata)
}
type ssPacketConn struct {
net.PacketConn
rAddr net.Addr
}
func (spc *ssPacketConn) WriteTo(b []byte, addr net.Addr) (n int, err error) {
packet, err := socks5.EncodeUDPPacket(socks5.ParseAddrToSocksAddr(addr), b)
if err != nil {
return
}
return spc.PacketConn.WriteTo(packet[3:], spc.rAddr)
}
func (spc *ssPacketConn) ReadFrom(b []byte) (int, net.Addr, error) {
n, _, e := spc.PacketConn.ReadFrom(b)
if e != nil {
return 0, nil, e
}
addr := socks5.SplitAddr(b[:n])
if addr == nil {
return 0, nil, errors.New("parse addr error")
}
udpAddr := addr.UDPAddr()
if udpAddr == nil {
return 0, nil, errors.New("parse addr error")
}
copy(b, b[len(addr):])
return n - len(addr), udpAddr, e
func NewShadowsocksR(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.ShadowsocksROutboundOptions) (adapter.Outbound, error) {
return nil, os.ErrInvalid
}

View File

@@ -12,5 +12,5 @@ import (
)
func NewShadowsocksR(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.ShadowsocksROutboundOptions) (adapter.Outbound, error) {
return nil, E.New(`ShadowsocksR is not included in this build, rebuild with -tags with_shadowsocksr`)
return nil, E.New("ShadowsocksR is deprecated and removed in sing-box 1.6.0")
}

View File

@@ -18,7 +18,6 @@ import (
"github.com/sagernet/sing-box/transport/wireguard"
"github.com/sagernet/sing-dns"
"github.com/sagernet/sing-tun"
"github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/debug"
E "github.com/sagernet/sing/common/exceptions"
M "github.com/sagernet/sing/common/metadata"
@@ -71,8 +70,7 @@ func NewWireGuard(ctx context.Context, router adapter.Router, logger log.Context
return nil, err
}
outbound.bind = wireguard.NewClientBind(ctx, outbound, outboundDialer, isConnect, connectAddr, reserved)
localPrefixes := common.Map(options.LocalAddress, option.ListenPrefix.Build)
if len(localPrefixes) == 0 {
if len(options.LocalAddress) == 0 {
return nil, E.New("missing local address")
}
var privateKey string
@@ -143,7 +141,7 @@ func NewWireGuard(ctx context.Context, router adapter.Router, logger log.Context
ipcConf += "\npreshared_key=" + preSharedKey
}
var has4, has6 bool
for _, address := range localPrefixes {
for _, address := range options.LocalAddress {
if address.Addr().Is4() {
has4 = true
} else {
@@ -163,9 +161,9 @@ func NewWireGuard(ctx context.Context, router adapter.Router, logger log.Context
}
var wireTunDevice wireguard.Device
if !options.SystemInterface && tun.WithGVisor {
wireTunDevice, err = wireguard.NewStackDevice(localPrefixes, mtu)
wireTunDevice, err = wireguard.NewStackDevice(options.LocalAddress, mtu)
} else {
wireTunDevice, err = wireguard.NewSystemDevice(router, options.InterfaceName, localPrefixes, mtu)
wireTunDevice, err = wireguard.NewSystemDevice(router, options.InterfaceName, options.LocalAddress, mtu)
}
if err != nil {
return nil, E.Cause(err, "create WireGuard device")

View File

@@ -253,10 +253,10 @@ func NewRouter(
var inet4Range netip.Prefix
var inet6Range netip.Prefix
if fakeIPOptions.Inet4Range != nil {
inet4Range = fakeIPOptions.Inet4Range.Build()
inet4Range = *fakeIPOptions.Inet4Range
}
if fakeIPOptions.Inet6Range != nil {
inet6Range = fakeIPOptions.Inet6Range.Build()
inet6Range = *fakeIPOptions.Inet6Range
}
router.fakeIPStore = fakeip.NewStore(router, router.logger, inet4Range, inet6Range)
}
@@ -835,7 +835,7 @@ func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, m
}
}
if metadata.FakeIP {
conn = bufio.NewNATPacketConn(bufio.NewNetPacketConn(conn), metadata.OriginDestination, metadata.Destination)
conn = fakeip.NewNATPacketConn(conn, metadata.OriginDestination, metadata.Destination)
}
return detour.NewPacketConnection(ctx, conn, metadata)
}
@@ -930,9 +930,8 @@ func (r *Router) AutoDetectInterfaceFunc() control.Func {
return control.BindToInterfaceFunc(r.InterfaceFinder(), func(network string, address string) (interfaceName string, interfaceIndex int, err error) {
remoteAddr := M.ParseSocksaddr(address).Addr
if C.IsLinux {
interfaceName = r.InterfaceMonitor().DefaultInterfaceName(remoteAddr)
interfaceIndex = -1
if interfaceName == "" {
interfaceName, interfaceIndex = r.InterfaceMonitor().DefaultInterface(remoteAddr)
if interfaceIndex == -1 {
err = tun.ErrNoRoute
}
} else {

View File

@@ -2,15 +2,10 @@ package main
import (
"context"
"crypto/tls"
"io"
"net"
"net/http"
"testing"
"time"
"github.com/sagernet/quic-go"
"github.com/sagernet/quic-go/http3"
"github.com/sagernet/sing-box"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/option"
@@ -79,28 +74,6 @@ func testSuit(t *testing.T, clientPort uint16, testPort uint16) {
// require.NoError(t, testPacketConnTimeout(t, dialUDP))
}
func testQUIC(t *testing.T, clientPort uint16) {
dialer := socks.NewClient(N.SystemDialer, M.ParseSocksaddrHostPort("127.0.0.1", clientPort), socks.Version5, "", "")
client := &http.Client{
Transport: &http3.RoundTripper{
Dial: func(ctx context.Context, addr string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlyConnection, error) {
destination := M.ParseSocksaddr(addr)
udpConn, err := dialer.DialContext(ctx, N.NetworkUDP, destination)
if err != nil {
return nil, err
}
return quic.DialEarly(ctx, udpConn.(net.PacketConn), destination, tlsCfg, cfg)
},
},
}
response, err := client.Get("https://cloudflare.com/cdn-cgi/trace")
require.NoError(t, err)
require.Equal(t, http.StatusOK, response.StatusCode)
content, err := io.ReadAll(response.Body)
require.NoError(t, err)
println(string(content))
}
func testSuitLargeUDP(t *testing.T, clientPort uint16, testPort uint16) {
dialer := socks.NewClient(N.SystemDialer, M.ParseSocksaddrHostPort("127.0.0.1", clientPort), socks.Version5, "", "")
dialTCP := func() (net.Conn, error) {

View File

@@ -36,7 +36,6 @@ const (
ImageHysteria2 = "tobyxdd/hysteria:v2"
ImageNginx = "nginx:stable"
ImageShadowTLS = "ghcr.io/ihciah/shadow-tls:latest"
ImageShadowsocksR = "teddysun/shadowsocks-r:latest"
ImageXRayCore = "teddysun/xray:latest"
ImageShadowsocksLegacy = "mritd/shadowsocks:latest"
ImageTUICServer = "kilvn/tuic-server:latest"
@@ -54,7 +53,6 @@ var allImages = []string{
ImageHysteria2,
ImageNginx,
ImageShadowTLS,
ImageShadowsocksR,
ImageXRayCore,
ImageShadowsocksLegacy,
ImageTUICServer,

View File

@@ -1,83 +0,0 @@
package main
import (
"net/netip"
"testing"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/option"
dns "github.com/sagernet/sing-dns"
"github.com/gofrs/uuid/v5"
)
func TestTUICDomainUDP(t *testing.T) {
_, certPem, keyPem := createSelfSignedCertificate(t, "example.org")
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.TypeTUIC,
TUICOptions: option.TUICInboundOptions{
ListenOptions: option.ListenOptions{
Listen: option.NewListenAddress(netip.IPv4Unspecified()),
ListenPort: serverPort,
InboundOptions: option.InboundOptions{
DomainStrategy: option.DomainStrategy(dns.DomainStrategyUseIPv6),
},
},
Users: []option.TUICUser{{
UUID: uuid.Nil.String(),
}},
TLS: &option.InboundTLSOptions{
Enabled: true,
ServerName: "example.org",
CertificatePath: certPem,
KeyPath: keyPem,
},
},
},
},
Outbounds: []option.Outbound{
{
Type: C.TypeDirect,
},
{
Type: C.TypeTUIC,
Tag: "tuic-out",
TUICOptions: option.TUICOutboundOptions{
ServerOptions: option.ServerOptions{
Server: "127.0.0.1",
ServerPort: serverPort,
},
UUID: uuid.Nil.String(),
TLS: &option.OutboundTLSOptions{
Enabled: true,
ServerName: "example.org",
CertificatePath: certPem,
},
},
},
},
Route: &option.RouteOptions{
Rules: []option.Rule{
{
DefaultOptions: option.DefaultRule{
Inbound: []string{"mixed-in"},
Outbound: "tuic-out",
},
},
},
},
})
testQUIC(t, clientPort)
}

View File

@@ -6,37 +6,34 @@ require github.com/sagernet/sing-box v0.0.0
replace github.com/sagernet/sing-box => ../
replace github.com/sagernet/sing-quic => ../../sing-quic
require (
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-20230919101909-0cc6c5dcecee
github.com/sagernet/sing v0.2.15
github.com/sagernet/sing-dns v0.1.10
github.com/sagernet/sing-quic v0.1.2
github.com/sagernet/sing v0.2.13-0.20231001063649-e0ec961fb1ab
github.com/sagernet/sing-quic v0.1.1
github.com/sagernet/sing-shadowsocks v0.2.5
github.com/sagernet/sing-shadowsocks2 v0.1.4
github.com/spyzhov/ajson v0.9.0
github.com/stretchr/testify v1.8.4
go.uber.org/goleak v1.3.0
golang.org/x/net v0.17.0
go.uber.org/goleak v1.2.1
golang.org/x/net v0.15.0
)
require (
berty.tech/go-libtor v1.0.385 // indirect
github.com/Dreamacro/clash v1.17.0 // indirect
github.com/Dreamacro/protobytes v0.0.0-20230617041236-6500a9f4f158 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/Microsoft/go-winio v0.6.0 // indirect
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.5 // indirect
github.com/cloudflare/circl v1.3.3 // 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
github.com/docker/distribution v2.8.3+incompatible // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/docker/distribution v2.8.1+incompatible // indirect
github.com/docker/go-units v0.4.0 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/go-chi/chi/v5 v5.0.10 // indirect
github.com/go-chi/cors v1.2.1 // indirect
github.com/go-chi/render v1.0.3 // indirect
@@ -47,7 +44,7 @@ require (
github.com/google/btree v1.1.2 // indirect
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
github.com/hashicorp/yamux v0.1.1 // indirect
github.com/insomniacslk/dhcp v0.0.0-20231016090811-6a2c8fbdcc1c // indirect
github.com/insomniacslk/dhcp v0.0.0-20230908212754-65c27093e38a // indirect
github.com/josharian/native v1.1.0 // indirect
github.com/klauspost/compress v1.15.15 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
@@ -57,7 +54,7 @@ require (
github.com/logrusorgru/aurora v2.0.3+incompatible // indirect
github.com/mholt/acmez v1.2.0 // indirect
github.com/miekg/dns v1.1.56 // indirect
github.com/moby/term v0.5.0 // indirect
github.com/moby/term v0.0.0-20221205130635-1aeaba878587 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/onsi/ginkgo/v2 v2.9.5 // indirect
github.com/ooni/go-libtor v1.1.8 // indirect
@@ -65,20 +62,20 @@ require (
github.com/opencontainers/image-spec v1.0.2 // indirect
github.com/oschwald/maxminddb-golang v1.12.0 // indirect
github.com/pierrec/lz4/v4 v4.1.14 // indirect
github.com/pires/go-proxyproto v0.7.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/quic-go/qpack v0.4.0 // indirect
github.com/quic-go/qtls-go1-20 v0.3.4 // indirect
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a // indirect
github.com/sagernet/cloudflare-tls v0.0.0-20230829051644-4a68352d0c4a // indirect
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 // indirect
github.com/sagernet/gvisor v0.0.0-20230627031050-1ab0276e0dd2 // indirect
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 // indirect
github.com/sagernet/quic-go v0.0.0-20231001051131-0fc736a289bb // indirect
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 // indirect
github.com/sagernet/sing-dns v0.1.10 // 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.16 // indirect
github.com/sagernet/sing-tun v0.1.14 // 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
@@ -89,20 +86,21 @@ require (
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 // indirect
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
github.com/zeebo/blake3 v0.2.3 // indirect
go.etcd.io/bbolt v1.3.7 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.26.0 // indirect
go4.org/netipx v0.0.0-20230824141953-6213f710f925 // indirect
golang.org/x/crypto v0.14.0 // indirect
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
golang.org/x/mod v0.13.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/crypto v0.13.0 // indirect
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/sys v0.12.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.14.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
google.golang.org/grpc v1.59.0 // indirect
golang.org/x/tools v0.13.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect
google.golang.org/grpc v1.58.2 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gotest.tools/v3 v3.5.1 // indirect
gotest.tools/v3 v3.4.0 // indirect
lukechampine.com/blake3 v1.2.1 // indirect
)

View File

@@ -1,12 +1,8 @@
berty.tech/go-libtor v1.0.385 h1:RWK94C3hZj6Z2GdvePpHJLnWYobFr3bY/OdUJ5aoEXw=
berty.tech/go-libtor v1.0.385/go.mod h1:9swOOQVb+kmvuAlsgWUK/4c52pm69AdbJsxLzk+fJEw=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
github.com/Dreamacro/clash v1.17.0 h1:LWtp6KcnrCiujY58ufI8pylI+hbCBgSCsLI90EWhpi4=
github.com/Dreamacro/clash v1.17.0/go.mod h1:PtcAft7sdsK325BD6uwm8wvhOkMV3TCeED6dfZ/lnfE=
github.com/Dreamacro/protobytes v0.0.0-20230617041236-6500a9f4f158 h1:JFnwKplz9hj8ubqYjm8HkgZS1Rvz9yW+u/XCNNTxr0k=
github.com/Dreamacro/protobytes v0.0.0-20230617041236-6500a9f4f158/go.mod h1:QvmEZ/h6KXszPOr2wUFl7Zn3hfFNYdfbXwPVDTyZs6k=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
@@ -16,26 +12,24 @@ 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.5 h1:g+wWynZqVALYAlpSQFAa7TscDnUK8mKYtrxMpw6AUKo=
github.com/cloudflare/circl v1.3.5/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs=
github.com/cloudflare/circl v1.3.3/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=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0=
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/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68=
github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
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=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk=
github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
@@ -63,8 +57,8 @@ github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLe
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/insomniacslk/dhcp v0.0.0-20231016090811-6a2c8fbdcc1c h1:PgxFEySCI41sH0mB7/2XswdXbUykQsRUGod8Rn+NubM=
github.com/insomniacslk/dhcp v0.0.0-20231016090811-6a2c8fbdcc1c/go.mod h1:3A9PQ1cunSDF/1rbTq99Ts4pVnycWg+vlPkfeD2NLFI=
github.com/insomniacslk/dhcp v0.0.0-20230908212754-65c27093e38a h1:S33o3djA1nPRd+d/bf7jbbXytXuK/EoXow7+aa76grQ=
github.com/insomniacslk/dhcp v0.0.0-20230908212754-65c27093e38a/go.mod h1:zmdm3sTSDP3vOOX3CEWRkkRHtKr1DxBx+J1OQFoDQQs=
github.com/josharian/native v1.0.1-0.20221213033349-c1e37c09b531/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
@@ -89,8 +83,8 @@ github.com/mholt/acmez v1.2.0 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30=
github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE=
github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE=
github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY=
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
github.com/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA=
github.com/moby/term v0.0.0-20221205130635-1aeaba878587/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
@@ -107,8 +101,6 @@ github.com/oschwald/maxminddb-golang v1.12.0 h1:9FnTOD0YOhP7DGxGsq4glzpGy5+w7pq5
github.com/oschwald/maxminddb-golang v1.12.0/go.mod h1:q0Nob5lTCqyQ8WT6FYgS1L7PXKVVbgiymefNwIjPzgY=
github.com/pierrec/lz4/v4 v4.1.14 h1:+fL8AQEZtz/ijeNnpduH0bROTu0O3NZAlPjQxGn8LwE=
github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pires/go-proxyproto v0.7.0 h1:IukmRewDQFWC7kfnb66CSomk2q/seBuilHBYFwyq0Hs=
github.com/pires/go-proxyproto v0.7.0/go.mod h1:Vz/1JPY/OACxWGQNIRY2BeyDmpoaWmEP40O9LbuiFR4=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -117,8 +109,6 @@ github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
github.com/quic-go/qtls-go1-20 v0.3.4 h1:MfFAPULvst4yoMgY9QmtpYmfij/em7O8UUi+bNVm7Cg=
github.com/quic-go/qtls-go1-20 v0.3.4/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a h1:+NkI2670SQpQWvkkD2QgdTuzQG263YZ+2emfpeyGqW0=
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a/go.mod h1:63s7jpZqcDAIpj8oI/1v4Izok+npJOHACFCU6+huCkM=
github.com/sagernet/cloudflare-tls v0.0.0-20230829051644-4a68352d0c4a h1:wZHruBxZCsQLXHAozWpnJBL3wJ/XufDpz0qKtgpSnA4=
github.com/sagernet/cloudflare-tls v0.0.0-20230829051644-4a68352d0c4a/go.mod h1:dNV1ZP9y3qx5ltULeKaQZTZWTLHflgW5DES+Ses7cMI=
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 h1:5+m7c6AkmAylhauulqN/c5dnh8/KssrE9c93TQrXldA=
@@ -127,28 +117,26 @@ github.com/sagernet/gvisor v0.0.0-20230627031050-1ab0276e0dd2 h1:dnkKrzapqtAwjTS
github.com/sagernet/gvisor v0.0.0-20230627031050-1ab0276e0dd2/go.mod h1:1JUiV7nGuf++YFm9eWZ8q2lrwHmhcUGzptMl/vL1+LA=
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-20230919101909-0cc6c5dcecee h1:ykuhl9jCS638N+jw1vC9AvT9bbQn6xRNScP2FWPV9dM=
github.com/sagernet/quic-go v0.0.0-20230919101909-0cc6c5dcecee/go.mod h1:0CfhWwZAeXGYM9+Nkkw1zcQtFHQC8KWjbpeDv7pu8iw=
github.com/sagernet/quic-go v0.0.0-20231001051131-0fc736a289bb h1:jlrVCepGBoob4QsPChIbe1j0d/lZSJkyVj2ukX3D4PE=
github.com/sagernet/quic-go v0.0.0-20231001051131-0fc736a289bb/go.mod h1:uJGpmJCOcMQqMlHKc3P1Vz6uygmpz4bPeVIoOhdVQnM=
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc=
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.15 h1:PFwyiMzkyJkq+YGOVznJUsRVOT6EoVxRGIsllLuvHXA=
github.com/sagernet/sing v0.2.15/go.mod h1:AhNEHu0GXrpqkuzvTwvC8+j2cQUU/dh+zLEmq4C99pg=
github.com/sagernet/sing v0.2.13-0.20231001063649-e0ec961fb1ab h1:ccXgrc2HGcPlFFtNISITE95YeUiChU+7GCQaeWriylk=
github.com/sagernet/sing v0.2.13-0.20231001063649-e0ec961fb1ab/go.mod h1:GQ673iPfUnkbK/dIPkfd1Xh1MjOGo36gkl/mkiHY7Jg=
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.3 h1:fAf7PZa2A55mCeh0KKM02f1k2Y4vEmxuZZ/51ahkkLA=
github.com/sagernet/sing-mux v0.1.3/go.mod h1:wGeIeiiFLx4HUM5LAg65wrNZ/X1muOimqK0PEhNbPi0=
github.com/sagernet/sing-quic v0.1.2 h1:+u9CRf0KHi5HgXmJ3eB0CtqpWXtF0lx2QlWq+ZFZ+XY=
github.com/sagernet/sing-quic v0.1.2/go.mod h1:H1TX0/y9UUM43wyaLQ+qjg2+o901ibYtwWX2rWG+a3o=
github.com/sagernet/sing-shadowsocks v0.2.5 h1:qxIttos4xu6ii7MTVJYA8EFQR7Q3KG6xMqmLJIFtBaY=
github.com/sagernet/sing-shadowsocks v0.2.5/go.mod h1:MGWGkcU2xW2G2mfArT9/QqpVLOGU+dBaahZCtPHdt7A=
github.com/sagernet/sing-shadowsocks2 v0.1.4 h1:vht2M8t3m5DTgXR2j24KbYOygG5aOp+MUhpQnAux728=
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.16 h1:RHXYIVg6uacvdfbYMiPEz9VX5uu6mNrvP7u9yAH3oNc=
github.com/sagernet/sing-tun v0.1.16/go.mod h1:S3q8GCjeyRniK+KLmo4XqKY0bS3x2UdKkKbqxT/Agl8=
github.com/sagernet/sing-tun v0.1.14 h1:Vsval4r78kngCsZsz0FExT6p6akiUeRuiVXjfgnN3Ok=
github.com/sagernet/sing-tun v0.1.14/go.mod h1:Z2WibDUoQh/3wwFCfkIzIG0n/NlAlPuEbLTq3rD1aQY=
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=
@@ -183,8 +171,10 @@ github.com/zeebo/blake3 v0.2.3 h1:TFoLXsjeXqRNFxSbk35Dk4YtszE/MQQGK10BH4ptoTg=
github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvvKCaQ=
github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ=
go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
@@ -196,26 +186,26 @@ 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.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -223,15 +213,17 @@ golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/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.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.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/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU=
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.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@@ -243,16 +235,17 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M=
google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk=
google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM=
google.golang.org/grpc v1.58.2 h1:SXUpjxeVF3FKrTYQI4f4KvbGD5u2xccdYdurwowix5I=
google.golang.org/grpc v1.58.2/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
@@ -262,7 +255,7 @@ gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8X
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g=
lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI=
lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=

View File

@@ -97,7 +97,7 @@ func testHysteria2Self(t *testing.T, salamanderPassword string) {
},
},
})
testSuitLargeUDP(t, clientPort, testPort)
testSuit(t, clientPort, testPort)
}
func TestHysteria2Inbound(t *testing.T) {

View File

@@ -1,48 +0,0 @@
package main
import (
"net/netip"
"testing"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/option"
)
func TestShadowsocksR(t *testing.T) {
startDockerContainer(t, DockerOptions{
Image: ImageShadowsocksR,
Ports: []uint16{serverPort, testPort},
Bind: map[string]string{
"shadowsocksr.json": "/etc/shadowsocks-r/config.json",
},
})
startInstance(t, option.Options{
Inbounds: []option.Inbound{
{
Type: C.TypeMixed,
MixedOptions: option.HTTPMixedInboundOptions{
ListenOptions: option.ListenOptions{
Listen: option.NewListenAddress(netip.IPv4Unspecified()),
ListenPort: clientPort,
},
},
},
},
Outbounds: []option.Outbound{
{
Type: C.TypeShadowsocksR,
ShadowsocksROptions: option.ShadowsocksROutboundOptions{
ServerOptions: option.ServerOptions{
Server: "127.0.0.1",
ServerPort: serverPort,
},
Method: "aes-256-cfb",
Password: "password0",
Obfs: "plain",
Protocol: "origin",
},
},
},
})
testSuit(t, clientPort, testPort)
}

View File

@@ -40,7 +40,7 @@ func _TestWireGuard(t *testing.T) {
Server: "127.0.0.1",
ServerPort: serverPort,
},
LocalAddress: []netip.Prefix{netip.MustParsePrefix("10.0.0.2/32")},
LocalAddress: []option.ListenPrefix{option.ListenPrefix(netip.MustParsePrefix("10.0.0.2/32"))},
PrivateKey: "qGnwlkZljMxeECW8fbwAWdvgntnbK7B8UmMFl3zM0mk=",
PeerPublicKey: "QsdcBm+oJw2oNv0cIFXLIq1E850lgTBonup4qnKEQBg=",
},

View File

@@ -1,9 +0,0 @@
package obfs
type Base struct {
Host string
Port int
Key []byte
IVSize int
Param string
}

View File

@@ -1,9 +0,0 @@
package obfs
func init() {
register("http_post", newHTTPPost, 0)
}
func newHTTPPost(b *Base) Obfs {
return &httpObfs{Base: b, post: true}
}

View File

@@ -1,405 +0,0 @@
package obfs
import (
"bytes"
"encoding/hex"
"io"
"math/rand"
"net"
"strconv"
"strings"
"github.com/Dreamacro/clash/common/pool"
)
func init() {
register("http_simple", newHTTPSimple, 0)
}
type httpObfs struct {
*Base
post bool
}
func newHTTPSimple(b *Base) Obfs {
return &httpObfs{Base: b}
}
type httpConn struct {
net.Conn
*httpObfs
hasSentHeader bool
hasRecvHeader bool
buf []byte
}
func (h *httpObfs) StreamConn(c net.Conn) net.Conn {
return &httpConn{Conn: c, httpObfs: h}
}
func (c *httpConn) Read(b []byte) (int, error) {
if c.buf != nil {
n := copy(b, c.buf)
if n == len(c.buf) {
c.buf = nil
} else {
c.buf = c.buf[n:]
}
return n, nil
}
if c.hasRecvHeader {
return c.Conn.Read(b)
}
buf := pool.Get(pool.RelayBufferSize)
defer pool.Put(buf)
n, err := c.Conn.Read(buf)
if err != nil {
return 0, err
}
pos := bytes.Index(buf[:n], []byte("\r\n\r\n"))
if pos == -1 {
return 0, io.EOF
}
c.hasRecvHeader = true
dataLength := n - pos - 4
n = copy(b, buf[4+pos:n])
if dataLength > n {
c.buf = append(c.buf, buf[4+pos+n:4+pos+dataLength]...)
}
return n, nil
}
func (c *httpConn) Write(b []byte) (int, error) {
if c.hasSentHeader {
return c.Conn.Write(b)
}
// 30: head length
headLength := c.IVSize + 30
bLength := len(b)
headDataLength := bLength
if bLength-headLength > 64 {
headDataLength = headLength + rand.Intn(65)
}
headData := b[:headDataLength]
b = b[headDataLength:]
var body string
host := c.Host
if len(c.Param) > 0 {
pos := strings.Index(c.Param, "#")
if pos != -1 {
body = strings.ReplaceAll(c.Param[pos+1:], "\n", "\r\n")
body = strings.ReplaceAll(body, "\\n", "\r\n")
host = c.Param[:pos]
} else {
host = c.Param
}
}
hosts := strings.Split(host, ",")
host = hosts[rand.Intn(len(hosts))]
buf := pool.GetBuffer()
defer pool.PutBuffer(buf)
if c.post {
buf.WriteString("POST /")
} else {
buf.WriteString("GET /")
}
packURLEncodedHeadData(buf, headData)
buf.WriteString(" HTTP/1.1\r\nHost: " + host)
if c.Port != 80 {
buf.WriteString(":" + strconv.Itoa(c.Port))
}
buf.WriteString("\r\n")
if len(body) > 0 {
buf.WriteString(body + "\r\n\r\n")
} else {
buf.WriteString("User-Agent: ")
buf.WriteString(userAgent[rand.Intn(len(userAgent))])
buf.WriteString("\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nAccept-Language: en-US,en;q=0.8\r\nAccept-Encoding: gzip, deflate\r\n")
if c.post {
packBoundary(buf)
}
buf.WriteString("DNT: 1\r\nConnection: keep-alive\r\n\r\n")
}
buf.Write(b)
_, err := c.Conn.Write(buf.Bytes())
if err != nil {
return 0, nil
}
c.hasSentHeader = true
return bLength, nil
}
func packURLEncodedHeadData(buf *bytes.Buffer, data []byte) {
dataLength := len(data)
for i := 0; i < dataLength; i++ {
buf.WriteRune('%')
buf.WriteString(hex.EncodeToString(data[i : i+1]))
}
}
func packBoundary(buf *bytes.Buffer) {
buf.WriteString("Content-Type: multipart/form-data; boundary=")
set := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
for i := 0; i < 32; i++ {
buf.WriteByte(set[rand.Intn(62)])
}
buf.WriteString("\r\n")
}
var userAgent = []string{
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.162 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36",
"Mozilla/5.0 (Linux; Android 7.0; Moto C Build/NRD90M.059) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Mobile Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36",
"Mozilla/5.0 (Linux; Android 6.0.1; SM-G532M Build/MMB29T; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/55.0.2883.91 Mobile Safari/537.36",
"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.111 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36",
"Mozilla/5.0 (Linux; Android 5.1.1; SM-J120M Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Mobile Safari/537.36",
"Mozilla/5.0 (Windows NT 6.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36",
"Mozilla/5.0 (Linux; Android 7.0; Moto G (5) Build/NPPS25.137-93-14) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Mobile Safari/537.36",
"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36",
"Mozilla/5.0 (Linux; Android 7.0; SM-G570M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.80 Mobile Safari/537.36",
"Mozilla/5.0 (Windows NT 5.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36",
"Mozilla/5.0 (Linux; Android 6.0; CAM-L03 Build/HUAWEICAM-L03) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Mobile Safari/537.36",
"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.76 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.117 Safari/537.36",
"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.3 (KHTML, like Gecko) Chrome/6.0.472.63 Safari/534.3",
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36",
"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.7 (KHTML, like Gecko) Chrome/7.0.517.44 Safari/534.7",
"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.75 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36",
"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.3 (KHTML, like Gecko) Chrome/6.0.472.63 Safari/534.3",
"Mozilla/5.0 (Linux; Android 8.0.0; FIG-LX3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.80 Mobile Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36",
"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/8.0.552.237 Safari/534.10",
"Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36",
"Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/533.2 (KHTML, like Gecko) Chrome/5.0.342.1 Safari/533.2",
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.110 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.89 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.81 Safari/537.36",
"Mozilla/5.0 (X11; Datanyze; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36",
"Mozilla/5.0 (Linux; Android 5.1.1; SM-J111M Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Mobile Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.120 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",
"Mozilla/5.0 (Linux; Android 6.0.1; SM-J700M Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Mobile Safari/537.36",
"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.63 Safari/537.36",
"Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.30 (KHTML, like Gecko) Slackware/Chrome/12.0.742.100 Safari/534.30",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.167 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
"Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.100 Safari/534.30",
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",
"Mozilla/5.0 (Linux; Android 8.0.0; WAS-LX3 Build/HUAWEIWAS-LX3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Mobile Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.1805 Safari/537.36 MVisionPlayer/1.0.0.0",
"Mozilla/5.0 (Linux; Android 7.0; TRT-LX3 Build/HUAWEITRT-LX3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Mobile Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.89 Safari/537.36",
"Mozilla/5.0 (Linux; Android 6.0; vivo 1610 Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.124 Mobile Safari/537.36",
"Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.111 Safari/537.36",
"Mozilla/5.0 (Linux; Android 4.4.2; de-de; SAMSUNG GT-I9195 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Version/1.5 Chrome/28.0.1500.94 Mobile Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.110 Safari/537.36",
"Mozilla/5.0 (Linux; Android 8.0.0; ANE-LX3 Build/HUAWEIANE-LX3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Mobile Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
"Mozilla/5.0 (X11; U; Linux i586; en-US) AppleWebKit/533.2 (KHTML, like Gecko) Chrome/5.0.342.1 Safari/533.2",
"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.65 Safari/537.36",
"Mozilla/5.0 (Linux; Android 7.0; SM-G610M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.80 Mobile Safari/537.36",
"Mozilla/5.0 (Linux; Android 6.0.1; SM-J500M Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Mobile Safari/537.36",
"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.7 (KHTML, like Gecko) Chrome/7.0.517.44 Safari/534.7",
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.104 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
"Mozilla/5.0 (Linux; Android 6.0; vivo 1606 Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.124 Mobile Safari/537.36",
"Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36",
"Mozilla/5.0 (Linux; Android 7.0; SM-G610M Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Mobile Safari/537.36",
"Mozilla/5.0 (Linux; Android 7.1; vivo 1716 Build/N2G47H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.98 Mobile Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.93 Safari/537.36",
"Mozilla/5.0 (Linux; Android 7.0; SM-G570M Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Mobile Safari/537.36",
"Mozilla/5.0 (Windows NT 6.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36",
"Mozilla/5.0 (Linux; Android 6.0; MYA-L22 Build/HUAWEIMYA-L22) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36",
"Mozilla/5.0 (Linux; Android 5.1; A1601 Build/LMY47I) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.98 Mobile Safari/537.36",
"Mozilla/5.0 (Linux; Android 7.0; TRT-LX2 Build/HUAWEITRT-LX2; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/59.0.3071.125 Mobile Safari/537.36",
"Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36",
"Mozilla/5.0 (Windows NT 5.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36",
"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.17 (KHTML, like Gecko) Chrome/10.0.649.0 Safari/534.17",
"Mozilla/5.0 (Linux; Android 6.0; CAM-L21 Build/HUAWEICAM-L21; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/62.0.3202.84 Mobile Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.3 Safari/534.24",
"Mozilla/5.0 (Linux; Android 7.1.2; Redmi 4X Build/N2G47H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.111 Mobile Safari/537.36",
"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36",
"Mozilla/5.0 (Linux; Android 4.4.2; SM-G7102 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36",
"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.109 Safari/537.36",
"Mozilla/5.0 (Linux; Android 5.1; HUAWEI CUN-L22 Build/HUAWEICUN-L22; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/62.0.3202.84 Mobile Safari/537.36",
"Mozilla/5.0 (Linux; Android 5.1.1; A37fw Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36",
"Mozilla/5.0 (Linux; Android 7.0; SM-J730GM Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.111 Mobile Safari/537.36",
"Mozilla/5.0 (Linux; Android 7.0; SM-G610F Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.111 Mobile Safari/537.36",
"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36",
"Mozilla/5.0 (Linux; Android 7.1.2; Redmi Note 5A Build/N2G47H; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/63.0.3239.111 Mobile Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36",
"Mozilla/5.0 (Linux; Android 7.0; Redmi Note 4 Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.111 Mobile Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36",
"Mozilla/5.0 (Unknown; Linux) AppleWebKit/538.1 (KHTML, like Gecko) Chrome/v1.0.0 Safari/538.1",
"Mozilla/5.0 (Linux; Android 7.0; BLL-L22 Build/HUAWEIBLL-L22) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"Mozilla/5.0 (Linux; Android 7.0; SM-J710F Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36",
"Mozilla/5.0 (Linux; Android 6.0.1; SM-G532M Build/MMB29T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36",
"Mozilla/5.0 (Linux; Android 7.1.1; CPH1723 Build/N6F26Q) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.98 Mobile Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.94 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36",
"Mozilla/5.0 (Linux; Android 8.0.0; FIG-LX3 Build/HUAWEIFIG-LX3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Mobile Safari/537.36",
"Mozilla/5.0 (Windows; U; Windows NT 6.1; de-DE) AppleWebKit/534.17 (KHTML, like Gecko) Chrome/10.0.649.0 Safari/534.17",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.63 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.65 Safari/537.36",
"Mozilla/5.0 (Linux; Android 7.1; Mi A1 Build/N2G47H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.83 Mobile Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.117 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36",
"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.99 Safari/533.4",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.89 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.111 Safari/537.36 MVisionPlayer/1.0.0.0",
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36",
"Mozilla/5.0 (Linux; Android 5.1; A37f Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.93 Mobile Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.76 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36",
"Mozilla/5.0 (Windows NT 5.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36",
"Mozilla/5.0 (Linux; Android 6.0.1; CPH1607 Build/MMB29M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/63.0.3239.111 Mobile Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36",
"Mozilla/5.0 (Linux; Android 6.0.1; vivo 1603 Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.83 Mobile Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36",
"Mozilla/5.0 (Linux; Android 6.0.1; SM-G532M Build/MMB29T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Mobile Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36",
"Mozilla/5.0 (Linux; Android 6.0.1; Redmi 4A Build/MMB29M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/60.0.3112.116 Mobile Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36",
"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.71 Safari/537.36",
"Mozilla/5.0 (Windows NT 5.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.31",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36",
"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",
"Mozilla/5.0 (Linux; Android 6.0.1; SM-G532G Build/MMB29T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.83 Mobile Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.109 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.117 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.131 Safari/537.36",
"Mozilla/5.0 (Linux; Android 6.0; vivo 1713 Build/MRA58K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.124 Mobile Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.89 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36",
}

View File

@@ -1,42 +0,0 @@
package obfs
import (
"errors"
"fmt"
"net"
)
var (
errTLS12TicketAuthIncorrectMagicNumber = errors.New("tls1.2_ticket_auth incorrect magic number")
errTLS12TicketAuthTooShortData = errors.New("tls1.2_ticket_auth too short data")
errTLS12TicketAuthHMACError = errors.New("tls1.2_ticket_auth hmac verifying failed")
)
type authData struct {
clientID [32]byte
}
type Obfs interface {
StreamConn(net.Conn) net.Conn
}
type obfsCreator func(b *Base) Obfs
var obfsList = make(map[string]struct {
overhead int
new obfsCreator
})
func register(name string, c obfsCreator, o int) {
obfsList[name] = struct {
overhead int
new obfsCreator
}{overhead: o, new: c}
}
func PickObfs(name string, b *Base) (Obfs, int, error) {
if choice, ok := obfsList[name]; ok {
return choice.new(b), choice.overhead, nil
}
return nil, 0, fmt.Errorf("Obfs %s not supported", name)
}

View File

@@ -1,15 +0,0 @@
package obfs
import "net"
type plain struct{}
func init() {
register("plain", newPlain, 0)
}
func newPlain(b *Base) Obfs {
return &plain{}
}
func (p *plain) StreamConn(c net.Conn) net.Conn { return c }

View File

@@ -1,71 +0,0 @@
package obfs
import (
"encoding/binary"
"hash/crc32"
"math/rand"
"net"
"github.com/Dreamacro/clash/common/pool"
)
func init() {
register("random_head", newRandomHead, 0)
}
type randomHead struct {
*Base
}
func newRandomHead(b *Base) Obfs {
return &randomHead{Base: b}
}
type randomHeadConn struct {
net.Conn
*randomHead
hasSentHeader bool
rawTransSent bool
rawTransRecv bool
buf []byte
}
func (r *randomHead) StreamConn(c net.Conn) net.Conn {
return &randomHeadConn{Conn: c, randomHead: r}
}
func (c *randomHeadConn) Read(b []byte) (int, error) {
if c.rawTransRecv {
return c.Conn.Read(b)
}
buf := pool.Get(pool.RelayBufferSize)
defer pool.Put(buf)
c.Conn.Read(buf)
c.rawTransRecv = true
c.Write(nil)
return 0, nil
}
func (c *randomHeadConn) Write(b []byte) (int, error) {
if c.rawTransSent {
return c.Conn.Write(b)
}
c.buf = append(c.buf, b...)
if !c.hasSentHeader {
c.hasSentHeader = true
dataLength := rand.Intn(96) + 4
buf := pool.Get(dataLength + 4)
defer pool.Put(buf)
rand.Read(buf[:dataLength])
binary.LittleEndian.PutUint32(buf[dataLength:], 0xffffffff-crc32.ChecksumIEEE(buf[:dataLength]))
_, err := c.Conn.Write(buf)
return len(b), err
}
if c.rawTransRecv {
_, err := c.Conn.Write(c.buf)
c.buf = nil
c.rawTransSent = true
return len(b), err
}
return len(b), nil
}

View File

@@ -1,226 +0,0 @@
package obfs
import (
"bytes"
"crypto/hmac"
"encoding/binary"
"math/rand"
"net"
"strings"
"time"
"github.com/Dreamacro/clash/common/pool"
"github.com/Dreamacro/clash/transport/ssr/tools"
)
func init() {
register("tls1.2_ticket_auth", newTLS12Ticket, 5)
register("tls1.2_ticket_fastauth", newTLS12Ticket, 5)
}
type tls12Ticket struct {
*Base
*authData
}
func newTLS12Ticket(b *Base) Obfs {
r := &tls12Ticket{Base: b, authData: &authData{}}
rand.Read(r.clientID[:])
return r
}
type tls12TicketConn struct {
net.Conn
*tls12Ticket
handshakeStatus int
decoded bytes.Buffer
underDecoded bytes.Buffer
sendBuf bytes.Buffer
}
func (t *tls12Ticket) StreamConn(c net.Conn) net.Conn {
return &tls12TicketConn{Conn: c, tls12Ticket: t}
}
func (c *tls12TicketConn) Read(b []byte) (int, error) {
if c.decoded.Len() > 0 {
return c.decoded.Read(b)
}
buf := pool.Get(pool.RelayBufferSize)
defer pool.Put(buf)
n, err := c.Conn.Read(buf)
if err != nil {
return 0, err
}
if c.handshakeStatus == 8 {
c.underDecoded.Write(buf[:n])
for c.underDecoded.Len() > 5 {
if !bytes.Equal(c.underDecoded.Bytes()[:3], []byte{0x17, 3, 3}) {
c.underDecoded.Reset()
return 0, errTLS12TicketAuthIncorrectMagicNumber
}
size := int(binary.BigEndian.Uint16(c.underDecoded.Bytes()[3:5]))
if c.underDecoded.Len() < 5+size {
break
}
c.underDecoded.Next(5)
c.decoded.Write(c.underDecoded.Next(size))
}
n, _ = c.decoded.Read(b)
return n, nil
}
if n < 11+32+1+32 {
return 0, errTLS12TicketAuthTooShortData
}
if !hmac.Equal(buf[33:43], c.hmacSHA1(buf[11:33])[:10]) || !hmac.Equal(buf[n-10:n], c.hmacSHA1(buf[:n-10])[:10]) {
return 0, errTLS12TicketAuthHMACError
}
c.Write(nil)
return 0, nil
}
func (c *tls12TicketConn) Write(b []byte) (int, error) {
length := len(b)
if c.handshakeStatus == 8 {
buf := pool.GetBuffer()
defer pool.PutBuffer(buf)
for len(b) > 2048 {
size := rand.Intn(4096) + 100
if len(b) < size {
size = len(b)
}
packData(buf, b[:size])
b = b[size:]
}
if len(b) > 0 {
packData(buf, b)
}
_, err := c.Conn.Write(buf.Bytes())
if err != nil {
return 0, err
}
return length, nil
}
if len(b) > 0 {
packData(&c.sendBuf, b)
}
if c.handshakeStatus == 0 {
c.handshakeStatus = 1
data := pool.GetBuffer()
defer pool.PutBuffer(data)
data.Write([]byte{3, 3})
c.packAuthData(data)
data.WriteByte(0x20)
data.Write(c.clientID[:])
data.Write([]byte{0x00, 0x1c, 0xc0, 0x2b, 0xc0, 0x2f, 0xcc, 0xa9, 0xcc, 0xa8, 0xcc, 0x14, 0xcc, 0x13, 0xc0, 0x0a, 0xc0, 0x14, 0xc0, 0x09, 0xc0, 0x13, 0x00, 0x9c, 0x00, 0x35, 0x00, 0x2f, 0x00, 0x0a})
data.Write([]byte{0x1, 0x0})
ext := pool.GetBuffer()
defer pool.PutBuffer(ext)
host := c.getHost()
ext.Write([]byte{0xff, 0x01, 0x00, 0x01, 0x00})
packSNIData(ext, host)
ext.Write([]byte{0, 0x17, 0, 0})
c.packTicketBuf(ext, host)
ext.Write([]byte{0x00, 0x0d, 0x00, 0x16, 0x00, 0x14, 0x06, 0x01, 0x06, 0x03, 0x05, 0x01, 0x05, 0x03, 0x04, 0x01, 0x04, 0x03, 0x03, 0x01, 0x03, 0x03, 0x02, 0x01, 0x02, 0x03})
ext.Write([]byte{0x00, 0x05, 0x00, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00})
ext.Write([]byte{0x00, 0x12, 0x00, 0x00})
ext.Write([]byte{0x75, 0x50, 0x00, 0x00})
ext.Write([]byte{0x00, 0x0b, 0x00, 0x02, 0x01, 0x00})
ext.Write([]byte{0x00, 0x0a, 0x00, 0x06, 0x00, 0x04, 0x00, 0x17, 0x00, 0x18})
binary.Write(data, binary.BigEndian, uint16(ext.Len()))
data.ReadFrom(ext)
ret := pool.GetBuffer()
defer pool.PutBuffer(ret)
ret.Write([]byte{0x16, 3, 1})
binary.Write(ret, binary.BigEndian, uint16(data.Len()+4))
ret.Write([]byte{1, 0})
binary.Write(ret, binary.BigEndian, uint16(data.Len()))
ret.ReadFrom(data)
_, err := c.Conn.Write(ret.Bytes())
if err != nil {
return 0, err
}
return length, nil
} else if c.handshakeStatus == 1 && len(b) == 0 {
buf := pool.GetBuffer()
defer pool.PutBuffer(buf)
buf.Write([]byte{0x14, 3, 3, 0, 1, 1, 0x16, 3, 3, 0, 0x20})
tools.AppendRandBytes(buf, 22)
buf.Write(c.hmacSHA1(buf.Bytes())[:10])
buf.ReadFrom(&c.sendBuf)
c.handshakeStatus = 8
_, err := c.Conn.Write(buf.Bytes())
return 0, err
}
return length, nil
}
func packData(buf *bytes.Buffer, data []byte) {
buf.Write([]byte{0x17, 3, 3})
binary.Write(buf, binary.BigEndian, uint16(len(data)))
buf.Write(data)
}
func (t *tls12Ticket) packAuthData(buf *bytes.Buffer) {
binary.Write(buf, binary.BigEndian, uint32(time.Now().Unix()))
tools.AppendRandBytes(buf, 18)
buf.Write(t.hmacSHA1(buf.Bytes()[buf.Len()-22:])[:10])
}
func packSNIData(buf *bytes.Buffer, u string) {
len := uint16(len(u))
buf.Write([]byte{0, 0})
binary.Write(buf, binary.BigEndian, len+5)
binary.Write(buf, binary.BigEndian, len+3)
buf.WriteByte(0)
binary.Write(buf, binary.BigEndian, len)
buf.WriteString(u)
}
func (c *tls12TicketConn) packTicketBuf(buf *bytes.Buffer, u string) {
length := 16 * (rand.Intn(17) + 8)
buf.Write([]byte{0, 0x23})
binary.Write(buf, binary.BigEndian, uint16(length))
tools.AppendRandBytes(buf, length)
}
func (t *tls12Ticket) hmacSHA1(data []byte) []byte {
key := pool.Get(len(t.Key) + 32)
defer pool.Put(key)
copy(key, t.Key)
copy(key[len(t.Key):], t.clientID[:])
sha1Data := tools.HmacSHA1(key, data)
return sha1Data[:10]
}
func (t *tls12Ticket) getHost() string {
host := t.Param
if len(host) == 0 {
host = t.Host
}
if len(host) > 0 && host[len(host)-1] >= '0' && host[len(host)-1] <= '9' {
host = ""
}
hosts := strings.Split(host, ",")
host = hosts[rand.Intn(len(hosts))]
return host
}

View File

@@ -1,18 +0,0 @@
package protocol
import "github.com/Dreamacro/clash/transport/ssr/tools"
func init() {
register("auth_aes128_md5", newAuthAES128MD5, 9)
}
func newAuthAES128MD5(b *Base) Protocol {
a := &authAES128{
Base: b,
authData: &authData{},
authAES128Function: &authAES128Function{salt: "auth_aes128_md5", hmac: tools.HmacMD5, hashDigest: tools.MD5Sum},
userData: &userData{},
}
a.initUserData()
return a
}

View File

@@ -1,277 +0,0 @@
package protocol
import (
"bytes"
"encoding/binary"
"math"
"math/rand"
"net"
"strconv"
"strings"
"github.com/Dreamacro/clash/common/pool"
"github.com/Dreamacro/clash/transport/ssr/tools"
)
type (
hmacMethod func(key, data []byte) []byte
hashDigestMethod func([]byte) []byte
)
func init() {
register("auth_aes128_sha1", newAuthAES128SHA1, 9)
}
type authAES128Function struct {
salt string
hmac hmacMethod
hashDigest hashDigestMethod
}
type authAES128 struct {
*Base
*authData
*authAES128Function
*userData
iv []byte
hasSentHeader bool
rawTrans bool
packID uint32
recvID uint32
}
func newAuthAES128SHA1(b *Base) Protocol {
a := &authAES128{
Base: b,
authData: &authData{},
authAES128Function: &authAES128Function{salt: "auth_aes128_sha1", hmac: tools.HmacSHA1, hashDigest: tools.SHA1Sum},
userData: &userData{},
}
a.initUserData()
return a
}
func (a *authAES128) initUserData() {
params := strings.Split(a.Param, ":")
if len(params) > 1 {
if userID, err := strconv.ParseUint(params[0], 10, 32); err == nil {
binary.LittleEndian.PutUint32(a.userID[:], uint32(userID))
a.userKey = a.hashDigest([]byte(params[1]))
}
}
if len(a.userKey) == 0 {
a.userKey = a.Key
rand.Read(a.userID[:])
}
}
func (a *authAES128) StreamConn(c net.Conn, iv []byte) net.Conn {
p := &authAES128{
Base: a.Base,
authData: a.next(),
authAES128Function: a.authAES128Function,
userData: a.userData,
packID: 1,
recvID: 1,
}
p.iv = iv
return &Conn{Conn: c, Protocol: p}
}
func (a *authAES128) PacketConn(c net.PacketConn) net.PacketConn {
p := &authAES128{
Base: a.Base,
authAES128Function: a.authAES128Function,
userData: a.userData,
}
return &PacketConn{PacketConn: c, Protocol: p}
}
func (a *authAES128) Decode(dst, src *bytes.Buffer) error {
if a.rawTrans {
dst.ReadFrom(src)
return nil
}
for src.Len() > 4 {
macKey := pool.Get(len(a.userKey) + 4)
defer pool.Put(macKey)
copy(macKey, a.userKey)
binary.LittleEndian.PutUint32(macKey[len(a.userKey):], a.recvID)
if !bytes.Equal(a.hmac(macKey, src.Bytes()[:2])[:2], src.Bytes()[2:4]) {
src.Reset()
return errAuthAES128MACError
}
length := int(binary.LittleEndian.Uint16(src.Bytes()[:2]))
if length >= 8192 || length < 7 {
a.rawTrans = true
src.Reset()
return errAuthAES128LengthError
}
if length > src.Len() {
break
}
if !bytes.Equal(a.hmac(macKey, src.Bytes()[:length-4])[:4], src.Bytes()[length-4:length]) {
a.rawTrans = true
src.Reset()
return errAuthAES128ChksumError
}
a.recvID++
pos := int(src.Bytes()[4])
if pos < 255 {
pos += 4
} else {
pos = int(binary.LittleEndian.Uint16(src.Bytes()[5:7])) + 4
}
dst.Write(src.Bytes()[pos : length-4])
src.Next(length)
}
return nil
}
func (a *authAES128) Encode(buf *bytes.Buffer, b []byte) error {
fullDataLength := len(b)
if !a.hasSentHeader {
dataLength := getDataLength(b)
a.packAuthData(buf, b[:dataLength])
b = b[dataLength:]
a.hasSentHeader = true
}
for len(b) > 8100 {
a.packData(buf, b[:8100], fullDataLength)
b = b[8100:]
}
if len(b) > 0 {
a.packData(buf, b, fullDataLength)
}
return nil
}
func (a *authAES128) DecodePacket(b []byte) ([]byte, error) {
if len(b) < 4 {
return nil, errAuthAES128LengthError
}
if !bytes.Equal(a.hmac(a.Key, b[:len(b)-4])[:4], b[len(b)-4:]) {
return nil, errAuthAES128ChksumError
}
return b[:len(b)-4], nil
}
func (a *authAES128) EncodePacket(buf *bytes.Buffer, b []byte) error {
buf.Write(b)
buf.Write(a.userID[:])
buf.Write(a.hmac(a.userKey, buf.Bytes())[:4])
return nil
}
func (a *authAES128) packData(poolBuf *bytes.Buffer, data []byte, fullDataLength int) {
dataLength := len(data)
randDataLength := a.getRandDataLengthForPackData(dataLength, fullDataLength)
/*
2: uint16 LittleEndian packedDataLength
2: hmac of packedDataLength
3: maxRandDataLengthPrefix (min:1)
4: hmac of packedData except the last 4 bytes
*/
packedDataLength := 2 + 2 + 3 + randDataLength + dataLength + 4
if randDataLength < 128 {
packedDataLength -= 2
}
macKey := pool.Get(len(a.userKey) + 4)
defer pool.Put(macKey)
copy(macKey, a.userKey)
binary.LittleEndian.PutUint32(macKey[len(a.userKey):], a.packID)
a.packID++
binary.Write(poolBuf, binary.LittleEndian, uint16(packedDataLength))
poolBuf.Write(a.hmac(macKey, poolBuf.Bytes()[poolBuf.Len()-2:])[:2])
a.packRandData(poolBuf, randDataLength)
poolBuf.Write(data)
poolBuf.Write(a.hmac(macKey, poolBuf.Bytes()[poolBuf.Len()-packedDataLength+4:])[:4])
}
func trapezoidRandom(max int, d float64) int {
base := rand.Float64()
if d-0 > 1e-6 {
a := 1 - d
base = (math.Sqrt(a*a+4*d*base) - a) / (2 * d)
}
return int(base * float64(max))
}
func (a *authAES128) getRandDataLengthForPackData(dataLength, fullDataLength int) int {
if fullDataLength >= 32*1024-a.Overhead {
return 0
}
// 1460: tcp_mss
revLength := 1460 - dataLength - 9
if revLength == 0 {
return 0
}
if revLength < 0 {
if revLength > -1460 {
return trapezoidRandom(revLength+1460, -0.3)
}
return rand.Intn(32)
}
if dataLength > 900 {
return rand.Intn(revLength)
}
return trapezoidRandom(revLength, -0.3)
}
func (a *authAES128) packAuthData(poolBuf *bytes.Buffer, data []byte) {
if len(data) == 0 {
return
}
dataLength := len(data)
randDataLength := a.getRandDataLengthForPackAuthData(dataLength)
/*
7: checkHead(1) and hmac of checkHead(6)
4: userID
16: encrypted data of authdata(12), uint16 BigEndian packedDataLength(2) and uint16 BigEndian randDataLength(2)
4: hmac of userID and encrypted data
4: hmac of packedAuthData except the last 4 bytes
*/
packedAuthDataLength := 7 + 4 + 16 + 4 + randDataLength + dataLength + 4
macKey := pool.Get(len(a.iv) + len(a.Key))
defer pool.Put(macKey)
copy(macKey, a.iv)
copy(macKey[len(a.iv):], a.Key)
poolBuf.WriteByte(byte(rand.Intn(256)))
poolBuf.Write(a.hmac(macKey, poolBuf.Bytes())[:6])
poolBuf.Write(a.userID[:])
err := a.authData.putEncryptedData(poolBuf, a.userKey, [2]int{packedAuthDataLength, randDataLength}, a.salt)
if err != nil {
poolBuf.Reset()
return
}
poolBuf.Write(a.hmac(macKey, poolBuf.Bytes()[7:])[:4])
tools.AppendRandBytes(poolBuf, randDataLength)
poolBuf.Write(data)
poolBuf.Write(a.hmac(a.userKey, poolBuf.Bytes())[:4])
}
func (a *authAES128) getRandDataLengthForPackAuthData(size int) int {
if size > 400 {
return rand.Intn(512)
}
return rand.Intn(1024)
}
func (a *authAES128) packRandData(poolBuf *bytes.Buffer, size int) {
if size < 128 {
poolBuf.WriteByte(byte(size + 1))
tools.AppendRandBytes(poolBuf, size)
return
}
poolBuf.WriteByte(255)
binary.Write(poolBuf, binary.LittleEndian, uint16(size+3))
tools.AppendRandBytes(poolBuf, size)
}

View File

@@ -1,306 +0,0 @@
package protocol
import (
"bytes"
"crypto/cipher"
"crypto/rand"
"crypto/rc4"
"encoding/base64"
"encoding/binary"
"net"
"strconv"
"strings"
"github.com/Dreamacro/clash/common/pool"
"github.com/Dreamacro/clash/transport/shadowsocks/core"
"github.com/Dreamacro/clash/transport/ssr/tools"
)
func init() {
register("auth_chain_a", newAuthChainA, 4)
}
type randDataLengthMethod func(int, []byte, *tools.XorShift128Plus) int
type authChainA struct {
*Base
*authData
*userData
iv []byte
salt string
hasSentHeader bool
rawTrans bool
lastClientHash []byte
lastServerHash []byte
encrypter cipher.Stream
decrypter cipher.Stream
randomClient tools.XorShift128Plus
randomServer tools.XorShift128Plus
randDataLength randDataLengthMethod
packID uint32
recvID uint32
}
func newAuthChainA(b *Base) Protocol {
a := &authChainA{
Base: b,
authData: &authData{},
userData: &userData{},
salt: "auth_chain_a",
}
a.initUserData()
return a
}
func (a *authChainA) initUserData() {
params := strings.Split(a.Param, ":")
if len(params) > 1 {
if userID, err := strconv.ParseUint(params[0], 10, 32); err == nil {
binary.LittleEndian.PutUint32(a.userID[:], uint32(userID))
a.userKey = []byte(params[1])
}
}
if len(a.userKey) == 0 {
a.userKey = a.Key
rand.Read(a.userID[:])
}
}
func (a *authChainA) StreamConn(c net.Conn, iv []byte) net.Conn {
p := &authChainA{
Base: a.Base,
authData: a.next(),
userData: a.userData,
salt: a.salt,
packID: 1,
recvID: 1,
}
p.iv = iv
p.randDataLength = p.getRandLength
return &Conn{Conn: c, Protocol: p}
}
func (a *authChainA) PacketConn(c net.PacketConn) net.PacketConn {
p := &authChainA{
Base: a.Base,
salt: a.salt,
userData: a.userData,
}
return &PacketConn{PacketConn: c, Protocol: p}
}
func (a *authChainA) Decode(dst, src *bytes.Buffer) error {
if a.rawTrans {
dst.ReadFrom(src)
return nil
}
for src.Len() > 4 {
macKey := pool.Get(len(a.userKey) + 4)
defer pool.Put(macKey)
copy(macKey, a.userKey)
binary.LittleEndian.PutUint32(macKey[len(a.userKey):], a.recvID)
dataLength := int(binary.LittleEndian.Uint16(src.Bytes()[:2]) ^ binary.LittleEndian.Uint16(a.lastServerHash[14:16]))
randDataLength := a.randDataLength(dataLength, a.lastServerHash, &a.randomServer)
length := dataLength + randDataLength
if length >= 4096 {
a.rawTrans = true
src.Reset()
return errAuthChainLengthError
}
if 4+length > src.Len() {
break
}
serverHash := tools.HmacMD5(macKey, src.Bytes()[:length+2])
if !bytes.Equal(serverHash[:2], src.Bytes()[length+2:length+4]) {
a.rawTrans = true
src.Reset()
return errAuthChainChksumError
}
a.lastServerHash = serverHash
pos := 2
if dataLength > 0 && randDataLength > 0 {
pos += getRandStartPos(randDataLength, &a.randomServer)
}
wantedData := src.Bytes()[pos : pos+dataLength]
a.decrypter.XORKeyStream(wantedData, wantedData)
if a.recvID == 1 {
dst.Write(wantedData[2:])
} else {
dst.Write(wantedData)
}
a.recvID++
src.Next(length + 4)
}
return nil
}
func (a *authChainA) Encode(buf *bytes.Buffer, b []byte) error {
if !a.hasSentHeader {
dataLength := getDataLength(b)
a.packAuthData(buf, b[:dataLength])
b = b[dataLength:]
a.hasSentHeader = true
}
for len(b) > 2800 {
a.packData(buf, b[:2800])
b = b[2800:]
}
if len(b) > 0 {
a.packData(buf, b)
}
return nil
}
func (a *authChainA) DecodePacket(b []byte) ([]byte, error) {
if len(b) < 9 {
return nil, errAuthChainLengthError
}
if !bytes.Equal(tools.HmacMD5(a.userKey, b[:len(b)-1])[:1], b[len(b)-1:]) {
return nil, errAuthChainChksumError
}
md5Data := tools.HmacMD5(a.Key, b[len(b)-8:len(b)-1])
randDataLength := udpGetRandLength(md5Data, &a.randomServer)
key := core.Kdf(base64.StdEncoding.EncodeToString(a.userKey)+base64.StdEncoding.EncodeToString(md5Data), 16)
rc4Cipher, err := rc4.NewCipher(key)
if err != nil {
return nil, err
}
wantedData := b[:len(b)-8-randDataLength]
rc4Cipher.XORKeyStream(wantedData, wantedData)
return wantedData, nil
}
func (a *authChainA) EncodePacket(buf *bytes.Buffer, b []byte) error {
authData := pool.Get(3)
defer pool.Put(authData)
rand.Read(authData)
md5Data := tools.HmacMD5(a.Key, authData)
randDataLength := udpGetRandLength(md5Data, &a.randomClient)
key := core.Kdf(base64.StdEncoding.EncodeToString(a.userKey)+base64.StdEncoding.EncodeToString(md5Data), 16)
rc4Cipher, err := rc4.NewCipher(key)
if err != nil {
return err
}
rc4Cipher.XORKeyStream(b, b)
buf.Write(b)
tools.AppendRandBytes(buf, randDataLength)
buf.Write(authData)
binary.Write(buf, binary.LittleEndian, binary.LittleEndian.Uint32(a.userID[:])^binary.LittleEndian.Uint32(md5Data[:4]))
buf.Write(tools.HmacMD5(a.userKey, buf.Bytes())[:1])
return nil
}
func (a *authChainA) packAuthData(poolBuf *bytes.Buffer, data []byte) {
/*
dataLength := len(data)
12: checkHead(4) and hmac of checkHead(8)
4: uint32 LittleEndian uid (uid = userID ^ last client hash)
16: encrypted data of authdata(12), uint16 LittleEndian overhead(2) and uint16 LittleEndian number zero(2)
4: last server hash(4)
packedAuthDataLength := 12 + 4 + 16 + 4 + dataLength
*/
macKey := pool.Get(len(a.iv) + len(a.Key))
defer pool.Put(macKey)
copy(macKey, a.iv)
copy(macKey[len(a.iv):], a.Key)
// check head
tools.AppendRandBytes(poolBuf, 4)
a.lastClientHash = tools.HmacMD5(macKey, poolBuf.Bytes())
a.initRC4Cipher()
poolBuf.Write(a.lastClientHash[:8])
// uid
binary.Write(poolBuf, binary.LittleEndian, binary.LittleEndian.Uint32(a.userID[:])^binary.LittleEndian.Uint32(a.lastClientHash[8:12]))
// encrypted data
err := a.putEncryptedData(poolBuf, a.userKey, [2]int{a.Overhead, 0}, a.salt)
if err != nil {
poolBuf.Reset()
return
}
// last server hash
a.lastServerHash = tools.HmacMD5(a.userKey, poolBuf.Bytes()[12:])
poolBuf.Write(a.lastServerHash[:4])
// packed data
a.packData(poolBuf, data)
}
func (a *authChainA) packData(poolBuf *bytes.Buffer, data []byte) {
a.encrypter.XORKeyStream(data, data)
macKey := pool.Get(len(a.userKey) + 4)
defer pool.Put(macKey)
copy(macKey, a.userKey)
binary.LittleEndian.PutUint32(macKey[len(a.userKey):], a.packID)
a.packID++
length := uint16(len(data)) ^ binary.LittleEndian.Uint16(a.lastClientHash[14:16])
originalLength := poolBuf.Len()
binary.Write(poolBuf, binary.LittleEndian, length)
a.putMixedRandDataAndData(poolBuf, data)
a.lastClientHash = tools.HmacMD5(macKey, poolBuf.Bytes()[originalLength:])
poolBuf.Write(a.lastClientHash[:2])
}
func (a *authChainA) putMixedRandDataAndData(poolBuf *bytes.Buffer, data []byte) {
randDataLength := a.randDataLength(len(data), a.lastClientHash, &a.randomClient)
if len(data) == 0 {
tools.AppendRandBytes(poolBuf, randDataLength)
return
}
if randDataLength > 0 {
startPos := getRandStartPos(randDataLength, &a.randomClient)
tools.AppendRandBytes(poolBuf, startPos)
poolBuf.Write(data)
tools.AppendRandBytes(poolBuf, randDataLength-startPos)
return
}
poolBuf.Write(data)
}
func getRandStartPos(length int, random *tools.XorShift128Plus) int {
if length == 0 {
return 0
}
return int(int64(random.Next()%8589934609) % int64(length))
}
func (a *authChainA) getRandLength(length int, lastHash []byte, random *tools.XorShift128Plus) int {
if length > 1440 {
return 0
}
random.InitFromBinAndLength(lastHash, length)
if length > 1300 {
return int(random.Next() % 31)
}
if length > 900 {
return int(random.Next() % 127)
}
if length > 400 {
return int(random.Next() % 521)
}
return int(random.Next() % 1021)
}
func (a *authChainA) initRC4Cipher() {
key := core.Kdf(base64.StdEncoding.EncodeToString(a.userKey)+base64.StdEncoding.EncodeToString(a.lastClientHash), 16)
a.encrypter, _ = rc4.NewCipher(key)
a.decrypter, _ = rc4.NewCipher(key)
}
func udpGetRandLength(lastHash []byte, random *tools.XorShift128Plus) int {
random.InitFromBin(lastHash)
return int(random.Next() % 127)
}

View File

@@ -1,97 +0,0 @@
package protocol
import (
"net"
"sort"
"github.com/Dreamacro/clash/transport/ssr/tools"
)
func init() {
register("auth_chain_b", newAuthChainB, 4)
}
type authChainB struct {
*authChainA
dataSizeList []int
dataSizeList2 []int
}
func newAuthChainB(b *Base) Protocol {
a := &authChainB{
authChainA: &authChainA{
Base: b,
authData: &authData{},
userData: &userData{},
salt: "auth_chain_b",
},
}
a.initUserData()
return a
}
func (a *authChainB) StreamConn(c net.Conn, iv []byte) net.Conn {
p := &authChainB{
authChainA: &authChainA{
Base: a.Base,
authData: a.next(),
userData: a.userData,
salt: a.salt,
packID: 1,
recvID: 1,
},
}
p.iv = iv
p.randDataLength = p.getRandLength
p.initDataSize()
return &Conn{Conn: c, Protocol: p}
}
func (a *authChainB) initDataSize() {
a.dataSizeList = a.dataSizeList[:0]
a.dataSizeList2 = a.dataSizeList2[:0]
a.randomServer.InitFromBin(a.Key)
length := a.randomServer.Next()%8 + 4
for ; length > 0; length-- {
a.dataSizeList = append(a.dataSizeList, int(a.randomServer.Next()%2340%2040%1440))
}
sort.Ints(a.dataSizeList)
length = a.randomServer.Next()%16 + 8
for ; length > 0; length-- {
a.dataSizeList2 = append(a.dataSizeList2, int(a.randomServer.Next()%2340%2040%1440))
}
sort.Ints(a.dataSizeList2)
}
func (a *authChainB) getRandLength(length int, lashHash []byte, random *tools.XorShift128Plus) int {
if length >= 1440 {
return 0
}
random.InitFromBinAndLength(lashHash, length)
pos := sort.Search(len(a.dataSizeList), func(i int) bool { return a.dataSizeList[i] >= length+a.Overhead })
finalPos := pos + int(random.Next()%uint64(len(a.dataSizeList)))
if finalPos < len(a.dataSizeList) {
return a.dataSizeList[finalPos] - length - a.Overhead
}
pos = sort.Search(len(a.dataSizeList2), func(i int) bool { return a.dataSizeList2[i] >= length+a.Overhead })
finalPos = pos + int(random.Next()%uint64(len(a.dataSizeList2)))
if finalPos < len(a.dataSizeList2) {
return a.dataSizeList2[finalPos] - length - a.Overhead
}
if finalPos < pos+len(a.dataSizeList2)-1 {
return 0
}
if length > 1300 {
return int(random.Next() % 31)
}
if length > 900 {
return int(random.Next() % 127)
}
if length > 400 {
return int(random.Next() % 521)
}
return int(random.Next() % 1021)
}

View File

@@ -1,182 +0,0 @@
package protocol
import (
"bytes"
"encoding/binary"
"hash/adler32"
"hash/crc32"
"math/rand"
"net"
"github.com/Dreamacro/clash/common/pool"
"github.com/Dreamacro/clash/transport/ssr/tools"
)
func init() {
register("auth_sha1_v4", newAuthSHA1V4, 7)
}
type authSHA1V4 struct {
*Base
*authData
iv []byte
hasSentHeader bool
rawTrans bool
}
func newAuthSHA1V4(b *Base) Protocol {
return &authSHA1V4{Base: b, authData: &authData{}}
}
func (a *authSHA1V4) StreamConn(c net.Conn, iv []byte) net.Conn {
p := &authSHA1V4{Base: a.Base, authData: a.next()}
p.iv = iv
return &Conn{Conn: c, Protocol: p}
}
func (a *authSHA1V4) PacketConn(c net.PacketConn) net.PacketConn {
return c
}
func (a *authSHA1V4) Decode(dst, src *bytes.Buffer) error {
if a.rawTrans {
dst.ReadFrom(src)
return nil
}
for src.Len() > 4 {
if uint16(crc32.ChecksumIEEE(src.Bytes()[:2])&0xffff) != binary.LittleEndian.Uint16(src.Bytes()[2:4]) {
src.Reset()
return errAuthSHA1V4CRC32Error
}
length := int(binary.BigEndian.Uint16(src.Bytes()[:2]))
if length >= 8192 || length < 7 {
a.rawTrans = true
src.Reset()
return errAuthSHA1V4LengthError
}
if length > src.Len() {
break
}
if adler32.Checksum(src.Bytes()[:length-4]) != binary.LittleEndian.Uint32(src.Bytes()[length-4:length]) {
a.rawTrans = true
src.Reset()
return errAuthSHA1V4Adler32Error
}
pos := int(src.Bytes()[4])
if pos < 255 {
pos += 4
} else {
pos = int(binary.BigEndian.Uint16(src.Bytes()[5:7])) + 4
}
dst.Write(src.Bytes()[pos : length-4])
src.Next(length)
}
return nil
}
func (a *authSHA1V4) Encode(buf *bytes.Buffer, b []byte) error {
if !a.hasSentHeader {
dataLength := getDataLength(b)
a.packAuthData(buf, b[:dataLength])
b = b[dataLength:]
a.hasSentHeader = true
}
for len(b) > 8100 {
a.packData(buf, b[:8100])
b = b[8100:]
}
if len(b) > 0 {
a.packData(buf, b)
}
return nil
}
func (a *authSHA1V4) DecodePacket(b []byte) ([]byte, error) { return b, nil }
func (a *authSHA1V4) EncodePacket(buf *bytes.Buffer, b []byte) error {
buf.Write(b)
return nil
}
func (a *authSHA1V4) packData(poolBuf *bytes.Buffer, data []byte) {
dataLength := len(data)
randDataLength := a.getRandDataLength(dataLength)
/*
2: uint16 BigEndian packedDataLength
2: uint16 LittleEndian crc32Data & 0xffff
3: maxRandDataLengthPrefix (min:1)
4: adler32Data
*/
packedDataLength := 2 + 2 + 3 + randDataLength + dataLength + 4
if randDataLength < 128 {
packedDataLength -= 2
}
binary.Write(poolBuf, binary.BigEndian, uint16(packedDataLength))
binary.Write(poolBuf, binary.LittleEndian, uint16(crc32.ChecksumIEEE(poolBuf.Bytes()[poolBuf.Len()-2:])&0xffff))
a.packRandData(poolBuf, randDataLength)
poolBuf.Write(data)
binary.Write(poolBuf, binary.LittleEndian, adler32.Checksum(poolBuf.Bytes()[poolBuf.Len()-packedDataLength+4:]))
}
func (a *authSHA1V4) packAuthData(poolBuf *bytes.Buffer, data []byte) {
dataLength := len(data)
randDataLength := a.getRandDataLength(12 + dataLength)
/*
2: uint16 BigEndian packedAuthDataLength
4: uint32 LittleEndian crc32Data
3: maxRandDataLengthPrefix (min: 1)
12: authDataLength
10: hmacSHA1DataLength
*/
packedAuthDataLength := 2 + 4 + 3 + randDataLength + 12 + dataLength + 10
if randDataLength < 128 {
packedAuthDataLength -= 2
}
salt := []byte("auth_sha1_v4")
crcData := pool.Get(len(salt) + len(a.Key) + 2)
defer pool.Put(crcData)
binary.BigEndian.PutUint16(crcData, uint16(packedAuthDataLength))
copy(crcData[2:], salt)
copy(crcData[2+len(salt):], a.Key)
key := pool.Get(len(a.iv) + len(a.Key))
defer pool.Put(key)
copy(key, a.iv)
copy(key[len(a.iv):], a.Key)
poolBuf.Write(crcData[:2])
binary.Write(poolBuf, binary.LittleEndian, crc32.ChecksumIEEE(crcData))
a.packRandData(poolBuf, randDataLength)
a.putAuthData(poolBuf)
poolBuf.Write(data)
poolBuf.Write(tools.HmacSHA1(key, poolBuf.Bytes()[poolBuf.Len()-packedAuthDataLength+10:])[:10])
}
func (a *authSHA1V4) packRandData(poolBuf *bytes.Buffer, size int) {
if size < 128 {
poolBuf.WriteByte(byte(size + 1))
tools.AppendRandBytes(poolBuf, size)
return
}
poolBuf.WriteByte(255)
binary.Write(poolBuf, binary.BigEndian, uint16(size+3))
tools.AppendRandBytes(poolBuf, size)
}
func (a *authSHA1V4) getRandDataLength(size int) int {
if size > 1200 {
return 0
}
if size > 400 {
return rand.Intn(256)
}
return rand.Intn(512)
}

View File

@@ -1,75 +0,0 @@
package protocol
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"encoding/binary"
"math/rand"
"sync"
"time"
"github.com/Dreamacro/clash/common/pool"
"github.com/Dreamacro/clash/transport/shadowsocks/core"
)
type Base struct {
Key []byte
Overhead int
Param string
}
type userData struct {
userKey []byte
userID [4]byte
}
type authData struct {
clientID [4]byte
connectionID uint32
mutex sync.Mutex
}
func (a *authData) next() *authData {
r := &authData{}
a.mutex.Lock()
defer a.mutex.Unlock()
if a.connectionID > 0xff000000 || a.connectionID == 0 {
rand.Read(a.clientID[:])
a.connectionID = rand.Uint32() & 0xffffff
}
a.connectionID++
copy(r.clientID[:], a.clientID[:])
r.connectionID = a.connectionID
return r
}
func (a *authData) putAuthData(buf *bytes.Buffer) {
binary.Write(buf, binary.LittleEndian, uint32(time.Now().Unix()))
buf.Write(a.clientID[:])
binary.Write(buf, binary.LittleEndian, a.connectionID)
}
func (a *authData) putEncryptedData(b *bytes.Buffer, userKey []byte, paddings [2]int, salt string) error {
encrypt := pool.Get(16)
defer pool.Put(encrypt)
binary.LittleEndian.PutUint32(encrypt, uint32(time.Now().Unix()))
copy(encrypt[4:], a.clientID[:])
binary.LittleEndian.PutUint32(encrypt[8:], a.connectionID)
binary.LittleEndian.PutUint16(encrypt[12:], uint16(paddings[0]))
binary.LittleEndian.PutUint16(encrypt[14:], uint16(paddings[1]))
cipherKey := core.Kdf(base64.StdEncoding.EncodeToString(userKey)+salt, 16)
block, err := aes.NewCipher(cipherKey)
if err != nil {
return err
}
iv := bytes.Repeat([]byte{0}, 16)
cbcCipher := cipher.NewCBCEncrypter(block, iv)
cbcCipher.CryptBlocks(encrypt, encrypt)
b.Write(encrypt)
return nil
}

View File

@@ -1,33 +0,0 @@
package protocol
import (
"bytes"
"net"
)
type origin struct{}
func init() { register("origin", newOrigin, 0) }
func newOrigin(b *Base) Protocol { return &origin{} }
func (o *origin) StreamConn(c net.Conn, iv []byte) net.Conn { return c }
func (o *origin) PacketConn(c net.PacketConn) net.PacketConn { return c }
func (o *origin) Decode(dst, src *bytes.Buffer) error {
dst.ReadFrom(src)
return nil
}
func (o *origin) Encode(buf *bytes.Buffer, b []byte) error {
buf.Write(b)
return nil
}
func (o *origin) DecodePacket(b []byte) ([]byte, error) { return b, nil }
func (o *origin) EncodePacket(buf *bytes.Buffer, b []byte) error {
buf.Write(b)
return nil
}

View File

@@ -1,36 +0,0 @@
package protocol
import (
"net"
"github.com/Dreamacro/clash/common/pool"
)
type PacketConn struct {
net.PacketConn
Protocol
}
func (c *PacketConn) WriteTo(b []byte, addr net.Addr) (int, error) {
buf := pool.GetBuffer()
defer pool.PutBuffer(buf)
err := c.EncodePacket(buf, b)
if err != nil {
return 0, err
}
_, err = c.PacketConn.WriteTo(buf.Bytes(), addr)
return len(b), err
}
func (c *PacketConn) ReadFrom(b []byte) (int, net.Addr, error) {
n, addr, err := c.PacketConn.ReadFrom(b)
if err != nil {
return n, addr, err
}
decoded, err := c.DecodePacket(b[:n])
if err != nil {
return n, addr, err
}
copy(b, decoded)
return len(decoded), addr, nil
}

View File

@@ -1,76 +0,0 @@
package protocol
import (
"bytes"
"errors"
"fmt"
"math/rand"
"net"
)
var (
errAuthSHA1V4CRC32Error = errors.New("auth_sha1_v4 decode data wrong crc32")
errAuthSHA1V4LengthError = errors.New("auth_sha1_v4 decode data wrong length")
errAuthSHA1V4Adler32Error = errors.New("auth_sha1_v4 decode data wrong adler32")
errAuthAES128MACError = errors.New("auth_aes128 decode data wrong mac")
errAuthAES128LengthError = errors.New("auth_aes128 decode data wrong length")
errAuthAES128ChksumError = errors.New("auth_aes128 decode data wrong checksum")
errAuthChainLengthError = errors.New("auth_chain decode data wrong length")
errAuthChainChksumError = errors.New("auth_chain decode data wrong checksum")
)
type Protocol interface {
StreamConn(net.Conn, []byte) net.Conn
PacketConn(net.PacketConn) net.PacketConn
Decode(dst, src *bytes.Buffer) error
Encode(buf *bytes.Buffer, b []byte) error
DecodePacket([]byte) ([]byte, error)
EncodePacket(buf *bytes.Buffer, b []byte) error
}
type protocolCreator func(b *Base) Protocol
var protocolList = make(map[string]struct {
overhead int
new protocolCreator
})
func register(name string, c protocolCreator, o int) {
protocolList[name] = struct {
overhead int
new protocolCreator
}{overhead: o, new: c}
}
func PickProtocol(name string, b *Base) (Protocol, error) {
if choice, ok := protocolList[name]; ok {
b.Overhead += choice.overhead
return choice.new(b), nil
}
return nil, fmt.Errorf("protocol %s not supported", name)
}
func getHeadSize(b []byte, defaultValue int) int {
if len(b) < 2 {
return defaultValue
}
headType := b[0] & 7
switch headType {
case 1:
return 7
case 4:
return 19
case 3:
return 4 + int(b[1])
}
return defaultValue
}
func getDataLength(b []byte) int {
bLength := len(b)
dataLength := getHeadSize(b, 30) + rand.Intn(32)
if bLength < dataLength {
return bLength
}
return dataLength
}

View File

@@ -1,50 +0,0 @@
package protocol
import (
"bytes"
"net"
"github.com/Dreamacro/clash/common/pool"
)
type Conn struct {
net.Conn
Protocol
decoded bytes.Buffer
underDecoded bytes.Buffer
}
func (c *Conn) Read(b []byte) (int, error) {
if c.decoded.Len() > 0 {
return c.decoded.Read(b)
}
buf := pool.Get(pool.RelayBufferSize)
defer pool.Put(buf)
n, err := c.Conn.Read(buf)
if err != nil {
return 0, err
}
c.underDecoded.Write(buf[:n])
err = c.Decode(&c.decoded, &c.underDecoded)
if err != nil {
return 0, err
}
n, _ = c.decoded.Read(b)
return n, nil
}
func (c *Conn) Write(b []byte) (int, error) {
bLength := len(b)
buf := pool.GetBuffer()
defer pool.PutBuffer(buf)
err := c.Encode(buf, b)
if err != nil {
return 0, err
}
_, err = c.Conn.Write(buf.Bytes())
if err != nil {
return 0, err
}
return bLength, nil
}

View File

@@ -64,7 +64,7 @@ func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, opt
serverAddr: serverAddr,
host: options.Host,
method: options.Method,
headers: make(http.Header),
headers: options.Headers.Build(),
transport: transport,
http2: tlsConfig != nil,
}
@@ -83,9 +83,6 @@ func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, opt
if err != nil {
return nil, E.New("failed to set path: " + err.Error())
}
for key, valueList := range options.Headers {
client.headers[key] = valueList
}
client.url = &uri
return client, nil
}

View File

@@ -55,7 +55,7 @@ func NewServer(ctx context.Context, options option.V2RayHTTPOptions, tlsConfig t
host: options.Host,
path: options.Path,
method: options.Method,
headers: make(http.Header),
headers: options.Headers.Build(),
}
if server.method == "" {
server.method = "PUT"
@@ -63,9 +63,6 @@ func NewServer(ctx context.Context, options option.V2RayHTTPOptions, tlsConfig t
if !strings.HasPrefix(server.path, "/") {
server.path = "/" + server.path
}
for key, value := range options.Headers {
server.headers[key] = value
}
server.httpServer = &http.Server{
Handler: server,
ReadHeaderTimeout: C.TCPTimeout,

View File

@@ -286,6 +286,10 @@ func (ep *wireEndpoint) ARPHardwareType() header.ARPHardwareType {
func (ep *wireEndpoint) AddHeader(buffer stack.PacketBufferPtr) {
}
func (ep *wireEndpoint) ParseHeader(ptr stack.PacketBufferPtr) bool {
return true
}
func (ep *wireEndpoint) WritePackets(list stack.PacketBufferList) (int, tcpip.Error) {
for _, packetBuffer := range list.AsSlice() {
packetBuffer.IncRef()