github.com/eagleql/xray-core@v1.4.4/proxy/trojan/protocol.go (about) 1 package trojan 2 3 import ( 4 "context" 5 "encoding/binary" 6 fmt "fmt" 7 "io" 8 "runtime" 9 "syscall" 10 11 "github.com/eagleql/xray-core/common/buf" 12 "github.com/eagleql/xray-core/common/errors" 13 "github.com/eagleql/xray-core/common/net" 14 "github.com/eagleql/xray-core/common/protocol" 15 "github.com/eagleql/xray-core/common/session" 16 "github.com/eagleql/xray-core/common/signal" 17 "github.com/eagleql/xray-core/features/stats" 18 "github.com/eagleql/xray-core/transport/internet" 19 "github.com/eagleql/xray-core/transport/internet/xtls" 20 ) 21 22 var ( 23 crlf = []byte{'\r', '\n'} 24 25 addrParser = protocol.NewAddressParser( 26 protocol.AddressFamilyByte(0x01, net.AddressFamilyIPv4), 27 protocol.AddressFamilyByte(0x04, net.AddressFamilyIPv6), 28 protocol.AddressFamilyByte(0x03, net.AddressFamilyDomain), 29 ) 30 31 xtls_show = false 32 ) 33 34 const ( 35 maxLength = 8192 36 // XRS is constant for XTLS splice mode 37 XRS = "xtls-rprx-splice" 38 // XRD is constant for XTLS direct mode 39 XRD = "xtls-rprx-direct" 40 // XRO is constant for XTLS origin mode 41 XRO = "xtls-rprx-origin" 42 43 commandTCP byte = 1 44 commandUDP byte = 3 45 46 // for XTLS 47 commandXRD byte = 0xf0 // XTLS direct mode 48 commandXRO byte = 0xf1 // XTLS origin mode 49 ) 50 51 // ConnWriter is TCP Connection Writer Wrapper for trojan protocol 52 type ConnWriter struct { 53 io.Writer 54 Target net.Destination 55 Account *MemoryAccount 56 Flow string 57 headerSent bool 58 } 59 60 // Write implements io.Writer 61 func (c *ConnWriter) Write(p []byte) (n int, err error) { 62 if !c.headerSent { 63 if err := c.writeHeader(); err != nil { 64 return 0, newError("failed to write request header").Base(err) 65 } 66 } 67 68 return c.Writer.Write(p) 69 } 70 71 // WriteMultiBuffer implements buf.Writer 72 func (c *ConnWriter) WriteMultiBuffer(mb buf.MultiBuffer) error { 73 defer buf.ReleaseMulti(mb) 74 75 for _, b := range mb { 76 if !b.IsEmpty() { 77 if _, err := c.Write(b.Bytes()); err != nil { 78 return err 79 } 80 } 81 } 82 83 return nil 84 } 85 86 func (c *ConnWriter) writeHeader() error { 87 buffer := buf.StackNew() 88 defer buffer.Release() 89 90 command := commandTCP 91 if c.Target.Network == net.Network_UDP { 92 command = commandUDP 93 } else if c.Flow == XRD { 94 command = commandXRD 95 } else if c.Flow == XRO { 96 command = commandXRO 97 } 98 99 if _, err := buffer.Write(c.Account.Key); err != nil { 100 return err 101 } 102 if _, err := buffer.Write(crlf); err != nil { 103 return err 104 } 105 if err := buffer.WriteByte(command); err != nil { 106 return err 107 } 108 if err := addrParser.WriteAddressPort(&buffer, c.Target.Address, c.Target.Port); err != nil { 109 return err 110 } 111 if _, err := buffer.Write(crlf); err != nil { 112 return err 113 } 114 115 _, err := c.Writer.Write(buffer.Bytes()) 116 if err == nil { 117 c.headerSent = true 118 } 119 120 return err 121 } 122 123 // PacketWriter UDP Connection Writer Wrapper for trojan protocol 124 type PacketWriter struct { 125 io.Writer 126 Target net.Destination 127 } 128 129 // WriteMultiBuffer implements buf.Writer 130 func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error { 131 for { 132 mb2, b := buf.SplitFirst(mb) 133 mb = mb2 134 if b == nil { 135 break 136 } 137 target := &w.Target 138 if b.UDP != nil { 139 target = b.UDP 140 } 141 if _, err := w.writePacket(b.Bytes(), *target); err != nil { 142 buf.ReleaseMulti(mb) 143 return err 144 } 145 } 146 return nil 147 } 148 149 func (w *PacketWriter) writePacket(payload []byte, dest net.Destination) (int, error) { 150 buffer := buf.StackNew() 151 defer buffer.Release() 152 153 length := len(payload) 154 lengthBuf := [2]byte{} 155 binary.BigEndian.PutUint16(lengthBuf[:], uint16(length)) 156 if err := addrParser.WriteAddressPort(&buffer, dest.Address, dest.Port); err != nil { 157 return 0, err 158 } 159 if _, err := buffer.Write(lengthBuf[:]); err != nil { 160 return 0, err 161 } 162 if _, err := buffer.Write(crlf); err != nil { 163 return 0, err 164 } 165 if _, err := buffer.Write(payload); err != nil { 166 return 0, err 167 } 168 _, err := w.Write(buffer.Bytes()) 169 if err != nil { 170 return 0, err 171 } 172 173 return length, nil 174 } 175 176 // ConnReader is TCP Connection Reader Wrapper for trojan protocol 177 type ConnReader struct { 178 io.Reader 179 Target net.Destination 180 Flow string 181 headerParsed bool 182 } 183 184 // ParseHeader parses the trojan protocol header 185 func (c *ConnReader) ParseHeader() error { 186 var crlf [2]byte 187 var command [1]byte 188 var hash [56]byte 189 if _, err := io.ReadFull(c.Reader, hash[:]); err != nil { 190 return newError("failed to read user hash").Base(err) 191 } 192 193 if _, err := io.ReadFull(c.Reader, crlf[:]); err != nil { 194 return newError("failed to read crlf").Base(err) 195 } 196 197 if _, err := io.ReadFull(c.Reader, command[:]); err != nil { 198 return newError("failed to read command").Base(err) 199 } 200 201 network := net.Network_TCP 202 if command[0] == commandUDP { 203 network = net.Network_UDP 204 } else if command[0] == commandXRD { 205 c.Flow = XRD 206 } else if command[0] == commandXRO { 207 c.Flow = XRO 208 } 209 210 addr, port, err := addrParser.ReadAddressPort(nil, c.Reader) 211 if err != nil { 212 return newError("failed to read address and port").Base(err) 213 } 214 c.Target = net.Destination{Network: network, Address: addr, Port: port} 215 216 if _, err := io.ReadFull(c.Reader, crlf[:]); err != nil { 217 return newError("failed to read crlf").Base(err) 218 } 219 220 c.headerParsed = true 221 return nil 222 } 223 224 // Read implements io.Reader 225 func (c *ConnReader) Read(p []byte) (int, error) { 226 if !c.headerParsed { 227 if err := c.ParseHeader(); err != nil { 228 return 0, err 229 } 230 } 231 232 return c.Reader.Read(p) 233 } 234 235 // ReadMultiBuffer implements buf.Reader 236 func (c *ConnReader) ReadMultiBuffer() (buf.MultiBuffer, error) { 237 b := buf.New() 238 _, err := b.ReadFrom(c) 239 return buf.MultiBuffer{b}, err 240 } 241 242 // PacketReader is UDP Connection Reader Wrapper for trojan protocol 243 type PacketReader struct { 244 io.Reader 245 } 246 247 // ReadMultiBuffer implements buf.Reader 248 func (r *PacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) { 249 addr, port, err := addrParser.ReadAddressPort(nil, r) 250 if err != nil { 251 return nil, newError("failed to read address and port").Base(err) 252 } 253 254 var lengthBuf [2]byte 255 if _, err := io.ReadFull(r, lengthBuf[:]); err != nil { 256 return nil, newError("failed to read payload length").Base(err) 257 } 258 259 remain := int(binary.BigEndian.Uint16(lengthBuf[:])) 260 if remain > maxLength { 261 return nil, newError("oversize payload") 262 } 263 264 var crlf [2]byte 265 if _, err := io.ReadFull(r, crlf[:]); err != nil { 266 return nil, newError("failed to read crlf").Base(err) 267 } 268 269 dest := net.UDPDestination(addr, port) 270 var mb buf.MultiBuffer 271 for remain > 0 { 272 length := buf.Size 273 if remain < length { 274 length = remain 275 } 276 277 b := buf.New() 278 b.UDP = &dest 279 mb = append(mb, b) 280 n, err := b.ReadFullFrom(r, int32(length)) 281 if err != nil { 282 buf.ReleaseMulti(mb) 283 return nil, newError("failed to read payload").Base(err) 284 } 285 286 remain -= int(n) 287 } 288 289 return mb, nil 290 } 291 292 func ReadV(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, conn *xtls.Conn, rawConn syscall.RawConn, counter stats.Counter, sctx context.Context) error { 293 err := func() error { 294 var ct stats.Counter 295 for { 296 if conn.DirectIn { 297 conn.DirectIn = false 298 if sctx != nil { 299 if inbound := session.InboundFromContext(sctx); inbound != nil && inbound.Conn != nil { 300 iConn := inbound.Conn 301 statConn, ok := iConn.(*internet.StatCouterConnection) 302 if ok { 303 iConn = statConn.Connection 304 } 305 if xc, ok := iConn.(*xtls.Conn); ok { 306 iConn = xc.Connection 307 } 308 if tc, ok := iConn.(*net.TCPConn); ok { 309 if conn.SHOW { 310 fmt.Println(conn.MARK, "Splice") 311 } 312 runtime.Gosched() // necessary 313 w, err := tc.ReadFrom(conn.Connection) 314 if counter != nil { 315 counter.Add(w) 316 } 317 if statConn != nil && statConn.WriteCounter != nil { 318 statConn.WriteCounter.Add(w) 319 } 320 return err 321 } else { 322 panic("XTLS Splice: not TCP inbound") 323 } 324 } else { 325 //panic("XTLS Splice: nil inbound or nil inbound.Conn") 326 } 327 } 328 reader = buf.NewReadVReader(conn.Connection, rawConn) 329 ct = counter 330 if conn.SHOW { 331 fmt.Println(conn.MARK, "ReadV") 332 } 333 } 334 buffer, err := reader.ReadMultiBuffer() 335 if !buffer.IsEmpty() { 336 if ct != nil { 337 ct.Add(int64(buffer.Len())) 338 } 339 timer.Update() 340 if werr := writer.WriteMultiBuffer(buffer); werr != nil { 341 return werr 342 } 343 } 344 if err != nil { 345 return err 346 } 347 } 348 }() 349 if err != nil && errors.Cause(err) != io.EOF { 350 return err 351 } 352 return nil 353 }