Compare commits

..
Author SHA1 Message Date
Fangliding c84753dae6 fmt 2026-09-20 17:09:02 +08:00
Fangliding d17906c2f1 Optimize logger 2026-09-20 17:00:49 +08:00
82 changed files with 2507 additions and 282 deletions
+1 -1
View File
@@ -23,7 +23,7 @@ func newFakeDNSSniffer(ctx context.Context) (protocolSnifferWithMetadata, error)
}
if fakeDNSEngine == nil {
errNotInit := errors.New("FakeDNSEngine is not initialized, but such a sniffer is used").AtError()
errNotInit := errors.New("FakeDNSEngine is not initialized, but such a sniffer is used")
return protocolSnifferWithMetadata{}, errNotInit
}
return protocolSnifferWithMetadata{protocolSniffer: func(ctx context.Context, bytes []byte) (SniffResult, error) {
+1 -1
View File
@@ -28,7 +28,7 @@ func toNetIP(addrs []net.Address) ([]net.IP, error) {
if addr.Family().IsIP() {
ips = append(ips, addr.IP())
} else {
return nil, errors.New("Failed to convert address", addr, "to Net IP.").AtWarning()
return nil, errors.New("Failed to convert address", addr, "to Net IP.")
}
}
return ips, nil
+2 -2
View File
@@ -188,10 +188,10 @@ func parseResponse(payload []byte) (*IPRecord, error) {
var parser dnsmessage.Parser
h, err := parser.Start(payload)
if err != nil {
return nil, errors.New("failed to parse DNS response").Base(err).AtWarning()
return nil, errors.New("failed to parse DNS response").Base(err)
}
if err := parser.SkipAllQuestions(); err != nil {
return nil, errors.New("failed to skip questions in DNS response").Base(err).AtWarning()
return nil, errors.New("failed to skip questions in DNS response").Base(err)
}
now := time.Now()
+3 -3
View File
@@ -58,7 +58,7 @@ func NewFakeDNSHolder() (*Holder, error) {
var err error
if fkdns, err = NewFakeDNSHolderConfigOnly(nil); err != nil {
return nil, errors.New("Unable to create Fake Dns Engine").Base(err).AtError()
return nil, errors.New("Unable to create Fake Dns Engine").Base(err)
}
err = fkdns.initialize(dns.FakeIPv4Pool, 65535)
if err != nil {
@@ -80,13 +80,13 @@ func (fkdns *Holder) initialize(ipPoolCidr string, lruSize int) error {
var err error
if _, ipRange, err = net.ParseCIDR(ipPoolCidr); err != nil {
return errors.New("Unable to parse CIDR for Fake DNS IP assignment").Base(err).AtError()
return errors.New("Unable to parse CIDR for Fake DNS IP assignment").Base(err)
}
ones, bits := ipRange.Mask.Size()
rooms := bits - ones
if math.Log2(float64(lruSize)) >= float64(rooms) {
return errors.New("LRU size is bigger than subnet size").AtError()
return errors.New("LRU size is bigger than subnet size")
}
fkdns.domainToIP = cache.NewLru(lruSize)
fkdns.ipRange = ipRange
+4 -4
View File
@@ -84,7 +84,7 @@ func NewServer(ctx context.Context, dest net.Destination, dispatcher routing.Dis
if dest.Network == net.Network_UDP { // UDP classic DNS mode
return NewClassicNameServer(dest, dispatcher, disableCache, serveStale, serveExpiredTTL, clientIP), nil
}
return nil, errors.New("No available name server could be created from ", dest).AtWarning()
return nil, errors.New("No available name server could be created from ", dest)
}
// NewClient creates a DNS client managing a name server with client IP, domain rules and expected IPs.
@@ -102,7 +102,7 @@ func NewClient(
// Create a new server for each client for now
server, err := NewServer(ctx, ns.Address.AsDestination(), dispatcher, disableCache, serveStale, serveExpiredTTL, clientIP)
if err != nil {
return errors.New("failed to create nameserver").Base(err).AtWarning()
return errors.New("failed to create nameserver").Base(err)
}
_, isLocalDNS := server.(*LocalNameServer)
@@ -113,7 +113,7 @@ func NewClient(
if len(ns.ExpectedIp) > 0 {
expectedMatcher, err = geodata.IPReg.BuildIPMatcher(ns.ExpectedIp)
if err != nil {
return errors.New("failed to create expected ip matcher").Base(err).AtWarning()
return errors.New("failed to create expected ip matcher").Base(err)
}
}
@@ -122,7 +122,7 @@ func NewClient(
if len(ns.UnexpectedIp) > 0 {
unexpectedMatcher, err = geodata.IPReg.BuildIPMatcher(ns.UnexpectedIp)
if err != nil {
return errors.New("failed to create unexpected ip matcher").Base(err).AtWarning()
return errors.New("failed to create unexpected ip matcher").Base(err)
}
}
+2 -2
View File
@@ -27,7 +27,7 @@ func (s *FakeDNSServer) IsDisableCache() bool {
func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, opt dns.IPOption) ([]net.IP, uint32, error) {
if f.fakeDNSEngine == nil {
return nil, 0, errors.New("Unable to locate a fake DNS Engine").AtError()
return nil, 0, errors.New("Unable to locate a fake DNS Engine")
}
var ips []net.Address
@@ -39,7 +39,7 @@ func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, opt dns.IPOp
netIP, err := toNetIP(ips)
if err != nil {
return nil, 0, errors.New("Unable to convert IP to net ip").Base(err).AtError()
return nil, 0, errors.New("Unable to convert IP to net ip").Base(err)
}
errors.LogInfo(ctx, f.Name(), " got answer: ", domain, " -> ", ips)
+6 -2
View File
@@ -89,10 +89,10 @@ func (g *Instance) startInternal() error {
g.active = true
if err := g.initAccessLogger(); err != nil {
return errors.New("failed to initialize access logger").Base(err).AtWarning()
return errors.New("failed to initialize access logger").Base(err)
}
if err := g.initErrorLogger(); err != nil {
return errors.New("failed to initialize error logger").Base(err).AtWarning()
return errors.New("failed to initialize error logger").Base(err)
}
return nil
@@ -141,6 +141,10 @@ func (g *Instance) Handle(msg log.Message) {
}
}
func (g *Instance) Severity() log.Severity {
return g.config.ErrorLogLevel
}
// Close implements common.Closable.Close().
func (g *Instance) Close() error {
errors.LogDebug(context.Background(), "Logger closing")
+1 -1
View File
@@ -66,7 +66,7 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
}
mss, err := internet.ToMemoryStreamConfig(receiverConfig.StreamSettings)
if err != nil {
return nil, errors.New("failed to parse stream config").Base(err).AtWarning()
return nil, errors.New("failed to parse stream config").Base(err)
}
newCtx := session.ContextWithInbound(ctx, &session.Inbound{Tag: tag, Source: src})
+1 -1
View File
@@ -165,7 +165,7 @@ func NewHandler(ctx context.Context, config *core.InboundHandlerConfig) (inbound
receiverSettings, ok := rawReceiverSettings.(*proxyman.ReceiverConfig)
if !ok {
return nil, errors.New("not a ReceiverConfig").AtError()
return nil, errors.New("not a ReceiverConfig")
}
streamSettings := receiverSettings.StreamSettings
+2 -2
View File
@@ -142,7 +142,7 @@ func (w *tcpWorker) Start() error {
go w.callback(conn)
})
if err != nil {
return errors.New("failed to listen TCP on ", w.port).AtWarning().Base(err)
return errors.New("failed to listen TCP on ", w.port).Base(err)
}
w.hub = hub
return nil
@@ -528,7 +528,7 @@ func (w *dsWorker) Start() error {
go w.callback(conn)
})
if err != nil {
return errors.New("failed to listen Unix Domain Socket on ", w.address).AtWarning().Base(err)
return errors.New("failed to listen Unix Domain Socket on ", w.address).Base(err)
}
w.hub = hub
return nil
+2 -2
View File
@@ -87,7 +87,7 @@ func NewHandler(ctx context.Context, config *core.OutboundHandlerConfig) (outbou
h.senderSettings = s
mss, err := internet.ToMemoryStreamConfig(s.StreamSettings)
if err != nil {
return nil, errors.New("failed to parse stream settings").Base(err).AtWarning()
return nil, errors.New("failed to parse stream settings").Base(err)
}
h.streamSettings = mss
default:
@@ -217,7 +217,7 @@ func (h *Handler) Dispatch(ctx context.Context, link *transport.Link) {
if ob.Target.Network == net.Network_UDP && ob.Target.Port == 443 {
switch h.udp443 {
case "reject":
test(errors.New("XUDP rejected UDP/443 traffic").AtInfo())
test(errors.New("XUDP rejected UDP/443 traffic"))
return
case "skip":
goto out
+2 -2
View File
@@ -68,13 +68,13 @@ func (p *Portal) HandleConnection(ctx context.Context, link *transport.Link) err
outbounds := session.OutboundsFromContext(ctx)
ob := outbounds[len(outbounds)-1]
if ob == nil {
return errors.New("outbound metadata not found").AtError()
return errors.New("outbound metadata not found")
}
if isDomain(ob.Target, p.domain) {
muxClient, err := mux.NewClientWorker(*link, mux.ClientStrategy{})
if err != nil {
return errors.New("failed to create mux client worker").Base(err).AtWarning()
return errors.New("failed to create mux client worker").Base(err)
}
worker, err := NewPortalWorker(muxClient)
+2 -2
View File
@@ -115,7 +115,7 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
}
if conds.Len() == 0 {
return nil, errors.New("this rule has no effective fields").AtWarning()
return nil, errors.New("this rule has no effective fields")
}
return conds, nil
@@ -145,7 +145,7 @@ func (br *BalancingRule) Build(ohm outbound.Manager, dispatcher routing.Dispatch
}
s, ok := i.(*StrategyLeastLoadConfig)
if !ok {
return nil, errors.New("not a StrategyLeastLoadConfig").AtError()
return nil, errors.New("not a StrategyLeastLoadConfig")
}
leastLoadStrategy := NewLeastLoadStrategy(s)
return &Balancer{
+13 -65
View File
@@ -18,17 +18,12 @@ type hasInnerError interface {
Unwrap() error
}
type hasSeverity interface {
Severity() log.Severity
}
// Error is an error object with underlying error.
type Error struct {
prefix []interface{}
message []interface{}
caller string
inner error
severity log.Severity
prefix []interface{}
message []interface{}
caller string
inner error
}
// Error implements error.Error().
@@ -69,46 +64,6 @@ func (err *Error) Base(e error) *Error {
return err
}
func (err *Error) atSeverity(s log.Severity) *Error {
err.severity = s
return err
}
func (err *Error) Severity() log.Severity {
if err.inner == nil {
return err.severity
}
if s, ok := err.inner.(hasSeverity); ok {
as := s.Severity()
if as < err.severity {
return as
}
}
return err.severity
}
// AtDebug sets the severity to debug.
func (err *Error) AtDebug() *Error {
return err.atSeverity(log.Severity_Debug)
}
// AtInfo sets the severity to info.
func (err *Error) AtInfo() *Error {
return err.atSeverity(log.Severity_Info)
}
// AtWarning sets the severity to warning.
func (err *Error) AtWarning() *Error {
return err.atSeverity(log.Severity_Warning)
}
// AtError sets the severity to error.
func (err *Error) AtError() *Error {
return err.atSeverity(log.Severity_Error)
}
// String returns the string representation of this error.
func (err *Error) String() string {
return err.Error()
@@ -132,9 +87,8 @@ func New(msg ...interface{}) *Error {
details = details[:i]
}
return &Error{
message: msg,
severity: log.Severity_Info,
caller: details,
message: msg,
caller: details,
}
}
@@ -171,6 +125,9 @@ func LogErrorInner(ctx context.Context, inner error, msg ...interface{}) {
}
func doLog(ctx context.Context, inner error, severity log.Severity, msg ...interface{}) {
if log.GetSeverity() < severity {
return
}
pc, _, _, _ := runtime.Caller(2)
details := runtime.FuncForPC(pc).Name()
if len(details) >= trim {
@@ -181,10 +138,9 @@ func doLog(ctx context.Context, inner error, severity log.Severity, msg ...inter
details = details[:i]
}
err := &Error{
message: msg,
severity: severity,
caller: details,
inner: inner,
message: msg,
caller: details,
inner: inner,
}
if ctx != nil && ctx != context.Background() {
id := uint32(c.IDFromContext(ctx))
@@ -193,7 +149,7 @@ func doLog(ctx context.Context, inner error, severity log.Severity, msg ...inter
}
}
log.Record(&log.GeneralMessage{
Severity: GetSeverity(err),
Severity: severity,
Content: err,
})
}
@@ -217,11 +173,3 @@ L:
}
return err
}
// GetSeverity returns the actual severity of the error, including inner errors.
func GetSeverity(err error) log.Severity {
if s, ok := err.(hasSeverity); ok {
return s.Severity()
}
return log.Severity_Info
}
+6 -15
View File
@@ -7,30 +7,21 @@ import (
"github.com/google/go-cmp/cmp"
. "github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/log"
)
func TestError(t *testing.T) {
err := New("TestError")
if v := GetSeverity(err); v != log.Severity_Info {
t.Error("severity: ", v)
if v := err.Error(); !strings.Contains(v, "TestError") {
t.Error("error: ", v)
}
err = New("TestError2").Base(io.EOF)
if v := GetSeverity(err); v != log.Severity_Info {
t.Error("severity: ", v)
if v := err.Error(); !strings.Contains(v, "EOF") {
t.Error("error: ", v)
}
err = New("TestError3").Base(io.EOF).AtWarning()
if v := GetSeverity(err); v != log.Severity_Warning {
t.Error("severity: ", v)
}
err = New("TestError4").Base(io.EOF).AtWarning()
err = New("TestError5").Base(err)
if v := GetSeverity(err); v != log.Severity_Warning {
t.Error("severity: ", v)
}
err = New("TestError3").Base(io.EOF)
err = New("TestError4").Base(err)
if v := err.Error(); !strings.Contains(v, "EOF") {
t.Error("error: ", v)
}
+21 -25
View File
@@ -1,7 +1,7 @@
package log // import "github.com/xtls/xray-core/common/log"
import (
"sync"
"sync/atomic"
"github.com/xtls/xray-core/common/serial"
)
@@ -29,36 +29,32 @@ func (m *GeneralMessage) String() string {
// Record writes a message into log stream.
func Record(msg Message) {
logHandler.Handle(msg)
if h := logHandler.Load(); h != nil {
(*h).Handle(msg)
}
}
var logHandler syncHandler
type SeverityLogger interface {
Handler
Severity() Severity
}
func GetSeverity() Severity {
if h := logHandler.Load(); h != nil {
if sh, ok := (*h).(SeverityLogger); ok {
return sh.Severity()
}
}
// log everything by default
return Severity_Debug
}
var logHandler atomic.Pointer[Handler]
// RegisterHandler registers a new handler as current log handler. Previous registered handler will be discarded.
func RegisterHandler(handler Handler) {
if handler == nil {
panic("Log handler is nil")
}
logHandler.Set(handler)
}
type syncHandler struct {
sync.RWMutex
Handler
}
func (h *syncHandler) Handle(msg Message) {
h.RLock()
defer h.RUnlock()
if h.Handler != nil {
h.Handler.Handle(msg)
}
}
func (h *syncHandler) Set(handler Handler) {
h.Lock()
defer h.Unlock()
h.Handler = handler
logHandler.Store(&handler)
}
+4
View File
@@ -68,6 +68,10 @@ func (l *serverityLogger) Handle(msg Message) {
}
}
func (l *serverityLogger) Severity() Severity {
return l.logLevel
}
func (l *generalLogger) run() {
defer l.access.Signal()
+1 -1
View File
@@ -38,7 +38,7 @@ func (m *ClientManager) Dispatch(ctx context.Context, link *transport.Link) erro
}
}
return errors.New("unable to find an available mux client").AtWarning()
return errors.New("unable to find an available mux client")
}
type WorkerPicker interface {
+1 -1
View File
@@ -117,7 +117,7 @@ func (f *FrameMetadata) Unmarshal(reader io.Reader, readSourceAndLocal bool) err
return err
}
if metaLen > 512 {
return errors.New("invalid metalen ", metaLen).AtError()
return errors.New("invalid metalen ", metaLen)
}
b := buf.New()
+1 -1
View File
@@ -351,7 +351,7 @@ func (w *ServerWorker) handleFrame(ctx context.Context, reader *buf.BufferedRead
err = w.handleStatusKeep(&meta, reader)
default:
status := meta.SessionStatus
return errors.New("unknown status: ", status).AtError()
return errors.New("unknown status: ", status)
}
if err != nil {
+1 -1
View File
@@ -7,7 +7,7 @@ import (
func (u *User) GetTypedAccount() (Account, error) {
if u.GetAccount() == nil {
return nil, errors.New("Account is missing").AtWarning()
return nil, errors.New("Account is missing")
}
rawAccount, err := u.Account.GetInstance()
+19 -6
View File
@@ -7,6 +7,7 @@ import (
"github.com/xtls/xray-core/common/ctx"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/features/outbound"
"github.com/xtls/xray-core/features/routing"
)
//go:linkname IndependentCancelCtx context.newCancelCtx
@@ -19,13 +20,14 @@ const (
isReverseMuxKey ctx.SessionKey = 4 // is reverse mux
sockoptSessionKey ctx.SessionKey = 5 // used by dokodemo to only receive sockopt.Mark
trackedConnectionErrorKey ctx.SessionKey = 6 // used by observer to get outbound error
timeoutOnlyKey ctx.SessionKey = 7 // mux context's child contexts to only cancel when its own traffic times out
allowedNetworkKey ctx.SessionKey = 8 // muxcool server control incoming request tcp/udp
fullHandlerKey ctx.SessionKey = 9 // outbound gets full handler
mitmAlpn11Key ctx.SessionKey = 10 // used by TLS dialer
mitmServerNameKey ctx.SessionKey = 11 // used by TLS dialer
dispatcherKey ctx.SessionKey = 7 // used by ss2022 inbounds to get dispatcher
timeoutOnlyKey ctx.SessionKey = 8 // mux context's child contexts to only cancel when its own traffic times out
allowedNetworkKey ctx.SessionKey = 9 // muxcool server control incoming request tcp/udp
fullHandlerKey ctx.SessionKey = 10 // outbound gets full handler
mitmAlpn11Key ctx.SessionKey = 11 // used by TLS dialer
mitmServerNameKey ctx.SessionKey = 12 // used by TLS dialer
streamSettingsKey ctx.SessionKey = 12
streamSettingsKey ctx.SessionKey = 13
)
func ContextWithInbound(ctx context.Context, inbound *Inbound) context.Context {
@@ -127,6 +129,17 @@ func TrackedConnectionError(ctx context.Context, tracker TrackedRequestErrorFeed
return context.WithValue(ctx, trackedConnectionErrorKey, tracker)
}
func ContextWithDispatcher(ctx context.Context, dispatcher routing.Dispatcher) context.Context {
return context.WithValue(ctx, dispatcherKey, dispatcher)
}
func DispatcherFromContext(ctx context.Context) routing.Dispatcher {
if dispatcher, ok := ctx.Value(dispatcherKey).(routing.Dispatcher); ok {
return dispatcher
}
return nil
}
func ContextWithTimeoutOnly(ctx context.Context, only bool) context.Context {
return context.WithValue(ctx, timeoutOnlyKey, only)
}
+53
View File
@@ -0,0 +1,53 @@
package singbridge
import (
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net"
)
func ToNetwork(network string) net.Network {
switch N.NetworkName(network) {
case N.NetworkTCP:
return net.Network_TCP
case N.NetworkUDP:
return net.Network_UDP
default:
return net.Network_Unknown
}
}
func ToDestination(socksaddr M.Socksaddr, network net.Network) (net.Destination, error) {
// IsFqdn() implicitly checks if the domain name is valid
if socksaddr.IsFqdn() {
return net.Destination{
Network: network,
Address: net.DomainAddress(socksaddr.Fqdn),
Port: net.Port(socksaddr.Port),
}, nil
}
// IsIP() implicitly checks if the IP address is valid
if socksaddr.IsIP() {
return net.Destination{
Network: network,
Address: net.IPAddress(socksaddr.Addr.AsSlice()),
Port: net.Port(socksaddr.Port),
}, nil
}
return net.Destination{}, errors.New("invalid socks address: ", socksaddr)
}
func ToSocksaddr(destination net.Destination) M.Socksaddr {
var addr M.Socksaddr
switch destination.Address.Family() {
case net.AddressFamilyDomain:
addr.Fqdn = destination.Address.Domain()
default:
addr.Addr = M.AddrFromIP(destination.Address.IP())
}
addr.Port = uint16(destination.Port)
return addr
}
+72
View File
@@ -0,0 +1,72 @@
package singbridge
import (
"context"
"os"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/net/cnc"
"github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/proxy"
"github.com/xtls/xray-core/transport"
"github.com/xtls/xray-core/transport/internet"
"github.com/xtls/xray-core/transport/pipe"
)
var _ N.Dialer = (*XrayDialer)(nil)
type XrayDialer struct {
internet.Dialer
}
func NewDialer(dialer internet.Dialer) *XrayDialer {
return &XrayDialer{dialer}
}
func (d *XrayDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
dest, err := ToDestination(destination, ToNetwork(network))
if err != nil {
return nil, err
}
return d.Dialer.Dial(ctx, dest)
}
func (d *XrayDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
return nil, os.ErrInvalid
}
type XrayOutboundDialer struct {
outbound proxy.Outbound
dialer internet.Dialer
}
func NewOutboundDialer(outbound proxy.Outbound, dialer internet.Dialer) *XrayOutboundDialer {
return &XrayOutboundDialer{outbound, dialer}
}
func (d *XrayOutboundDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
dest, err := ToDestination(destination, ToNetwork(network))
if err != nil {
return nil, err
}
outbounds := session.OutboundsFromContext(ctx)
if len(outbounds) == 0 {
outbounds = []*session.Outbound{{}}
ctx = session.ContextWithOutbounds(ctx, outbounds)
}
ob := outbounds[len(outbounds)-1]
ob.Target = dest
opts := []pipe.Option{pipe.WithSizeLimit(64 * 1024)}
uplinkReader, uplinkWriter := pipe.New(opts...)
downlinkReader, downlinkWriter := pipe.New(opts...)
conn := cnc.NewConnection(cnc.ConnectionInputMulti(downlinkWriter), cnc.ConnectionOutputMulti(uplinkReader))
go d.outbound.Process(ctx, &transport.Link{Reader: downlinkReader, Writer: uplinkWriter}, d.dialer)
return conn, nil
}
func (d *XrayOutboundDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
return nil, os.ErrInvalid
}
+10
View File
@@ -0,0 +1,10 @@
package singbridge
import E "github.com/sagernet/sing/common/exceptions"
func ReturnError(err error) error {
if E.IsClosedOrCanceled(err) {
return nil
}
return err
}
+58
View File
@@ -0,0 +1,58 @@
package singbridge
import (
"context"
"io"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/features/routing"
"github.com/xtls/xray-core/transport"
)
var (
_ N.TCPConnectionHandler = (*Dispatcher)(nil)
_ N.UDPConnectionHandler = (*Dispatcher)(nil)
)
type Dispatcher struct {
upstream routing.Dispatcher
newErrorFunc func(values ...any) *errors.Error
}
func NewDispatcher(dispatcher routing.Dispatcher, newErrorFunc func(values ...any) *errors.Error) *Dispatcher {
return &Dispatcher{
upstream: dispatcher,
newErrorFunc: newErrorFunc,
}
}
func (d *Dispatcher) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error {
dest, err := ToDestination(metadata.Destination, net.Network_TCP)
if err != nil {
return err
}
xConn := NewConn(conn)
return d.upstream.DispatchLink(ctx, dest, &transport.Link{
Reader: xConn,
Writer: xConn,
})
}
func (d *Dispatcher) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
dest, err := ToDestination(metadata.Destination, net.Network_UDP)
if err != nil {
return err
}
return d.upstream.DispatchLink(ctx, dest, &transport.Link{
Reader: buf.NewPacketReader(conn.(io.Reader)),
Writer: buf.NewWriter(conn.(io.Writer)),
})
}
func (d *Dispatcher) NewError(ctx context.Context, err error) {
errors.LogInfo(ctx, err.Error())
}
+70
View File
@@ -0,0 +1,70 @@
package singbridge
import (
"context"
"github.com/sagernet/sing/common/logger"
"github.com/xtls/xray-core/common/errors"
)
var _ logger.ContextLogger = (*XrayLogger)(nil)
type XrayLogger struct {
newError func(values ...any) *errors.Error
}
func NewLogger(newErrorFunc func(values ...any) *errors.Error) *XrayLogger {
return &XrayLogger{
newErrorFunc,
}
}
func (l *XrayLogger) Trace(args ...any) {
}
func (l *XrayLogger) Debug(args ...any) {
errors.LogDebug(context.Background(), args...)
}
func (l *XrayLogger) Info(args ...any) {
errors.LogInfo(context.Background(), args...)
}
func (l *XrayLogger) Warn(args ...any) {
errors.LogWarning(context.Background(), args...)
}
func (l *XrayLogger) Error(args ...any) {
errors.LogError(context.Background(), args...)
}
func (l *XrayLogger) Fatal(args ...any) {
}
func (l *XrayLogger) Panic(args ...any) {
}
func (l *XrayLogger) TraceContext(ctx context.Context, args ...any) {
}
func (l *XrayLogger) DebugContext(ctx context.Context, args ...any) {
errors.LogDebug(ctx, args...)
}
func (l *XrayLogger) InfoContext(ctx context.Context, args ...any) {
errors.LogInfo(ctx, args...)
}
func (l *XrayLogger) WarnContext(ctx context.Context, args ...any) {
errors.LogWarning(ctx, args...)
}
func (l *XrayLogger) ErrorContext(ctx context.Context, args ...any) {
errors.LogError(ctx, args...)
}
func (l *XrayLogger) FatalContext(ctx context.Context, args ...any) {
}
func (l *XrayLogger) PanicContext(ctx context.Context, args ...any) {
}
+107
View File
@@ -0,0 +1,107 @@
package singbridge
import (
"context"
"time"
B "github.com/sagernet/sing/common/buf"
"github.com/sagernet/sing/common/bufio"
M "github.com/sagernet/sing/common/metadata"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/signal"
"github.com/xtls/xray-core/transport"
)
func CopyPacketConn(ctx context.Context, inboundConn net.Conn, link *transport.Link, destination net.Destination, serverConn net.PacketConn) error {
cancel := func() {
common.Interrupt(link.Reader)
common.Interrupt(serverConn)
}
conn := &PacketConnWrapper{
Reader: link.Reader,
Writer: link.Writer,
Dest: destination,
Conn: inboundConn,
T: signal.CancelAfterInactivity(ctx, cancel, 300*time.Second),
}
return ReturnError(bufio.CopyPacketConn(ctx, conn, bufio.NewPacketConn(serverConn)))
}
type PacketConnWrapper struct {
buf.Reader
buf.Writer
net.Conn
Dest net.Destination
cached buf.MultiBuffer
// A simple patch to avoid goroutine leak since sing infra cannot awake read block by write err
T *signal.ActivityTimer
}
func (w *PacketConnWrapper) ReadPacket(buffer *B.Buffer) (addr M.Socksaddr, err error) {
w.T.Update()
defer func() {
if err != nil {
// uplinkonly
w.T.SetTimeout(2 * time.Second)
}
}()
if w.cached != nil {
mb, bb := buf.SplitFirst(w.cached)
if bb == nil {
w.cached = nil
} else {
buffer.Write(bb.Bytes())
w.cached = mb
var destination net.Destination
if bb.UDP != nil {
destination = *bb.UDP
} else {
destination = w.Dest
}
bb.Release()
return ToSocksaddr(destination), nil
}
}
mb, err := w.ReadMultiBuffer()
nb, bb := buf.SplitFirst(mb)
if bb == nil {
return M.Socksaddr{}, nil
} else {
buffer.Write(bb.Bytes())
w.cached = nb
var destination net.Destination
if bb.UDP != nil {
destination = *bb.UDP
} else {
destination = w.Dest
}
bb.Release()
return ToSocksaddr(destination), nil
}
}
func (w *PacketConnWrapper) WritePacket(buffer *B.Buffer, destination M.Socksaddr) (err error) {
w.T.Update()
defer func() {
if err != nil {
// downlinkonly
w.T.SetTimeout(5 * time.Second)
}
}()
endpoint, err := ToDestination(destination, net.Network_UDP)
if err != nil {
return err
}
vBuf := buf.New()
vBuf.Write(buffer.Bytes())
vBuf.UDP = &endpoint
return w.WriteMultiBuffer(buf.MultiBuffer{vBuf})
}
func (w *PacketConnWrapper) Close() error {
buf.ReleaseMulti(w.cached)
return nil
}
+81
View File
@@ -0,0 +1,81 @@
package singbridge
import (
"context"
"io"
"net"
"time"
"github.com/sagernet/sing/common/bufio"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/signal"
"github.com/xtls/xray-core/transport"
)
func CopyConn(ctx context.Context, inboundConn net.Conn, link *transport.Link, serverConn net.Conn) error {
conn := &PipeConnWrapper{
W: link.Writer,
Conn: inboundConn,
}
if ir, ok := link.Reader.(io.Reader); ok {
conn.R = ir
} else {
conn.R = &buf.BufferedReader{Reader: link.Reader}
}
cancel := func() {
common.Interrupt(link.Reader)
common.Interrupt(serverConn)
}
conn.T = signal.CancelAfterInactivity(ctx, cancel, 300*time.Second)
return ReturnError(bufio.CopyConn(ctx, conn, serverConn))
}
type PipeConnWrapper struct {
R io.Reader
W buf.Writer
net.Conn
// A simple patch to avoid goroutine leak since sing infra cannot awake read block by write err
T *signal.ActivityTimer
}
func (w *PipeConnWrapper) Close() error {
return nil
}
func (w *PipeConnWrapper) Read(b []byte) (n int, err error) {
w.T.Update()
n, err = w.R.Read(b)
if err != nil {
// uplinkonly
w.T.SetTimeout(2 * time.Second)
}
return
}
func (w *PipeConnWrapper) Write(p []byte) (n int, err error) {
w.T.Update()
n = len(p)
var mb buf.MultiBuffer
pLen := len(p)
for pLen > 0 {
buffer := buf.New()
if pLen > buf.Size {
_, err = buffer.Write(p[:buf.Size])
p = p[buf.Size:]
} else {
buffer.Write(p)
}
pLen -= int(buffer.Len())
mb = append(mb, buffer)
}
err = w.W.WriteMultiBuffer(mb)
if err != nil {
n = 0
buf.ReleaseMulti(mb)
// downlinkonly
w.T.SetTimeout(5 * time.Second)
}
return
}
+66
View File
@@ -0,0 +1,66 @@
package singbridge
import (
"time"
"github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/bufio"
N "github.com/sagernet/sing/common/network"
"github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/net"
)
var (
_ buf.Reader = (*Conn)(nil)
_ buf.TimeoutReader = (*Conn)(nil)
_ buf.Writer = (*Conn)(nil)
)
type Conn struct {
net.Conn
writer N.VectorisedWriter
}
func NewConn(conn net.Conn) *Conn {
writer, _ := bufio.CreateVectorisedWriter(conn)
return &Conn{
Conn: conn,
writer: writer,
}
}
func (c *Conn) ReadMultiBuffer() (buf.MultiBuffer, error) {
buffer, err := buf.ReadBuffer(c.Conn)
if err != nil {
return nil, err
}
return buf.MultiBuffer{buffer}, nil
}
func (c *Conn) ReadMultiBufferTimeout(duration time.Duration) (buf.MultiBuffer, error) {
err := c.SetReadDeadline(time.Now().Add(duration))
if err != nil {
return nil, err
}
defer c.SetReadDeadline(time.Time{})
return c.ReadMultiBuffer()
}
func (c *Conn) WriteMultiBuffer(bufferList buf.MultiBuffer) error {
defer buf.ReleaseMulti(bufferList)
if c.writer != nil {
bytesList := make([][]byte, len(bufferList))
for i, buffer := range bufferList {
bytesList[i] = buffer.Bytes()
}
return common.Error(bufio.WriteVectorised(c.writer, bytesList))
}
// Since this conn is only used by tun, we don't force buffer writes to merge.
for _, buffer := range bufferList {
_, err := c.Conn.Write(buffer.Bytes())
if err != nil {
return err
}
}
return nil
}
+2 -2
View File
@@ -16,7 +16,7 @@ var typeCreatorRegistry = make(map[reflect.Type]ConfigCreator)
func RegisterConfig(config interface{}, configCreator ConfigCreator) error {
configType := reflect.TypeOf(config)
if _, found := typeCreatorRegistry[configType]; found {
return errors.New(configType.Name() + " is already registered").AtError()
return errors.New(configType.Name() + " is already registered")
}
typeCreatorRegistry[configType] = configCreator
return nil
@@ -27,7 +27,7 @@ func CreateObject(ctx context.Context, config interface{}) (interface{}, error)
configType := reflect.TypeOf(config)
creator, found := typeCreatorRegistry[configType]
if !found {
return nil, errors.New(configType.String() + " is not registered").AtError()
return nil, errors.New(configType.String() + " is not registered")
}
return creator(ctx, config)
}
+4 -4
View File
@@ -125,7 +125,7 @@ func LoadConfig(formatName string, input interface{}) (*Config, error) {
}
if f == "" {
return nil, errors.New("Failed to get format of ", file).AtWarning()
return nil, errors.New("Failed to get format of ", file)
}
if f == "protobuf" {
@@ -142,7 +142,7 @@ func LoadConfig(formatName string, input interface{}) (*Config, error) {
if len(v) == 1 {
return configLoaderByName["protobuf"].Loader(v)
} else {
return nil, errors.New("Only one protobuf config file is allowed").AtWarning()
return nil, errors.New("Only one protobuf config file is allowed")
}
}
@@ -152,11 +152,11 @@ func LoadConfig(formatName string, input interface{}) (*Config, error) {
if f, found := configLoaderByName[formatName]; found {
return f.Loader(v)
} else {
return nil, errors.New("Unable to load config in", formatName).AtWarning()
return nil, errors.New("Unable to load config in", formatName)
}
}
return nil, errors.New("Unable to load config").AtWarning()
return nil, errors.New("Unable to load config")
}
func loadProtobufConfig(data []byte) (*Config, error) {
+2
View File
@@ -18,6 +18,8 @@ require (
github.com/pires/go-proxyproto v0.15.0
github.com/refraction-networking/utls v1.8.3-0.20260301010127-aa6edf4b11af
github.com/robfig/cron/v3 v3.0.1
github.com/sagernet/sing v0.5.1
github.com/sagernet/sing-shadowsocks v0.2.7
github.com/stretchr/testify v1.12.1
github.com/vishvananda/netlink v1.3.1
github.com/xtls/reality v0.0.0-20260908062103-8cdf7bf9c7f0
+4
View File
@@ -76,6 +76,10 @@ github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/go-internal v1.16.0 h1:O9DK+vNMDVGLr2BeZqmpLeMjiMNkuXfcqntWbZV6S5g=
github.com/rogpeppe/go-internal v1.16.0/go.mod h1:DrUVZyrJU+txYW5/1kwtXQSMFio52ZOxX7yM1VHvnxs=
github.com/sagernet/sing v0.5.1 h1:mhL/MZVq0TjuvHcpYcFtmSD1BFOxZ/+8ofbNZcg1k1Y=
github.com/sagernet/sing v0.5.1/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
github.com/sagernet/sing-shadowsocks v0.2.7 h1:zaopR1tbHEw5Nk6FAkM05wCslV6ahVegEZaKMv9ipx8=
github.com/sagernet/sing-shadowsocks v0.2.7/go.mod h1:0rIKJZBR65Qi0zwdKezt4s57y/Tl1ofkaq6NlkzVuyE=
github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE=
github.com/stretchr/testify v1.12.1/go.mod h1:MDEgiDPPsNp5cuIrHPPCyornHKgEVbtFUmoNlxoYthg=
github.com/vishvananda/netlink v1.3.1 h1:3AEMt62VKqz90r0tmNhog0r/PpWKmrEShJU0wJW6bV0=
+2 -2
View File
@@ -97,7 +97,7 @@ func (v *HTTPClientConfig) Build() (proto.Message, error) {
user.Email = v.Email
} else {
if err := json.Unmarshal(rawUser, user); err != nil {
return nil, errors.New("failed to parse HTTP user").Base(err).AtError()
return nil, errors.New("failed to parse HTTP user").Base(err)
}
}
account := new(HTTPAccount)
@@ -106,7 +106,7 @@ func (v *HTTPClientConfig) Build() (proto.Message, error) {
account.Password = v.Password
} else {
if err := json.Unmarshal(rawUser, account); err != nil {
return nil, errors.New("failed to parse HTTP account").Base(err).AtError()
return nil, errors.New("failed to parse HTTP account").Base(err)
}
}
user.Account = serial.ToTypedMessage(account.Build())
+1 -1
View File
@@ -18,7 +18,7 @@ func RegisterConfigureFilePostProcessingStage(name string, stage ConfigureFilePo
func PostProcessConfigureFile(conf *Config) error {
for k, v := range configureFilePostProcessingStages {
if err := v.Process(conf); err != nil {
return errors.New("Rejected by Postprocessing Stage ", k).AtError().Base(err)
return errors.New("Rejected by Postprocessing Stage ", k).Base(err)
}
}
return nil
+2 -2
View File
@@ -13,7 +13,7 @@ type ConfigCreatorCache map[string]ConfigCreator
func (v ConfigCreatorCache) RegisterCreator(id string, creator ConfigCreator) error {
if _, found := v[id]; found {
return errors.New(id, " already registered.").AtError()
return errors.New(id, " already registered.")
}
v[id] = creator
@@ -61,7 +61,7 @@ func (v *JSONConfigLoader) Load(raw []byte) (interface{}, string, error) {
}
rawID, found := obj[v.idKey]
if !found {
return nil, "", errors.New(v.idKey, " not found in JSON context").AtError()
return nil, "", errors.New(v.idKey, " not found in JSON context")
}
var id string
if err := json.Unmarshal(rawID, &id); err != nil {
+1 -1
View File
@@ -30,7 +30,7 @@ func MergeConfigFromFiles(files []*core.ConfigSource) (string, error) {
if j, ok := creflect.MarshalToJson(c, true); ok {
return j, nil
}
return "", errors.New("marshal to json failed.").AtError()
return "", errors.New("marshal to json failed.")
}
func mergeConfigs(files []*core.ConfigSource) (*conf.Config, error) {
+104 -4
View File
@@ -3,11 +3,14 @@ package conf
import (
"strings"
"github.com/sagernet/sing-shadowsocks/shadowaead_2022"
C "github.com/sagernet/sing/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/common/serial"
"github.com/xtls/xray-core/common/task"
"github.com/xtls/xray-core/proxy/shadowsocks"
"github.com/xtls/xray-core/proxy/shadowsocks_2022"
"google.golang.org/protobuf/proto"
)
@@ -27,10 +30,12 @@ func cipherFromString(c string) shadowsocks.CipherType {
}
type ShadowsocksUserConfig struct {
Cipher string `json:"method"`
Password string `json:"password"`
Level byte `json:"level"`
Email string `json:"email"`
Cipher string `json:"method"`
Password string `json:"password"`
Level byte `json:"level"`
Email string `json:"email"`
Address *Address `json:"address"`
Port uint16 `json:"port"`
}
type ShadowsocksServerConfig struct {
@@ -50,6 +55,10 @@ func (v *ShadowsocksServerConfig) Build() (proto.Message, error) {
v.Users = v.Clients
}
if C.Contains(shadowaead_2022.List, v.Cipher) {
return buildShadowsocks2022(v)
}
config := new(shadowsocks.ServerConfig)
config.Network = v.NetworkList.Build()
@@ -101,6 +110,72 @@ func (v *ShadowsocksServerConfig) Build() (proto.Message, error) {
return config, nil
}
func buildShadowsocks2022(v *ShadowsocksServerConfig) (proto.Message, error) {
if len(v.Users) == 0 {
config := new(shadowsocks_2022.ServerConfig)
config.Method = v.Cipher
config.Key = v.Password
config.Network = v.NetworkList.Build()
config.Email = v.Email
return config, nil
}
if v.Cipher == "" {
return nil, errors.New("shadowsocks 2022 (multi-user): missing server method")
}
if !strings.Contains(v.Cipher, "aes") {
return nil, errors.New("shadowsocks 2022 (multi-user): only blake3-aes-*-gcm methods are supported")
}
if v.Users[0].Address == nil {
config := new(shadowsocks_2022.MultiUserServerConfig)
config.Method = v.Cipher
config.Key = v.Password
config.Network = v.NetworkList.Build()
config.Users = make([]*protocol.User, len(v.Users))
processUser := func(idx int) error {
user := v.Users[idx]
if user.Cipher != "" {
return errors.New("shadowsocks 2022 (multi-user): users must have empty method")
}
account := &shadowsocks_2022.Account{
Key: user.Password,
}
config.Users[idx] = &protocol.User{
Email: user.Email,
Level: uint32(user.Level),
Account: serial.ToTypedMessage(account),
}
return nil
}
if err := task.ParallelForN(len(v.Users), processUser); err != nil {
return nil, err
}
return config, nil
}
config := new(shadowsocks_2022.RelayServerConfig)
config.Method = v.Cipher
config.Key = v.Password
config.Network = v.NetworkList.Build()
for _, user := range v.Users {
if user.Cipher != "" {
return nil, errors.New("shadowsocks 2022 (relay): users must have empty method")
}
if user.Address == nil {
return nil, errors.New("shadowsocks 2022 (relay): all users must have relay address")
}
config.Destinations = append(config.Destinations, &shadowsocks_2022.RelayDestination{
Key: user.Password,
Email: user.Email,
Address: user.Address.Build(),
Port: uint32(user.Port),
})
}
return config, nil
}
type ShadowsocksServerTarget struct {
Address *Address `json:"address"`
Port uint16 `json:"port"`
@@ -139,8 +214,33 @@ func (v *ShadowsocksClientConfig) Build() (proto.Message, error) {
return nil, errors.New(`Shadowsocks settings: "servers" should have one and only one member. Multiple endpoints in "servers" should use multiple Shadowsocks outbounds and routing balancer instead`)
}
if len(v.Servers) == 1 {
server := v.Servers[0]
if C.Contains(shadowaead_2022.List, server.Cipher) {
if server.Address == nil {
return nil, errors.New("Shadowsocks server address is not set.")
}
if server.Port == 0 {
return nil, errors.New("Invalid Shadowsocks port.")
}
if server.Password == "" {
return nil, errors.New("Shadowsocks password is not specified.")
}
config := new(shadowsocks_2022.ClientConfig)
config.Address = server.Address.Build()
config.Port = uint32(server.Port)
config.Method = server.Cipher
config.Key = server.Password
return config, nil
}
}
config := new(shadowsocks.ClientConfig)
for _, server := range v.Servers {
if C.Contains(shadowaead_2022.List, server.Cipher) {
return nil, errors.New("Shadowsocks 2022 accept no multi servers")
}
if server.Address == nil {
return nil, errors.New("Shadowsocks server address is not set.")
}
+2 -3
View File
@@ -44,7 +44,6 @@ func (v *SocksServerConfig) Build() (proto.Message, error) {
case AuthMethodUserPass:
config.AuthType = socks.AuthType_PASSWORD
default:
// errors.New("unknown socks auth method: ", v.AuthMethod, ". Default to noauth.").AtWarning().WriteToLog()
config.AuthType = socks.AuthType_NO_AUTH
}
@@ -115,7 +114,7 @@ func (v *SocksClientConfig) Build() (proto.Message, error) {
user.Email = v.Email
} else {
if err := json.Unmarshal(rawUser, user); err != nil {
return nil, errors.New("failed to parse Socks user").Base(err).AtError()
return nil, errors.New("failed to parse Socks user").Base(err)
}
}
account := new(SocksAccount)
@@ -124,7 +123,7 @@ func (v *SocksClientConfig) Build() (proto.Message, error) {
account.Password = v.Password
} else {
if err := json.Unmarshal(rawUser, account); err != nil {
return nil, errors.New("failed to parse socks account").Base(err).AtError()
return nil, errors.New("failed to parse socks account").Base(err)
}
}
user.Account = serial.ToTypedMessage(account.Build())
+4 -4
View File
@@ -121,7 +121,7 @@ func (v *AuthenticatorRequest) Build() (*http.RequestConfig, error) {
for _, key := range headerNames {
value := v.Headers[key]
if value == nil {
return nil, errors.New("empty HTTP header value: " + key).AtError()
return nil, errors.New("empty HTTP header value: " + key)
}
config.Header = append(config.Header, &http.Header{
Name: key,
@@ -189,7 +189,7 @@ func (v *AuthenticatorResponse) Build() (*http.ResponseConfig, error) {
for _, key := range headerNames {
value := v.Headers[key]
if value == nil {
return nil, errors.New("empty HTTP header value: " + key).AtError()
return nil, errors.New("empty HTTP header value: " + key)
}
config.Header = append(config.Header, &http.Header{
Name: key,
@@ -239,11 +239,11 @@ func (c *TCPConfig) Build() (proto.Message, error) {
if len(c.HeaderConfig) > 0 {
headerConfig, _, err := tcpHeaderLoader.Load(c.HeaderConfig)
if err != nil {
return nil, errors.New("invalid TCP header config").Base(err).AtError()
return nil, errors.New("invalid TCP header config").Base(err)
}
ts, err := headerConfig.(Buildable).Build()
if err != nil {
return nil, errors.New("invalid TCP header config").Base(err).AtError()
return nil, errors.New("invalid TCP header config").Base(err)
}
config.HeaderSettings = serial.ToTypedMessage(ts)
}
@@ -13,6 +13,7 @@ import (
"github.com/xtls/xray-core/infra/conf"
"github.com/xtls/xray-core/infra/conf/serial"
"github.com/xtls/xray-core/proxy/shadowsocks"
"github.com/xtls/xray-core/proxy/shadowsocks_2022"
"github.com/xtls/xray-core/proxy/trojan"
vlessin "github.com/xtls/xray-core/proxy/vless/inbound"
vmessin "github.com/xtls/xray-core/proxy/vmess/inbound"
@@ -85,6 +86,8 @@ func extractInboundUsers(inb *core.InboundHandlerConfig) []*protocol.User {
return ty.Users
case *shadowsocks.ServerConfig:
return ty.Users
case *shadowsocks_2022.MultiUserServerConfig:
return ty.Users
default:
fmt.Println("unsupported inbound type")
}
+5 -1
View File
@@ -4,6 +4,7 @@ import (
"context"
"crypto/rand"
"io"
"strings"
"sync/atomic"
"time"
@@ -163,9 +164,12 @@ func getDefaultFinalRule(inbound *session.Inbound) *FinalRule {
switch inbound.Name {
case "vless-reverse":
return defaultBlockAllRule
case "vless", "vmess", "trojan", "hysteria", "wireguard", "shadowsocks":
case "vless", "vmess", "trojan", "hysteria", "wireguard":
return defaultBlockPrivateRule
default:
if strings.HasPrefix(inbound.Name, "shadowsocks") {
return defaultBlockPrivateRule
}
}
return nil
}
+4 -8
View File
@@ -115,11 +115,7 @@ Start:
request, err := http.ReadRequest(reader)
if err != nil {
trace := errors.New("failed to read http request").Base(err)
if errors.Cause(err) != io.EOF && !isTimeout(errors.Cause(err)) {
trace.AtWarning()
}
return trace
return errors.New("failed to read http request").Base(err)
}
if len(s.config.Accounts) > 0 {
@@ -147,7 +143,7 @@ Start:
}
dest, err := http_proto.ParseHost(host, defaultPort)
if err != nil {
return errors.New("malformed proxy host: ", host).AtWarning().Base(err)
return errors.New("malformed proxy host: ", host).Base(err)
}
ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{
From: conn.RemoteAddr(),
@@ -262,7 +258,7 @@ func (s *Server) handlePlainHTTP(ctx context.Context, request *http.Request, wri
requestWriter := buf.NewBufferedWriter(link.Writer)
common.Must(requestWriter.SetBuffered(false))
if err := request.Write(requestWriter); err != nil {
return errors.New("failed to write whole request").Base(err).AtWarning()
return errors.New("failed to write whole request").Base(err)
}
return nil
}
@@ -299,7 +295,7 @@ func (s *Server) handlePlainHTTP(ctx context.Context, request *http.Request, wri
response.Header.Set("Proxy-Connection", "close")
}
if err := response.Write(writer); err != nil {
return errors.New("failed to write response").Base(err).AtWarning()
return errors.New("failed to write response").Base(err)
}
return nil
}
+1 -1
View File
@@ -62,7 +62,7 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
conn, err := dialer.Dial(hysteria.ContextWithDatagram(ctx, target.Network == net.Network_UDP), c.server.Destination)
if err != nil {
return errors.New("failed to find an available destination").AtWarning().Base(err)
return errors.New("failed to find an available destination").Base(err)
}
defer conn.Close()
errors.LogInfo(ctx, "tunneling request to ", target, " via ", target.Network, ":", c.server.Destination.NetAddr())
+2 -2
View File
@@ -40,11 +40,11 @@ func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
for _, user := range config.Users {
u, err := user.ToMemoryUser()
if err != nil {
return nil, errors.New("failed to get hysteria user").Base(err).AtError()
return nil, errors.New("failed to get hysteria user").Base(err)
}
if err := validator.Add(u); err != nil {
return nil, errors.New("failed to add user").Base(err).AtError()
return nil, errors.New("failed to add user").Base(err)
}
}
+1 -1
View File
@@ -56,7 +56,7 @@ func (l *Loopback) init(config *Config, dispatcherInstance routing.Dispatcher) e
if config.Sniffing.GetEnabled() {
request, err := proxyman.BuildSniffingRequest(config.Sniffing)
if err != nil {
return errors.New("failed to build loopback sniffing request").Base(err).AtError()
return errors.New("failed to build loopback sniffing request").Base(err)
}
l.sniffingRequest = request
}
+2 -2
View File
@@ -71,7 +71,7 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
return nil
})
if err != nil {
return errors.New("failed to find an available destination").AtWarning().Base(err)
return errors.New("failed to find an available destination").Base(err)
}
errors.LogInfo(ctx, "tunneling request to ", destination, " via ", network, ":", server.Destination.NetAddr())
@@ -124,7 +124,7 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
}
if err = buf.CopyOnceTimeout(link.Reader, bodyWriter, time.Millisecond*100); err != nil && err != buf.ErrNotTimeoutReader && err != buf.ErrReadTimeout {
return errors.New("failed to write A request payload").Base(err).AtWarning()
return errors.New("failed to write A request payload").Base(err)
}
if err := bufferedWriter.SetBuffered(false); err != nil {
+2 -2
View File
@@ -98,7 +98,7 @@ func ReadTCPSession(validator *Validator, reader io.Reader) (*protocol.RequestHe
iv := append([]byte(nil), buffer.BytesTo(ivLen)...)
r, err = account.Cipher.NewDecryptionReader(account.Key, iv, reader)
if err != nil {
return nil, nil, drain.WithError(drainer, reader, errors.New("failed to initialize decoding stream").Base(err).AtError())
return nil, nil, drain.WithError(drainer, reader, errors.New("failed to initialize decoding stream").Base(err))
}
}
}
@@ -146,7 +146,7 @@ func WriteTCPRequest(request *protocol.RequestHeader, writer io.Writer) (buf.Wri
w, err := account.Cipher.NewEncryptionWriter(account.Key, iv, writer)
if err != nil {
return nil, errors.New("failed to create encoding stream").Base(err).AtError()
return nil, errors.New("failed to create encoding stream").Base(err)
}
header := buf.New()
+3 -3
View File
@@ -34,11 +34,11 @@ func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
for _, user := range config.Users {
u, err := user.ToMemoryUser()
if err != nil {
return nil, errors.New("failed to get shadowsocks user").Base(err).AtError()
return nil, errors.New("failed to get shadowsocks user").Base(err)
}
if err := validator.Add(u); err != nil {
return nil, errors.New("failed to add user").Base(err).AtError()
return nil, errors.New("failed to add user").Base(err)
}
}
@@ -200,7 +200,7 @@ func (s *Server) handleUDPPayload(ctx context.Context, conn stat.Connection, dis
func (s *Server) handleConnection(ctx context.Context, conn stat.Connection, dispatcher routing.Dispatcher) error {
sessionPolicy := s.policyManager.ForLevel(0)
if err := conn.SetReadDeadline(time.Now().Add(sessionPolicy.Timeouts.Handshake)); err != nil {
return errors.New("unable to set read deadline").Base(err).AtWarning()
return errors.New("unable to set read deadline").Base(err)
}
bufferedReader := buf.BufferedReader{Reader: buf.NewReader(conn)}
+33
View File
@@ -0,0 +1,33 @@
package shadowsocks_2022
import (
"google.golang.org/protobuf/proto"
"github.com/xtls/xray-core/common/protocol"
)
// MemoryAccount is an account type converted from Account.
type MemoryAccount struct {
Key string
}
// AsAccount implements protocol.AsAccount.
func (u *Account) AsAccount() (protocol.Account, error) {
return &MemoryAccount{
Key: u.GetKey(),
}, nil
}
// Equals implements protocol.Account.Equals().
func (a *MemoryAccount) Equals(another protocol.Account) bool {
if account, ok := another.(*MemoryAccount); ok {
return a.Key == account.Key
}
return false
}
func (a *MemoryAccount) ToProto() proto.Message {
return &Account{
Key: a.Key,
}
}
+523
View File
@@ -0,0 +1,523 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v6.33.5
// source: proxy/shadowsocks_2022/config.proto
package shadowsocks_2022
import (
net "github.com/xtls/xray-core/common/net"
protocol "github.com/xtls/xray-core/common/protocol"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type ServerConfig struct {
state protoimpl.MessageState `protogen:"open.v1"`
Method string `protobuf:"bytes,1,opt,name=method,proto3" json:"method,omitempty"`
Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
Email string `protobuf:"bytes,3,opt,name=email,proto3" json:"email,omitempty"`
Level int32 `protobuf:"varint,4,opt,name=level,proto3" json:"level,omitempty"`
Network []net.Network `protobuf:"varint,5,rep,packed,name=network,proto3,enum=xray.common.net.Network" json:"network,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ServerConfig) Reset() {
*x = ServerConfig{}
mi := &file_proxy_shadowsocks_2022_config_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ServerConfig) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ServerConfig) ProtoMessage() {}
func (x *ServerConfig) ProtoReflect() protoreflect.Message {
mi := &file_proxy_shadowsocks_2022_config_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ServerConfig.ProtoReflect.Descriptor instead.
func (*ServerConfig) Descriptor() ([]byte, []int) {
return file_proxy_shadowsocks_2022_config_proto_rawDescGZIP(), []int{0}
}
func (x *ServerConfig) GetMethod() string {
if x != nil {
return x.Method
}
return ""
}
func (x *ServerConfig) GetKey() string {
if x != nil {
return x.Key
}
return ""
}
func (x *ServerConfig) GetEmail() string {
if x != nil {
return x.Email
}
return ""
}
func (x *ServerConfig) GetLevel() int32 {
if x != nil {
return x.Level
}
return 0
}
func (x *ServerConfig) GetNetwork() []net.Network {
if x != nil {
return x.Network
}
return nil
}
type MultiUserServerConfig struct {
state protoimpl.MessageState `protogen:"open.v1"`
Method string `protobuf:"bytes,1,opt,name=method,proto3" json:"method,omitempty"`
Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
Users []*protocol.User `protobuf:"bytes,3,rep,name=users,proto3" json:"users,omitempty"`
Network []net.Network `protobuf:"varint,4,rep,packed,name=network,proto3,enum=xray.common.net.Network" json:"network,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *MultiUserServerConfig) Reset() {
*x = MultiUserServerConfig{}
mi := &file_proxy_shadowsocks_2022_config_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *MultiUserServerConfig) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*MultiUserServerConfig) ProtoMessage() {}
func (x *MultiUserServerConfig) ProtoReflect() protoreflect.Message {
mi := &file_proxy_shadowsocks_2022_config_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use MultiUserServerConfig.ProtoReflect.Descriptor instead.
func (*MultiUserServerConfig) Descriptor() ([]byte, []int) {
return file_proxy_shadowsocks_2022_config_proto_rawDescGZIP(), []int{1}
}
func (x *MultiUserServerConfig) GetMethod() string {
if x != nil {
return x.Method
}
return ""
}
func (x *MultiUserServerConfig) GetKey() string {
if x != nil {
return x.Key
}
return ""
}
func (x *MultiUserServerConfig) GetUsers() []*protocol.User {
if x != nil {
return x.Users
}
return nil
}
func (x *MultiUserServerConfig) GetNetwork() []net.Network {
if x != nil {
return x.Network
}
return nil
}
type RelayDestination struct {
state protoimpl.MessageState `protogen:"open.v1"`
Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
Address *net.IPOrDomain `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"`
Port uint32 `protobuf:"varint,3,opt,name=port,proto3" json:"port,omitempty"`
Email string `protobuf:"bytes,4,opt,name=email,proto3" json:"email,omitempty"`
Level int32 `protobuf:"varint,5,opt,name=level,proto3" json:"level,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *RelayDestination) Reset() {
*x = RelayDestination{}
mi := &file_proxy_shadowsocks_2022_config_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *RelayDestination) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RelayDestination) ProtoMessage() {}
func (x *RelayDestination) ProtoReflect() protoreflect.Message {
mi := &file_proxy_shadowsocks_2022_config_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RelayDestination.ProtoReflect.Descriptor instead.
func (*RelayDestination) Descriptor() ([]byte, []int) {
return file_proxy_shadowsocks_2022_config_proto_rawDescGZIP(), []int{2}
}
func (x *RelayDestination) GetKey() string {
if x != nil {
return x.Key
}
return ""
}
func (x *RelayDestination) GetAddress() *net.IPOrDomain {
if x != nil {
return x.Address
}
return nil
}
func (x *RelayDestination) GetPort() uint32 {
if x != nil {
return x.Port
}
return 0
}
func (x *RelayDestination) GetEmail() string {
if x != nil {
return x.Email
}
return ""
}
func (x *RelayDestination) GetLevel() int32 {
if x != nil {
return x.Level
}
return 0
}
type RelayServerConfig struct {
state protoimpl.MessageState `protogen:"open.v1"`
Method string `protobuf:"bytes,1,opt,name=method,proto3" json:"method,omitempty"`
Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
Destinations []*RelayDestination `protobuf:"bytes,3,rep,name=destinations,proto3" json:"destinations,omitempty"`
Network []net.Network `protobuf:"varint,4,rep,packed,name=network,proto3,enum=xray.common.net.Network" json:"network,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *RelayServerConfig) Reset() {
*x = RelayServerConfig{}
mi := &file_proxy_shadowsocks_2022_config_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *RelayServerConfig) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RelayServerConfig) ProtoMessage() {}
func (x *RelayServerConfig) ProtoReflect() protoreflect.Message {
mi := &file_proxy_shadowsocks_2022_config_proto_msgTypes[3]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RelayServerConfig.ProtoReflect.Descriptor instead.
func (*RelayServerConfig) Descriptor() ([]byte, []int) {
return file_proxy_shadowsocks_2022_config_proto_rawDescGZIP(), []int{3}
}
func (x *RelayServerConfig) GetMethod() string {
if x != nil {
return x.Method
}
return ""
}
func (x *RelayServerConfig) GetKey() string {
if x != nil {
return x.Key
}
return ""
}
func (x *RelayServerConfig) GetDestinations() []*RelayDestination {
if x != nil {
return x.Destinations
}
return nil
}
func (x *RelayServerConfig) GetNetwork() []net.Network {
if x != nil {
return x.Network
}
return nil
}
type Account struct {
state protoimpl.MessageState `protogen:"open.v1"`
Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *Account) Reset() {
*x = Account{}
mi := &file_proxy_shadowsocks_2022_config_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *Account) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Account) ProtoMessage() {}
func (x *Account) ProtoReflect() protoreflect.Message {
mi := &file_proxy_shadowsocks_2022_config_proto_msgTypes[4]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Account.ProtoReflect.Descriptor instead.
func (*Account) Descriptor() ([]byte, []int) {
return file_proxy_shadowsocks_2022_config_proto_rawDescGZIP(), []int{4}
}
func (x *Account) GetKey() string {
if x != nil {
return x.Key
}
return ""
}
type ClientConfig struct {
state protoimpl.MessageState `protogen:"open.v1"`
Address *net.IPOrDomain `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
Port uint32 `protobuf:"varint,2,opt,name=port,proto3" json:"port,omitempty"`
Method string `protobuf:"bytes,3,opt,name=method,proto3" json:"method,omitempty"`
Key string `protobuf:"bytes,4,opt,name=key,proto3" json:"key,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ClientConfig) Reset() {
*x = ClientConfig{}
mi := &file_proxy_shadowsocks_2022_config_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ClientConfig) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ClientConfig) ProtoMessage() {}
func (x *ClientConfig) ProtoReflect() protoreflect.Message {
mi := &file_proxy_shadowsocks_2022_config_proto_msgTypes[5]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ClientConfig.ProtoReflect.Descriptor instead.
func (*ClientConfig) Descriptor() ([]byte, []int) {
return file_proxy_shadowsocks_2022_config_proto_rawDescGZIP(), []int{5}
}
func (x *ClientConfig) GetAddress() *net.IPOrDomain {
if x != nil {
return x.Address
}
return nil
}
func (x *ClientConfig) GetPort() uint32 {
if x != nil {
return x.Port
}
return 0
}
func (x *ClientConfig) GetMethod() string {
if x != nil {
return x.Method
}
return ""
}
func (x *ClientConfig) GetKey() string {
if x != nil {
return x.Key
}
return ""
}
var File_proxy_shadowsocks_2022_config_proto protoreflect.FileDescriptor
const file_proxy_shadowsocks_2022_config_proto_rawDesc = "" +
"\n" +
"#proxy/shadowsocks_2022/config.proto\x12\x1bxray.proxy.shadowsocks_2022\x1a\x18common/net/network.proto\x1a\x18common/net/address.proto\x1a\x1acommon/protocol/user.proto\"\x98\x01\n" +
"\fServerConfig\x12\x16\n" +
"\x06method\x18\x01 \x01(\tR\x06method\x12\x10\n" +
"\x03key\x18\x02 \x01(\tR\x03key\x12\x14\n" +
"\x05email\x18\x03 \x01(\tR\x05email\x12\x14\n" +
"\x05level\x18\x04 \x01(\x05R\x05level\x122\n" +
"\anetwork\x18\x05 \x03(\x0e2\x18.xray.common.net.NetworkR\anetwork\"\xa7\x01\n" +
"\x15MultiUserServerConfig\x12\x16\n" +
"\x06method\x18\x01 \x01(\tR\x06method\x12\x10\n" +
"\x03key\x18\x02 \x01(\tR\x03key\x120\n" +
"\x05users\x18\x03 \x03(\v2\x1a.xray.common.protocol.UserR\x05users\x122\n" +
"\anetwork\x18\x04 \x03(\x0e2\x18.xray.common.net.NetworkR\anetwork\"\x9b\x01\n" +
"\x10RelayDestination\x12\x10\n" +
"\x03key\x18\x01 \x01(\tR\x03key\x125\n" +
"\aaddress\x18\x02 \x01(\v2\x1b.xray.common.net.IPOrDomainR\aaddress\x12\x12\n" +
"\x04port\x18\x03 \x01(\rR\x04port\x12\x14\n" +
"\x05email\x18\x04 \x01(\tR\x05email\x12\x14\n" +
"\x05level\x18\x05 \x01(\x05R\x05level\"\xc4\x01\n" +
"\x11RelayServerConfig\x12\x16\n" +
"\x06method\x18\x01 \x01(\tR\x06method\x12\x10\n" +
"\x03key\x18\x02 \x01(\tR\x03key\x12Q\n" +
"\fdestinations\x18\x03 \x03(\v2-.xray.proxy.shadowsocks_2022.RelayDestinationR\fdestinations\x122\n" +
"\anetwork\x18\x04 \x03(\x0e2\x18.xray.common.net.NetworkR\anetwork\"\x1b\n" +
"\aAccount\x12\x10\n" +
"\x03key\x18\x01 \x01(\tR\x03key\"\x83\x01\n" +
"\fClientConfig\x125\n" +
"\aaddress\x18\x01 \x01(\v2\x1b.xray.common.net.IPOrDomainR\aaddress\x12\x12\n" +
"\x04port\x18\x02 \x01(\rR\x04port\x12\x16\n" +
"\x06method\x18\x03 \x01(\tR\x06method\x12\x10\n" +
"\x03key\x18\x04 \x01(\tR\x03keyBr\n" +
"\x1fcom.xray.proxy.shadowsocks_2022P\x01Z0github.com/xtls/xray-core/proxy/shadowsocks_2022\xaa\x02\x1aXray.Proxy.Shadowsocks2022b\x06proto3"
var (
file_proxy_shadowsocks_2022_config_proto_rawDescOnce sync.Once
file_proxy_shadowsocks_2022_config_proto_rawDescData []byte
)
func file_proxy_shadowsocks_2022_config_proto_rawDescGZIP() []byte {
file_proxy_shadowsocks_2022_config_proto_rawDescOnce.Do(func() {
file_proxy_shadowsocks_2022_config_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_proxy_shadowsocks_2022_config_proto_rawDesc), len(file_proxy_shadowsocks_2022_config_proto_rawDesc)))
})
return file_proxy_shadowsocks_2022_config_proto_rawDescData
}
var file_proxy_shadowsocks_2022_config_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_proxy_shadowsocks_2022_config_proto_goTypes = []any{
(*ServerConfig)(nil), // 0: xray.proxy.shadowsocks_2022.ServerConfig
(*MultiUserServerConfig)(nil), // 1: xray.proxy.shadowsocks_2022.MultiUserServerConfig
(*RelayDestination)(nil), // 2: xray.proxy.shadowsocks_2022.RelayDestination
(*RelayServerConfig)(nil), // 3: xray.proxy.shadowsocks_2022.RelayServerConfig
(*Account)(nil), // 4: xray.proxy.shadowsocks_2022.Account
(*ClientConfig)(nil), // 5: xray.proxy.shadowsocks_2022.ClientConfig
(net.Network)(0), // 6: xray.common.net.Network
(*protocol.User)(nil), // 7: xray.common.protocol.User
(*net.IPOrDomain)(nil), // 8: xray.common.net.IPOrDomain
}
var file_proxy_shadowsocks_2022_config_proto_depIdxs = []int32{
6, // 0: xray.proxy.shadowsocks_2022.ServerConfig.network:type_name -> xray.common.net.Network
7, // 1: xray.proxy.shadowsocks_2022.MultiUserServerConfig.users:type_name -> xray.common.protocol.User
6, // 2: xray.proxy.shadowsocks_2022.MultiUserServerConfig.network:type_name -> xray.common.net.Network
8, // 3: xray.proxy.shadowsocks_2022.RelayDestination.address:type_name -> xray.common.net.IPOrDomain
2, // 4: xray.proxy.shadowsocks_2022.RelayServerConfig.destinations:type_name -> xray.proxy.shadowsocks_2022.RelayDestination
6, // 5: xray.proxy.shadowsocks_2022.RelayServerConfig.network:type_name -> xray.common.net.Network
8, // 6: xray.proxy.shadowsocks_2022.ClientConfig.address:type_name -> xray.common.net.IPOrDomain
7, // [7:7] is the sub-list for method output_type
7, // [7:7] is the sub-list for method input_type
7, // [7:7] is the sub-list for extension type_name
7, // [7:7] is the sub-list for extension extendee
0, // [0:7] is the sub-list for field type_name
}
func init() { file_proxy_shadowsocks_2022_config_proto_init() }
func file_proxy_shadowsocks_2022_config_proto_init() {
if File_proxy_shadowsocks_2022_config_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_proxy_shadowsocks_2022_config_proto_rawDesc), len(file_proxy_shadowsocks_2022_config_proto_rawDesc)),
NumEnums: 0,
NumMessages: 6,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_proxy_shadowsocks_2022_config_proto_goTypes,
DependencyIndexes: file_proxy_shadowsocks_2022_config_proto_depIdxs,
MessageInfos: file_proxy_shadowsocks_2022_config_proto_msgTypes,
}.Build()
File_proxy_shadowsocks_2022_config_proto = out.File
file_proxy_shadowsocks_2022_config_proto_goTypes = nil
file_proxy_shadowsocks_2022_config_proto_depIdxs = nil
}
+52
View File
@@ -0,0 +1,52 @@
syntax = "proto3";
package xray.proxy.shadowsocks_2022;
option csharp_namespace = "Xray.Proxy.Shadowsocks2022";
option go_package = "github.com/xtls/xray-core/proxy/shadowsocks_2022";
option java_package = "com.xray.proxy.shadowsocks_2022";
option java_multiple_files = true;
import "common/net/network.proto";
import "common/net/address.proto";
import "common/protocol/user.proto";
message ServerConfig {
string method = 1;
string key = 2;
string email = 3;
int32 level = 4;
repeated xray.common.net.Network network = 5;
}
message MultiUserServerConfig {
string method = 1;
string key = 2;
repeated xray.common.protocol.User users = 3;
repeated xray.common.net.Network network = 4;
}
message RelayDestination {
string key = 1;
xray.common.net.IPOrDomain address = 2;
uint32 port = 3;
string email = 4;
int32 level = 5;
}
message RelayServerConfig {
string method = 1;
string key = 2;
repeated RelayDestination destinations = 3;
repeated xray.common.net.Network network = 4;
}
message Account {
string key = 1;
}
message ClientConfig {
xray.common.net.IPOrDomain address = 1;
uint32 port = 2;
string method = 3;
string key = 4;
}
+183
View File
@@ -0,0 +1,183 @@
package shadowsocks_2022
import (
"context"
"time"
shadowsocks "github.com/sagernet/sing-shadowsocks"
"github.com/sagernet/sing-shadowsocks/shadowaead_2022"
C "github.com/sagernet/sing/common"
B "github.com/sagernet/sing/common/buf"
"github.com/sagernet/sing/common/bufio"
E "github.com/sagernet/sing/common/exceptions"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/log"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/common/signal"
"github.com/xtls/xray-core/common/singbridge"
"github.com/xtls/xray-core/features/routing"
"github.com/xtls/xray-core/transport/internet/stat"
)
func init() {
common.Must(common.RegisterConfig((*ServerConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
return NewServer(ctx, config.(*ServerConfig))
}))
}
type Inbound struct {
networks []net.Network
service shadowsocks.Service
email string
level int
}
func NewServer(ctx context.Context, config *ServerConfig) (*Inbound, error) {
networks := config.Network
if len(networks) == 0 {
networks = []net.Network{
net.Network_TCP,
net.Network_UDP,
}
}
inbound := &Inbound{
networks: networks,
email: config.Email,
level: int(config.Level),
}
if !C.Contains(shadowaead_2022.List, config.Method) {
return nil, errors.New("unsupported method ", config.Method)
}
service, err := shadowaead_2022.NewServiceWithPassword(config.Method, config.Key, 500, inbound, nil)
if err != nil {
return nil, errors.New("create service").Base(err)
}
inbound.service = service
return inbound, nil
}
func (i *Inbound) Network() []net.Network {
return i.networks
}
func (i *Inbound) Process(ctx context.Context, network net.Network, connection stat.Connection, dispatcher routing.Dispatcher) error {
inbound := session.InboundFromContext(ctx)
inbound.Name = "shadowsocks-2022"
inbound.CanSpliceCopy = 3
var metadata M.Metadata
if inbound.Source.IsValid() {
metadata.Source = M.ParseSocksaddr(inbound.Source.NetAddr())
}
ctx = session.ContextWithDispatcher(ctx, dispatcher)
if network == net.Network_TCP {
return singbridge.ReturnError(i.service.NewConnection(ctx, connection, metadata))
} else {
reader := buf.NewReader(connection)
pc := &natPacketConn{connection}
for {
mb, err := reader.ReadMultiBuffer()
if err != nil {
buf.ReleaseMulti(mb)
return singbridge.ReturnError(err)
}
for _, buffer := range mb {
packet := B.As(buffer.Bytes()).ToOwned()
buffer.Release()
err = i.service.NewPacket(ctx, pc, packet, metadata)
if err != nil {
packet.Release()
buf.ReleaseMulti(mb)
return err
}
}
}
}
}
func (i *Inbound) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error {
inbound := session.InboundFromContext(ctx)
inbound.User = &protocol.MemoryUser{
Email: i.email,
Level: uint32(i.level),
}
ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{
From: metadata.Source,
To: metadata.Destination,
Status: log.AccessAccepted,
Email: i.email,
})
errors.LogInfo(ctx, "tunnelling request to tcp:", metadata.Destination)
dispatcher := session.DispatcherFromContext(ctx)
destination, err := singbridge.ToDestination(metadata.Destination, net.Network_TCP)
if err != nil {
return err
}
link, err := dispatcher.Dispatch(ctx, destination)
if err != nil {
return err
}
return singbridge.CopyConn(ctx, nil, link, conn)
}
func (i *Inbound) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
inbound := session.InboundFromContext(ctx)
inbound.User = &protocol.MemoryUser{
Email: i.email,
Level: uint32(i.level),
}
ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{
From: metadata.Source,
To: metadata.Destination,
Status: log.AccessAccepted,
Email: i.email,
})
errors.LogInfo(ctx, "tunnelling request to udp:", metadata.Destination)
dispatcher := session.DispatcherFromContext(ctx)
destination, err := singbridge.ToDestination(metadata.Destination, net.Network_UDP)
if err != nil {
return err
}
link, err := dispatcher.Dispatch(ctx, destination)
if err != nil {
return err
}
outConn := &singbridge.PacketConnWrapper{
Reader: link.Reader,
Writer: link.Writer,
Dest: destination,
T: signal.CancelAfterInactivity(ctx, func() {
common.Interrupt(link.Reader)
}, 300*time.Second),
}
return bufio.CopyPacketConn(ctx, conn, outConn)
}
func (i *Inbound) NewError(ctx context.Context, err error) {
if E.IsClosed(err) {
return
}
errors.LogWarning(ctx, err.Error())
}
type natPacketConn struct {
net.Conn
}
func (c *natPacketConn) ReadPacket(buffer *B.Buffer) (addr M.Socksaddr, err error) {
_, err = buffer.ReadFrom(c)
return
}
func (c *natPacketConn) WritePacket(buffer *B.Buffer, addr M.Socksaddr) error {
_, err := buffer.WriteTo(c)
return err
}
+290
View File
@@ -0,0 +1,290 @@
package shadowsocks_2022
import (
"context"
"encoding/base64"
"strconv"
"strings"
"sync"
"time"
"github.com/sagernet/sing-shadowsocks/shadowaead_2022"
C "github.com/sagernet/sing/common"
A "github.com/sagernet/sing/common/auth"
B "github.com/sagernet/sing/common/buf"
"github.com/sagernet/sing/common/bufio"
E "github.com/sagernet/sing/common/exceptions"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/log"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/common/signal"
"github.com/xtls/xray-core/common/singbridge"
"github.com/xtls/xray-core/common/uuid"
"github.com/xtls/xray-core/features/routing"
"github.com/xtls/xray-core/transport/internet/stat"
)
func init() {
common.Must(common.RegisterConfig((*MultiUserServerConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
return NewMultiServer(ctx, config.(*MultiUserServerConfig))
}))
}
type MultiUserInbound struct {
sync.Mutex
networks []net.Network
users []*protocol.MemoryUser
service *shadowaead_2022.MultiService[int]
}
func NewMultiServer(ctx context.Context, config *MultiUserServerConfig) (*MultiUserInbound, error) {
networks := config.Network
if len(networks) == 0 {
networks = []net.Network{
net.Network_TCP,
net.Network_UDP,
}
}
memUsers := []*protocol.MemoryUser{}
for i, user := range config.Users {
if user.Email == "" {
u := uuid.New()
user.Email = "unnamed-user-" + strconv.Itoa(i) + "-" + u.String()
}
u, err := user.ToMemoryUser()
if err != nil {
return nil, errors.New("failed to get shadowsocks user").Base(err)
}
memUsers = append(memUsers, u)
}
inbound := &MultiUserInbound{
networks: networks,
users: memUsers,
}
if config.Key == "" {
return nil, errors.New("missing key")
}
psk, err := base64.StdEncoding.DecodeString(config.Key)
if err != nil {
return nil, errors.New("parse config").Base(err)
}
service, err := shadowaead_2022.NewMultiService[int](config.Method, psk, 500, inbound, nil)
if err != nil {
return nil, errors.New("create service").Base(err)
}
err = service.UpdateUsersWithPasswords(
C.MapIndexed(memUsers, func(index int, it *protocol.MemoryUser) int { return index }),
C.Map(memUsers, func(it *protocol.MemoryUser) string { return it.Account.(*MemoryAccount).Key }),
)
if err != nil {
return nil, errors.New("create service").Base(err)
}
inbound.service = service
return inbound, nil
}
// AddUser implements proxy.UserManager.AddUser().
func (i *MultiUserInbound) AddUser(ctx context.Context, u *protocol.MemoryUser) error {
i.Lock()
defer i.Unlock()
if u.Email != "" {
for idx := range i.users {
if i.users[idx].Email == u.Email {
return errors.New("User ", u.Email, " already exists.")
}
}
}
i.users = append(i.users, u)
// sync to multi service
// Considering implements shadowsocks2022 in xray-core may have better performance.
i.service.UpdateUsersWithPasswords(
C.MapIndexed(i.users, func(index int, it *protocol.MemoryUser) int { return index }),
C.Map(i.users, func(it *protocol.MemoryUser) string { return it.Account.(*MemoryAccount).Key }),
)
return nil
}
// RemoveUser implements proxy.UserManager.RemoveUser().
func (i *MultiUserInbound) RemoveUser(ctx context.Context, email string) error {
if email == "" {
return errors.New("Email must not be empty.")
}
i.Lock()
defer i.Unlock()
idx := -1
for ii, u := range i.users {
if strings.EqualFold(u.Email, email) {
idx = ii
break
}
}
if idx == -1 {
return errors.New("User ", email, " not found.")
}
ulen := len(i.users)
i.users[idx] = i.users[ulen-1]
i.users[ulen-1] = nil
i.users = i.users[:ulen-1]
// sync to multi service
// Considering implements shadowsocks2022 in xray-core may have better performance.
i.service.UpdateUsersWithPasswords(
C.MapIndexed(i.users, func(index int, it *protocol.MemoryUser) int { return index }),
C.Map(i.users, func(it *protocol.MemoryUser) string { return it.Account.(*MemoryAccount).Key }),
)
return nil
}
// GetUser implements proxy.UserManager.GetUser().
func (i *MultiUserInbound) GetUser(ctx context.Context, email string) *protocol.MemoryUser {
if email == "" {
return nil
}
i.Lock()
defer i.Unlock()
for _, u := range i.users {
if strings.EqualFold(u.Email, email) {
return u
}
}
return nil
}
// GetUsers implements proxy.UserManager.GetUsers().
func (i *MultiUserInbound) GetUsers(ctx context.Context) []*protocol.MemoryUser {
i.Lock()
defer i.Unlock()
dst := make([]*protocol.MemoryUser, len(i.users))
copy(dst, i.users)
return dst
}
// GetUsersCount implements proxy.UserManager.GetUsersCount().
func (i *MultiUserInbound) GetUsersCount(context.Context) int64 {
i.Lock()
defer i.Unlock()
return int64(len(i.users))
}
func (i *MultiUserInbound) Network() []net.Network {
return i.networks
}
func (i *MultiUserInbound) Process(ctx context.Context, network net.Network, connection stat.Connection, dispatcher routing.Dispatcher) error {
inbound := session.InboundFromContext(ctx)
inbound.Name = "shadowsocks-2022-multi"
inbound.CanSpliceCopy = 3
var metadata M.Metadata
if inbound.Source.IsValid() {
metadata.Source = M.ParseSocksaddr(inbound.Source.NetAddr())
}
ctx = session.ContextWithDispatcher(ctx, dispatcher)
if network == net.Network_TCP {
return singbridge.ReturnError(i.service.NewConnection(ctx, connection, metadata))
} else {
reader := buf.NewReader(connection)
pc := &natPacketConn{connection}
for {
mb, err := reader.ReadMultiBuffer()
if err != nil {
buf.ReleaseMulti(mb)
return singbridge.ReturnError(err)
}
for _, buffer := range mb {
packet := B.As(buffer.Bytes()).ToOwned()
buffer.Release()
err = i.service.NewPacket(ctx, pc, packet, metadata)
if err != nil {
packet.Release()
buf.ReleaseMulti(mb)
return err
}
}
}
}
}
func (i *MultiUserInbound) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error {
inbound := session.InboundFromContext(ctx)
userInt, _ := A.UserFromContext[int](ctx)
user := i.users[userInt]
inbound.User = user
ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{
From: metadata.Source,
To: metadata.Destination,
Status: log.AccessAccepted,
Email: user.Email,
})
errors.LogInfo(ctx, "tunnelling request to tcp:", metadata.Destination)
dispatcher := session.DispatcherFromContext(ctx)
destination, err := singbridge.ToDestination(metadata.Destination, net.Network_TCP)
if err != nil {
return err
}
link, err := dispatcher.Dispatch(ctx, destination)
if err != nil {
return err
}
return singbridge.CopyConn(ctx, conn, link, conn)
}
func (i *MultiUserInbound) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
inbound := session.InboundFromContext(ctx)
userInt, _ := A.UserFromContext[int](ctx)
user := i.users[userInt]
inbound.User = user
ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{
From: metadata.Source,
To: metadata.Destination,
Status: log.AccessAccepted,
Email: user.Email,
})
errors.LogInfo(ctx, "tunnelling request to udp:", metadata.Destination)
dispatcher := session.DispatcherFromContext(ctx)
destination, err := singbridge.ToDestination(metadata.Destination, net.Network_UDP)
if err != nil {
return err
}
link, err := dispatcher.Dispatch(ctx, destination)
if err != nil {
return err
}
outConn := &singbridge.PacketConnWrapper{
Reader: link.Reader,
Writer: link.Writer,
Dest: destination,
T: signal.CancelAfterInactivity(ctx, func() {
common.Interrupt(link.Reader)
}, 300*time.Second),
}
return bufio.CopyPacketConn(ctx, conn, outConn)
}
func (i *MultiUserInbound) NewError(ctx context.Context, err error) {
if E.IsClosed(err) {
return
}
errors.LogWarning(ctx, err.Error())
}
+194
View File
@@ -0,0 +1,194 @@
package shadowsocks_2022
import (
"context"
"strconv"
"strings"
"time"
"github.com/sagernet/sing-shadowsocks/shadowaead_2022"
C "github.com/sagernet/sing/common"
A "github.com/sagernet/sing/common/auth"
B "github.com/sagernet/sing/common/buf"
"github.com/sagernet/sing/common/bufio"
E "github.com/sagernet/sing/common/exceptions"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/log"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/common/signal"
"github.com/xtls/xray-core/common/singbridge"
"github.com/xtls/xray-core/common/uuid"
"github.com/xtls/xray-core/features/routing"
"github.com/xtls/xray-core/transport/internet/stat"
)
func init() {
common.Must(common.RegisterConfig((*RelayServerConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
return NewRelayServer(ctx, config.(*RelayServerConfig))
}))
}
type RelayInbound struct {
networks []net.Network
destinations []*RelayDestination
service *shadowaead_2022.RelayService[int]
}
func NewRelayServer(ctx context.Context, config *RelayServerConfig) (*RelayInbound, error) {
networks := config.Network
if len(networks) == 0 {
networks = []net.Network{
net.Network_TCP,
net.Network_UDP,
}
}
inbound := &RelayInbound{
networks: networks,
destinations: config.Destinations,
}
if !C.Contains(shadowaead_2022.List, config.Method) || !strings.Contains(config.Method, "aes") {
return nil, errors.New("unsupported method ", config.Method)
}
service, err := shadowaead_2022.NewRelayServiceWithPassword[int](config.Method, config.Key, 500, inbound)
if err != nil {
return nil, errors.New("create service").Base(err)
}
for i, destination := range config.Destinations {
if destination.Email == "" {
u := uuid.New()
destination.Email = "unnamed-destination-" + strconv.Itoa(i) + "-" + u.String()
}
}
err = service.UpdateUsersWithPasswords(
C.MapIndexed(config.Destinations, func(index int, it *RelayDestination) int { return index }),
C.Map(config.Destinations, func(it *RelayDestination) string { return it.Key }),
C.Map(config.Destinations, func(it *RelayDestination) M.Socksaddr {
return singbridge.ToSocksaddr(net.Destination{
Address: it.Address.AsAddress(),
Port: net.Port(it.Port),
})
}),
)
if err != nil {
return nil, errors.New("create service").Base(err)
}
inbound.service = service
return inbound, nil
}
func (i *RelayInbound) Network() []net.Network {
return i.networks
}
func (i *RelayInbound) Process(ctx context.Context, network net.Network, connection stat.Connection, dispatcher routing.Dispatcher) error {
inbound := session.InboundFromContext(ctx)
inbound.Name = "shadowsocks-2022-relay"
inbound.CanSpliceCopy = 3
var metadata M.Metadata
if inbound.Source.IsValid() {
metadata.Source = M.ParseSocksaddr(inbound.Source.NetAddr())
}
ctx = session.ContextWithDispatcher(ctx, dispatcher)
if network == net.Network_TCP {
return singbridge.ReturnError(i.service.NewConnection(ctx, connection, metadata))
} else {
reader := buf.NewReader(connection)
pc := &natPacketConn{connection}
for {
mb, err := reader.ReadMultiBuffer()
if err != nil {
buf.ReleaseMulti(mb)
return singbridge.ReturnError(err)
}
for _, buffer := range mb {
packet := B.As(buffer.Bytes()).ToOwned()
buffer.Release()
err = i.service.NewPacket(ctx, pc, packet, metadata)
if err != nil {
packet.Release()
buf.ReleaseMulti(mb)
return err
}
}
}
}
}
func (i *RelayInbound) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error {
inbound := session.InboundFromContext(ctx)
userInt, _ := A.UserFromContext[int](ctx)
user := i.destinations[userInt]
inbound.User = &protocol.MemoryUser{
Email: user.Email,
Level: uint32(user.Level),
}
ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{
From: metadata.Source,
To: metadata.Destination,
Status: log.AccessAccepted,
Email: user.Email,
})
errors.LogInfo(ctx, "tunnelling request to tcp:", metadata.Destination)
dispatcher := session.DispatcherFromContext(ctx)
destination, err := singbridge.ToDestination(metadata.Destination, net.Network_TCP)
if err != nil {
return err
}
link, err := dispatcher.Dispatch(ctx, destination)
if err != nil {
return err
}
return singbridge.CopyConn(ctx, nil, link, conn)
}
func (i *RelayInbound) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
inbound := session.InboundFromContext(ctx)
userInt, _ := A.UserFromContext[int](ctx)
user := i.destinations[userInt]
inbound.User = &protocol.MemoryUser{
Email: user.Email,
Level: uint32(user.Level),
}
ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{
From: metadata.Source,
To: metadata.Destination,
Status: log.AccessAccepted,
Email: user.Email,
})
errors.LogInfo(ctx, "tunnelling request to udp:", metadata.Destination)
dispatcher := session.DispatcherFromContext(ctx)
destination, err := singbridge.ToDestination(metadata.Destination, net.Network_UDP)
if err != nil {
return err
}
link, err := dispatcher.Dispatch(ctx, destination)
if err != nil {
return err
}
outConn := &singbridge.PacketConnWrapper{
Reader: link.Reader,
Writer: link.Writer,
Dest: destination,
T: signal.CancelAfterInactivity(ctx, func() {
common.Interrupt(link.Reader)
}, 300*time.Second),
}
return bufio.CopyPacketConn(ctx, conn, outConn)
}
func (i *RelayInbound) NewError(ctx context.Context, err error) {
if E.IsClosed(err) {
return
}
errors.LogWarning(ctx, err.Error())
}
+147
View File
@@ -0,0 +1,147 @@
package shadowsocks_2022
import (
"context"
"time"
shadowsocks "github.com/sagernet/sing-shadowsocks"
"github.com/sagernet/sing-shadowsocks/shadowaead_2022"
C "github.com/sagernet/sing/common"
B "github.com/sagernet/sing/common/buf"
"github.com/sagernet/sing/common/bufio"
N "github.com/sagernet/sing/common/network"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/common/signal"
"github.com/xtls/xray-core/common/singbridge"
"github.com/xtls/xray-core/transport"
"github.com/xtls/xray-core/transport/internet"
)
func init() {
common.Must(common.RegisterConfig((*ClientConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
return NewClient(ctx, config.(*ClientConfig))
}))
}
type Outbound struct {
ctx context.Context
server net.Destination
method shadowsocks.Method
}
func NewClient(ctx context.Context, config *ClientConfig) (*Outbound, error) {
o := &Outbound{
ctx: ctx,
server: net.Destination{
Address: config.Address.AsAddress(),
Port: net.Port(config.Port),
Network: net.Network_TCP,
},
}
if C.Contains(shadowaead_2022.List, config.Method) {
if config.Key == "" {
return nil, errors.New("missing psk")
}
method, err := shadowaead_2022.NewWithPassword(config.Method, config.Key, nil)
if err != nil {
return nil, errors.New("create method").Base(err)
}
o.method = method
} else {
return nil, errors.New("unknown method ", config.Method)
}
return o, nil
}
func (o *Outbound) Process(ctx context.Context, link *transport.Link, dialer internet.Dialer) error {
var inboundConn net.Conn
inbound := session.InboundFromContext(ctx)
if inbound != nil {
inboundConn = inbound.Conn
}
outbounds := session.OutboundsFromContext(ctx)
ob := outbounds[len(outbounds)-1]
if !ob.Target.IsValid() {
return errors.New("target not specified")
}
ob.Name = "shadowsocks-2022"
ob.CanSpliceCopy = 3
destination := ob.Target
network := destination.Network
errors.LogInfo(ctx, "tunneling request to ", destination, " via ", o.server.NetAddr())
serverDestination := o.server
serverDestination.Network = network
connection, err := dialer.Dial(ctx, serverDestination)
if err != nil {
return errors.New("failed to connect to server").Base(err)
}
defer connection.Close()
if session.TimeoutOnlyFromContext(ctx) {
ctx, _ = context.WithCancel(context.Background())
}
if network == net.Network_TCP {
serverConn := o.method.DialEarlyConn(connection, singbridge.ToSocksaddr(destination))
var handshake bool
if timeoutReader, isTimeoutReader := link.Reader.(buf.TimeoutReader); isTimeoutReader {
mb, err := timeoutReader.ReadMultiBufferTimeout(time.Millisecond * 100)
if err != nil && err != buf.ErrNotTimeoutReader && err != buf.ErrReadTimeout {
return errors.New("read payload").Base(err)
}
payload := B.New()
for {
payload.Reset()
nb, n := buf.SplitBytes(mb, payload.FreeBytes())
if n > 0 {
payload.Truncate(n)
_, err = serverConn.Write(payload.Bytes())
if err != nil {
payload.Release()
return errors.New("write payload").Base(err)
}
handshake = true
}
if nb.IsEmpty() {
break
}
mb = nb
}
payload.Release()
}
if !handshake {
_, err = serverConn.Write(nil)
if err != nil {
return errors.New("client handshake").Base(err)
}
}
return singbridge.CopyConn(ctx, inboundConn, link, serverConn)
} else {
var packetConn N.PacketConn
if pc, isPacketConn := inboundConn.(N.PacketConn); isPacketConn {
packetConn = pc
} else if nc, isNetPacket := inboundConn.(net.PacketConn); isNetPacket {
packetConn = bufio.NewPacketConn(nc)
} else {
packetConn = &singbridge.PacketConnWrapper{
Reader: link.Reader,
Writer: link.Writer,
Conn: inboundConn,
Dest: destination,
T: signal.CancelAfterInactivity(ctx, func() {
common.Interrupt(link.Reader)
}, 300*time.Second),
}
}
serverConn := o.method.DialPacketConn(connection)
return singbridge.ReturnError(bufio.CopyPacketConn(ctx, packetConn, serverConn))
}
}
@@ -0,0 +1 @@
package shadowsocks_2022
+1 -1
View File
@@ -105,7 +105,7 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
}
udpRequest, err := ClientHandshake(request, conn, conn)
if err != nil {
return errors.New("failed to establish connection to server").AtWarning().Base(err)
return errors.New("failed to establish connection to server").Base(err)
}
if udpRequest != nil {
if udpRequest.Address == net.AnyIP || udpRequest.Address == net.AnyIPv6 {
+2 -2
View File
@@ -458,10 +458,10 @@ func ClientHandshake(request *protocol.RequestHeader, reader io.Reader, writer i
}
if b.Byte(0) != socks5Version {
return nil, errors.New("unexpected server version: ", b.Byte(0)).AtWarning()
return nil, errors.New("unexpected server version: ", b.Byte(0))
}
if b.Byte(1) != authByte {
return nil, errors.New("auth method not supported.").AtWarning()
return nil, errors.New("auth method not supported.")
}
if authByte == authPassword {
+5 -5
View File
@@ -69,7 +69,7 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
return nil
})
if err != nil {
return errors.New("failed to find an available destination").AtWarning().Base(err)
return errors.New("failed to find an available destination").Base(err)
}
errors.LogInfo(ctx, "tunneling request to ", destination, " via ", server.Destination.NetAddr())
@@ -116,21 +116,21 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
// write some request payload to buffer
if err = buf.CopyOnceTimeout(link.Reader, bodyWriter, time.Millisecond*100); err != nil && err != buf.ErrNotTimeoutReader && err != buf.ErrReadTimeout {
return errors.New("failed to write A request payload").Base(err).AtWarning()
return errors.New("failed to write A request payload").Base(err)
}
// Flush; bufferWriter.WriteMultiBuffer now is bufferWriter.writer.WriteMultiBuffer
if err = bufferWriter.SetBuffered(false); err != nil {
return errors.New("failed to flush payload").Base(err).AtWarning()
return errors.New("failed to flush payload").Base(err)
}
// Send header if not sent yet
if _, err = connWriter.Write([]byte{}); err != nil {
return err.(*errors.Error).AtWarning()
return err
}
if err = buf.Copy(link.Reader, bodyWriter, buf.UpdateActivity(timer)); err != nil {
return errors.New("failed to transfer request payload").Base(err).AtInfo()
return errors.New("failed to transfer request payload").Base(err)
}
return nil
+12 -12
View File
@@ -47,11 +47,11 @@ func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
for _, user := range config.Users {
u, err := user.ToMemoryUser()
if err != nil {
return nil, errors.New("failed to get trojan user").Base(err).AtError()
return nil, errors.New("failed to get trojan user").Base(err)
}
if err := validator.Add(u); err != nil {
return nil, errors.New("failed to add user").Base(err).AtError()
return nil, errors.New("failed to add user").Base(err)
}
}
@@ -151,7 +151,7 @@ func (s *Server) Process(ctx context.Context, network net.Network, conn stat.Con
sessionPolicy := s.policyManager.ForLevel(0)
if err := conn.SetReadDeadline(time.Now().Add(sessionPolicy.Timeouts.Handshake)); err != nil {
return errors.New("unable to set read deadline").Base(err).AtWarning()
return errors.New("unable to set read deadline").Base(err)
}
first := buf.FromBytes(make([]byte, buf.Size))
@@ -219,7 +219,7 @@ func (s *Server) Process(ctx context.Context, network net.Network, conn stat.Con
destination := clientReader.Target
if err := conn.SetReadDeadline(time.Time{}); err != nil {
return errors.New("unable to set read deadline").Base(err).AtWarning()
return errors.New("unable to set read deadline").Base(err)
}
inbound := session.InboundFromContext(ctx)
@@ -402,7 +402,7 @@ func (s *Server) fallback(ctx context.Context, err error, sessionPolicy policy.S
}
apfb := napfb[name]
if apfb == nil {
return errors.New(`failed to find the default "name" config`).AtWarning()
return errors.New(`failed to find the default "name" config`)
}
if apfb[alpn] == nil {
@@ -410,7 +410,7 @@ func (s *Server) fallback(ctx context.Context, err error, sessionPolicy policy.S
}
pfb := apfb[alpn]
if pfb == nil {
return errors.New(`failed to find the default "alpn" config`).AtWarning()
return errors.New(`failed to find the default "alpn" config`)
}
path := ""
@@ -444,7 +444,7 @@ func (s *Server) fallback(ctx context.Context, err error, sessionPolicy policy.S
}
fb := pfb[path]
if fb == nil {
return errors.New(`failed to find the default "path" config`).AtWarning()
return errors.New(`failed to find the default "path" config`)
}
ctx, cancel := context.WithCancel(ctx)
@@ -460,7 +460,7 @@ func (s *Server) fallback(ctx context.Context, err error, sessionPolicy policy.S
}
return nil
}); err != nil {
return errors.New("failed to dial to " + fb.Dest).Base(err).AtWarning()
return errors.New("failed to dial to " + fb.Dest).Base(err)
}
defer conn.Close()
@@ -520,11 +520,11 @@ func (s *Server) fallback(ctx context.Context, err error, sessionPolicy policy.S
common.Must2(pro.Write([]byte{byte(p1 >> 8), byte(p1), byte(p2 >> 8), byte(p2)}))
}
if err := serverWriter.WriteMultiBuffer(buf.MultiBuffer{pro}); err != nil {
return errors.New("failed to set PROXY protocol v", fb.Xver).Base(err).AtWarning()
return errors.New("failed to set PROXY protocol v", fb.Xver).Base(err)
}
}
if err := buf.Copy(reader, serverWriter, buf.UpdateActivity(timer)); err != nil {
return errors.New("failed to fallback request payload").Base(err).AtInfo()
return errors.New("failed to fallback request payload").Base(err)
}
return nil
}
@@ -534,7 +534,7 @@ func (s *Server) fallback(ctx context.Context, err error, sessionPolicy policy.S
getResponse := func() error {
defer timer.SetTimeout(sessionPolicy.Timeouts.UplinkOnly)
if err := buf.Copy(serverReader, writer, buf.UpdateActivity(timer)); err != nil {
return errors.New("failed to deliver response payload").Base(err).AtInfo()
return errors.New("failed to deliver response payload").Base(err)
}
return nil
}
@@ -542,7 +542,7 @@ func (s *Server) fallback(ctx context.Context, err error, sessionPolicy policy.S
if err := task.Run(ctx, task.OnSuccess(postRequest, task.Close(serverWriter)), task.OnSuccess(getResponse, task.Close(writer))); err != nil {
common.Must(common.Interrupt(serverReader))
common.Must(common.Interrupt(serverWriter))
return errors.New("fallback ends").Base(err).AtInfo()
return errors.New("fallback ends").Base(err)
}
return nil
+1 -1
View File
@@ -12,7 +12,7 @@ import (
func (a *Account) AsAccount() (protocol.Account, error) {
id, err := uuid.ParseString(a.Id)
if err != nil {
return nil, errors.New("failed to parse ID").Base(err).AtError()
return nil, errors.New("failed to parse ID").Base(err)
}
return &MemoryAccount{
ID: protocol.NewID(id),
+25 -25
View File
@@ -61,10 +61,10 @@ func init() {
for _, user := range c.Users {
u, err := user.ToMemoryUser()
if err != nil {
return nil, errors.New("failed to get VLESS user").Base(err).AtError()
return nil, errors.New("failed to get VLESS user").Base(err)
}
if err := validator.Add(u); err != nil {
return nil, errors.New("failed to initiate user").Base(err).AtError()
return nil, errors.New("failed to initiate user").Base(err)
}
}
@@ -110,7 +110,7 @@ func New(ctx context.Context, config *Config, dc dns.Client, validator vless.Val
}
handler.decryption = &encryption.ServerInstance{}
if err := handler.decryption.Init(nfsSKeysBytes, config.XorMode, config.SecondsFrom, config.SecondsTo, config.Padding); err != nil {
return nil, errors.New("failed to use decryption").Base(err).AtError()
return nil, errors.New("failed to use decryption").Base(err)
}
}
@@ -128,7 +128,7 @@ func New(ctx context.Context, config *Config, dc dns.Client, validator vless.Val
/*
if fb.Path != "" {
if r, err := regexp.Compile(fb.Path); err != nil {
return nil, errors.New("invalid path regexp").Base(err).AtError()
return nil, errors.New("invalid path regexp").Base(err)
} else {
handler.regexps[fb.Path] = r
}
@@ -274,13 +274,13 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
if h.decryption != nil {
var err error
if connection, err = h.decryption.Handshake(connection, nil); err != nil {
return errors.New("ML-KEM-768 handshake failed").Base(err).AtInfo()
return errors.New("ML-KEM-768 handshake failed").Base(err)
}
}
sessionPolicy := h.policyManager.ForLevel(0)
if err := connection.SetReadDeadline(time.Now().Add(sessionPolicy.Timeouts.Handshake)); err != nil {
return errors.New("unable to set read deadline").Base(err).AtWarning()
return errors.New("unable to set read deadline").Base(err)
}
first := buf.FromBytes(make([]byte, buf.Size))
@@ -352,7 +352,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
}
apfb := napfb[name]
if apfb == nil {
return errors.New(`failed to find the default "name" config`).AtWarning()
return errors.New(`failed to find the default "name" config`)
}
if apfb[alpn] == nil {
@@ -360,7 +360,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
}
pfb := apfb[alpn]
if pfb == nil {
return errors.New(`failed to find the default "alpn" config`).AtWarning()
return errors.New(`failed to find the default "alpn" config`)
}
path := ""
@@ -369,7 +369,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
if lines := bytes.Split(firstBytes, []byte{'\r', '\n'}); len(lines) > 1 {
if s := bytes.Split(lines[0], []byte{' '}); len(s) == 3 {
if len(s[0]) < 8 && len(s[1]) > 0 && len(s[2]) == 8 {
errors.New("realPath = " + string(s[1])).AtInfo().WriteToLog(sid)
errors.New("realPath = " + string(s[1])).WriteToLog(sid)
for _, fb := range pfb {
if fb.Path != "" && h.regexps[fb.Path].Match(s[1]) {
path = fb.Path
@@ -409,7 +409,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
}
fb := pfb[path]
if fb == nil {
return errors.New(`failed to find the default "path" config`).AtWarning()
return errors.New(`failed to find the default "path" config`)
}
ctx, cancel := context.WithCancel(ctx)
@@ -425,7 +425,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
}
return nil
}); err != nil {
return errors.New("failed to dial to " + fb.Dest).Base(err).AtWarning()
return errors.New("failed to dial to " + fb.Dest).Base(err)
}
defer conn.Close()
@@ -485,11 +485,11 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
pro.Write([]byte{byte(p1 >> 8), byte(p1), byte(p2 >> 8), byte(p2)})
}
if err := serverWriter.WriteMultiBuffer(buf.MultiBuffer{pro}); err != nil {
return errors.New("failed to set PROXY protocol v", fb.Xver).Base(err).AtWarning()
return errors.New("failed to set PROXY protocol v", fb.Xver).Base(err)
}
}
if err := buf.Copy(reader, serverWriter, buf.UpdateActivity(timer)); err != nil {
return errors.New("failed to fallback request payload").Base(err).AtInfo()
return errors.New("failed to fallback request payload").Base(err)
}
return nil
}
@@ -499,7 +499,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
getResponse := func() error {
defer timer.SetTimeout(sessionPolicy.Timeouts.UplinkOnly)
if err := buf.Copy(serverReader, writer, buf.UpdateActivity(timer)); err != nil {
return errors.New("failed to deliver response payload").Base(err).AtInfo()
return errors.New("failed to deliver response payload").Base(err)
}
return nil
}
@@ -507,7 +507,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
if err := task.Run(ctx, task.OnSuccess(postRequest, task.Close(serverWriter)), task.OnSuccess(getResponse, task.Close(writer))); err != nil {
common.Interrupt(serverReader)
common.Interrupt(serverWriter)
return errors.New("fallback ends").Base(err).AtInfo()
return errors.New("fallback ends").Base(err)
}
return nil
}
@@ -519,7 +519,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
Status: log.AccessRejected,
Reason: err,
})
err = errors.New("invalid request from ", connection.RemoteAddr()).Base(err).AtInfo()
err = errors.New("invalid request from ", connection.RemoteAddr()).Base(err)
}
return err
}
@@ -555,7 +555,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
inbound.CanSpliceCopy = 2
switch request.Command {
case protocol.RequestCommandUDP:
return errors.New(requestAddons.Flow + " doesn't support UDP").AtWarning()
return errors.New(requestAddons.Flow + " doesn't support UDP")
case protocol.RequestCommandMux, protocol.RequestCommandRvs:
inbound.CanSpliceCopy = 3
fallthrough // we will break Mux connections that contain TCP requests
@@ -570,7 +570,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
p = uintptr(unsafe.Pointer(commonConn))
} else if tlsConn, ok := iConn.(*tls.Conn); ok {
if tlsConn.ConnectionState().Version != gotls.VersionTLS13 {
return errors.New(`failed to use `+requestAddons.Flow+`, found outer tls version `, tlsConn.ConnectionState().Version).AtWarning()
return errors.New(`failed to use `+requestAddons.Flow+`, found outer tls version `, tlsConn.ConnectionState().Version)
}
t = reflect.TypeOf(tlsConn.Conn).Elem()
p = uintptr(unsafe.Pointer(tlsConn.Conn))
@@ -578,7 +578,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
t = reflect.TypeOf(realityConn.Conn).Elem()
p = uintptr(unsafe.Pointer(realityConn.Conn))
} else {
return errors.New("XTLS only supports TLS and REALITY directly for now.").AtWarning()
return errors.New("XTLS only supports TLS and REALITY directly for now.")
}
i, _ := t.FieldByName("input")
r, _ := t.FieldByName("rawInput")
@@ -586,15 +586,15 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
rawInput = (*bytes.Buffer)(unsafe.Pointer(p + r.Offset))
}
} else {
return errors.New("account " + account.ID.String() + " is not able to use the flow " + requestAddons.Flow).AtWarning()
return errors.New("account " + account.ID.String() + " is not able to use the flow " + requestAddons.Flow)
}
case "":
inbound.CanSpliceCopy = 3
if account.Flow == vless.XRV && (request.Command == protocol.RequestCommandTCP || isMuxAndNotXUDP(request, first)) {
return errors.New("account " + account.ID.String() + " is rejected since the client flow is empty. Note that the pure TLS proxy has certain TLS in TLS characters.").AtWarning()
return errors.New("account " + account.ID.String() + " is rejected since the client flow is empty. Note that the pure TLS proxy has certain TLS in TLS characters.")
}
default:
return errors.New("unknown request flow " + requestAddons.Flow).AtWarning()
return errors.New("unknown request flow " + requestAddons.Flow)
}
if request.Command != protocol.RequestCommandMux {
@@ -617,7 +617,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
bufferWriter := buf.NewBufferedWriter(buf.NewWriter(connection))
if err := encoding.EncodeResponseHeader(bufferWriter, request, responseAddons); err != nil {
return errors.New("failed to encode response header").Base(err).AtWarning()
return errors.New("failed to encode response header").Base(err)
}
clientWriter := encoding.EncodeBodyAddons(bufferWriter, request, requestAddons, trafficState, false, ctx, connection, nil)
bufferWriter.SetFlushNext()
@@ -654,11 +654,11 @@ func (r *Reverse) Tag() string {
func (r *Reverse) NewMux(ctx context.Context, link *transport.Link, observer features.Feature) error {
muxClient, err := mux.NewClientWorker(*link, mux.ClientStrategy{})
if err != nil {
return errors.New("failed to create mux client worker").Base(err).AtWarning()
return errors.New("failed to create mux client worker").Base(err)
}
worker, err := reverse.NewPortalWorker(muxClient)
if err != nil {
return errors.New("failed to create portal worker").Base(err).AtWarning()
return errors.New("failed to create portal worker").Base(err)
}
r.picker.AddWorker(worker)
if burstObs, ok := observer.(extension.BurstObservatory); ok {
+18 -18
View File
@@ -73,7 +73,7 @@ func New(ctx context.Context, config *Config) (*Handler, error) {
}
server, err := protocol.NewServerSpecFromPB(config.Vnext)
if err != nil {
return nil, errors.New("failed to get server spec").Base(err).AtError()
return nil, errors.New("failed to get server spec").Base(err)
}
v := core.MustFromContext(ctx)
@@ -93,7 +93,7 @@ func New(ctx context.Context, config *Config) (*Handler, error) {
}
handler.encryption = &encryption.ClientInstance{}
if err := handler.encryption.Init(nfsPKeysBytes, a.XorMode, a.Seconds, a.Padding); err != nil {
return nil, errors.New("failed to use encryption").Base(err).AtError()
return nil, errors.New("failed to use encryption").Base(err)
}
}
@@ -106,7 +106,7 @@ func New(ctx context.Context, config *Config) (*Handler, error) {
if sc := a.Reverse.Sniffing; sc != nil && sc.Enabled {
request, err := proxymanConfig.BuildSniffingRequest(sc)
if err != nil {
return nil, errors.New("failed to build reverse sniffing request").Base(err).AtError()
return nil, errors.New("failed to build reverse sniffing request").Base(err)
}
rvsCtx = session.ContextWithContent(rvsCtx, &session.Content{
SniffingRequest: request,
@@ -149,7 +149,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
outbounds := session.OutboundsFromContext(ctx)
ob := outbounds[len(outbounds)-1]
if !ob.Target.IsValid() && ob.Target.Address.String() != "v1.rvs.cool" {
return errors.New("target not specified").AtError()
return errors.New("target not specified")
}
ob.Name = "vless"
@@ -178,7 +178,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
for {
connTime := <-h.preConns
if connTime == nil {
return errors.New("closed handler").AtWarning()
return errors.New("closed handler")
}
if time.Now().Before(connTime.Expire) {
conn = connTime.Conn
@@ -197,7 +197,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
}
return nil
}); err != nil {
return errors.New("failed to find an available destination").Base(err).AtWarning()
return errors.New("failed to find an available destination").Base(err)
}
}
defer conn.Close()
@@ -209,7 +209,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
if h.encryption != nil {
var err error
if conn, err = h.encryption.Handshake(conn); err != nil {
return errors.New("ML-KEM-768 handshake failed").Base(err).AtInfo()
return errors.New("ML-KEM-768 handshake failed").Base(err)
}
}
@@ -223,7 +223,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
command = protocol.RequestCommandMux
case "v1.rvs.cool":
if target.Network != net.Network_Unknown {
return errors.New("nice try baby").AtError()
return errors.New("nice try baby")
}
command = protocol.RequestCommandRvs
}
@@ -256,7 +256,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
switch request.Command {
case protocol.RequestCommandUDP:
if !allowUDP443 && request.Port == 443 {
return errors.New("XTLS rejected UDP/443 traffic").AtInfo()
return errors.New("XTLS rejected UDP/443 traffic")
}
case protocol.RequestCommandMux:
fallthrough // let server break Mux connections that contain TCP requests
@@ -279,7 +279,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
t = reflect.TypeOf(realityConn.Conn).Elem()
p = uintptr(unsafe.Pointer(realityConn.Conn))
} else {
return errors.New("XTLS only supports TLS and REALITY directly for now.").AtWarning()
return errors.New("XTLS only supports TLS and REALITY directly for now.")
}
i, _ := t.FieldByName("input")
r, _ := t.FieldByName("rawInput")
@@ -321,7 +321,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
bufferWriter := buf.NewBufferedWriter(buf.NewWriter(conn))
if err := encoding.EncodeRequestHeader(bufferWriter, request, requestAddons); err != nil {
return errors.New("failed to encode request header").Base(err).AtWarning()
return errors.New("failed to encode request header").Base(err)
}
// default: serverWriter := bufferWriter
@@ -350,23 +350,23 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
}
// Flush; bufferWriter.WriteMultiBuffer now is bufferWriter.writer.WriteMultiBuffer
if err := bufferWriter.SetBuffered(false); err != nil {
return errors.New("failed to write A request payload").Base(err).AtWarning()
return errors.New("failed to write A request payload").Base(err)
}
if requestAddons.Flow == vless.XRV {
if tlsConn, ok := iConn.(*tls.Conn); ok {
if tlsConn.ConnectionState().Version != gotls.VersionTLS13 {
return errors.New(`failed to use `+requestAddons.Flow+`, found outer tls version `, tlsConn.ConnectionState().Version).AtWarning()
return errors.New(`failed to use `+requestAddons.Flow+`, found outer tls version `, tlsConn.ConnectionState().Version)
}
} else if utlsConn, ok := iConn.(*tls.UConn); ok {
if utlsConn.ConnectionState().Version != utls.VersionTLS13 {
return errors.New(`failed to use `+requestAddons.Flow+`, found outer tls version `, utlsConn.ConnectionState().Version).AtWarning()
return errors.New(`failed to use `+requestAddons.Flow+`, found outer tls version `, utlsConn.ConnectionState().Version)
}
}
}
err := buf.Copy(clientReader, serverWriter, buf.UpdateActivity(timer))
if err != nil {
return errors.New("failed to transfer request payload").Base(err).AtInfo()
return errors.New("failed to transfer request payload").Base(err)
}
// Indicates the end of request payload.
@@ -381,7 +381,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
responseAddons, err := encoding.DecodeResponseHeader(conn, request)
if err != nil {
return errors.New("failed to decode response header").Base(err).AtInfo()
return errors.New("failed to decode response header").Base(err)
}
// default: serverReader := buf.NewReader(conn)
@@ -405,7 +405,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
}
if err != nil {
return errors.New("failed to transfer response payload").Base(err).AtInfo()
return errors.New("failed to transfer response payload").Base(err)
}
return nil
@@ -416,7 +416,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
}
if err := task.Run(ctx, postRequest, task.OnSuccess(getResponse, task.Close(clientWriter))); err != nil {
return errors.New("connection ends").Base(err).AtInfo()
return errors.New("connection ends").Base(err)
}
return nil
+1 -1
View File
@@ -49,7 +49,7 @@ func (a *MemoryAccount) ToProto() proto.Message {
func (a *Account) AsAccount() (protocol.Account, error) {
id, err := uuid.ParseString(a.Id)
if err != nil {
return nil, errors.New("failed to parse ID").Base(err).AtError()
return nil, errors.New("failed to parse ID").Base(err)
}
protoID := protocol.NewID(id)
var AuthenticatedLength, NoTerminationSignal bool
+1 -1
View File
@@ -209,7 +209,7 @@ func (c *ClientSession) DecodeResponseHeader(reader io.Reader) (*protocol.Respon
defer buffer.Release()
if _, err := buffer.ReadFullFrom(c.responseReader, 4); err != nil {
return nil, errors.New("failed to read response header").Base(err).AtWarning()
return nil, errors.New("failed to read response header").Base(err)
}
if buffer.Byte(0) != c.responseHeader {
+2 -2
View File
@@ -227,7 +227,7 @@ func transferResponse(timer signal.ActivityUpdater, session *encoding.ServerSess
func (h *Handler) Process(ctx context.Context, network net.Network, connection stat.Connection, dispatcher routing.Dispatcher) error {
sessionPolicy := h.policyManager.ForLevel(0)
if err := connection.SetReadDeadline(time.Now().Add(sessionPolicy.Timeouts.Handshake)); err != nil {
return errors.New("unable to set read deadline").Base(err).AtWarning()
return errors.New("unable to set read deadline").Base(err)
}
iConn := stat.TryUnwrapStatsConn(connection)
@@ -247,7 +247,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
Status: log.AccessRejected,
Reason: err,
})
err = errors.New("invalid request from ", connection.RemoteAddr()).Base(err).AtInfo()
err = errors.New("invalid request from ", connection.RemoteAddr()).Base(err)
}
return err
}
+3 -3
View File
@@ -60,7 +60,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
outbounds := session.OutboundsFromContext(ctx)
ob := outbounds[len(outbounds)-1]
if !ob.Target.IsValid() {
return errors.New("target not specified").AtError()
return errors.New("target not specified")
}
ob.Name = "vmess"
ob.CanSpliceCopy = 3
@@ -78,7 +78,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
return nil
})
if err != nil {
return errors.New("failed to find an available destination").Base(err).AtWarning()
return errors.New("failed to find an available destination").Base(err)
}
defer conn.Close()
@@ -154,7 +154,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
writer := buf.NewBufferedWriter(buf.NewWriter(conn))
if err := session.EncodeRequestHeader(request, writer); err != nil {
return errors.New("failed to encode request").Base(err).AtWarning()
return errors.New("failed to encode request").Base(err)
}
bodyWriter, err := session.EncodeRequestBody(request, writer)
+221
View File
@@ -0,0 +1,221 @@
package scenarios
import (
"crypto/rand"
"encoding/base64"
"testing"
"time"
"github.com/sagernet/sing-shadowsocks/shadowaead_2022"
"github.com/xtls/xray-core/app/log"
"github.com/xtls/xray-core/app/proxyman"
"github.com/xtls/xray-core/common"
clog "github.com/xtls/xray-core/common/log"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/serial"
"github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/proxy/dokodemo"
"github.com/xtls/xray-core/proxy/freedom"
"github.com/xtls/xray-core/proxy/shadowsocks_2022"
"github.com/xtls/xray-core/testing/servers/tcp"
"github.com/xtls/xray-core/testing/servers/udp"
"golang.org/x/sync/errgroup"
)
func TestShadowsocks2022Tcp(t *testing.T) {
for _, method := range shadowaead_2022.List {
password := make([]byte, 32)
rand.Read(password)
t.Run(method, func(t *testing.T) {
testShadowsocks2022Tcp(t, method, base64.StdEncoding.EncodeToString(password))
})
}
}
func TestShadowsocks2022UdpAES128(t *testing.T) {
password := make([]byte, 32)
rand.Read(password)
testShadowsocks2022Udp(t, shadowaead_2022.List[0], base64.StdEncoding.EncodeToString(password))
}
func TestShadowsocks2022UdpAES256(t *testing.T) {
password := make([]byte, 32)
rand.Read(password)
testShadowsocks2022Udp(t, shadowaead_2022.List[1], base64.StdEncoding.EncodeToString(password))
}
func TestShadowsocks2022UdpChacha(t *testing.T) {
password := make([]byte, 32)
rand.Read(password)
testShadowsocks2022Udp(t, shadowaead_2022.List[2], base64.StdEncoding.EncodeToString(password))
}
func testShadowsocks2022Tcp(t *testing.T, method string, password string) {
tcpServer := tcp.Server{
MsgProcessor: xor,
}
dest, err := tcpServer.Start()
common.Must(err)
defer tcpServer.Close()
serverPort := tcp.PickPort()
serverConfig := &core.Config{
App: []*serial.TypedMessage{
serial.ToTypedMessage(&log.Config{
ErrorLogLevel: clog.Severity_Debug,
ErrorLogType: log.LogType_Console,
}),
},
Inbound: []*core.InboundHandlerConfig{
{
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(serverPort)}},
Listen: net.NewIPOrDomain(net.LocalHostIP),
}),
ProxySettings: serial.ToTypedMessage(&shadowsocks_2022.ServerConfig{
Method: method,
Key: password,
Network: []net.Network{net.Network_TCP},
}),
},
},
Outbound: []*core.OutboundHandlerConfig{
{
ProxySettings: serial.ToTypedMessage(&freedom.Config{
FinalRules: []*freedom.FinalRuleConfig{{Action: freedom.RuleAction_Allow}},
}),
},
},
}
clientPort := tcp.PickPort()
clientConfig := &core.Config{
App: []*serial.TypedMessage{
serial.ToTypedMessage(&log.Config{
ErrorLogLevel: clog.Severity_Debug,
ErrorLogType: log.LogType_Console,
}),
},
Inbound: []*core.InboundHandlerConfig{
{
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(clientPort)}},
Listen: net.NewIPOrDomain(net.LocalHostIP),
}),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
RewriteAddress: net.NewIPOrDomain(dest.Address),
RewritePort: uint32(dest.Port),
AllowedNetworks: []net.Network{net.Network_TCP},
}),
},
},
Outbound: []*core.OutboundHandlerConfig{
{
ProxySettings: serial.ToTypedMessage(&shadowsocks_2022.ClientConfig{
Address: net.NewIPOrDomain(net.LocalHostIP),
Port: uint32(serverPort),
Method: method,
Key: password,
}),
},
},
}
servers, err := InitializeServerConfigs(serverConfig, clientConfig)
common.Must(err)
defer CloseAllServers(servers)
var errGroup errgroup.Group
for range 3 {
errGroup.Go(testTCPConn(clientPort, 10240*1024, time.Second*20))
}
if err := errGroup.Wait(); err != nil {
t.Error(err)
}
}
func testShadowsocks2022Udp(t *testing.T, method string, password string) {
udpServer := udp.Server{
MsgProcessor: xor,
}
udpDest, err := udpServer.Start()
common.Must(err)
defer udpServer.Close()
serverPort := udp.PickPort()
serverConfig := &core.Config{
App: []*serial.TypedMessage{
serial.ToTypedMessage(&log.Config{
ErrorLogLevel: clog.Severity_Debug,
ErrorLogType: log.LogType_Console,
}),
},
Inbound: []*core.InboundHandlerConfig{
{
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(serverPort)}},
Listen: net.NewIPOrDomain(net.LocalHostIP),
}),
ProxySettings: serial.ToTypedMessage(&shadowsocks_2022.ServerConfig{
Method: method,
Key: password,
Network: []net.Network{net.Network_UDP},
}),
},
},
Outbound: []*core.OutboundHandlerConfig{
{
ProxySettings: serial.ToTypedMessage(&freedom.Config{
FinalRules: []*freedom.FinalRuleConfig{{Action: freedom.RuleAction_Allow}},
}),
},
},
}
udpClientPort := udp.PickPort()
clientConfig := &core.Config{
App: []*serial.TypedMessage{
serial.ToTypedMessage(&log.Config{
ErrorLogLevel: clog.Severity_Debug,
ErrorLogType: log.LogType_Console,
}),
},
Inbound: []*core.InboundHandlerConfig{
{
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(udpClientPort)}},
Listen: net.NewIPOrDomain(net.LocalHostIP),
}),
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
RewriteAddress: net.NewIPOrDomain(udpDest.Address),
RewritePort: uint32(udpDest.Port),
AllowedNetworks: []net.Network{net.Network_UDP},
}),
},
},
Outbound: []*core.OutboundHandlerConfig{
{
ProxySettings: serial.ToTypedMessage(&shadowsocks_2022.ClientConfig{
Address: net.NewIPOrDomain(net.LocalHostIP),
Port: uint32(serverPort),
Method: method,
Key: password,
}),
},
},
}
servers, err := InitializeServerConfigs(serverConfig, clientConfig)
common.Must(err)
defer CloseAllServers(servers)
var errGroup errgroup.Group
for range 3 {
errGroup.Go(testUDPConn(udpClientPort, 1024, time.Second*5))
}
if err := errGroup.Wait(); err != nil {
t.Error(err)
}
}
+1 -1
View File
@@ -27,7 +27,7 @@ var strategy = [11][3]byte{
func RegisterProtocolConfigCreator(name string, creator ConfigCreator) error {
if _, found := globalTransportConfigCreatorCache[name]; found {
return errors.New("protocol ", name, " is already registered").AtError()
return errors.New("protocol ", name, " is already registered")
}
globalTransportConfigCreatorCache[name] = creator
return nil
+6 -6
View File
@@ -38,7 +38,7 @@ var transportDialerCache = make(map[string]dialFunc)
// RegisterTransportDialer registers a Dialer with given name.
func RegisterTransportDialer(protocol string, dialer dialFunc) error {
if _, found := transportDialerCache[protocol]; found {
return errors.New(protocol, " dialer already registered").AtError()
return errors.New(protocol, " dialer already registered")
}
transportDialerCache[protocol] = dialer
return nil
@@ -58,7 +58,7 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *MemoryStrea
protocol := streamSettings.ProtocolName
dialer := transportDialerCache[protocol]
if dialer == nil {
return nil, errors.New(protocol, " dialer not registered").AtError()
return nil, errors.New(protocol, " dialer not registered")
}
return dialer(ctx, dest, streamSettings)
}
@@ -66,7 +66,7 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *MemoryStrea
if dest.Network == net.Network_UDP {
udpDialer := transportDialerCache["udp"]
if udpDialer == nil {
return nil, errors.New("UDP dialer not registered").AtError()
return nil, errors.New("UDP dialer not registered")
}
return udpDialer(ctx, dest, streamSettings)
}
@@ -86,7 +86,7 @@ var (
func LookupForIP(domain string, strategy DomainStrategy, localAddr net.Address) ([]net.IP, error) {
if dnsClient == nil {
return nil, errors.New("DNS client not initialized").AtError()
return nil, errors.New("DNS client not initialized")
}
ips, _, err := dnsClient.LookupIP(domain, dns.IPOption{
@@ -269,11 +269,11 @@ func DialSystem(ctx context.Context, dest net.Destination, sockopt *SocketConfig
if len(sockopt.DialerProxy) > 0 {
if obm == nil {
return nil, errors.New("there is no outbound manager for dialerProxy").AtError()
return nil, errors.New("there is no outbound manager for dialerProxy")
}
h := obm.GetHandler(sockopt.DialerProxy)
if h == nil {
return nil, errors.New("there is no outbound handler for dialerProxy").AtError()
return nil, errors.New("there is no outbound handler for dialerProxy")
}
return redirect(ctx, dest, sockopt.DialerProxy, h), nil
}
+1 -1
View File
@@ -53,7 +53,7 @@ func DialKCP(ctx context.Context, dest net.Destination, streamSettings *internet
conn, err := internet.DialSystem(ctx, dest, streamSettings.SocketSettings)
if err != nil {
return nil, errors.New("failed to dial to dest: ", err).AtWarning().Base(err)
return nil, errors.New("failed to dial to dest: ", err).Base(err)
}
if streamSettings.UdpmaskManager != nil {
+2 -2
View File
@@ -132,7 +132,7 @@ func UClient(c net.Conn, config *Config, ctx context.Context, dest net.Destinati
uConn.ServerName = utlsConfig.ServerName
fingerprint := tls.GetFingerprint(config.Fingerprint)
if fingerprint == nil {
return nil, errors.New("REALITY: failed to get fingerprint").AtError()
return nil, errors.New("REALITY: failed to get fingerprint")
}
uConn.UConn = utls.UClient(c, utlsConfig, *fingerprint)
{
@@ -271,7 +271,7 @@ func UClient(c net.Conn, config *Config, ctx context.Context, dest net.Destinati
// Do not close the connection
}()
time.Sleep(time.Duration(crypto.RandBetween(config.SpiderY[8], config.SpiderY[9])) * time.Millisecond) // return
return nil, errors.New("REALITY: processed invalid connection").AtWarning()
return nil, errors.New("REALITY: processed invalid connection")
}
return uConn, nil
}
+2 -2
View File
@@ -288,14 +288,14 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig)
func setReuseAddr(fd uintptr) error {
if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEADDR, 1); err != nil {
return errors.New("failed to set SO_REUSEADDR").Base(err).AtWarning()
return errors.New("failed to set SO_REUSEADDR").Base(err)
}
return nil
}
func setReusePort(fd uintptr) error {
if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEPORT, 1); err != nil {
return errors.New("failed to set SO_REUSEPORT").Base(err).AtWarning()
return errors.New("failed to set SO_REUSEPORT").Base(err)
}
return nil
}
+2 -2
View File
@@ -224,7 +224,7 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig)
func setReuseAddr(fd uintptr) error {
if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1); err != nil {
return errors.New("failed to set SO_REUSEADDR").Base(err).AtWarning()
return errors.New("failed to set SO_REUSEADDR").Base(err)
}
return nil
}
@@ -232,7 +232,7 @@ func setReuseAddr(fd uintptr) error {
func setReusePort(fd uintptr) error {
if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, soReUsePortLB, 1); err != nil {
if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, soReUsePort, 1); err != nil {
return errors.New("failed to set SO_REUSEPORT").Base(err).AtWarning()
return errors.New("failed to set SO_REUSEPORT").Base(err)
}
}
return nil
+2 -2
View File
@@ -234,14 +234,14 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig)
func setReuseAddr(fd uintptr) error {
if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1); err != nil {
return errors.New("failed to set SO_REUSEADDR").Base(err).AtWarning()
return errors.New("failed to set SO_REUSEADDR").Base(err)
}
return nil
}
func setReusePort(fd uintptr) error {
if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, unix.SO_REUSEPORT, 1); err != nil {
return errors.New("failed to set SO_REUSEPORT").Base(err).AtWarning()
return errors.New("failed to set SO_REUSEPORT").Base(err)
}
return nil
}
+4 -4
View File
@@ -86,14 +86,14 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
}
if err != nil {
if isFromMitmVerify {
return nil, errors.New("MITM freedom RAW TLS: failed to verify Domain Fronting certificate from " + mitmServerName).Base(err).AtWarning()
return nil, errors.New("MITM freedom RAW TLS: failed to verify Domain Fronting certificate from " + mitmServerName).Base(err)
}
return nil, err
}
negotiatedProtocol := conn.(tls.Interface).NegotiatedProtocol()
if isFromMitmAlpn && !mitmAlpn11 && negotiatedProtocol != "h2" {
conn.Close()
return nil, errors.New("MITM freedom RAW TLS: unexpected Negotiated Protocol (" + negotiatedProtocol + ") with " + mitmServerName).AtWarning()
return nil, errors.New("MITM freedom RAW TLS: unexpected Negotiated Protocol (" + negotiatedProtocol + ") with " + mitmServerName)
}
} else if config := reality.ConfigFromStreamSettings(streamSettings); config != nil {
if conn, err = reality.UClient(conn, config, ctx, dest); err != nil {
@@ -105,11 +105,11 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
if tcpSettings.HeaderSettings != nil {
headerConfig, err := tcpSettings.HeaderSettings.GetInstance()
if err != nil {
return nil, errors.New("failed to get header settings").Base(err).AtError()
return nil, errors.New("failed to get header settings").Base(err)
}
auth, err := internet.CreateConnectionAuthenticator(headerConfig)
if err != nil {
return nil, errors.New("failed to create header authenticator").Base(err).AtError()
return nil, errors.New("failed to create header authenticator").Base(err)
}
conn = auth.Client(conn)
}
+2 -2
View File
@@ -82,11 +82,11 @@ func ListenTCP(ctx context.Context, address net.Address, port net.Port, streamSe
if tcpSettings.HeaderSettings != nil {
headerConfig, err := tcpSettings.HeaderSettings.GetInstance()
if err != nil {
return nil, errors.New("invalid header settings").Base(err).AtError()
return nil, errors.New("invalid header settings").Base(err)
}
auth, err := internet.CreateConnectionAuthenticator(headerConfig)
if err != nil {
return nil, errors.New("invalid header settings.").Base(err).AtError()
return nil, errors.New("invalid header settings.").Base(err)
}
l.authConfig = auth
}
+3 -3
View File
@@ -12,7 +12,7 @@ var transportListenerCache = make(map[string]ListenFunc)
func RegisterTransportListener(protocol string, listener ListenFunc) error {
if _, found := transportListenerCache[protocol]; found {
return errors.New(protocol, " listener already registered.").AtError()
return errors.New(protocol, " listener already registered.")
}
transportListenerCache[protocol] = listener
return nil
@@ -40,7 +40,7 @@ func ListenUnix(ctx context.Context, address net.Address, settings *MemoryStream
protocol := settings.ProtocolName
listenFunc := transportListenerCache[protocol]
if listenFunc == nil {
return nil, errors.New(protocol, " unix listener not registered.").AtError()
return nil, errors.New(protocol, " unix listener not registered.")
}
listener, err := listenFunc(ctx, address, net.Port(0), settings, handler)
if err != nil {
@@ -72,7 +72,7 @@ func ListenTCP(ctx context.Context, address net.Address, port net.Port, settings
protocol := settings.ProtocolName
listenFunc := transportListenerCache[protocol]
if listenFunc == nil {
return nil, errors.New(protocol, " listener not registered.").AtError()
return nil, errors.New(protocol, " listener not registered.")
}
listener, err := listenFunc(ctx, address, port, settings, handler)
if err != nil {
+1 -1
View File
@@ -39,7 +39,7 @@ func (c *Config) loadSelfCertPool() (*x509.CertPool, error) {
root := x509.NewCertPool()
for _, cert := range c.Certificate {
if !root.AppendCertsFromPEM(cert.Certificate) {
return nil, errors.New("failed to append cert").AtWarning()
return nil, errors.New("failed to append cert")
}
}
return root, nil
+2 -2
View File
@@ -44,11 +44,11 @@ func (c *Config) getCertPool() (*x509.CertPool, error) {
pool, err := x509.SystemCertPool()
if err != nil {
return nil, errors.New("system root").AtWarning().Base(err)
return nil, errors.New("system root").Base(err)
}
for _, cert := range c.Certificate {
if !pool.AppendCertsFromPEM(cert.Certificate) {
return nil, errors.New("append cert to root").AtWarning().Base(err)
return nil, errors.New("append cert to root").Base(err)
}
}
return pool, nil