mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-14 04:43:17 +00:00
Add user rule item
This commit is contained in:
parent
cf845d946e
commit
d1e83882e5
|
@ -21,6 +21,7 @@ type InboundContext struct {
|
||||||
Destination M.Socksaddr
|
Destination M.Socksaddr
|
||||||
Domain string
|
Domain string
|
||||||
Protocol string
|
Protocol string
|
||||||
|
User string
|
||||||
Outbound string
|
Outbound string
|
||||||
|
|
||||||
// cache
|
// cache
|
||||||
|
|
|
@ -1,111 +1,14 @@
|
||||||
package settings
|
package settings
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
F "github.com/sagernet/sing/common/format"
|
F "github.com/sagernet/sing/common/format"
|
||||||
|
"github.com/sagernet/sing/common/wininet"
|
||||||
"golang.org/x/sys/windows"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
modwininet = windows.NewLazySystemDLL("settings.dll")
|
|
||||||
procInternetSetOptionW = modwininet.NewProc("InternetSetOptionW")
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
internetOptionPerConnectionOption = 75
|
|
||||||
internetOptionSettingsChanged = 39
|
|
||||||
internetOptionRefresh = 37
|
|
||||||
internetOptionProxySettingsChanged = 95
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
internetPerConnFlags = 1
|
|
||||||
internetPerConnProxyServer = 2
|
|
||||||
internetPerConnProxyBypass = 3
|
|
||||||
internetPerConnAutoconfigUrl = 4
|
|
||||||
internetPerConnAutodiscoveryFlags = 5
|
|
||||||
internetPerConnAutoconfigSecondaryUrl = 6
|
|
||||||
internetPerConnAutoconfigReloadDelayMins = 7
|
|
||||||
internetPerConnAutoconfigLastDetectTime = 8
|
|
||||||
internetPerConnAutoconfigLastDetectUrl = 9
|
|
||||||
internetPerConnFlagsUi = 10
|
|
||||||
internetOptionProxyUsername = 43
|
|
||||||
internetOptionProxyPassword = 44
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
proxyTypeDirect = 1
|
|
||||||
proxyTypeProxy = 2
|
|
||||||
proxyTypeAutoProxyUrl = 4
|
|
||||||
proxyTypeAutoDetect = 8
|
|
||||||
)
|
|
||||||
|
|
||||||
type internetPerConnOptionList struct {
|
|
||||||
dwSize uint32
|
|
||||||
pszConnection uintptr
|
|
||||||
dwOptionCount uint32
|
|
||||||
dwOptionError uint32
|
|
||||||
pOptions uintptr
|
|
||||||
}
|
|
||||||
|
|
||||||
type internetPerConnOption struct {
|
|
||||||
dwOption uint32
|
|
||||||
value [8]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func internetSetOption(option uintptr, lpBuffer uintptr, dwBufferSize uintptr) error {
|
|
||||||
r0, _, err := syscall.SyscallN(procInternetSetOptionW.Addr(), 0, option, lpBuffer, dwBufferSize)
|
|
||||||
if r0 != 1 {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func setOptions(options ...internetPerConnOption) error {
|
|
||||||
var optionList internetPerConnOptionList
|
|
||||||
optionList.dwSize = uint32(unsafe.Sizeof(optionList))
|
|
||||||
optionList.dwOptionCount = uint32(len(options))
|
|
||||||
optionList.dwOptionError = 0
|
|
||||||
optionList.pOptions = uintptr(unsafe.Pointer(&options[0]))
|
|
||||||
err := internetSetOption(internetOptionPerConnectionOption, uintptr(unsafe.Pointer(&optionList)), uintptr(optionList.dwSize))
|
|
||||||
if err != nil {
|
|
||||||
return os.NewSyscallError("InternetSetOption(Direct)", err)
|
|
||||||
}
|
|
||||||
err = internetSetOption(internetOptionSettingsChanged, 0, 0)
|
|
||||||
if err != nil {
|
|
||||||
return os.NewSyscallError("InternetSetOption(SettingsChanged)", err)
|
|
||||||
}
|
|
||||||
err = internetSetOption(internetOptionProxySettingsChanged, 0, 0)
|
|
||||||
if err != nil {
|
|
||||||
return os.NewSyscallError("InternetSetOption(ProxySettingsChanged)", err)
|
|
||||||
}
|
|
||||||
err = internetSetOption(internetOptionRefresh, 0, 0)
|
|
||||||
if err != nil {
|
|
||||||
return os.NewSyscallError("InternetSetOption(Refresh)", err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func ClearSystemProxy() error {
|
func ClearSystemProxy() error {
|
||||||
var flagsOption internetPerConnOption
|
return wininet.ClearSystemProxy()
|
||||||
flagsOption.dwOption = internetPerConnFlags
|
|
||||||
*((*uint32)(unsafe.Pointer(&flagsOption.value))) = proxyTypeDirect | proxyTypeAutoDetect
|
|
||||||
return setOptions(flagsOption)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetSystemProxy(port uint16, mixed bool) error {
|
func SetSystemProxy(port uint16, mixed bool) error {
|
||||||
var flagsOption internetPerConnOption
|
return wininet.SetSystemProxy(F.ToString("http://127.0.0.1:", port), "local")
|
||||||
flagsOption.dwOption = internetPerConnFlags
|
|
||||||
*((*uint32)(unsafe.Pointer(&flagsOption.value))) = proxyTypeProxy | proxyTypeDirect
|
|
||||||
var proxyOption internetPerConnOption
|
|
||||||
proxyOption.dwOption = internetPerConnProxyServer
|
|
||||||
*((*uintptr)(unsafe.Pointer(&proxyOption.value))) = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(F.ToString("http://127.0.0.1:", port))))
|
|
||||||
var bypassOption internetPerConnOption
|
|
||||||
bypassOption.dwOption = internetPerConnProxyBypass
|
|
||||||
*((*uintptr)(unsafe.Pointer(&bypassOption.value))) = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr("local")))
|
|
||||||
return setOptions(flagsOption, proxyOption, bypassOption)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,10 @@
|
||||||
"mixed-in"
|
"mixed-in"
|
||||||
],
|
],
|
||||||
"network": "tcp",
|
"network": "tcp",
|
||||||
|
"user": [
|
||||||
|
"usera",
|
||||||
|
"userb"
|
||||||
|
],
|
||||||
"protocol": [
|
"protocol": [
|
||||||
"tls",
|
"tls",
|
||||||
"http",
|
"http",
|
||||||
|
@ -80,6 +84,14 @@ Tags of [inbound](../inbound).
|
||||||
|
|
||||||
`tcp` or `udp`.
|
`tcp` or `udp`.
|
||||||
|
|
||||||
|
#### user
|
||||||
|
|
||||||
|
Username, see each inbound for details.
|
||||||
|
|
||||||
|
#### protocol
|
||||||
|
|
||||||
|
Sniffed protocol, see [Sniff](/configuration/route/sniff/) for details.
|
||||||
|
|
||||||
#### domain
|
#### domain
|
||||||
|
|
||||||
Match full domain.
|
Match full domain.
|
||||||
|
|
|
@ -47,9 +47,7 @@ Enable tcp fast open for listener.
|
||||||
|
|
||||||
Enable sniffing.
|
Enable sniffing.
|
||||||
|
|
||||||
Reads domain names for routing, supports HTTP TLS for TCP, QUIC for UDP.
|
See [Sniff](/configuration/route/sniff/) for details.
|
||||||
|
|
||||||
This does not break zero copy, like splice.
|
|
||||||
|
|
||||||
#### sniff_override_destination
|
#### sniff_override_destination
|
||||||
|
|
||||||
|
|
|
@ -51,9 +51,7 @@ Enable tcp fast open for listener.
|
||||||
|
|
||||||
Enable sniffing.
|
Enable sniffing.
|
||||||
|
|
||||||
Reads domain names for routing, supports HTTP TLS for TCP, QUIC for UDP.
|
See [Sniff](/configuration/route/sniff/) for details.
|
||||||
|
|
||||||
This does not break zero copy, like splice.
|
|
||||||
|
|
||||||
#### sniff_override_destination
|
#### sniff_override_destination
|
||||||
|
|
||||||
|
|
|
@ -51,9 +51,7 @@ Enable tcp fast open for listener.
|
||||||
|
|
||||||
Enable sniffing.
|
Enable sniffing.
|
||||||
|
|
||||||
Reads domain names for routing, supports HTTP TLS for TCP, QUIC for UDP.
|
See [Sniff](/configuration/route/sniff/) for details.
|
||||||
|
|
||||||
This does not break zero copy, like splice.
|
|
||||||
|
|
||||||
#### sniff_override_destination
|
#### sniff_override_destination
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
{
|
{
|
||||||
"type": "redirect",
|
"type": "redirect",
|
||||||
"tag": "redirect-in",
|
"tag": "redirect-in",
|
||||||
|
|
||||||
"listen": "::",
|
"listen": "::",
|
||||||
"listen_port": 5353,
|
"listen_port": 5353,
|
||||||
"sniff": false,
|
"sniff": false,
|
||||||
|
@ -36,9 +37,7 @@ Listen port.
|
||||||
|
|
||||||
Enable sniffing.
|
Enable sniffing.
|
||||||
|
|
||||||
Reads domain names for routing, supports HTTP TLS for TCP, QUIC for UDP.
|
See [Sniff](/configuration/route/sniff/) for details.
|
||||||
|
|
||||||
This does not break zero copy, like splice.
|
|
||||||
|
|
||||||
#### sniff_override_destination
|
#### sniff_override_destination
|
||||||
|
|
||||||
|
|
|
@ -47,9 +47,7 @@ Enable tcp fast open for listener.
|
||||||
|
|
||||||
Enable sniffing.
|
Enable sniffing.
|
||||||
|
|
||||||
Reads domain names for routing, supports HTTP TLS for TCP, QUIC for UDP.
|
See [Sniff](/configuration/route/sniff/) for details.
|
||||||
|
|
||||||
This does not break zero copy, like splice.
|
|
||||||
|
|
||||||
#### sniff_override_destination
|
#### sniff_override_destination
|
||||||
|
|
||||||
|
|
|
@ -49,9 +49,7 @@ Enable tcp fast open for listener.
|
||||||
|
|
||||||
Enable sniffing.
|
Enable sniffing.
|
||||||
|
|
||||||
Reads domain names for routing, supports HTTP TLS for TCP, QUIC for UDP.
|
See [Sniff](/configuration/route/sniff/) for details.
|
||||||
|
|
||||||
This does not break zero copy, like splice.
|
|
||||||
|
|
||||||
#### sniff_override_destination
|
#### sniff_override_destination
|
||||||
|
|
||||||
|
|
|
@ -40,9 +40,7 @@ Listen port.
|
||||||
|
|
||||||
Enable sniffing.
|
Enable sniffing.
|
||||||
|
|
||||||
Reads domain names for routing, supports HTTP TLS for TCP, QUIC for UDP.
|
See [Sniff](/configuration/route/sniff/) for details.
|
||||||
|
|
||||||
This does not break zero copy, like splice.
|
|
||||||
|
|
||||||
#### sniff_override_destination
|
#### sniff_override_destination
|
||||||
|
|
||||||
|
|
|
@ -59,9 +59,7 @@ Hijack TCP/UDP DNS requests to the built-in DNS adapter.
|
||||||
|
|
||||||
Enable sniffing.
|
Enable sniffing.
|
||||||
|
|
||||||
Reads domain names for routing, supports HTTP TLS for TCP, QUIC for UDP.
|
See [Sniff](/configuration/route/sniff/) for details.
|
||||||
|
|
||||||
This does not break zero copy, like splice.
|
|
||||||
|
|
||||||
#### sniff_override_destination
|
#### sniff_override_destination
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,10 @@
|
||||||
"mixed-in"
|
"mixed-in"
|
||||||
],
|
],
|
||||||
"network": "tcp",
|
"network": "tcp",
|
||||||
|
"user": [
|
||||||
|
"usera",
|
||||||
|
"userb"
|
||||||
|
],
|
||||||
"protocol": [
|
"protocol": [
|
||||||
"tls",
|
"tls",
|
||||||
"http",
|
"http",
|
||||||
|
@ -79,6 +83,14 @@
|
||||||
|
|
||||||
Tags of [inbound](../inbound).
|
Tags of [inbound](../inbound).
|
||||||
|
|
||||||
|
#### user
|
||||||
|
|
||||||
|
Username, see each inbound for details.
|
||||||
|
|
||||||
|
#### protocol
|
||||||
|
|
||||||
|
Sniffed protocol, see [Sniff](/configuration/route/sniff/) for details.
|
||||||
|
|
||||||
#### network
|
#### network
|
||||||
|
|
||||||
`tcp` or `udp`.
|
`tcp` or `udp`.
|
||||||
|
|
10
docs/configuration/route/sniff.md
Normal file
10
docs/configuration/route/sniff.md
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
If enabled in the inbound, the protocol and domain name (if present) of by the connection can be sniffed.
|
||||||
|
|
||||||
|
#### Supported Protocols
|
||||||
|
|
||||||
|
| Network | Protocol | Domain Name |
|
||||||
|
|:---------:|:----------:|:-------------:|
|
||||||
|
| TCP | HTTP | Host |
|
||||||
|
| TCP | TLS | Server Name |
|
||||||
|
| UDP | QUIC | Server Name |
|
||||||
|
| UDP | STUN | / |
|
4
go.mod
4
go.mod
|
@ -7,9 +7,9 @@ require (
|
||||||
github.com/goccy/go-json v0.9.10
|
github.com/goccy/go-json v0.9.10
|
||||||
github.com/logrusorgru/aurora v2.0.3+incompatible
|
github.com/logrusorgru/aurora v2.0.3+incompatible
|
||||||
github.com/oschwald/maxminddb-golang v1.9.0
|
github.com/oschwald/maxminddb-golang v1.9.0
|
||||||
github.com/sagernet/sing v0.0.0-20220716021830-bd79d31e3b10
|
github.com/sagernet/sing v0.0.0-20220717063925-00f98eb6bc34
|
||||||
github.com/sagernet/sing-dns v0.0.0-20220711062726-c64e938e4619
|
github.com/sagernet/sing-dns v0.0.0-20220711062726-c64e938e4619
|
||||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220716012931-952ae62e05d7
|
github.com/sagernet/sing-shadowsocks v0.0.0-20220717063942-45a2ad9cd41f
|
||||||
github.com/sagernet/sing-tun v0.0.0-20220717030718-f53aabff275f
|
github.com/sagernet/sing-tun v0.0.0-20220717030718-f53aabff275f
|
||||||
github.com/spf13/cobra v1.5.0
|
github.com/spf13/cobra v1.5.0
|
||||||
github.com/stretchr/testify v1.8.0
|
github.com/stretchr/testify v1.8.0
|
||||||
|
|
8
go.sum
8
go.sum
|
@ -25,12 +25,12 @@ github.com/oschwald/maxminddb-golang v1.9.0/go.mod h1:TK+s/Z2oZq0rSl4PSeAEoP0bgm
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
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/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/sagernet/sing v0.0.0-20220716021830-bd79d31e3b10 h1:CQSsVgvVT6KcYNQASP4jnPTg7epSxHGI3MS011LIXkA=
|
github.com/sagernet/sing v0.0.0-20220717063925-00f98eb6bc34 h1:1kFruA2QzuH2R6txJXEDSasfdxzsjNyzC4Z1kZjMkHg=
|
||||||
github.com/sagernet/sing v0.0.0-20220716021830-bd79d31e3b10/go.mod h1:3ZmoGNg/nNJTyHAZFNRSPaXpNIwpDvyIiAUd0KIWV5c=
|
github.com/sagernet/sing v0.0.0-20220717063925-00f98eb6bc34/go.mod h1:GbtQfZSpmtD3cXeD1qX2LCMwY8dH+bnnInDTqd92IsM=
|
||||||
github.com/sagernet/sing-dns v0.0.0-20220711062726-c64e938e4619 h1:oHbOmq1WS0XaZmXp6WpxzyB2xeyRIA1/L8EJKuNntfY=
|
github.com/sagernet/sing-dns v0.0.0-20220711062726-c64e938e4619 h1:oHbOmq1WS0XaZmXp6WpxzyB2xeyRIA1/L8EJKuNntfY=
|
||||||
github.com/sagernet/sing-dns v0.0.0-20220711062726-c64e938e4619/go.mod h1:y2fpvoxukw3G7eApIZwkcpcG/NE4AB8pCQI0Qd8rMqk=
|
github.com/sagernet/sing-dns v0.0.0-20220711062726-c64e938e4619/go.mod h1:y2fpvoxukw3G7eApIZwkcpcG/NE4AB8pCQI0Qd8rMqk=
|
||||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220716012931-952ae62e05d7 h1:7xQvlMSxNWphQ4t+7fHfR4OnkH23GukLIjImnM1CMLA=
|
github.com/sagernet/sing-shadowsocks v0.0.0-20220717063942-45a2ad9cd41f h1:F6yiuKbBoXgWiuoP7R0YA14pDEl3emxA1mL7M16Q7gc=
|
||||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220716012931-952ae62e05d7/go.mod h1:NtHwPOk1wEOPdjjsjtrYoaQuXtlDCrx0mrcWBrNE0sA=
|
github.com/sagernet/sing-shadowsocks v0.0.0-20220717063942-45a2ad9cd41f/go.mod h1:cDrLwa3zwY8AaW6a4sjipn4xgdIr3CT8TPqSW6iFOi0=
|
||||||
github.com/sagernet/sing-tun v0.0.0-20220717030718-f53aabff275f h1:o3YN4sFC7lQznAwutagPqBb23hal7MkgVq/VEvd7Vug=
|
github.com/sagernet/sing-tun v0.0.0-20220717030718-f53aabff275f h1:o3YN4sFC7lQznAwutagPqBb23hal7MkgVq/VEvd7Vug=
|
||||||
github.com/sagernet/sing-tun v0.0.0-20220717030718-f53aabff275f/go.mod h1:p7QbUBs2ejf6UQsiHyy1xGAWOk9JWQjZTHy8pOmkWmo=
|
github.com/sagernet/sing-tun v0.0.0-20220717030718-f53aabff275f/go.mod h1:p7QbUBs2ejf6UQsiHyy1xGAWOk9JWQjZTHy8pOmkWmo=
|
||||||
github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=
|
github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
"github.com/sagernet/sing/common/auth"
|
"github.com/sagernet/sing/common/auth"
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
|
N "github.com/sagernet/sing/common/network"
|
||||||
"github.com/sagernet/sing/protocol/http"
|
"github.com/sagernet/sing/protocol/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -40,5 +41,25 @@ func NewHTTP(ctx context.Context, router adapter.Router, logger log.ContextLogge
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *HTTP) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
|
func (h *HTTP) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
|
||||||
return http.HandleConnection(ctx, conn, std_bufio.NewReader(conn), h.authenticator, h.upstreamHandler(metadata), M.Metadata{})
|
return http.HandleConnection(ctx, conn, std_bufio.NewReader(conn), h.authenticator, h.upstreamUserHandler(metadata), M.Metadata{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *myInboundAdapter) upstreamUserHandler(metadata adapter.InboundContext) adapter.UpstreamHandlerAdapter {
|
||||||
|
return adapter.NewUpstreamHandler(metadata, a.newUserConnection, a.streamUserPacketConnection, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *myInboundAdapter) newUserConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
|
||||||
|
user, loaded := auth.UserFromContext[string](ctx)
|
||||||
|
if !loaded {
|
||||||
|
a.logger.InfoContext(ctx, "inbound connection to ", metadata.Destination)
|
||||||
|
return a.router.RouteConnection(ctx, conn, metadata)
|
||||||
|
}
|
||||||
|
metadata.User = user
|
||||||
|
a.logger.InfoContext(ctx, "[", user, "] inbound connection to ", metadata.Destination)
|
||||||
|
return a.router.RouteConnection(ctx, conn, metadata)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *myInboundAdapter) streamUserPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
|
||||||
|
a.logger.InfoContext(ctx, "inbound packet connection to ", metadata.Destination)
|
||||||
|
return a.router.RoutePacketConnection(ctx, conn, metadata)
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,8 +52,8 @@ func (h *Mixed) NewConnection(ctx context.Context, conn net.Conn, metadata adapt
|
||||||
}
|
}
|
||||||
switch headerType {
|
switch headerType {
|
||||||
case socks4.Version, socks5.Version:
|
case socks4.Version, socks5.Version:
|
||||||
return socks.HandleConnection0(ctx, conn, headerType, h.authenticator, h.upstreamHandler(metadata), M.Metadata{})
|
return socks.HandleConnection0(ctx, conn, headerType, h.authenticator, h.upstreamUserHandler(metadata), M.Metadata{})
|
||||||
}
|
}
|
||||||
reader := std_bufio.NewReader(bufio.NewCachedReader(conn, buf.As([]byte{headerType})))
|
reader := std_bufio.NewReader(bufio.NewCachedReader(conn, buf.As([]byte{headerType})))
|
||||||
return http.HandleConnection(ctx, conn, reader, h.authenticator, h.upstreamHandler(metadata), M.Metadata{})
|
return http.HandleConnection(ctx, conn, reader, h.authenticator, h.upstreamUserHandler(metadata), M.Metadata{})
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,5 +77,17 @@ func (h *Shadowsocks) NewConnection(ctx context.Context, conn net.Conn, metadata
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Shadowsocks) NewPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, metadata adapter.InboundContext) error {
|
func (h *Shadowsocks) NewPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, metadata adapter.InboundContext) error {
|
||||||
return h.service.NewPacket(adapter.WithContext(log.ContextWithNewID(ctx), &metadata), conn, buffer, adapter.UpstreamMetadata(metadata))
|
return h.service.NewPacket(adapter.WithContext(ctx, &metadata), conn, buffer, adapter.UpstreamMetadata(metadata))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Shadowsocks) newConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
|
||||||
|
h.logger.InfoContext(ctx, "inbound connection to ", metadata.Destination)
|
||||||
|
return h.router.RouteConnection(ctx, conn, metadata)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Shadowsocks) newPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
|
||||||
|
ctx = log.ContextWithNewID(ctx)
|
||||||
|
h.logger.InfoContext(ctx, "inbound packet connection from ", metadata.Source)
|
||||||
|
h.logger.InfoContext(ctx, "inbound packet connection to ", metadata.Destination)
|
||||||
|
return h.router.RoutePacketConnection(ctx, conn, metadata)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,14 +3,15 @@ package inbound
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net"
|
"net"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
"github.com/sagernet/sing-shadowsocks"
|
|
||||||
"github.com/sagernet/sing-shadowsocks/shadowaead_2022"
|
"github.com/sagernet/sing-shadowsocks/shadowaead_2022"
|
||||||
"github.com/sagernet/sing/common"
|
"github.com/sagernet/sing/common"
|
||||||
|
"github.com/sagernet/sing/common/auth"
|
||||||
"github.com/sagernet/sing/common/buf"
|
"github.com/sagernet/sing/common/buf"
|
||||||
F "github.com/sagernet/sing/common/format"
|
F "github.com/sagernet/sing/common/format"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
@ -72,24 +73,34 @@ func (h *ShadowsocksMulti) NewConnection(ctx context.Context, conn net.Conn, met
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ShadowsocksMulti) NewPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, metadata adapter.InboundContext) error {
|
func (h *ShadowsocksMulti) NewPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, metadata adapter.InboundContext) error {
|
||||||
return h.service.NewPacket(adapter.WithContext(log.ContextWithNewID(ctx), &metadata), conn, buffer, adapter.UpstreamMetadata(metadata))
|
return h.service.NewPacket(adapter.WithContext(ctx, &metadata), conn, buffer, adapter.UpstreamMetadata(metadata))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ShadowsocksMulti) newConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
|
func (h *ShadowsocksMulti) newConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
|
||||||
userCtx := ctx.(*shadowsocks.UserContext[int])
|
userIndex, loaded := auth.UserFromContext[int](ctx)
|
||||||
user := h.users[userCtx.User].Name
|
if !loaded {
|
||||||
|
return os.ErrInvalid
|
||||||
|
}
|
||||||
|
user := h.users[userIndex].Name
|
||||||
if user == "" {
|
if user == "" {
|
||||||
user = F.ToString(userCtx.User)
|
user = F.ToString(userIndex)
|
||||||
|
} else {
|
||||||
|
metadata.User = user
|
||||||
}
|
}
|
||||||
h.logger.InfoContext(ctx, "[", user, "] inbound connection to ", metadata.Destination)
|
h.logger.InfoContext(ctx, "[", user, "] inbound connection to ", metadata.Destination)
|
||||||
return h.router.RouteConnection(ctx, conn, metadata)
|
return h.router.RouteConnection(ctx, conn, metadata)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ShadowsocksMulti) newPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
|
func (h *ShadowsocksMulti) newPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
|
||||||
userCtx := ctx.(*shadowsocks.UserContext[int])
|
userIndex, loaded := auth.UserFromContext[int](ctx)
|
||||||
user := h.users[userCtx.User].Name
|
if !loaded {
|
||||||
|
return os.ErrInvalid
|
||||||
|
}
|
||||||
|
user := h.users[userIndex].Name
|
||||||
if user == "" {
|
if user == "" {
|
||||||
user = F.ToString(userCtx.User)
|
user = F.ToString(userIndex)
|
||||||
|
} else {
|
||||||
|
metadata.User = user
|
||||||
}
|
}
|
||||||
ctx = log.ContextWithNewID(ctx)
|
ctx = log.ContextWithNewID(ctx)
|
||||||
h.logger.InfoContext(ctx, "[", user, "] inbound packet connection from ", metadata.Source)
|
h.logger.InfoContext(ctx, "[", user, "] inbound packet connection from ", metadata.Source)
|
||||||
|
|
|
@ -3,14 +3,15 @@ package inbound
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net"
|
"net"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
"github.com/sagernet/sing-shadowsocks"
|
|
||||||
"github.com/sagernet/sing-shadowsocks/shadowaead_2022"
|
"github.com/sagernet/sing-shadowsocks/shadowaead_2022"
|
||||||
"github.com/sagernet/sing/common"
|
"github.com/sagernet/sing/common"
|
||||||
|
"github.com/sagernet/sing/common/auth"
|
||||||
"github.com/sagernet/sing/common/buf"
|
"github.com/sagernet/sing/common/buf"
|
||||||
F "github.com/sagernet/sing/common/format"
|
F "github.com/sagernet/sing/common/format"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
@ -72,24 +73,34 @@ func (h *ShadowsocksRelay) NewConnection(ctx context.Context, conn net.Conn, met
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ShadowsocksRelay) NewPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, metadata adapter.InboundContext) error {
|
func (h *ShadowsocksRelay) NewPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, metadata adapter.InboundContext) error {
|
||||||
return h.service.NewPacket(adapter.WithContext(log.ContextWithNewID(ctx), &metadata), conn, buffer, adapter.UpstreamMetadata(metadata))
|
return h.service.NewPacket(adapter.WithContext(ctx, &metadata), conn, buffer, adapter.UpstreamMetadata(metadata))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ShadowsocksRelay) newConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
|
func (h *ShadowsocksRelay) newConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
|
||||||
userCtx := ctx.(*shadowsocks.UserContext[int])
|
destinationIndex, loaded := auth.UserFromContext[int](ctx)
|
||||||
destination := h.destinations[userCtx.User].Name
|
if !loaded {
|
||||||
|
return os.ErrInvalid
|
||||||
|
}
|
||||||
|
destination := h.destinations[destinationIndex].Name
|
||||||
if destination == "" {
|
if destination == "" {
|
||||||
destination = F.ToString(userCtx.User)
|
destination = F.ToString(destinationIndex)
|
||||||
|
} else {
|
||||||
|
metadata.User = destination
|
||||||
}
|
}
|
||||||
h.logger.InfoContext(ctx, "[", destination, "] inbound connection to ", metadata.Destination)
|
h.logger.InfoContext(ctx, "[", destination, "] inbound connection to ", metadata.Destination)
|
||||||
return h.router.RouteConnection(ctx, conn, metadata)
|
return h.router.RouteConnection(ctx, conn, metadata)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ShadowsocksRelay) newPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
|
func (h *ShadowsocksRelay) newPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
|
||||||
userCtx := ctx.(*shadowsocks.UserContext[int])
|
destinationIndex, loaded := auth.UserFromContext[int](ctx)
|
||||||
destination := h.destinations[userCtx.User].Name
|
if !loaded {
|
||||||
|
return os.ErrInvalid
|
||||||
|
}
|
||||||
|
destination := h.destinations[destinationIndex].Name
|
||||||
if destination == "" {
|
if destination == "" {
|
||||||
destination = F.ToString(userCtx.User)
|
destination = F.ToString(destinationIndex)
|
||||||
|
} else {
|
||||||
|
metadata.User = destination
|
||||||
}
|
}
|
||||||
ctx = log.ContextWithNewID(ctx)
|
ctx = log.ContextWithNewID(ctx)
|
||||||
h.logger.InfoContext(ctx, "[", destination, "] inbound packet connection from ", metadata.Source)
|
h.logger.InfoContext(ctx, "[", destination, "] inbound packet connection from ", metadata.Source)
|
||||||
|
|
|
@ -38,5 +38,5 @@ func NewSocks(ctx context.Context, router adapter.Router, logger log.ContextLogg
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Socks) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
|
func (h *Socks) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
|
||||||
return socks.HandleConnection(ctx, conn, h.authenticator, h.upstreamHandler(metadata), M.Metadata{})
|
return socks.HandleConnection(ctx, conn, h.authenticator, h.upstreamUserHandler(metadata), M.Metadata{})
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,6 +61,7 @@ nav:
|
||||||
- GeoIP: configuration/route/geoip.md
|
- GeoIP: configuration/route/geoip.md
|
||||||
- Geosite: configuration/route/geosite.md
|
- Geosite: configuration/route/geosite.md
|
||||||
- Route Rule: configuration/route/rule.md
|
- Route Rule: configuration/route/rule.md
|
||||||
|
- Protocol Sniff: configuration/route/sniff.md
|
||||||
- Examples:
|
- Examples:
|
||||||
- examples/index.md
|
- examples/index.md
|
||||||
- Shadowsocks Server: examples/ss-server.md
|
- Shadowsocks Server: examples/ss-server.md
|
||||||
|
|
|
@ -91,6 +91,7 @@ func (r *DNSRule) UnmarshalJSON(bytes []byte) error {
|
||||||
type DefaultDNSRule struct {
|
type DefaultDNSRule struct {
|
||||||
Inbound Listable[string] `json:"inbound,omitempty"`
|
Inbound Listable[string] `json:"inbound,omitempty"`
|
||||||
Network string `json:"network,omitempty"`
|
Network string `json:"network,omitempty"`
|
||||||
|
User Listable[string] `json:"user,omitempty"`
|
||||||
Protocol Listable[string] `json:"protocol,omitempty"`
|
Protocol Listable[string] `json:"protocol,omitempty"`
|
||||||
Domain Listable[string] `json:"domain,omitempty"`
|
Domain Listable[string] `json:"domain,omitempty"`
|
||||||
DomainSuffix Listable[string] `json:"domain_suffix,omitempty"`
|
DomainSuffix Listable[string] `json:"domain_suffix,omitempty"`
|
||||||
|
@ -114,6 +115,7 @@ func (r DefaultDNSRule) IsValid() bool {
|
||||||
func (r DefaultDNSRule) Equals(other DefaultDNSRule) bool {
|
func (r DefaultDNSRule) Equals(other DefaultDNSRule) bool {
|
||||||
return common.ComparableSliceEquals(r.Inbound, other.Inbound) &&
|
return common.ComparableSliceEquals(r.Inbound, other.Inbound) &&
|
||||||
r.Network == other.Network &&
|
r.Network == other.Network &&
|
||||||
|
common.ComparableSliceEquals(r.User, other.User) &&
|
||||||
common.ComparableSliceEquals(r.Protocol, other.Protocol) &&
|
common.ComparableSliceEquals(r.Protocol, other.Protocol) &&
|
||||||
common.ComparableSliceEquals(r.Domain, other.Domain) &&
|
common.ComparableSliceEquals(r.Domain, other.Domain) &&
|
||||||
common.ComparableSliceEquals(r.DomainSuffix, other.DomainSuffix) &&
|
common.ComparableSliceEquals(r.DomainSuffix, other.DomainSuffix) &&
|
||||||
|
|
|
@ -89,6 +89,7 @@ type DefaultRule struct {
|
||||||
Inbound Listable[string] `json:"inbound,omitempty"`
|
Inbound Listable[string] `json:"inbound,omitempty"`
|
||||||
IPVersion int `json:"ip_version,omitempty"`
|
IPVersion int `json:"ip_version,omitempty"`
|
||||||
Network string `json:"network,omitempty"`
|
Network string `json:"network,omitempty"`
|
||||||
|
User Listable[string] `json:"user,omitempty"`
|
||||||
Protocol Listable[string] `json:"protocol,omitempty"`
|
Protocol Listable[string] `json:"protocol,omitempty"`
|
||||||
Domain Listable[string] `json:"domain,omitempty"`
|
Domain Listable[string] `json:"domain,omitempty"`
|
||||||
DomainSuffix Listable[string] `json:"domain_suffix,omitempty"`
|
DomainSuffix Listable[string] `json:"domain_suffix,omitempty"`
|
||||||
|
@ -114,6 +115,7 @@ func (r DefaultRule) Equals(other DefaultRule) bool {
|
||||||
return common.ComparableSliceEquals(r.Inbound, other.Inbound) &&
|
return common.ComparableSliceEquals(r.Inbound, other.Inbound) &&
|
||||||
r.IPVersion == other.IPVersion &&
|
r.IPVersion == other.IPVersion &&
|
||||||
r.Network == other.Network &&
|
r.Network == other.Network &&
|
||||||
|
common.ComparableSliceEquals(r.User, other.User) &&
|
||||||
common.ComparableSliceEquals(r.Protocol, other.Protocol) &&
|
common.ComparableSliceEquals(r.Protocol, other.Protocol) &&
|
||||||
common.ComparableSliceEquals(r.Domain, other.Domain) &&
|
common.ComparableSliceEquals(r.Domain, other.Domain) &&
|
||||||
common.ComparableSliceEquals(r.DomainSuffix, other.DomainSuffix) &&
|
common.ComparableSliceEquals(r.DomainSuffix, other.DomainSuffix) &&
|
||||||
|
|
|
@ -82,8 +82,13 @@ func NewDefaultRule(router adapter.Router, logger log.ContextLogger, options opt
|
||||||
return nil, E.New("invalid network: ", options.Network)
|
return nil, E.New("invalid network: ", options.Network)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if len(options.User) > 0 {
|
||||||
|
item := NewUserItem(options.User)
|
||||||
|
rule.items = append(rule.items, item)
|
||||||
|
rule.allItems = append(rule.allItems, item)
|
||||||
|
}
|
||||||
if len(options.Protocol) > 0 {
|
if len(options.Protocol) > 0 {
|
||||||
item := NewProtocolItem(options.Protocol)
|
item := NewUserItem(options.Protocol)
|
||||||
rule.items = append(rule.items, item)
|
rule.items = append(rule.items, item)
|
||||||
rule.allItems = append(rule.allItems, item)
|
rule.allItems = append(rule.allItems, item)
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,8 +66,13 @@ func NewDefaultDNSRule(router adapter.Router, logger log.ContextLogger, options
|
||||||
return nil, E.New("invalid network: ", options.Network)
|
return nil, E.New("invalid network: ", options.Network)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if len(options.User) > 0 {
|
||||||
|
item := NewUserItem(options.User)
|
||||||
|
rule.items = append(rule.items, item)
|
||||||
|
rule.allItems = append(rule.allItems, item)
|
||||||
|
}
|
||||||
if len(options.Protocol) > 0 {
|
if len(options.Protocol) > 0 {
|
||||||
item := NewProtocolItem(options.Protocol)
|
item := NewUserItem(options.Protocol)
|
||||||
rule.items = append(rule.items, item)
|
rule.items = append(rule.items, item)
|
||||||
rule.allItems = append(rule.allItems, item)
|
rule.allItems = append(rule.allItems, item)
|
||||||
}
|
}
|
||||||
|
|
37
route/rule_user.go
Normal file
37
route/rule_user.go
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
package route
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
F "github.com/sagernet/sing/common/format"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ RuleItem = (*UserItem)(nil)
|
||||||
|
|
||||||
|
type UserItem struct {
|
||||||
|
users []string
|
||||||
|
userMap map[string]bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUserItem(users []string) *UserItem {
|
||||||
|
userMap := make(map[string]bool)
|
||||||
|
for _, protocol := range users {
|
||||||
|
userMap[protocol] = true
|
||||||
|
}
|
||||||
|
return &UserItem{
|
||||||
|
users: users,
|
||||||
|
userMap: userMap,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *UserItem) Match(metadata *adapter.InboundContext) bool {
|
||||||
|
return r.userMap[metadata.User]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *UserItem) String() string {
|
||||||
|
if len(r.users) == 1 {
|
||||||
|
return F.ToString("user=", r.users[0])
|
||||||
|
}
|
||||||
|
return F.ToString("user=[", strings.Join(r.users, " "), "]")
|
||||||
|
}
|
|
@ -46,15 +46,15 @@ func startInstance(t *testing.T, options option.Options) {
|
||||||
|
|
||||||
func testSuit(t *testing.T, clientPort uint16, testPort uint16) {
|
func testSuit(t *testing.T, clientPort uint16, testPort uint16) {
|
||||||
dialer := socks.NewClient(N.SystemDialer, M.ParseSocksaddrHostPort("127.0.0.1", clientPort), socks.Version5, "", "")
|
dialer := socks.NewClient(N.SystemDialer, M.ParseSocksaddrHostPort("127.0.0.1", clientPort), socks.Version5, "", "")
|
||||||
dialTCP := func() (net.Conn, error) {
|
dialTCP := func(port uint16) (net.Conn, error) {
|
||||||
return dialer.DialContext(context.Background(), "tcp", M.ParseSocksaddrHostPort("127.0.0.1", testPort))
|
return dialer.DialContext(context.Background(), "tcp", M.ParseSocksaddrHostPort("127.0.0.1", port))
|
||||||
}
|
}
|
||||||
dialUDP := func() (net.PacketConn, error) {
|
dialUDP := func(port uint16) (net.PacketConn, error) {
|
||||||
return dialer.ListenPacket(context.Background(), M.ParseSocksaddrHostPort("127.0.0.1", testPort))
|
return dialer.ListenPacket(context.Background(), M.ParseSocksaddrHostPort("127.0.0.1", port))
|
||||||
}
|
}
|
||||||
require.NoError(t, testPingPongWithConn(t, testPort, dialTCP))
|
require.NoError(t, testPingPongWithConn(t, dialTCP))
|
||||||
require.NoError(t, testLargeDataWithConn(t, testPort, dialTCP))
|
require.NoError(t, testLargeDataWithConn(t, dialTCP))
|
||||||
require.NoError(t, testPingPongWithPacketConn(t, testPort, dialUDP))
|
require.NoError(t, testPingPongWithPacketConn(t, dialUDP))
|
||||||
require.NoError(t, testLargeDataWithPacketConn(t, testPort, dialUDP))
|
require.NoError(t, testLargeDataWithPacketConn(t, dialUDP))
|
||||||
require.NoError(t, testPacketConnTimeout(t, dialUDP))
|
require.NoError(t, testPacketConnTimeout(t, dialUDP))
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,14 +152,15 @@ func newLargeDataPair() (chan hashPair, chan hashPair, func(t *testing.T) error)
|
||||||
return pingCh, pongCh, test
|
return pingCh, pongCh, test
|
||||||
}
|
}
|
||||||
|
|
||||||
func testPingPongWithConn(t *testing.T, port uint16, cc func() (net.Conn, error)) error {
|
func testPingPongWithConn(t *testing.T, cc func(port uint16) (net.Conn, error)) error {
|
||||||
|
port := mkPort(t)
|
||||||
l, err := listen("tcp", ":"+F.ToString(port))
|
l, err := listen("tcp", ":"+F.ToString(port))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer l.Close()
|
defer l.Close()
|
||||||
|
|
||||||
c, err := cc()
|
c, err := cc(port)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -198,7 +199,9 @@ func testPingPongWithConn(t *testing.T, port uint16, cc func() (net.Conn, error)
|
||||||
return test(t)
|
return test(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testPingPongWithPacketConn(t *testing.T, port uint16, pcc func() (net.PacketConn, error)) error {
|
func testPingPongWithPacketConn(t *testing.T, pcc func(port uint16) (net.PacketConn, error)) error {
|
||||||
|
port := mkPort(t)
|
||||||
|
|
||||||
l, err := listenPacket("udp", ":"+F.ToString(port))
|
l, err := listenPacket("udp", ":"+F.ToString(port))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer l.Close()
|
defer l.Close()
|
||||||
|
@ -219,7 +222,7 @@ func testPingPongWithPacketConn(t *testing.T, port uint16, pcc func() (net.Packe
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
pc, err := pcc()
|
pc, err := pcc(port)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -246,7 +249,8 @@ type hashPair struct {
|
||||||
recvHash map[int][]byte
|
recvHash map[int][]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func testLargeDataWithConn(t *testing.T, port uint16, cc func() (net.Conn, error)) error {
|
func testLargeDataWithConn(t *testing.T, cc func(port uint16) (net.Conn, error)) error {
|
||||||
|
port := mkPort(t)
|
||||||
l, err := listen("tcp", ":"+F.ToString(port))
|
l, err := listen("tcp", ":"+F.ToString(port))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer l.Close()
|
defer l.Close()
|
||||||
|
@ -275,7 +279,7 @@ func testLargeDataWithConn(t *testing.T, port uint16, cc func() (net.Conn, error
|
||||||
return hashMap, nil
|
return hashMap, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
c, err := cc()
|
c, err := cc(port)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -343,7 +347,8 @@ func testLargeDataWithConn(t *testing.T, port uint16, cc func() (net.Conn, error
|
||||||
return test(t)
|
return test(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testLargeDataWithPacketConn(t *testing.T, port uint16, pcc func() (net.PacketConn, error)) error {
|
func testLargeDataWithPacketConn(t *testing.T, pcc func(port uint16) (net.PacketConn, error)) error {
|
||||||
|
port := mkPort(t)
|
||||||
l, err := listenPacket("udp", ":"+F.ToString(port))
|
l, err := listenPacket("udp", ":"+F.ToString(port))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer l.Close()
|
defer l.Close()
|
||||||
|
@ -409,7 +414,7 @@ func testLargeDataWithPacketConn(t *testing.T, port uint16, pcc func() (net.Pack
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
pc, err := pcc()
|
pc, err := pcc(port)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -444,8 +449,8 @@ func testLargeDataWithPacketConn(t *testing.T, port uint16, pcc func() (net.Pack
|
||||||
return test(t)
|
return test(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testPacketConnTimeout(t *testing.T, pcc func() (net.PacketConn, error)) error {
|
func testPacketConnTimeout(t *testing.T, pcc func(port uint16) (net.PacketConn, error)) error {
|
||||||
pc, err := pcc()
|
pc, err := pcc(mkPort(t))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ go 1.18
|
||||||
require (
|
require (
|
||||||
github.com/docker/docker v20.10.17+incompatible
|
github.com/docker/docker v20.10.17+incompatible
|
||||||
github.com/docker/go-connections v0.4.0
|
github.com/docker/go-connections v0.4.0
|
||||||
github.com/sagernet/sing v0.0.0-20220716021830-bd79d31e3b10
|
github.com/sagernet/sing v0.0.0-20220717063925-00f98eb6bc34
|
||||||
github.com/sagernet/sing-box v0.0.0
|
github.com/sagernet/sing-box v0.0.0
|
||||||
github.com/stretchr/testify v1.8.0
|
github.com/stretchr/testify v1.8.0
|
||||||
golang.org/x/net v0.0.0-20220708220712-1185a9018129
|
golang.org/x/net v0.0.0-20220708220712-1185a9018129
|
||||||
|
@ -33,7 +33,7 @@ require (
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/sagernet/sing-dns v0.0.0-20220711062726-c64e938e4619 // indirect
|
github.com/sagernet/sing-dns v0.0.0-20220711062726-c64e938e4619 // indirect
|
||||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220716012931-952ae62e05d7 // indirect
|
github.com/sagernet/sing-shadowsocks v0.0.0-20220717063942-45a2ad9cd41f // indirect
|
||||||
github.com/sagernet/sing-tun v0.0.0-20220717030718-f53aabff275f // indirect
|
github.com/sagernet/sing-tun v0.0.0-20220717030718-f53aabff275f // indirect
|
||||||
github.com/sirupsen/logrus v1.8.1 // indirect
|
github.com/sirupsen/logrus v1.8.1 // indirect
|
||||||
github.com/vishvananda/netlink v1.1.0 // indirect
|
github.com/vishvananda/netlink v1.1.0 // indirect
|
||||||
|
|
|
@ -52,12 +52,12 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
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/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/sagernet/sing v0.0.0-20220716021830-bd79d31e3b10 h1:CQSsVgvVT6KcYNQASP4jnPTg7epSxHGI3MS011LIXkA=
|
github.com/sagernet/sing v0.0.0-20220717063925-00f98eb6bc34 h1:1kFruA2QzuH2R6txJXEDSasfdxzsjNyzC4Z1kZjMkHg=
|
||||||
github.com/sagernet/sing v0.0.0-20220716021830-bd79d31e3b10/go.mod h1:3ZmoGNg/nNJTyHAZFNRSPaXpNIwpDvyIiAUd0KIWV5c=
|
github.com/sagernet/sing v0.0.0-20220717063925-00f98eb6bc34/go.mod h1:GbtQfZSpmtD3cXeD1qX2LCMwY8dH+bnnInDTqd92IsM=
|
||||||
github.com/sagernet/sing-dns v0.0.0-20220711062726-c64e938e4619 h1:oHbOmq1WS0XaZmXp6WpxzyB2xeyRIA1/L8EJKuNntfY=
|
github.com/sagernet/sing-dns v0.0.0-20220711062726-c64e938e4619 h1:oHbOmq1WS0XaZmXp6WpxzyB2xeyRIA1/L8EJKuNntfY=
|
||||||
github.com/sagernet/sing-dns v0.0.0-20220711062726-c64e938e4619/go.mod h1:y2fpvoxukw3G7eApIZwkcpcG/NE4AB8pCQI0Qd8rMqk=
|
github.com/sagernet/sing-dns v0.0.0-20220711062726-c64e938e4619/go.mod h1:y2fpvoxukw3G7eApIZwkcpcG/NE4AB8pCQI0Qd8rMqk=
|
||||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220716012931-952ae62e05d7 h1:7xQvlMSxNWphQ4t+7fHfR4OnkH23GukLIjImnM1CMLA=
|
github.com/sagernet/sing-shadowsocks v0.0.0-20220717063942-45a2ad9cd41f h1:F6yiuKbBoXgWiuoP7R0YA14pDEl3emxA1mL7M16Q7gc=
|
||||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220716012931-952ae62e05d7/go.mod h1:NtHwPOk1wEOPdjjsjtrYoaQuXtlDCrx0mrcWBrNE0sA=
|
github.com/sagernet/sing-shadowsocks v0.0.0-20220717063942-45a2ad9cd41f/go.mod h1:cDrLwa3zwY8AaW6a4sjipn4xgdIr3CT8TPqSW6iFOi0=
|
||||||
github.com/sagernet/sing-tun v0.0.0-20220717030718-f53aabff275f h1:o3YN4sFC7lQznAwutagPqBb23hal7MkgVq/VEvd7Vug=
|
github.com/sagernet/sing-tun v0.0.0-20220717030718-f53aabff275f h1:o3YN4sFC7lQznAwutagPqBb23hal7MkgVq/VEvd7Vug=
|
||||||
github.com/sagernet/sing-tun v0.0.0-20220717030718-f53aabff275f/go.mod h1:p7QbUBs2ejf6UQsiHyy1xGAWOk9JWQjZTHy8pOmkWmo=
|
github.com/sagernet/sing-tun v0.0.0-20220717030718-f53aabff275f/go.mod h1:p7QbUBs2ejf6UQsiHyy1xGAWOk9JWQjZTHy8pOmkWmo=
|
||||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||||
|
|
Loading…
Reference in a new issue