2022-08-31 06:21:53 +00:00
|
|
|
package inbound
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"net"
|
|
|
|
|
|
|
|
"github.com/sagernet/sing-box/adapter"
|
|
|
|
"github.com/sagernet/sing-box/common/dialer"
|
|
|
|
C "github.com/sagernet/sing-box/constant"
|
|
|
|
"github.com/sagernet/sing-box/log"
|
|
|
|
"github.com/sagernet/sing-box/option"
|
2023-02-20 05:53:06 +00:00
|
|
|
"github.com/sagernet/sing-shadowtls"
|
2023-02-21 08:07:08 +00:00
|
|
|
"github.com/sagernet/sing/common"
|
2023-09-24 04:00:00 +00:00
|
|
|
"github.com/sagernet/sing/common/auth"
|
2022-08-31 06:21:53 +00:00
|
|
|
N "github.com/sagernet/sing/common/network"
|
|
|
|
)
|
|
|
|
|
|
|
|
type ShadowTLS struct {
|
|
|
|
myInboundAdapter
|
2023-02-20 05:53:06 +00:00
|
|
|
service *shadowtls.Service
|
2022-08-31 06:21:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func NewShadowTLS(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.ShadowTLSInboundOptions) (*ShadowTLS, error) {
|
|
|
|
inbound := &ShadowTLS{
|
|
|
|
myInboundAdapter: myInboundAdapter{
|
|
|
|
protocol: C.TypeShadowTLS,
|
|
|
|
network: []string{N.NetworkTCP},
|
|
|
|
ctx: ctx,
|
|
|
|
router: router,
|
|
|
|
logger: logger,
|
|
|
|
tag: tag,
|
|
|
|
listenOptions: options.ListenOptions,
|
|
|
|
},
|
2022-10-06 14:47:11 +00:00
|
|
|
}
|
2022-08-31 06:21:53 +00:00
|
|
|
|
2023-03-11 02:12:46 +00:00
|
|
|
if options.Version == 0 {
|
|
|
|
options.Version = 1
|
|
|
|
}
|
|
|
|
|
2023-02-21 08:07:08 +00:00
|
|
|
var handshakeForServerName map[string]shadowtls.HandshakeConfig
|
|
|
|
if options.Version > 1 {
|
|
|
|
handshakeForServerName = make(map[string]shadowtls.HandshakeConfig)
|
|
|
|
for serverName, serverOptions := range options.HandshakeForServerName {
|
2023-08-08 08:14:03 +00:00
|
|
|
handshakeDialer, err := dialer.New(router, serverOptions.DialerOptions)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2023-02-21 08:07:08 +00:00
|
|
|
handshakeForServerName[serverName] = shadowtls.HandshakeConfig{
|
|
|
|
Server: serverOptions.ServerOptions.Build(),
|
2023-08-08 08:14:03 +00:00
|
|
|
Dialer: handshakeDialer,
|
2023-02-21 08:07:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-08-08 08:14:03 +00:00
|
|
|
handshakeDialer, err := dialer.New(router, options.Handshake.DialerOptions)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2023-02-20 05:53:06 +00:00
|
|
|
service, err := shadowtls.NewService(shadowtls.ServiceConfig{
|
2023-02-21 08:07:08 +00:00
|
|
|
Version: options.Version,
|
|
|
|
Password: options.Password,
|
|
|
|
Users: common.Map(options.Users, func(it option.ShadowTLSUser) shadowtls.User {
|
|
|
|
return (shadowtls.User)(it)
|
|
|
|
}),
|
|
|
|
Handshake: shadowtls.HandshakeConfig{
|
|
|
|
Server: options.Handshake.ServerOptions.Build(),
|
2023-08-08 08:14:03 +00:00
|
|
|
Dialer: handshakeDialer,
|
2023-02-21 08:07:08 +00:00
|
|
|
},
|
|
|
|
HandshakeForServerName: handshakeForServerName,
|
2023-02-21 08:34:41 +00:00
|
|
|
StrictMode: options.StrictMode,
|
2023-09-24 04:00:00 +00:00
|
|
|
Handler: adapter.NewUpstreamContextHandler(inbound.newConnection, nil, inbound),
|
2023-02-21 08:07:08 +00:00
|
|
|
Logger: logger,
|
2023-02-20 05:53:06 +00:00
|
|
|
})
|
2022-08-31 06:21:53 +00:00
|
|
|
if err != nil {
|
2023-02-20 05:53:06 +00:00
|
|
|
return nil, err
|
2022-08-31 06:21:53 +00:00
|
|
|
}
|
2023-02-20 05:53:06 +00:00
|
|
|
inbound.service = service
|
|
|
|
inbound.connHandler = inbound
|
|
|
|
return inbound, nil
|
2022-08-31 06:21:53 +00:00
|
|
|
}
|
2022-10-06 14:47:11 +00:00
|
|
|
|
2023-02-20 05:53:06 +00:00
|
|
|
func (h *ShadowTLS) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
|
|
|
|
return h.service.NewConnection(adapter.WithContext(log.ContextWithNewID(ctx), &metadata), conn, adapter.UpstreamMetadata(metadata))
|
2022-10-06 14:47:11 +00:00
|
|
|
}
|
2023-09-24 04:00:00 +00:00
|
|
|
|
|
|
|
func (h *ShadowTLS) newConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
|
|
|
|
if userName, _ := auth.UserFromContext[string](ctx); userName != "" {
|
|
|
|
metadata.User = userName
|
|
|
|
h.logger.InfoContext(ctx, "[", userName, "] inbound connection to ", metadata.Destination)
|
|
|
|
} else {
|
|
|
|
h.logger.InfoContext(ctx, "inbound connection to ", metadata.Destination)
|
|
|
|
}
|
|
|
|
return h.router.RouteConnection(ctx, conn, metadata)
|
|
|
|
}
|