2022-11-25 22:30:37 +08:00
|
|
|
package trojan
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2024-06-24 09:49:15 +08:00
|
|
|
"encoding/binary"
|
2022-11-25 22:30:37 +08:00
|
|
|
"net"
|
|
|
|
|
|
|
|
"github.com/sagernet/sing/common/auth"
|
|
|
|
"github.com/sagernet/sing/common/buf"
|
|
|
|
"github.com/sagernet/sing/common/bufio"
|
|
|
|
E "github.com/sagernet/sing/common/exceptions"
|
2024-11-02 00:39:02 +08:00
|
|
|
"github.com/sagernet/sing/common/logger"
|
2022-11-25 22:30:37 +08:00
|
|
|
M "github.com/sagernet/sing/common/metadata"
|
|
|
|
N "github.com/sagernet/sing/common/network"
|
|
|
|
"github.com/sagernet/sing/common/rw"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Handler interface {
|
2024-11-23 22:34:02 +08:00
|
|
|
N.TCPConnectionHandlerEx
|
|
|
|
N.UDPConnectionHandlerEx
|
2022-11-25 22:30:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
type Service[K comparable] struct {
|
|
|
|
users map[K][56]byte
|
|
|
|
keys map[[56]byte]K
|
|
|
|
handler Handler
|
2024-11-23 22:34:02 +08:00
|
|
|
fallbackHandler N.TCPConnectionHandlerEx
|
2024-11-02 00:39:02 +08:00
|
|
|
logger logger.ContextLogger
|
2022-11-25 22:30:37 +08:00
|
|
|
}
|
|
|
|
|
2024-11-23 22:34:02 +08:00
|
|
|
func NewService[K comparable](handler Handler, fallbackHandler N.TCPConnectionHandlerEx, logger logger.ContextLogger) *Service[K] {
|
2022-11-25 22:30:37 +08:00
|
|
|
return &Service[K]{
|
|
|
|
users: make(map[K][56]byte),
|
|
|
|
keys: make(map[[56]byte]K),
|
|
|
|
handler: handler,
|
|
|
|
fallbackHandler: fallbackHandler,
|
2024-11-02 00:39:02 +08:00
|
|
|
logger: logger,
|
2022-11-25 22:30:37 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var ErrUserExists = E.New("user already exists")
|
|
|
|
|
|
|
|
func (s *Service[K]) UpdateUsers(userList []K, passwordList []string) error {
|
|
|
|
users := make(map[K][56]byte)
|
|
|
|
keys := make(map[[56]byte]K)
|
|
|
|
for i, user := range userList {
|
|
|
|
if _, loaded := users[user]; loaded {
|
|
|
|
return ErrUserExists
|
|
|
|
}
|
|
|
|
key := Key(passwordList[i])
|
|
|
|
if oldUser, loaded := keys[key]; loaded {
|
|
|
|
return E.Extend(ErrUserExists, "password used by ", oldUser)
|
|
|
|
}
|
|
|
|
users[user] = key
|
|
|
|
keys[key] = user
|
|
|
|
}
|
|
|
|
s.users = users
|
|
|
|
s.keys = keys
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-11-23 22:34:02 +08:00
|
|
|
func (s *Service[K]) NewConnection(ctx context.Context, conn net.Conn, source M.Socksaddr, onClose N.CloseHandlerFunc) error {
|
2022-11-25 22:30:37 +08:00
|
|
|
var key [KeyLength]byte
|
2023-07-03 21:45:32 +08:00
|
|
|
n, err := conn.Read(key[:])
|
2022-11-25 22:30:37 +08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
} else if n != KeyLength {
|
2024-11-23 22:34:02 +08:00
|
|
|
return s.fallback(ctx, conn, source, key[:n], E.New("bad request size"), onClose)
|
2022-11-25 22:30:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if user, loaded := s.keys[key]; loaded {
|
|
|
|
ctx = auth.ContextWithUser(ctx, user)
|
|
|
|
} else {
|
2024-11-23 22:34:02 +08:00
|
|
|
return s.fallback(ctx, conn, source, key[:], E.New("bad request"), onClose)
|
2022-11-25 22:30:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
err = rw.SkipN(conn, 2)
|
|
|
|
if err != nil {
|
|
|
|
return E.Cause(err, "skip crlf")
|
|
|
|
}
|
|
|
|
|
2024-06-24 09:49:15 +08:00
|
|
|
var command byte
|
|
|
|
err = binary.Read(conn, binary.BigEndian, &command)
|
2022-11-25 22:30:37 +08:00
|
|
|
if err != nil {
|
|
|
|
return E.Cause(err, "read command")
|
|
|
|
}
|
|
|
|
|
|
|
|
switch command {
|
|
|
|
case CommandTCP, CommandUDP, CommandMux:
|
|
|
|
default:
|
|
|
|
return E.New("unknown command ", command)
|
|
|
|
}
|
|
|
|
|
|
|
|
// var destination M.Socksaddr
|
|
|
|
destination, err := M.SocksaddrSerializer.ReadAddrPort(conn)
|
|
|
|
if err != nil {
|
|
|
|
return E.Cause(err, "read destination")
|
|
|
|
}
|
|
|
|
|
|
|
|
err = rw.SkipN(conn, 2)
|
|
|
|
if err != nil {
|
|
|
|
return E.Cause(err, "skip crlf")
|
|
|
|
}
|
|
|
|
|
|
|
|
switch command {
|
|
|
|
case CommandTCP:
|
2024-11-23 22:34:02 +08:00
|
|
|
s.handler.NewConnectionEx(ctx, conn, source, destination, onClose)
|
2022-11-25 22:30:37 +08:00
|
|
|
case CommandUDP:
|
2024-11-23 22:34:02 +08:00
|
|
|
s.handler.NewPacketConnectionEx(ctx, &PacketConn{Conn: conn}, source, destination, onClose)
|
2022-11-25 22:30:37 +08:00
|
|
|
// case CommandMux:
|
|
|
|
default:
|
2024-11-23 22:34:02 +08:00
|
|
|
return HandleMuxConnection(ctx, conn, source, s.handler, s.logger, onClose)
|
2022-11-25 22:30:37 +08:00
|
|
|
}
|
2024-11-23 22:34:02 +08:00
|
|
|
return nil
|
2022-11-25 22:30:37 +08:00
|
|
|
}
|
|
|
|
|
2024-11-23 22:34:02 +08:00
|
|
|
func (s *Service[K]) fallback(ctx context.Context, conn net.Conn, source M.Socksaddr, header []byte, err error, onClose N.CloseHandlerFunc) error {
|
2022-11-25 22:30:37 +08:00
|
|
|
if s.fallbackHandler == nil {
|
|
|
|
return E.Extend(err, "fallback disabled")
|
|
|
|
}
|
|
|
|
conn = bufio.NewCachedConn(conn, buf.As(header).ToOwned())
|
2024-11-23 22:34:02 +08:00
|
|
|
s.fallbackHandler.NewConnectionEx(ctx, conn, source, M.Socksaddr{}, onClose)
|
|
|
|
return nil
|
2022-11-25 22:30:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
type PacketConn struct {
|
|
|
|
net.Conn
|
2023-12-20 20:00:00 +08:00
|
|
|
readWaitOptions N.ReadWaitOptions
|
2022-11-25 22:30:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *PacketConn) ReadPacket(buffer *buf.Buffer) (M.Socksaddr, error) {
|
|
|
|
return ReadPacket(c.Conn, buffer)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *PacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error {
|
|
|
|
return WritePacket(c.Conn, buffer, destination)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *PacketConn) FrontHeadroom() int {
|
|
|
|
return M.MaxSocksaddrLength + 4
|
|
|
|
}
|
2023-04-19 21:48:54 +08:00
|
|
|
|
|
|
|
func (c *PacketConn) NeedAdditionalReadDeadline() bool {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *PacketConn) Upstream() any {
|
|
|
|
return c.Conn
|
|
|
|
}
|