sing-box/protocol/tuic/inbound.go

166 lines
5.2 KiB
Go
Raw Normal View History

2024-11-01 16:39:02 +00:00
package tuic
2023-07-23 06:42:19 +00:00
import (
"context"
"net"
"time"
"github.com/sagernet/sing-box/adapter"
2024-11-01 16:39:02 +00:00
"github.com/sagernet/sing-box/adapter/inbound"
"github.com/sagernet/sing-box/common/listener"
2023-07-23 06:42:19 +00:00
"github.com/sagernet/sing-box/common/tls"
"github.com/sagernet/sing-box/common/uot"
2023-07-23 06:42:19 +00:00
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing-quic/tuic"
2023-07-23 06:42:19 +00:00
"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"
2023-07-23 06:42:19 +00:00
N "github.com/sagernet/sing/common/network"
"github.com/gofrs/uuid/v5"
)
2024-11-01 16:39:02 +00:00
func RegisterInbound(registry *inbound.Registry) {
inbound.Register[option.TUICInboundOptions](registry, C.TypeTUIC, NewInbound)
}
2023-07-23 06:42:19 +00:00
2024-11-01 16:39:02 +00:00
type Inbound struct {
inbound.Adapter
router adapter.ConnectionRouterEx
logger log.ContextLogger
listener *listener.Listener
tlsConfig tls.ServerConfig
server *tuic.Service[int]
userNameList []string
2023-07-23 06:42:19 +00:00
}
2024-11-01 16:39:02 +00:00
func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.TUICInboundOptions) (adapter.Inbound, error) {
2023-07-23 06:42:19 +00:00
options.UDPFragmentDefault = true
if options.TLS == nil || !options.TLS.Enabled {
return nil, C.ErrTLSRequired
}
2023-08-29 05:43:42 +00:00
tlsConfig, err := tls.NewServer(ctx, logger, common.PtrValueOrDefault(options.TLS))
2023-07-23 06:42:19 +00:00
if err != nil {
return nil, err
}
2024-11-01 16:39:02 +00:00
inbound := &Inbound{
Adapter: inbound.NewAdapter(C.TypeTUIC, tag),
router: uot.NewRouter(router, logger),
logger: logger,
listener: listener.New(listener.Options{
Context: ctx,
Logger: logger,
Listen: options.ListenOptions,
}),
2023-10-25 04:00:00 +00:00
tlsConfig: tlsConfig,
2023-07-23 06:42:19 +00:00
}
var udpTimeout time.Duration
if options.UDPTimeout != 0 {
udpTimeout = time.Duration(options.UDPTimeout)
} else {
udpTimeout = C.UDPTimeout
}
service, err := tuic.NewService[int](tuic.ServiceOptions{
2023-07-23 06:42:19 +00:00
Context: ctx,
Logger: logger,
TLSConfig: tlsConfig,
2023-07-23 06:42:19 +00:00
CongestionControl: options.CongestionControl,
AuthTimeout: time.Duration(options.AuthTimeout),
ZeroRTTHandshake: options.ZeroRTTHandshake,
Heartbeat: time.Duration(options.Heartbeat),
UDPTimeout: udpTimeout,
Handler: inbound,
2023-07-23 06:42:19 +00:00
})
if err != nil {
return nil, err
}
var userList []int
var userNameList []string
var userUUIDList [][16]byte
var userPasswordList []string
for index, user := range options.Users {
if user.UUID == "" {
return nil, E.New("missing uuid for user ", index)
}
userUUID, err := uuid.FromString(user.UUID)
if err != nil {
return nil, E.Cause(err, "invalid uuid for user ", index)
}
userList = append(userList, index)
userNameList = append(userNameList, user.Name)
userUUIDList = append(userUUIDList, userUUID)
userPasswordList = append(userPasswordList, user.Password)
}
service.UpdateUsers(userList, userUUIDList, userPasswordList)
inbound.server = service
inbound.userNameList = userNameList
2023-07-23 06:42:19 +00:00
return inbound, nil
}
func (h *Inbound) NewConnectionEx(ctx context.Context, conn net.Conn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) {
2023-07-23 06:42:19 +00:00
ctx = log.ContextWithNewID(ctx)
var metadata adapter.InboundContext
2024-11-01 16:39:02 +00:00
metadata.Inbound = h.Tag()
metadata.InboundType = h.Type()
metadata.InboundDetour = h.listener.ListenOptions().Detour
metadata.InboundOptions = h.listener.ListenOptions().InboundOptions
metadata.OriginDestination = h.listener.UDPAddr()
metadata.Source = source
metadata.Destination = destination
h.logger.InfoContext(ctx, "inbound connection from ", metadata.Source)
userID, _ := auth.UserFromContext[int](ctx)
if userName := h.userNameList[userID]; userName != "" {
metadata.User = userName
2023-09-24 04:00:00 +00:00
h.logger.InfoContext(ctx, "[", userName, "] inbound connection to ", metadata.Destination)
} else {
h.logger.InfoContext(ctx, "inbound connection to ", metadata.Destination)
}
h.router.RouteConnectionEx(ctx, conn, metadata, onClose)
2023-07-23 06:42:19 +00:00
}
func (h *Inbound) NewPacketConnectionEx(ctx context.Context, conn N.PacketConn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) {
2023-07-23 06:42:19 +00:00
ctx = log.ContextWithNewID(ctx)
var metadata adapter.InboundContext
2024-11-01 16:39:02 +00:00
metadata.Inbound = h.Tag()
metadata.InboundType = h.Type()
metadata.InboundDetour = h.listener.ListenOptions().Detour
metadata.InboundOptions = h.listener.ListenOptions().InboundOptions
metadata.OriginDestination = h.listener.UDPAddr()
metadata.Source = source
metadata.Destination = destination
h.logger.InfoContext(ctx, "inbound packet connection from ", metadata.Source)
userID, _ := auth.UserFromContext[int](ctx)
if userName := h.userNameList[userID]; userName != "" {
metadata.User = userName
2023-09-24 04:00:00 +00:00
h.logger.InfoContext(ctx, "[", userName, "] inbound packet connection to ", metadata.Destination)
} else {
h.logger.InfoContext(ctx, "inbound packet connection to ", metadata.Destination)
}
h.router.RoutePacketConnectionEx(ctx, conn, metadata, onClose)
2023-07-23 06:42:19 +00:00
}
2024-11-01 16:39:02 +00:00
func (h *Inbound) Start() error {
2023-08-21 10:11:44 +00:00
if h.tlsConfig != nil {
err := h.tlsConfig.Start()
if err != nil {
return err
}
}
2024-11-01 16:39:02 +00:00
packetConn, err := h.listener.ListenUDP()
2023-07-23 06:42:19 +00:00
if err != nil {
return err
}
return h.server.Start(packetConn)
}
2024-11-01 16:39:02 +00:00
func (h *Inbound) Close() error {
2023-07-23 06:42:19 +00:00
return common.Close(
h.listener,
2023-08-29 05:43:42 +00:00
h.tlsConfig,
2023-07-23 06:42:19 +00:00
common.PtrOrNil(h.server),
)
}