proxy.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664
  1. // Package proxy contains all proxies used by Xray.
  2. //
  3. // To implement an inbound or outbound proxy, one needs to do the following:
  4. // 1. Implement the interface(s) below.
  5. // 2. Register a config creator through common.RegisterConfig.
  6. package proxy
  7. import (
  8. "bytes"
  9. "context"
  10. "crypto/rand"
  11. "io"
  12. "math/big"
  13. "runtime"
  14. "strconv"
  15. "time"
  16. "github.com/pires/go-proxyproto"
  17. "github.com/xtls/xray-core/app/dispatcher"
  18. "github.com/xtls/xray-core/common/buf"
  19. "github.com/xtls/xray-core/common/errors"
  20. "github.com/xtls/xray-core/common/net"
  21. "github.com/xtls/xray-core/common/protocol"
  22. "github.com/xtls/xray-core/common/session"
  23. "github.com/xtls/xray-core/common/signal"
  24. "github.com/xtls/xray-core/features/routing"
  25. "github.com/xtls/xray-core/features/stats"
  26. "github.com/xtls/xray-core/proxy/vless/encryption"
  27. "github.com/xtls/xray-core/transport"
  28. "github.com/xtls/xray-core/transport/internet"
  29. "github.com/xtls/xray-core/transport/internet/reality"
  30. "github.com/xtls/xray-core/transport/internet/stat"
  31. "github.com/xtls/xray-core/transport/internet/tls"
  32. )
  33. var (
  34. Tls13SupportedVersions = []byte{0x00, 0x2b, 0x00, 0x02, 0x03, 0x04}
  35. TlsClientHandShakeStart = []byte{0x16, 0x03}
  36. TlsServerHandShakeStart = []byte{0x16, 0x03, 0x03}
  37. TlsApplicationDataStart = []byte{0x17, 0x03, 0x03}
  38. Tls13CipherSuiteDic = map[uint16]string{
  39. 0x1301: "TLS_AES_128_GCM_SHA256",
  40. 0x1302: "TLS_AES_256_GCM_SHA384",
  41. 0x1303: "TLS_CHACHA20_POLY1305_SHA256",
  42. 0x1304: "TLS_AES_128_CCM_SHA256",
  43. 0x1305: "TLS_AES_128_CCM_8_SHA256",
  44. }
  45. )
  46. const (
  47. TlsHandshakeTypeClientHello byte = 0x01
  48. TlsHandshakeTypeServerHello byte = 0x02
  49. CommandPaddingContinue byte = 0x00
  50. CommandPaddingEnd byte = 0x01
  51. CommandPaddingDirect byte = 0x02
  52. )
  53. // An Inbound processes inbound connections.
  54. type Inbound interface {
  55. // Network returns a list of networks that this inbound supports. Connections with not-supported networks will not be passed into Process().
  56. Network() []net.Network
  57. // Process processes a connection of given network. If necessary, the Inbound can dispatch the connection to an Outbound.
  58. Process(context.Context, net.Network, stat.Connection, routing.Dispatcher) error
  59. }
  60. // An Outbound process outbound connections.
  61. type Outbound interface {
  62. // Process processes the given connection. The given dialer may be used to dial a system outbound connection.
  63. Process(context.Context, *transport.Link, internet.Dialer) error
  64. }
  65. // UserManager is the interface for Inbounds and Outbounds that can manage their users.
  66. type UserManager interface {
  67. // AddUser adds a new user.
  68. AddUser(context.Context, *protocol.MemoryUser) error
  69. // RemoveUser removes a user by email.
  70. RemoveUser(context.Context, string) error
  71. // Get user by email.
  72. GetUser(context.Context, string) *protocol.MemoryUser
  73. // Get all users.
  74. GetUsers(context.Context) []*protocol.MemoryUser
  75. // Get users count.
  76. GetUsersCount(context.Context) int64
  77. }
  78. type GetInbound interface {
  79. GetInbound() Inbound
  80. }
  81. type GetOutbound interface {
  82. GetOutbound() Outbound
  83. }
  84. // TrafficState is used to track uplink and downlink of one connection
  85. // It is used by XTLS to determine if switch to raw copy mode, It is used by Vision to calculate padding
  86. type TrafficState struct {
  87. UserUUID []byte
  88. NumberOfPacketToFilter int
  89. EnableXtls bool
  90. IsTLS12orAbove bool
  91. IsTLS bool
  92. Cipher uint16
  93. RemainingServerHello int32
  94. Inbound InboundState
  95. Outbound OutboundState
  96. }
  97. type InboundState struct {
  98. // reader link state
  99. WithinPaddingBuffers bool
  100. UplinkReaderDirectCopy bool
  101. RemainingCommand int32
  102. RemainingContent int32
  103. RemainingPadding int32
  104. CurrentCommand int
  105. // write link state
  106. IsPadding bool
  107. DownlinkWriterDirectCopy bool
  108. }
  109. type OutboundState struct {
  110. // reader link state
  111. WithinPaddingBuffers bool
  112. DownlinkReaderDirectCopy bool
  113. RemainingCommand int32
  114. RemainingContent int32
  115. RemainingPadding int32
  116. CurrentCommand int
  117. // write link state
  118. IsPadding bool
  119. UplinkWriterDirectCopy bool
  120. }
  121. func NewTrafficState(userUUID []byte) *TrafficState {
  122. return &TrafficState{
  123. UserUUID: userUUID,
  124. NumberOfPacketToFilter: 8,
  125. EnableXtls: false,
  126. IsTLS12orAbove: false,
  127. IsTLS: false,
  128. Cipher: 0,
  129. RemainingServerHello: -1,
  130. Inbound: InboundState{
  131. WithinPaddingBuffers: true,
  132. UplinkReaderDirectCopy: false,
  133. RemainingCommand: -1,
  134. RemainingContent: -1,
  135. RemainingPadding: -1,
  136. CurrentCommand: 0,
  137. IsPadding: true,
  138. DownlinkWriterDirectCopy: false,
  139. },
  140. Outbound: OutboundState{
  141. WithinPaddingBuffers: true,
  142. DownlinkReaderDirectCopy: false,
  143. RemainingCommand: -1,
  144. RemainingContent: -1,
  145. RemainingPadding: -1,
  146. CurrentCommand: 0,
  147. IsPadding: true,
  148. UplinkWriterDirectCopy: false,
  149. },
  150. }
  151. }
  152. // VisionReader is used to read xtls vision protocol
  153. // Note Vision probably only make sense as the inner most layer of reader, since it need assess traffic state from origin proxy traffic
  154. type VisionReader struct {
  155. buf.Reader
  156. trafficState *TrafficState
  157. ctx context.Context
  158. isUplink bool
  159. }
  160. func NewVisionReader(reader buf.Reader, state *TrafficState, isUplink bool, context context.Context) *VisionReader {
  161. return &VisionReader{
  162. Reader: reader,
  163. trafficState: state,
  164. ctx: context,
  165. isUplink: isUplink,
  166. }
  167. }
  168. func (w *VisionReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
  169. buffer, err := w.Reader.ReadMultiBuffer()
  170. if !buffer.IsEmpty() {
  171. var withinPaddingBuffers *bool
  172. var remainingContent *int32
  173. var remainingPadding *int32
  174. var currentCommand *int
  175. var switchToDirectCopy *bool
  176. if w.isUplink {
  177. withinPaddingBuffers = &w.trafficState.Inbound.WithinPaddingBuffers
  178. remainingContent = &w.trafficState.Inbound.RemainingContent
  179. remainingPadding = &w.trafficState.Inbound.RemainingPadding
  180. currentCommand = &w.trafficState.Inbound.CurrentCommand
  181. switchToDirectCopy = &w.trafficState.Inbound.UplinkReaderDirectCopy
  182. } else {
  183. withinPaddingBuffers = &w.trafficState.Outbound.WithinPaddingBuffers
  184. remainingContent = &w.trafficState.Outbound.RemainingContent
  185. remainingPadding = &w.trafficState.Outbound.RemainingPadding
  186. currentCommand = &w.trafficState.Outbound.CurrentCommand
  187. switchToDirectCopy = &w.trafficState.Outbound.DownlinkReaderDirectCopy
  188. }
  189. if *withinPaddingBuffers || w.trafficState.NumberOfPacketToFilter > 0 {
  190. mb2 := make(buf.MultiBuffer, 0, len(buffer))
  191. for _, b := range buffer {
  192. newbuffer := XtlsUnpadding(b, w.trafficState, w.isUplink, w.ctx)
  193. if newbuffer.Len() > 0 {
  194. mb2 = append(mb2, newbuffer)
  195. }
  196. }
  197. buffer = mb2
  198. if *remainingContent > 0 || *remainingPadding > 0 || *currentCommand == 0 {
  199. *withinPaddingBuffers = true
  200. } else if *currentCommand == 1 {
  201. *withinPaddingBuffers = false
  202. } else if *currentCommand == 2 {
  203. *withinPaddingBuffers = false
  204. *switchToDirectCopy = true
  205. } else {
  206. errors.LogInfo(w.ctx, "XtlsRead unknown command ", *currentCommand, buffer.Len())
  207. }
  208. }
  209. if w.trafficState.NumberOfPacketToFilter > 0 {
  210. XtlsFilterTls(buffer, w.trafficState, w.ctx)
  211. }
  212. }
  213. return buffer, err
  214. }
  215. // VisionWriter is used to write xtls vision protocol
  216. // Note Vision probably only make sense as the inner most layer of writer, since it need assess traffic state from origin proxy traffic
  217. type VisionWriter struct {
  218. buf.Writer
  219. trafficState *TrafficState
  220. ctx context.Context
  221. writeOnceUserUUID []byte
  222. isUplink bool
  223. }
  224. func NewVisionWriter(writer buf.Writer, state *TrafficState, isUplink bool, context context.Context) *VisionWriter {
  225. w := make([]byte, len(state.UserUUID))
  226. copy(w, state.UserUUID)
  227. return &VisionWriter{
  228. Writer: writer,
  229. trafficState: state,
  230. ctx: context,
  231. writeOnceUserUUID: w,
  232. isUplink: isUplink,
  233. }
  234. }
  235. func (w *VisionWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
  236. if w.trafficState.NumberOfPacketToFilter > 0 {
  237. XtlsFilterTls(mb, w.trafficState, w.ctx)
  238. }
  239. var isPadding *bool
  240. var switchToDirectCopy *bool
  241. if w.isUplink {
  242. isPadding = &w.trafficState.Outbound.IsPadding
  243. switchToDirectCopy = &w.trafficState.Outbound.UplinkWriterDirectCopy
  244. } else {
  245. isPadding = &w.trafficState.Inbound.IsPadding
  246. switchToDirectCopy = &w.trafficState.Inbound.DownlinkWriterDirectCopy
  247. }
  248. if *isPadding {
  249. if len(mb) == 1 && mb[0] == nil {
  250. mb[0] = XtlsPadding(nil, CommandPaddingContinue, &w.writeOnceUserUUID, true, w.ctx) // we do a long padding to hide vless header
  251. return w.Writer.WriteMultiBuffer(mb)
  252. }
  253. mb = ReshapeMultiBuffer(w.ctx, mb)
  254. longPadding := w.trafficState.IsTLS
  255. for i, b := range mb {
  256. if w.trafficState.IsTLS && b.Len() >= 6 && bytes.Equal(TlsApplicationDataStart, b.BytesTo(3)) {
  257. if w.trafficState.EnableXtls {
  258. *switchToDirectCopy = true
  259. }
  260. var command byte = CommandPaddingContinue
  261. if i == len(mb)-1 {
  262. command = CommandPaddingEnd
  263. if w.trafficState.EnableXtls {
  264. command = CommandPaddingDirect
  265. }
  266. }
  267. mb[i] = XtlsPadding(b, command, &w.writeOnceUserUUID, true, w.ctx)
  268. *isPadding = false // padding going to end
  269. longPadding = false
  270. continue
  271. } else if !w.trafficState.IsTLS12orAbove && w.trafficState.NumberOfPacketToFilter <= 1 { // For compatibility with earlier vision receiver, we finish padding 1 packet early
  272. *isPadding = false
  273. mb[i] = XtlsPadding(b, CommandPaddingEnd, &w.writeOnceUserUUID, longPadding, w.ctx)
  274. break
  275. }
  276. var command byte = CommandPaddingContinue
  277. if i == len(mb)-1 && !*isPadding {
  278. command = CommandPaddingEnd
  279. if w.trafficState.EnableXtls {
  280. command = CommandPaddingDirect
  281. }
  282. }
  283. mb[i] = XtlsPadding(b, command, &w.writeOnceUserUUID, longPadding, w.ctx)
  284. }
  285. }
  286. return w.Writer.WriteMultiBuffer(mb)
  287. }
  288. // ReshapeMultiBuffer prepare multi buffer for padding structure (max 21 bytes)
  289. func ReshapeMultiBuffer(ctx context.Context, buffer buf.MultiBuffer) buf.MultiBuffer {
  290. needReshape := 0
  291. for _, b := range buffer {
  292. if b.Len() >= buf.Size-21 {
  293. needReshape += 1
  294. }
  295. }
  296. if needReshape == 0 {
  297. return buffer
  298. }
  299. mb2 := make(buf.MultiBuffer, 0, len(buffer)+needReshape)
  300. toPrint := ""
  301. for i, buffer1 := range buffer {
  302. if buffer1.Len() >= buf.Size-21 {
  303. index := int32(bytes.LastIndex(buffer1.Bytes(), TlsApplicationDataStart))
  304. if index < 21 || index > buf.Size-21 {
  305. index = buf.Size / 2
  306. }
  307. buffer2 := buf.New()
  308. buffer2.Write(buffer1.BytesFrom(index))
  309. buffer1.Resize(0, index)
  310. mb2 = append(mb2, buffer1, buffer2)
  311. toPrint += " " + strconv.Itoa(int(buffer1.Len())) + " " + strconv.Itoa(int(buffer2.Len()))
  312. } else {
  313. mb2 = append(mb2, buffer1)
  314. toPrint += " " + strconv.Itoa(int(buffer1.Len()))
  315. }
  316. buffer[i] = nil
  317. }
  318. buffer = buffer[:0]
  319. errors.LogInfo(ctx, "ReshapeMultiBuffer ", toPrint)
  320. return mb2
  321. }
  322. // XtlsPadding add padding to eliminate length signature during tls handshake
  323. func XtlsPadding(b *buf.Buffer, command byte, userUUID *[]byte, longPadding bool, ctx context.Context) *buf.Buffer {
  324. var contentLen int32 = 0
  325. var paddingLen int32 = 0
  326. if b != nil {
  327. contentLen = b.Len()
  328. }
  329. if contentLen < 900 && longPadding {
  330. l, err := rand.Int(rand.Reader, big.NewInt(500))
  331. if err != nil {
  332. errors.LogDebugInner(ctx, err, "failed to generate padding")
  333. }
  334. paddingLen = int32(l.Int64()) + 900 - contentLen
  335. } else {
  336. l, err := rand.Int(rand.Reader, big.NewInt(256))
  337. if err != nil {
  338. errors.LogDebugInner(ctx, err, "failed to generate padding")
  339. }
  340. paddingLen = int32(l.Int64())
  341. }
  342. if paddingLen > buf.Size-21-contentLen {
  343. paddingLen = buf.Size - 21 - contentLen
  344. }
  345. newbuffer := buf.New()
  346. if userUUID != nil {
  347. newbuffer.Write(*userUUID)
  348. *userUUID = nil
  349. }
  350. newbuffer.Write([]byte{command, byte(contentLen >> 8), byte(contentLen), byte(paddingLen >> 8), byte(paddingLen)})
  351. if b != nil {
  352. newbuffer.Write(b.Bytes())
  353. b.Release()
  354. b = nil
  355. }
  356. newbuffer.Extend(paddingLen)
  357. errors.LogInfo(ctx, "XtlsPadding ", contentLen, " ", paddingLen, " ", command)
  358. return newbuffer
  359. }
  360. // XtlsUnpadding remove padding and parse command
  361. func XtlsUnpadding(b *buf.Buffer, s *TrafficState, isUplink bool, ctx context.Context) *buf.Buffer {
  362. var remainingCommand *int32
  363. var remainingContent *int32
  364. var remainingPadding *int32
  365. var currentCommand *int
  366. if isUplink {
  367. remainingCommand = &s.Inbound.RemainingCommand
  368. remainingContent = &s.Inbound.RemainingContent
  369. remainingPadding = &s.Inbound.RemainingPadding
  370. currentCommand = &s.Inbound.CurrentCommand
  371. } else {
  372. remainingCommand = &s.Outbound.RemainingCommand
  373. remainingContent = &s.Outbound.RemainingContent
  374. remainingPadding = &s.Outbound.RemainingPadding
  375. currentCommand = &s.Outbound.CurrentCommand
  376. }
  377. if *remainingCommand == -1 && *remainingContent == -1 && *remainingPadding == -1 { // initial state
  378. if b.Len() >= 21 && bytes.Equal(s.UserUUID, b.BytesTo(16)) {
  379. b.Advance(16)
  380. *remainingCommand = 5
  381. } else {
  382. return b
  383. }
  384. }
  385. newbuffer := buf.New()
  386. for b.Len() > 0 {
  387. if *remainingCommand > 0 {
  388. data, err := b.ReadByte()
  389. if err != nil {
  390. return newbuffer
  391. }
  392. switch *remainingCommand {
  393. case 5:
  394. *currentCommand = int(data)
  395. case 4:
  396. *remainingContent = int32(data) << 8
  397. case 3:
  398. *remainingContent = *remainingContent | int32(data)
  399. case 2:
  400. *remainingPadding = int32(data) << 8
  401. case 1:
  402. *remainingPadding = *remainingPadding | int32(data)
  403. errors.LogInfo(ctx, "Xtls Unpadding new block, content ", *remainingContent, " padding ", *remainingPadding, " command ", *currentCommand)
  404. }
  405. *remainingCommand--
  406. } else if *remainingContent > 0 {
  407. len := *remainingContent
  408. if b.Len() < len {
  409. len = b.Len()
  410. }
  411. data, err := b.ReadBytes(len)
  412. if err != nil {
  413. return newbuffer
  414. }
  415. newbuffer.Write(data)
  416. *remainingContent -= len
  417. } else { // remainingPadding > 0
  418. len := *remainingPadding
  419. if b.Len() < len {
  420. len = b.Len()
  421. }
  422. b.Advance(len)
  423. *remainingPadding -= len
  424. }
  425. if *remainingCommand <= 0 && *remainingContent <= 0 && *remainingPadding <= 0 { // this block done
  426. if *currentCommand == 0 {
  427. *remainingCommand = 5
  428. } else {
  429. *remainingCommand = -1 // set to initial state
  430. *remainingContent = -1
  431. *remainingPadding = -1
  432. if b.Len() > 0 { // shouldn't happen
  433. newbuffer.Write(b.Bytes())
  434. }
  435. break
  436. }
  437. }
  438. }
  439. b.Release()
  440. b = nil
  441. return newbuffer
  442. }
  443. // XtlsFilterTls filter and recognize tls 1.3 and other info
  444. func XtlsFilterTls(buffer buf.MultiBuffer, trafficState *TrafficState, ctx context.Context) {
  445. for _, b := range buffer {
  446. if b == nil {
  447. continue
  448. }
  449. trafficState.NumberOfPacketToFilter--
  450. if b.Len() >= 6 {
  451. startsBytes := b.BytesTo(6)
  452. if bytes.Equal(TlsServerHandShakeStart, startsBytes[:3]) && startsBytes[5] == TlsHandshakeTypeServerHello {
  453. trafficState.RemainingServerHello = (int32(startsBytes[3])<<8 | int32(startsBytes[4])) + 5
  454. trafficState.IsTLS12orAbove = true
  455. trafficState.IsTLS = true
  456. if b.Len() >= 79 && trafficState.RemainingServerHello >= 79 {
  457. sessionIdLen := int32(b.Byte(43))
  458. cipherSuite := b.BytesRange(43+sessionIdLen+1, 43+sessionIdLen+3)
  459. trafficState.Cipher = uint16(cipherSuite[0])<<8 | uint16(cipherSuite[1])
  460. } else {
  461. errors.LogInfo(ctx, "XtlsFilterTls short server hello, tls 1.2 or older? ", b.Len(), " ", trafficState.RemainingServerHello)
  462. }
  463. } else if bytes.Equal(TlsClientHandShakeStart, startsBytes[:2]) && startsBytes[5] == TlsHandshakeTypeClientHello {
  464. trafficState.IsTLS = true
  465. errors.LogInfo(ctx, "XtlsFilterTls found tls client hello! ", buffer.Len())
  466. }
  467. }
  468. if trafficState.RemainingServerHello > 0 {
  469. end := trafficState.RemainingServerHello
  470. if end > b.Len() {
  471. end = b.Len()
  472. }
  473. trafficState.RemainingServerHello -= b.Len()
  474. if bytes.Contains(b.BytesTo(end), Tls13SupportedVersions) {
  475. v, ok := Tls13CipherSuiteDic[trafficState.Cipher]
  476. if !ok {
  477. v = "Old cipher: " + strconv.FormatUint(uint64(trafficState.Cipher), 16)
  478. } else if v != "TLS_AES_128_CCM_8_SHA256" {
  479. trafficState.EnableXtls = true
  480. }
  481. errors.LogInfo(ctx, "XtlsFilterTls found tls 1.3! ", b.Len(), " ", v)
  482. trafficState.NumberOfPacketToFilter = 0
  483. return
  484. } else if trafficState.RemainingServerHello <= 0 {
  485. errors.LogInfo(ctx, "XtlsFilterTls found tls 1.2! ", b.Len())
  486. trafficState.NumberOfPacketToFilter = 0
  487. return
  488. }
  489. errors.LogInfo(ctx, "XtlsFilterTls inconclusive server hello ", b.Len(), " ", trafficState.RemainingServerHello)
  490. }
  491. if trafficState.NumberOfPacketToFilter <= 0 {
  492. errors.LogInfo(ctx, "XtlsFilterTls stop filtering", buffer.Len())
  493. }
  494. }
  495. }
  496. // UnwrapRawConn support unwrap encryption, stats, tls, utls, reality, proxyproto, uds-wrapper conn and get raw tcp/uds conn from it
  497. func UnwrapRawConn(conn net.Conn) (net.Conn, stats.Counter, stats.Counter) {
  498. var readCounter, writerCounter stats.Counter
  499. if conn != nil {
  500. isEncryption := false
  501. if commonConn, ok := conn.(*encryption.CommonConn); ok {
  502. conn = commonConn.Conn
  503. isEncryption = true
  504. }
  505. if xorConn, ok := conn.(*encryption.XorConn); ok {
  506. return xorConn, nil, nil // full-random xorConn should not be penetrated
  507. }
  508. if statConn, ok := conn.(*stat.CounterConnection); ok {
  509. conn = statConn.Connection
  510. readCounter = statConn.ReadCounter
  511. writerCounter = statConn.WriteCounter
  512. }
  513. if !isEncryption { // avoids double penetration
  514. if xc, ok := conn.(*tls.Conn); ok {
  515. conn = xc.NetConn()
  516. } else if utlsConn, ok := conn.(*tls.UConn); ok {
  517. conn = utlsConn.NetConn()
  518. } else if realityConn, ok := conn.(*reality.Conn); ok {
  519. conn = realityConn.NetConn()
  520. } else if realityUConn, ok := conn.(*reality.UConn); ok {
  521. conn = realityUConn.NetConn()
  522. }
  523. }
  524. if pc, ok := conn.(*proxyproto.Conn); ok {
  525. conn = pc.Raw()
  526. // 8192 > 4096, there is no need to process pc's bufReader
  527. }
  528. if uc, ok := conn.(*internet.UnixConnWrapper); ok {
  529. conn = uc.UnixConn
  530. }
  531. }
  532. return conn, readCounter, writerCounter
  533. }
  534. // CopyRawConnIfExist use the most efficient copy method.
  535. // - If caller don't want to turn on splice, do not pass in both reader conn and writer conn
  536. // - writer are from *transport.Link
  537. func CopyRawConnIfExist(ctx context.Context, readerConn net.Conn, writerConn net.Conn, writer buf.Writer, timer *signal.ActivityTimer, inTimer *signal.ActivityTimer) error {
  538. readerConn, readCounter, _ := UnwrapRawConn(readerConn)
  539. writerConn, _, writeCounter := UnwrapRawConn(writerConn)
  540. reader := buf.NewReader(readerConn)
  541. if runtime.GOOS != "linux" && runtime.GOOS != "android" {
  542. return readV(ctx, reader, writer, timer, readCounter)
  543. }
  544. tc, ok := writerConn.(*net.TCPConn)
  545. if !ok || readerConn == nil || writerConn == nil {
  546. return readV(ctx, reader, writer, timer, readCounter)
  547. }
  548. inbound := session.InboundFromContext(ctx)
  549. if inbound == nil || inbound.CanSpliceCopy == 3 {
  550. return readV(ctx, reader, writer, timer, readCounter)
  551. }
  552. outbounds := session.OutboundsFromContext(ctx)
  553. if len(outbounds) == 0 {
  554. return readV(ctx, reader, writer, timer, readCounter)
  555. }
  556. for _, ob := range outbounds {
  557. if ob.CanSpliceCopy == 3 {
  558. return readV(ctx, reader, writer, timer, readCounter)
  559. }
  560. }
  561. for {
  562. inbound := session.InboundFromContext(ctx)
  563. outbounds := session.OutboundsFromContext(ctx)
  564. var splice = inbound.CanSpliceCopy == 1
  565. for _, ob := range outbounds {
  566. if ob.CanSpliceCopy != 1 {
  567. splice = false
  568. }
  569. }
  570. if splice {
  571. errors.LogInfo(ctx, "CopyRawConn splice")
  572. statWriter, _ := writer.(*dispatcher.SizeStatWriter)
  573. //runtime.Gosched() // necessary
  574. time.Sleep(time.Millisecond) // without this, there will be a rare ssl error for freedom splice
  575. timer.SetTimeout(8 * time.Hour) // prevent leak, just in case
  576. if inTimer != nil {
  577. inTimer.SetTimeout(8 * time.Hour)
  578. }
  579. w, err := tc.ReadFrom(readerConn)
  580. if readCounter != nil {
  581. readCounter.Add(w) // outbound stats
  582. }
  583. if writeCounter != nil {
  584. writeCounter.Add(w) // inbound stats
  585. }
  586. if statWriter != nil {
  587. statWriter.Counter.Add(w) // user stats
  588. }
  589. if err != nil && errors.Cause(err) != io.EOF {
  590. return err
  591. }
  592. return nil
  593. }
  594. buffer, err := reader.ReadMultiBuffer()
  595. if !buffer.IsEmpty() {
  596. if readCounter != nil {
  597. readCounter.Add(int64(buffer.Len()))
  598. }
  599. timer.Update()
  600. if werr := writer.WriteMultiBuffer(buffer); werr != nil {
  601. return werr
  602. }
  603. }
  604. if err != nil {
  605. if errors.Cause(err) == io.EOF {
  606. return nil
  607. }
  608. return err
  609. }
  610. }
  611. }
  612. func readV(ctx context.Context, reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, readCounter stats.Counter) error {
  613. errors.LogInfo(ctx, "CopyRawConn (maybe) readv")
  614. if err := buf.Copy(reader, writer, buf.UpdateActivity(timer), buf.AddToStatCounter(readCounter)); err != nil {
  615. return errors.New("failed to process response").Base(err)
  616. }
  617. return nil
  618. }
  619. func IsRAWTransport(conn stat.Connection) bool {
  620. iConn := conn
  621. if statConn, ok := iConn.(*stat.CounterConnection); ok {
  622. iConn = statConn.Connection
  623. }
  624. _, ok1 := iConn.(*proxyproto.Conn)
  625. _, ok2 := iConn.(*net.TCPConn)
  626. _, ok3 := iConn.(*internet.UnixConnWrapper)
  627. return ok1 || ok2 || ok3
  628. }