mirror of
https://github.com/XTLS/Xray-core.git
synced 2024-11-26 17:03:02 +00:00
137 lines
4.2 KiB
Go
137 lines
4.2 KiB
Go
|
package shadowtls
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"os"
|
||
|
|
||
|
"github.com/sagernet/sing-shadowtls"
|
||
|
sing_common "github.com/sagernet/sing/common"
|
||
|
"github.com/sagernet/sing/common/auth"
|
||
|
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/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/singbridge"
|
||
|
"github.com/xtls/xray-core/core"
|
||
|
"github.com/xtls/xray-core/features/inbound"
|
||
|
"github.com/xtls/xray-core/features/routing"
|
||
|
"github.com/xtls/xray-core/proxy"
|
||
|
"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 {
|
||
|
service *shadowtls.Service
|
||
|
inboundManager inbound.Manager
|
||
|
detour string
|
||
|
}
|
||
|
|
||
|
func NewServer(ctx context.Context, config *ServerConfig) (*Inbound, error) {
|
||
|
v := core.MustFromContext(ctx)
|
||
|
inbound := &Inbound{
|
||
|
inboundManager: v.GetFeature(inbound.ManagerType()).(inbound.Manager),
|
||
|
detour: config.Detour,
|
||
|
}
|
||
|
var handshakeForServerName map[string]shadowtls.HandshakeConfig
|
||
|
if config.Version > 1 {
|
||
|
handshakeForServerName = make(map[string]shadowtls.HandshakeConfig)
|
||
|
for serverName, serverConfig := range config.HandshakeForServerName {
|
||
|
handshakeForServerName[serverName] = shadowtls.HandshakeConfig{
|
||
|
Server: singbridge.ToSocksaddr(net.Destination{
|
||
|
Address: serverConfig.Address.AsAddress(),
|
||
|
Port: net.Port(serverConfig.Port),
|
||
|
}),
|
||
|
Dialer: N.SystemDialer,
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
service, err := shadowtls.NewService(shadowtls.ServiceConfig{
|
||
|
Version: int(config.Version),
|
||
|
Password: config.Password,
|
||
|
Users: sing_common.Map(config.Users, func(it *User) shadowtls.User {
|
||
|
return shadowtls.User{
|
||
|
Name: it.Email,
|
||
|
Password: it.Password,
|
||
|
}
|
||
|
}),
|
||
|
Handshake: shadowtls.HandshakeConfig{
|
||
|
Server: singbridge.ToSocksaddr(net.Destination{
|
||
|
Address: config.Handshake.Address.AsAddress(),
|
||
|
Port: net.Port(config.Handshake.Port),
|
||
|
}),
|
||
|
Dialer: N.SystemDialer,
|
||
|
},
|
||
|
HandshakeForServerName: handshakeForServerName,
|
||
|
StrictMode: config.StrictMode,
|
||
|
Handler: inbound,
|
||
|
Logger: singbridge.NewLogger(newError),
|
||
|
})
|
||
|
if err != nil {
|
||
|
return nil, E.Cause(err, "create service")
|
||
|
}
|
||
|
inbound.service = service
|
||
|
return inbound, nil
|
||
|
}
|
||
|
|
||
|
func (i *Inbound) Network() []net.Network {
|
||
|
return []net.Network{net.Network_TCP}
|
||
|
}
|
||
|
|
||
|
func (i *Inbound) Process(ctx context.Context, network net.Network, connection stat.Connection, dispatcher routing.Dispatcher) error {
|
||
|
inbound := session.InboundFromContext(ctx)
|
||
|
var metadata M.Metadata
|
||
|
if inbound.Source.IsValid() {
|
||
|
metadata.Source = M.ParseSocksaddr(inbound.Source.NetAddr())
|
||
|
}
|
||
|
ctx = session.ContextWithDispatcher(ctx, dispatcher)
|
||
|
return singbridge.ReturnError(i.service.NewConnection(ctx, connection, metadata))
|
||
|
}
|
||
|
|
||
|
func (i *Inbound) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error {
|
||
|
inboundHandler, err := i.inboundManager.GetHandler(ctx, i.detour)
|
||
|
if err != nil {
|
||
|
return E.Cause(err, "detour not found")
|
||
|
}
|
||
|
|
||
|
inboundWrapper, loaded := inboundHandler.(proxy.GetInbound)
|
||
|
if !loaded {
|
||
|
return newError("can't get inbound proxy from handler.")
|
||
|
}
|
||
|
|
||
|
inboundDetour := inboundWrapper.GetInbound()
|
||
|
|
||
|
email, _ := auth.UserFromContext[string](ctx)
|
||
|
inbound := session.InboundFromContext(ctx)
|
||
|
inbound.User = &protocol.MemoryUser{
|
||
|
Email: email,
|
||
|
}
|
||
|
ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{
|
||
|
From: metadata.Source,
|
||
|
To: metadata.Destination,
|
||
|
Status: log.AccessAccepted,
|
||
|
Email: email,
|
||
|
})
|
||
|
newError("tunnelling request to detour").WriteToLog(session.ExportIDToError(ctx))
|
||
|
return inboundDetour.Process(ctx, net.Network_TCP, conn, session.DispatcherFromContext(ctx))
|
||
|
}
|
||
|
|
||
|
func (i *Inbound) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
|
||
|
return os.ErrInvalid
|
||
|
}
|
||
|
|
||
|
func (i *Inbound) NewError(ctx context.Context, err error) {
|
||
|
if E.IsClosed(err) {
|
||
|
return
|
||
|
}
|
||
|
newError(err).AtWarning().WriteToLog()
|
||
|
}
|