github.com/inazumav/sing-box@v0.0.0-20230926072359-ab51429a14f1/transport/hysteria2/salamander.go (about) 1 package hysteria2 2 3 import ( 4 "net" 5 6 "github.com/sagernet/sing/common" 7 "github.com/sagernet/sing/common/buf" 8 "github.com/sagernet/sing/common/bufio" 9 E "github.com/sagernet/sing/common/exceptions" 10 M "github.com/sagernet/sing/common/metadata" 11 N "github.com/sagernet/sing/common/network" 12 13 "golang.org/x/crypto/blake2b" 14 ) 15 16 const salamanderSaltLen = 8 17 18 const ObfsTypeSalamander = "salamander" 19 20 type Salamander struct { 21 net.PacketConn 22 password []byte 23 } 24 25 func NewSalamanderConn(conn net.PacketConn, password []byte) net.PacketConn { 26 writer, isVectorised := bufio.CreateVectorisedPacketWriter(conn) 27 if isVectorised { 28 return &VectorisedSalamander{ 29 Salamander: Salamander{ 30 PacketConn: conn, 31 password: password, 32 }, 33 writer: writer, 34 } 35 } else { 36 return &Salamander{ 37 PacketConn: conn, 38 password: password, 39 } 40 } 41 } 42 43 func (s *Salamander) ReadFrom(p []byte) (n int, addr net.Addr, err error) { 44 n, addr, err = s.PacketConn.ReadFrom(p) 45 if err != nil { 46 return 47 } 48 if n <= salamanderSaltLen { 49 return 0, nil, E.New("salamander: packet too short") 50 } 51 key := blake2b.Sum256(append(s.password, p[:salamanderSaltLen]...)) 52 for index, c := range p[salamanderSaltLen:n] { 53 p[index] = c ^ key[index%blake2b.Size256] 54 } 55 return n - salamanderSaltLen, addr, nil 56 } 57 58 func (s *Salamander) WriteTo(p []byte, addr net.Addr) (n int, err error) { 59 buffer := buf.NewSize(len(p) + salamanderSaltLen) 60 defer buffer.Release() 61 buffer.WriteRandom(salamanderSaltLen) 62 key := blake2b.Sum256(append(s.password, buffer.Bytes()...)) 63 for index, c := range p { 64 common.Must(buffer.WriteByte(c ^ key[index%blake2b.Size256])) 65 } 66 _, err = s.PacketConn.WriteTo(buffer.Bytes(), addr) 67 if err != nil { 68 return 69 } 70 return len(p), nil 71 } 72 73 type VectorisedSalamander struct { 74 Salamander 75 writer N.VectorisedPacketWriter 76 } 77 78 func (s *VectorisedSalamander) WriteTo(p []byte, addr net.Addr) (n int, err error) { 79 buffer := buf.NewSize(salamanderSaltLen) 80 buffer.WriteRandom(salamanderSaltLen) 81 key := blake2b.Sum256(append(s.password, buffer.Bytes()...)) 82 for i := range p { 83 p[i] ^= key[i%blake2b.Size256] 84 } 85 err = s.writer.WriteVectorisedPacket([]*buf.Buffer{buffer, buf.As(p)}, M.SocksaddrFromNet(addr)) 86 if err != nil { 87 return 88 } 89 return len(p), nil 90 } 91 92 func (s *VectorisedSalamander) WriteVectorisedPacket(buffers []*buf.Buffer, destination M.Socksaddr) error { 93 header := buf.NewSize(salamanderSaltLen) 94 defer header.Release() 95 header.WriteRandom(salamanderSaltLen) 96 key := blake2b.Sum256(append(s.password, header.Bytes()...)) 97 var bufferIndex int 98 for _, buffer := range buffers { 99 content := buffer.Bytes() 100 for index, c := range content { 101 content[bufferIndex+index] = c ^ key[bufferIndex+index%blake2b.Size256] 102 } 103 bufferIndex += len(content) 104 } 105 return s.writer.WriteVectorisedPacket(append([]*buf.Buffer{header}, buffers...), destination) 106 }