mirror of
https://github.com/SagerNet/sing.git
synced 2025-04-03 20:07:38 +03:00
Add shadowsocks multi service
This commit is contained in:
parent
5487ec681e
commit
41e416c4f4
7 changed files with 376 additions and 65 deletions
|
@ -1,6 +1,8 @@
|
|||
package shadowsocks
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
"github.com/sagernet/sing/protocol/socks"
|
||||
|
@ -16,3 +18,14 @@ type Handler interface {
|
|||
socks.UDPConnectionHandler
|
||||
E.Handler
|
||||
}
|
||||
|
||||
type MultiUserService[U comparable] interface {
|
||||
Service
|
||||
AddUser(user U, key []byte)
|
||||
RemoveUser(user U)
|
||||
}
|
||||
|
||||
type UserContext[U comparable] struct {
|
||||
context.Context
|
||||
User U
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ var List = []string{
|
|||
"2022-blake3-chacha20-poly1305",
|
||||
}
|
||||
|
||||
func New(method string, pskList [][]byte, secureRNG io.Reader) (shadowsocks.Method, error) {
|
||||
func New(method string, pskList [][KeySaltSize]byte, secureRNG io.Reader) (shadowsocks.Method, error) {
|
||||
m := &Method{
|
||||
name: method,
|
||||
psk: pskList[len(pskList)-1],
|
||||
|
@ -71,19 +71,13 @@ func New(method string, pskList [][]byte, secureRNG io.Reader) (shadowsocks.Meth
|
|||
replayFilter: replay.NewCuckoo(60),
|
||||
}
|
||||
|
||||
for _, psk := range pskList {
|
||||
if len(psk) != KeySaltSize {
|
||||
return nil, shadowaead.ErrBadKey
|
||||
}
|
||||
}
|
||||
|
||||
if len(pskList) > 1 {
|
||||
pskHash := make([]byte, len(pskList)-1*aes.BlockSize)
|
||||
for i, psk := range pskList {
|
||||
if i == 0 {
|
||||
continue
|
||||
}
|
||||
hash := blake3.Sum512(psk)
|
||||
hash := blake3.Sum512(psk[:])
|
||||
copy(pskHash[aes.BlockSize*(i-1):aes.BlockSize*i], hash[:aes.BlockSize])
|
||||
}
|
||||
m.pskHash = pskHash
|
||||
|
@ -94,23 +88,23 @@ func New(method string, pskList [][]byte, secureRNG io.Reader) (shadowsocks.Meth
|
|||
m.keyLength = 16
|
||||
m.constructor = newAESGCM
|
||||
m.blockConstructor = newAES
|
||||
m.udpBlockCipher = newAES(m.psk)
|
||||
m.udpBlockCipher = newAES(pskList[0][:])
|
||||
case "2022-blake3-aes-256-gcm":
|
||||
m.keyLength = 32
|
||||
m.constructor = newAESGCM
|
||||
m.blockConstructor = newAES
|
||||
m.udpBlockCipher = newAES(m.psk)
|
||||
m.udpBlockCipher = newAES(pskList[0][:])
|
||||
case "2022-blake3-chacha20-poly1305":
|
||||
m.keyLength = 32
|
||||
m.constructor = newChacha20Poly1305
|
||||
m.udpCipher = newXChacha20Poly1305(m.psk)
|
||||
m.udpCipher = newXChacha20Poly1305(m.psk[:])
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func Blake3DeriveKey(psk, salt []byte, keyLength int) []byte {
|
||||
func Blake3DeriveKey(psk []byte, salt []byte, keyLength int) []byte {
|
||||
sessionKey := buf.Make(len(psk) + len(salt))
|
||||
copy(sessionKey, psk)
|
||||
copy(sessionKey, psk[:])
|
||||
copy(sessionKey[len(psk):], salt)
|
||||
outKey := buf.Make(keyLength)
|
||||
blake3.DeriveKey(outKey, "shadowsocks 2022 session subkey", sessionKey)
|
||||
|
@ -150,8 +144,8 @@ type Method struct {
|
|||
blockConstructor func(key []byte) cipher.Block
|
||||
udpCipher cipher.AEAD
|
||||
udpBlockCipher cipher.Block
|
||||
psk []byte
|
||||
pskList [][]byte
|
||||
psk [KeySaltSize]byte
|
||||
pskList [][KeySaltSize]byte
|
||||
pskHash []byte
|
||||
secureRNG io.Reader
|
||||
replayFilter replay.Filter
|
||||
|
@ -208,7 +202,7 @@ func (m *Method) writeExtendedIdentityHeaders(request *buf.Buffer, salt []byte)
|
|||
}
|
||||
for i, psk := range m.pskList {
|
||||
keyMaterial := make([]byte, 2*KeySaltSize)
|
||||
copy(keyMaterial, psk)
|
||||
copy(keyMaterial, psk[:])
|
||||
copy(keyMaterial[KeySaltSize:], salt)
|
||||
_identitySubkey := buf.Make(m.keyLength)
|
||||
identitySubkey := common.Dup(_identitySubkey)
|
||||
|
@ -225,7 +219,7 @@ func (c *clientConn) writeRequest(payload []byte) error {
|
|||
salt := make([]byte, KeySaltSize)
|
||||
common.Must1(io.ReadFull(c.method.secureRNG, salt))
|
||||
|
||||
key := Blake3DeriveKey(c.method.psk, salt, c.method.keyLength)
|
||||
key := Blake3DeriveKey(c.method.psk[:], salt, c.method.keyLength)
|
||||
writer := shadowaead.NewWriter(
|
||||
c.Conn,
|
||||
c.method.constructor(common.Dup(key)),
|
||||
|
@ -300,7 +294,7 @@ func (c *clientConn) readResponse() error {
|
|||
return E.New("salt not unique")
|
||||
}
|
||||
|
||||
key := Blake3DeriveKey(c.method.psk, salt, c.method.keyLength)
|
||||
key := Blake3DeriveKey(c.method.psk[:], salt, c.method.keyLength)
|
||||
reader := shadowaead.NewReader(
|
||||
c.Conn,
|
||||
c.method.constructor(common.Dup(key)),
|
||||
|
@ -418,7 +412,7 @@ func (c *clientPacketConn) WritePacket(buffer *buf.Buffer, destination *M.AddrPo
|
|||
for textI := 0; textI < aes.BlockSize; textI++ {
|
||||
identityHeader[textI] = pskHash[textI] ^ header.Byte(textI)
|
||||
}
|
||||
c.method.blockConstructor(psk).Encrypt(identityHeader, identityHeader)
|
||||
c.method.blockConstructor(psk[:]).Encrypt(identityHeader, identityHeader)
|
||||
if i == pskLen-2 {
|
||||
break
|
||||
}
|
||||
|
@ -485,7 +479,7 @@ func (c *clientPacketConn) ReadPacket(buffer *buf.Buffer) (*M.AddrPort, error) {
|
|||
} else if sessionId == c.session.lastRemoteSessionId {
|
||||
remoteCipher = c.session.lastRemoteCipher
|
||||
} else {
|
||||
key := Blake3DeriveKey(c.method.psk, packetHeader[:8], c.method.keyLength)
|
||||
key := Blake3DeriveKey(c.method.psk[:], packetHeader[:8], c.method.keyLength)
|
||||
remoteCipher = c.method.constructor(common.Dup(key))
|
||||
}
|
||||
_, err = remoteCipher.Open(buffer.Index(0), packetHeader[4:16], buffer.Bytes(), nil)
|
||||
|
@ -583,7 +577,7 @@ func (m *Method) newUDPSession() *udpSession {
|
|||
if m.udpCipher == nil {
|
||||
sessionId := make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(sessionId, session.sessionId)
|
||||
key := Blake3DeriveKey(m.psk, sessionId, m.keyLength)
|
||||
key := Blake3DeriveKey(m.psk[:], sessionId, m.keyLength)
|
||||
session.cipher = m.constructor(common.Dup(key))
|
||||
}
|
||||
return session
|
||||
|
|
|
@ -34,14 +34,14 @@ type Service struct {
|
|||
blockConstructor func(key []byte) cipher.Block
|
||||
udpCipher cipher.AEAD
|
||||
udpBlockCipher cipher.Block
|
||||
psk []byte
|
||||
psk [KeySaltSize]byte
|
||||
replayFilter replay.Filter
|
||||
handler shadowsocks.Handler
|
||||
udpNat udpnat.Service[uint64]
|
||||
sessions cache.LruCache[uint64, *serverUDPSession]
|
||||
}
|
||||
|
||||
func NewService(method string, psk []byte, secureRNG io.Reader, udpTimeout int64, handler shadowsocks.Handler) (shadowsocks.Service, error) {
|
||||
func NewService(method string, psk [KeySaltSize]byte, secureRNG io.Reader, udpTimeout int64, handler shadowsocks.Handler) (shadowsocks.Service, error) {
|
||||
s := &Service{
|
||||
name: method,
|
||||
psk: psk,
|
||||
|
@ -51,25 +51,21 @@ func NewService(method string, psk []byte, secureRNG io.Reader, udpTimeout int64
|
|||
sessions: cache.NewLRU[uint64, *serverUDPSession](udpTimeout, true),
|
||||
}
|
||||
|
||||
if len(psk) != KeySaltSize {
|
||||
return nil, shadowaead.ErrBadKey
|
||||
}
|
||||
|
||||
switch method {
|
||||
case "2022-blake3-aes-128-gcm":
|
||||
s.keyLength = 16
|
||||
s.constructor = newAESGCM
|
||||
s.blockConstructor = newAES
|
||||
s.udpBlockCipher = newAES(s.psk)
|
||||
s.udpBlockCipher = newAES(s.psk[:])
|
||||
case "2022-blake3-aes-256-gcm":
|
||||
s.keyLength = 32
|
||||
s.constructor = newAESGCM
|
||||
s.blockConstructor = newAES
|
||||
s.udpBlockCipher = newAES(s.psk)
|
||||
s.udpBlockCipher = newAES(s.psk[:])
|
||||
case "2022-blake3-chacha20-poly1305":
|
||||
s.keyLength = 32
|
||||
s.constructor = newChacha20Poly1305
|
||||
s.udpCipher = newXChacha20Poly1305(s.psk)
|
||||
s.udpCipher = newXChacha20Poly1305(s.psk[:])
|
||||
}
|
||||
|
||||
s.udpNat = udpnat.New[uint64](udpTimeout, s)
|
||||
|
@ -87,7 +83,7 @@ func (s *Service) NewConnection(ctx context.Context, conn net.Conn, metadata M.M
|
|||
return E.New("salt not unique")
|
||||
}
|
||||
|
||||
requestKey := Blake3DeriveKey(s.psk, requestSalt, s.keyLength)
|
||||
requestKey := Blake3DeriveKey(s.psk[:], requestSalt, s.keyLength)
|
||||
reader := shadowaead.NewReader(
|
||||
conn,
|
||||
s.constructor(common.Dup(requestKey)),
|
||||
|
@ -135,6 +131,7 @@ func (s *Service) NewConnection(ctx context.Context, conn net.Conn, metadata M.M
|
|||
return s.handler.NewConnection(ctx, &serverConn{
|
||||
Service: s,
|
||||
Conn: conn,
|
||||
uPSK: s.psk,
|
||||
reader: reader,
|
||||
requestSalt: requestSalt,
|
||||
}, metadata)
|
||||
|
@ -143,6 +140,7 @@ func (s *Service) NewConnection(ctx context.Context, conn net.Conn, metadata M.M
|
|||
type serverConn struct {
|
||||
*Service
|
||||
net.Conn
|
||||
uPSK [KeySaltSize]byte
|
||||
access sync.Mutex
|
||||
reader *shadowaead.Reader
|
||||
writer *shadowaead.Writer
|
||||
|
@ -150,10 +148,10 @@ type serverConn struct {
|
|||
}
|
||||
|
||||
func (c *serverConn) writeResponse(payload []byte) (n int, err error) {
|
||||
_salt := make([]byte, KeySaltSize)
|
||||
salt := common.Dup(_salt)
|
||||
var _salt [KeySaltSize]byte
|
||||
salt := common.Dup(_salt[:])
|
||||
common.Must1(io.ReadFull(c.secureRNG, salt))
|
||||
key := Blake3DeriveKey(c.psk, salt, c.keyLength)
|
||||
key := Blake3DeriveKey(c.uPSK[:], salt, c.keyLength)
|
||||
writer := shadowaead.NewWriter(
|
||||
c.Conn,
|
||||
c.constructor(common.Dup(key)),
|
||||
|
@ -165,7 +163,7 @@ func (c *serverConn) writeResponse(payload []byte) (n int, err error) {
|
|||
|
||||
common.Must(rw.WriteByte(bufferedWriter, HeaderTypeServer))
|
||||
common.Must(binary.Write(bufferedWriter, binary.BigEndian, uint64(time.Now().Unix())))
|
||||
common.Must1(bufferedWriter.Write(c.requestSalt))
|
||||
common.Must1(bufferedWriter.Write(c.requestSalt[:]))
|
||||
c.requestSalt = nil
|
||||
|
||||
if len(payload) > 0 {
|
||||
|
@ -236,7 +234,7 @@ func (s *Service) NewPacket(conn socks.PacketConn, buffer *buf.Buffer, metadata
|
|||
if !loaded {
|
||||
session.remoteSessionId = sessionId
|
||||
if packetHeader != nil {
|
||||
key := Blake3DeriveKey(s.psk, packetHeader[:8], s.keyLength)
|
||||
key := Blake3DeriveKey(s.psk[:], packetHeader[:8], s.keyLength)
|
||||
session.remoteCipher = s.constructor(common.Dup(key))
|
||||
}
|
||||
}
|
||||
|
@ -376,7 +374,7 @@ func (m *Service) newUDPSession() *serverUDPSession {
|
|||
if m.udpCipher == nil {
|
||||
sessionId := make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(sessionId, session.sessionId)
|
||||
key := Blake3DeriveKey(m.psk, sessionId, m.keyLength)
|
||||
key := Blake3DeriveKey(m.psk[:], sessionId, m.keyLength)
|
||||
session.cipher = m.constructor(common.Dup(key))
|
||||
}
|
||||
return session
|
||||
|
|
286
protocol/shadowsocks/shadowaead_2022/service_multi.go
Normal file
286
protocol/shadowsocks/shadowaead_2022/service_multi.go
Normal file
|
@ -0,0 +1,286 @@
|
|||
package shadowaead_2022
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/aes"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"math"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/sing/common"
|
||||
"github.com/sagernet/sing/common/buf"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
"github.com/sagernet/sing/common/rw"
|
||||
"github.com/sagernet/sing/protocol/shadowsocks"
|
||||
"github.com/sagernet/sing/protocol/shadowsocks/shadowaead"
|
||||
"github.com/sagernet/sing/protocol/socks"
|
||||
"lukechampine.com/blake3"
|
||||
)
|
||||
|
||||
type MultiService[U comparable] struct {
|
||||
*Service
|
||||
|
||||
uPSK map[U][KeySaltSize]byte
|
||||
uPSKHash map[U][aes.BlockSize]byte
|
||||
uPSKHashR map[[aes.BlockSize]byte]U
|
||||
}
|
||||
|
||||
func (s *MultiService[U]) AddUser(user U, key []byte) {
|
||||
var uPSKHash [aes.BlockSize]byte
|
||||
hash512 := blake3.Sum512(key)
|
||||
copy(uPSKHash[:], hash512[:])
|
||||
|
||||
if oldHash, loaded := s.uPSKHash[user]; loaded {
|
||||
delete(s.uPSKHashR, oldHash)
|
||||
}
|
||||
|
||||
s.uPSKHash[user] = uPSKHash
|
||||
s.uPSKHashR[uPSKHash] = user
|
||||
|
||||
var uPSK [KeySaltSize]byte
|
||||
copy(uPSK[:], key)
|
||||
s.uPSK[user] = uPSK
|
||||
}
|
||||
|
||||
func (s *MultiService[U]) RemoveUser(user U) {
|
||||
if hash, loaded := s.uPSKHash[user]; loaded {
|
||||
delete(s.uPSKHashR, hash)
|
||||
}
|
||||
delete(s.uPSK, user)
|
||||
delete(s.uPSKHash, user)
|
||||
}
|
||||
|
||||
func NewMultiService[U comparable](method string, iPSK [KeySaltSize]byte, secureRNG io.Reader, udpTimeout int64, handler shadowsocks.Handler) (shadowsocks.MultiUserService[U], error) {
|
||||
switch method {
|
||||
case "2022-blake3-aes-128-gcm":
|
||||
case "2022-blake3-aes-256-gcm":
|
||||
default:
|
||||
return nil, E.New("unsupported method ", method)
|
||||
}
|
||||
|
||||
ss, err := NewService(method, iPSK, secureRNG, udpTimeout, handler)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s := &MultiService[U]{
|
||||
Service: ss.(*Service),
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (s *MultiService[U]) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error {
|
||||
requestSalt := make([]byte, KeySaltSize)
|
||||
_, err := io.ReadFull(conn, requestSalt)
|
||||
if err != nil {
|
||||
return E.Cause(err, "read request salt")
|
||||
}
|
||||
|
||||
if !s.replayFilter.Check(requestSalt) {
|
||||
return E.New("salt not unique")
|
||||
}
|
||||
|
||||
var _eiHeader [aes.BlockSize]byte
|
||||
eiHeader := common.Dup(_eiHeader[:])
|
||||
_, err = io.ReadFull(conn, eiHeader)
|
||||
if err != nil {
|
||||
return E.Cause(err, "read extended identity header")
|
||||
}
|
||||
|
||||
keyMaterial := make([]byte, 2*KeySaltSize)
|
||||
copy(keyMaterial, s.psk[:])
|
||||
copy(keyMaterial[KeySaltSize:], requestSalt)
|
||||
_identitySubkey := buf.Make(s.keyLength)
|
||||
identitySubkey := common.Dup(_identitySubkey)
|
||||
blake3.DeriveKey(identitySubkey, "shadowsocks 2022 identity subkey", keyMaterial)
|
||||
s.blockConstructor(identitySubkey).Decrypt(eiHeader, eiHeader)
|
||||
|
||||
var user U
|
||||
var uPSK [KeySaltSize]byte
|
||||
if u, loaded := s.uPSKHashR[_eiHeader]; loaded {
|
||||
user = u
|
||||
uPSK = s.uPSK[u]
|
||||
} else {
|
||||
return E.New("invalid request")
|
||||
}
|
||||
|
||||
requestKey := Blake3DeriveKey(uPSK[:], requestSalt, s.keyLength)
|
||||
reader := shadowaead.NewReader(
|
||||
conn,
|
||||
s.constructor(common.Dup(requestKey)),
|
||||
MaxPacketSize,
|
||||
)
|
||||
|
||||
headerType, err := rw.ReadByte(reader)
|
||||
if err != nil {
|
||||
return E.Cause(err, "read header")
|
||||
}
|
||||
|
||||
if headerType != HeaderTypeClient {
|
||||
return ErrBadHeaderType
|
||||
}
|
||||
|
||||
var epoch uint64
|
||||
err = binary.Read(reader, binary.BigEndian, &epoch)
|
||||
if err != nil {
|
||||
return E.Cause(err, "read timestamp")
|
||||
}
|
||||
if math.Abs(float64(time.Now().Unix()-int64(epoch))) > 30 {
|
||||
return ErrBadTimestamp
|
||||
}
|
||||
|
||||
destination, err := socks.AddressSerializer.ReadAddrPort(reader)
|
||||
if err != nil {
|
||||
return E.Cause(err, "read destination")
|
||||
}
|
||||
|
||||
var paddingLen uint16
|
||||
err = binary.Read(reader, binary.BigEndian, &paddingLen)
|
||||
if err != nil {
|
||||
return E.Cause(err, "read padding length")
|
||||
}
|
||||
|
||||
if paddingLen > 0 {
|
||||
err = reader.Discard(int(paddingLen))
|
||||
if err != nil {
|
||||
return E.Cause(err, "discard padding")
|
||||
}
|
||||
}
|
||||
|
||||
var userCtx shadowsocks.UserContext[U]
|
||||
userCtx.Context = ctx
|
||||
userCtx.User = user
|
||||
|
||||
metadata.Protocol = "shadowsocks"
|
||||
metadata.Destination = destination
|
||||
return s.handler.NewConnection(&userCtx, &serverConn{
|
||||
Service: s.Service,
|
||||
Conn: conn,
|
||||
uPSK: uPSK,
|
||||
reader: reader,
|
||||
requestSalt: requestSalt,
|
||||
}, metadata)
|
||||
}
|
||||
|
||||
func (s *MultiService[U]) NewPacket(conn socks.PacketConn, buffer *buf.Buffer, metadata M.Metadata) error {
|
||||
packetHeader := buffer.To(aes.BlockSize)
|
||||
s.udpBlockCipher.Decrypt(packetHeader, packetHeader)
|
||||
|
||||
var _eiHeader [aes.BlockSize]byte
|
||||
eiHeader := common.Dup(_eiHeader[:])
|
||||
s.udpBlockCipher.Decrypt(eiHeader, buffer.Range(aes.BlockSize, 2*aes.BlockSize))
|
||||
|
||||
for i := range eiHeader {
|
||||
eiHeader[i] = eiHeader[i] ^ packetHeader[i]
|
||||
}
|
||||
|
||||
var user U
|
||||
var uPSK [KeySaltSize]byte
|
||||
if u, loaded := s.uPSKHashR[_eiHeader]; loaded {
|
||||
user = u
|
||||
uPSK = s.uPSK[u]
|
||||
} else {
|
||||
return E.New("invalid request")
|
||||
}
|
||||
|
||||
var sessionId, packetId uint64
|
||||
err := binary.Read(buffer, binary.BigEndian, &sessionId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = binary.Read(buffer, binary.BigEndian, &packetId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
session, loaded := s.sessions.LoadOrStore(sessionId, func() *serverUDPSession {
|
||||
return s.newUDPSession(uPSK)
|
||||
})
|
||||
if !loaded {
|
||||
session.remoteSessionId = sessionId
|
||||
key := Blake3DeriveKey(uPSK[:], packetHeader[:8], s.keyLength)
|
||||
session.remoteCipher = s.constructor(common.Dup(key))
|
||||
}
|
||||
|
||||
goto process
|
||||
|
||||
returnErr:
|
||||
if !loaded {
|
||||
s.sessions.Delete(sessionId)
|
||||
}
|
||||
return err
|
||||
|
||||
process:
|
||||
if !session.filter.ValidateCounter(packetId, math.MaxUint64) {
|
||||
err = ErrPacketIdNotUnique
|
||||
goto returnErr
|
||||
}
|
||||
|
||||
if packetHeader != nil {
|
||||
_, err = session.remoteCipher.Open(buffer.Index(0), packetHeader[4:16], buffer.Bytes(), nil)
|
||||
if err != nil {
|
||||
err = E.Cause(err, "decrypt packet")
|
||||
goto returnErr
|
||||
}
|
||||
}
|
||||
|
||||
var headerType byte
|
||||
headerType, err = buffer.ReadByte()
|
||||
if err != nil {
|
||||
err = E.Cause(err, "decrypt packet")
|
||||
goto returnErr
|
||||
}
|
||||
if headerType != HeaderTypeClient {
|
||||
err = ErrBadHeaderType
|
||||
goto returnErr
|
||||
}
|
||||
|
||||
var epoch uint64
|
||||
err = binary.Read(buffer, binary.BigEndian, &epoch)
|
||||
if err != nil {
|
||||
goto returnErr
|
||||
}
|
||||
if math.Abs(float64(uint64(time.Now().Unix())-epoch)) > 30 {
|
||||
err = ErrBadTimestamp
|
||||
goto returnErr
|
||||
}
|
||||
|
||||
var paddingLength uint16
|
||||
err = binary.Read(buffer, binary.BigEndian, &paddingLength)
|
||||
if err != nil {
|
||||
err = E.Cause(err, "read padding length")
|
||||
goto returnErr
|
||||
}
|
||||
buffer.Advance(int(paddingLength))
|
||||
|
||||
destination, err := socks.AddressSerializer.ReadAddrPort(buffer)
|
||||
if err != nil {
|
||||
goto returnErr
|
||||
}
|
||||
|
||||
metadata.Destination = destination
|
||||
session.remoteAddr = metadata.Source
|
||||
|
||||
var userCtx shadowsocks.UserContext[U]
|
||||
userCtx.Context = context.Background()
|
||||
userCtx.User = user
|
||||
|
||||
s.udpNat.NewContextPacket(&userCtx, sessionId, func() socks.PacketWriter {
|
||||
return &serverPacketWriter{s.Service, conn, session}
|
||||
}, buffer, metadata)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MultiService[U]) newUDPSession(uPSK [KeySaltSize]byte) *serverUDPSession {
|
||||
session := &serverUDPSession{}
|
||||
common.Must(binary.Read(m.secureRNG, binary.BigEndian, &session.sessionId))
|
||||
session.packetId--
|
||||
sessionId := make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(sessionId, session.sessionId)
|
||||
key := Blake3DeriveKey(uPSK[:], sessionId, m.keyLength)
|
||||
session.cipher = m.constructor(common.Dup(key))
|
||||
return session
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue