github.com/metacubex/sing-shadowsocks@v0.2.6/shadowaead_2022/relay.go (about) 1 package shadowaead_2022 2 3 import ( 4 "context" 5 "crypto/aes" 6 "crypto/cipher" 7 "encoding/base64" 8 "encoding/binary" 9 "net" 10 "os" 11 12 "github.com/metacubex/sing-shadowsocks" 13 "github.com/metacubex/sing-shadowsocks/shadowaead" 14 "github.com/sagernet/sing/common/auth" 15 "github.com/sagernet/sing/common/buf" 16 "github.com/sagernet/sing/common/bufio" 17 E "github.com/sagernet/sing/common/exceptions" 18 M "github.com/sagernet/sing/common/metadata" 19 N "github.com/sagernet/sing/common/network" 20 "github.com/sagernet/sing/common/udpnat" 21 22 "lukechampine.com/blake3" 23 ) 24 25 var _ shadowsocks.Service = (*RelayService[int])(nil) 26 27 type RelayService[U comparable] struct { 28 name string 29 keySaltLength int 30 handler shadowsocks.Handler 31 32 constructor func(key []byte) (cipher.AEAD, error) 33 blockConstructor func(key []byte) (cipher.Block, error) 34 udpBlockCipher cipher.Block 35 36 iPSK []byte 37 uPSKHash map[[aes.BlockSize]byte]U 38 uDestination map[U]M.Socksaddr 39 uCipher map[U]cipher.Block 40 udpNat *udpnat.Service[uint64] 41 } 42 43 func (s *RelayService[U]) Name() string { 44 return s.name 45 } 46 47 func (s *RelayService[U]) Password() string { 48 return base64.StdEncoding.EncodeToString(s.iPSK) 49 } 50 51 func (s *RelayService[U]) UpdateUsers(userList []U, keyList [][]byte, destinationList []M.Socksaddr) error { 52 uPSKHash := make(map[[aes.BlockSize]byte]U) 53 uDestination := make(map[U]M.Socksaddr) 54 uCipher := make(map[U]cipher.Block) 55 for i, user := range userList { 56 key := keyList[i] 57 destination := destinationList[i] 58 if len(key) < s.keySaltLength { 59 return shadowsocks.ErrBadKey 60 } else if len(key) > s.keySaltLength { 61 key = Key(key, s.keySaltLength) 62 } 63 64 var hash [aes.BlockSize]byte 65 hash512 := blake3.Sum512(key) 66 copy(hash[:], hash512[:]) 67 68 uPSKHash[hash] = user 69 uDestination[user] = destination 70 var err error 71 uCipher[user], err = s.blockConstructor(key) 72 if err != nil { 73 return err 74 } 75 } 76 77 s.uPSKHash = uPSKHash 78 s.uDestination = uDestination 79 s.uCipher = uCipher 80 return nil 81 } 82 83 func (s *RelayService[U]) UpdateUsersWithPasswords(userList []U, passwordList []string, destinationList []M.Socksaddr) error { 84 keyList := make([][]byte, 0, len(passwordList)) 85 for _, password := range passwordList { 86 if password == "" { 87 return shadowsocks.ErrMissingPassword 88 } 89 uPSK, err := base64.StdEncoding.DecodeString(password) 90 if err != nil { 91 return E.Cause(err, "decode psk") 92 } 93 keyList = append(keyList, uPSK) 94 } 95 return s.UpdateUsers(userList, keyList, destinationList) 96 } 97 98 func NewRelayServiceWithPassword[U comparable](method string, password string, udpTimeout int64, handler shadowsocks.Handler) (*RelayService[U], error) { 99 if password == "" { 100 return nil, ErrMissingPSK 101 } 102 iPSK, err := base64.StdEncoding.DecodeString(password) 103 if err != nil { 104 return nil, E.Cause(err, "decode psk") 105 } 106 return NewRelayService[U](method, iPSK, udpTimeout, handler) 107 } 108 109 func NewRelayService[U comparable](method string, psk []byte, udpTimeout int64, handler shadowsocks.Handler) (*RelayService[U], error) { 110 s := &RelayService[U]{ 111 name: method, 112 handler: handler, 113 114 uPSKHash: make(map[[aes.BlockSize]byte]U), 115 uDestination: make(map[U]M.Socksaddr), 116 uCipher: make(map[U]cipher.Block), 117 118 udpNat: udpnat.New[uint64](udpTimeout, handler), 119 } 120 121 switch method { 122 case "2022-blake3-aes-128-gcm": 123 s.keySaltLength = 16 124 s.constructor = aeadCipher(aes.NewCipher, cipher.NewGCM) 125 s.blockConstructor = aes.NewCipher 126 case "2022-blake3-aes-256-gcm": 127 s.keySaltLength = 32 128 s.constructor = aeadCipher(aes.NewCipher, cipher.NewGCM) 129 s.blockConstructor = aes.NewCipher 130 default: 131 return nil, os.ErrInvalid 132 } 133 if len(psk) != s.keySaltLength { 134 if len(psk) < s.keySaltLength { 135 return nil, shadowsocks.ErrBadKey 136 } else { 137 psk = Key(psk, s.keySaltLength) 138 } 139 } 140 s.iPSK = psk 141 var err error 142 s.udpBlockCipher, err = s.blockConstructor(psk) 143 return s, err 144 } 145 146 func (s *RelayService[U]) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error { 147 err := s.newConnection(ctx, conn, metadata) 148 if err != nil { 149 err = &shadowsocks.ServerConnError{Conn: conn, Source: metadata.Source, Cause: err} 150 } 151 return err 152 } 153 154 func (s *RelayService[U]) newConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error { 155 requestHeader := buf.New() 156 defer requestHeader.Release() 157 n, err := requestHeader.ReadOnceFrom(conn) 158 if err != nil { 159 return err 160 } else if int(n) < s.keySaltLength+aes.BlockSize { 161 return shadowaead.ErrBadHeader 162 } 163 requestSalt := requestHeader.To(s.keySaltLength) 164 var _eiHeader [aes.BlockSize]byte 165 eiHeader := _eiHeader[:] 166 copy(eiHeader, requestHeader.Range(s.keySaltLength, s.keySaltLength+aes.BlockSize)) 167 168 keyMaterial := make([]byte, s.keySaltLength*2) 169 copy(keyMaterial, s.iPSK) 170 copy(keyMaterial[s.keySaltLength:], requestSalt) 171 identitySubkey := buf.NewSize(s.keySaltLength) 172 identitySubkey.Extend(identitySubkey.FreeLen()) 173 blake3.DeriveKey(identitySubkey.Bytes(), "shadowsocks 2022 identity subkey", keyMaterial) 174 b, err := s.blockConstructor(identitySubkey.Bytes()) 175 identitySubkey.Release() 176 if err != nil { 177 return err 178 } 179 b.Decrypt(eiHeader, eiHeader) 180 181 var user U 182 if u, loaded := s.uPSKHash[_eiHeader]; loaded { 183 user = u 184 } else { 185 return E.New("invalid request") 186 } 187 188 copy(requestHeader.Range(aes.BlockSize, aes.BlockSize+s.keySaltLength), requestHeader.To(s.keySaltLength)) 189 requestHeader.Advance(aes.BlockSize) 190 191 metadata.Protocol = "shadowsocks-relay" 192 metadata.Destination = s.uDestination[user] 193 conn = bufio.NewCachedConn(conn, requestHeader) 194 return s.handler.NewConnection(auth.ContextWithUser(ctx, user), conn, metadata) 195 } 196 197 func (s *RelayService[U]) WriteIsThreadUnsafe() { 198 } 199 200 func (s *RelayService[U]) NewPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, metadata M.Metadata) error { 201 err := s.newPacket(ctx, conn, buffer, metadata) 202 if err != nil { 203 err = &shadowsocks.ServerPacketError{Source: metadata.Source, Cause: err} 204 } 205 return err 206 } 207 208 func (s *RelayService[U]) newPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, metadata M.Metadata) error { 209 packetHeader := buffer.To(aes.BlockSize) 210 s.udpBlockCipher.Decrypt(packetHeader, packetHeader) 211 212 sessionId := binary.BigEndian.Uint64(packetHeader) 213 214 var _eiHeader [aes.BlockSize]byte 215 eiHeader := _eiHeader[:] 216 s.udpBlockCipher.Decrypt(eiHeader, buffer.Range(aes.BlockSize, 2*aes.BlockSize)) 217 xorWords(eiHeader, eiHeader, packetHeader) 218 219 var user U 220 if u, loaded := s.uPSKHash[_eiHeader]; loaded { 221 user = u 222 } else { 223 return E.New("invalid request") 224 } 225 226 s.uCipher[user].Encrypt(packetHeader, packetHeader) 227 copy(buffer.Range(aes.BlockSize, 2*aes.BlockSize), packetHeader) 228 buffer.Advance(aes.BlockSize) 229 230 metadata.Protocol = "shadowsocks-relay" 231 metadata.Destination = s.uDestination[user] 232 s.udpNat.NewContextPacket(ctx, sessionId, buffer, metadata, func(natConn N.PacketConn) (context.Context, N.PacketWriter) { 233 return auth.ContextWithUser(ctx, user), &udpnat.DirectBackWriter{Source: conn, Nat: natConn} 234 }) 235 return nil 236 } 237 238 func (s *RelayService[U]) NewError(ctx context.Context, err error) { 239 s.handler.NewError(ctx, err) 240 }