proxy.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  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/common/buf"
  18. "github.com/xtls/xray-core/common/errors"
  19. "github.com/xtls/xray-core/common/net"
  20. "github.com/xtls/xray-core/common/protocol"
  21. "github.com/xtls/xray-core/common/session"
  22. "github.com/xtls/xray-core/common/signal"
  23. "github.com/xtls/xray-core/features/routing"
  24. "github.com/xtls/xray-core/features/stats"
  25. "github.com/xtls/xray-core/transport"
  26. "github.com/xtls/xray-core/transport/internet"
  27. "github.com/xtls/xray-core/transport/internet/reality"
  28. "github.com/xtls/xray-core/transport/internet/stat"
  29. "github.com/xtls/xray-core/transport/internet/tls"
  30. )
  31. var (
  32. Tls13SupportedVersions = []byte{0x00, 0x2b, 0x00, 0x02, 0x03, 0x04}
  33. TlsClientHandShakeStart = []byte{0x16, 0x03}
  34. TlsServerHandShakeStart = []byte{0x16, 0x03, 0x03}
  35. TlsApplicationDataStart = []byte{0x17, 0x03, 0x03}
  36. Tls13CipherSuiteDic = map[uint16]string{
  37. 0x1301: "TLS_AES_128_GCM_SHA256",
  38. 0x1302: "TLS_AES_256_GCM_SHA384",
  39. 0x1303: "TLS_CHACHA20_POLY1305_SHA256",
  40. 0x1304: "TLS_AES_128_CCM_SHA256",
  41. 0x1305: "TLS_AES_128_CCM_8_SHA256",
  42. }
  43. )
  44. const (
  45. TlsHandshakeTypeClientHello byte = 0x01
  46. TlsHandshakeTypeServerHello byte = 0x02
  47. CommandPaddingContinue byte = 0x00
  48. CommandPaddingEnd byte = 0x01
  49. CommandPaddingDirect byte = 0x02
  50. )
  51. // An Inbound processes inbound connections.
  52. type Inbound interface {
  53. // Network returns a list of networks that this inbound supports. Connections with not-supported networks will not be passed into Process().
  54. Network() []net.Network
  55. // Process processes a connection of given network. If necessary, the Inbound can dispatch the connection to an Outbound.
  56. Process(context.Context, net.Network, stat.Connection, routing.Dispatcher) error
  57. }
  58. // An Outbound process outbound connections.
  59. type Outbound interface {
  60. // Process processes the given connection. The given dialer may be used to dial a system outbound connection.
  61. Process(context.Context, *transport.Link, internet.Dialer) error
  62. }
  63. // UserManager is the interface for Inbounds and Outbounds that can manage their users.
  64. type UserManager interface {
  65. // AddUser adds a new user.
  66. AddUser(context.Context, *protocol.MemoryUser) error
  67. // RemoveUser removes a user by email.
  68. RemoveUser(context.Context, string) error
  69. }
  70. type GetInbound interface {
  71. GetInbound() Inbound
  72. }
  73. type GetOutbound interface {
  74. GetOutbound() Outbound
  75. }
  76. // TrafficState is used to track uplink and downlink of one connection
  77. // It is used by XTLS to determine if switch to raw copy mode, It is used by Vision to calculate padding
  78. type TrafficState struct {
  79. UserUUID []byte
  80. NumberOfPacketToFilter int
  81. EnableXtls bool
  82. IsTLS12orAbove bool
  83. IsTLS bool
  84. Cipher uint16
  85. RemainingServerHello int32
  86. // reader link state
  87. WithinPaddingBuffers bool
  88. ReaderSwitchToDirectCopy bool
  89. RemainingCommand int32
  90. RemainingContent int32
  91. RemainingPadding int32
  92. CurrentCommand int
  93. // write link state
  94. IsPadding bool
  95. WriterSwitchToDirectCopy bool
  96. }
  97. func NewTrafficState(userUUID []byte) *TrafficState {
  98. return &TrafficState{
  99. UserUUID: userUUID,
  100. NumberOfPacketToFilter: 8,
  101. EnableXtls: false,
  102. IsTLS12orAbove: false,
  103. IsTLS: false,
  104. Cipher: 0,
  105. RemainingServerHello: -1,
  106. WithinPaddingBuffers: true,
  107. ReaderSwitchToDirectCopy: false,
  108. RemainingCommand: -1,
  109. RemainingContent: -1,
  110. RemainingPadding: -1,
  111. CurrentCommand: 0,
  112. IsPadding: true,
  113. WriterSwitchToDirectCopy: false,
  114. }
  115. }
  116. // VisionReader is used to read xtls vision protocol
  117. // Note Vision probably only make sense as the inner most layer of reader, since it need assess traffic state from origin proxy traffic
  118. type VisionReader struct {
  119. buf.Reader
  120. trafficState *TrafficState
  121. ctx context.Context
  122. }
  123. func NewVisionReader(reader buf.Reader, state *TrafficState, context context.Context) *VisionReader {
  124. return &VisionReader{
  125. Reader: reader,
  126. trafficState: state,
  127. ctx: context,
  128. }
  129. }
  130. func (w *VisionReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
  131. buffer, err := w.Reader.ReadMultiBuffer()
  132. if !buffer.IsEmpty() {
  133. if w.trafficState.WithinPaddingBuffers || w.trafficState.NumberOfPacketToFilter > 0 {
  134. mb2 := make(buf.MultiBuffer, 0, len(buffer))
  135. for _, b := range buffer {
  136. newbuffer := XtlsUnpadding(b, w.trafficState, w.ctx)
  137. if newbuffer.Len() > 0 {
  138. mb2 = append(mb2, newbuffer)
  139. }
  140. }
  141. buffer = mb2
  142. if w.trafficState.RemainingContent > 0 || w.trafficState.RemainingPadding > 0 || w.trafficState.CurrentCommand == 0 {
  143. w.trafficState.WithinPaddingBuffers = true
  144. } else if w.trafficState.CurrentCommand == 1 {
  145. w.trafficState.WithinPaddingBuffers = false
  146. } else if w.trafficState.CurrentCommand == 2 {
  147. w.trafficState.WithinPaddingBuffers = false
  148. w.trafficState.ReaderSwitchToDirectCopy = true
  149. } else {
  150. newError("XtlsRead unknown command ", w.trafficState.CurrentCommand, buffer.Len()).WriteToLog(session.ExportIDToError(w.ctx))
  151. }
  152. }
  153. if w.trafficState.NumberOfPacketToFilter > 0 {
  154. XtlsFilterTls(buffer, w.trafficState, w.ctx)
  155. }
  156. }
  157. return buffer, err
  158. }
  159. // VisionWriter is used to write xtls vision protocol
  160. // Note Vision probably only make sense as the inner most layer of writer, since it need assess traffic state from origin proxy traffic
  161. type VisionWriter struct {
  162. buf.Writer
  163. trafficState *TrafficState
  164. ctx context.Context
  165. writeOnceUserUUID []byte
  166. }
  167. func NewVisionWriter(writer buf.Writer, state *TrafficState, context context.Context) *VisionWriter {
  168. w := make([]byte, len(state.UserUUID))
  169. copy(w, state.UserUUID)
  170. return &VisionWriter{
  171. Writer: writer,
  172. trafficState: state,
  173. ctx: context,
  174. writeOnceUserUUID: w,
  175. }
  176. }
  177. func (w *VisionWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
  178. if w.trafficState.NumberOfPacketToFilter > 0 {
  179. XtlsFilterTls(mb, w.trafficState, w.ctx)
  180. }
  181. if w.trafficState.IsPadding {
  182. if len(mb) == 1 && mb[0] == nil {
  183. mb[0] = XtlsPadding(nil, CommandPaddingContinue, &w.writeOnceUserUUID, true, w.ctx) // we do a long padding to hide vless header
  184. return w.Writer.WriteMultiBuffer(mb)
  185. }
  186. mb = ReshapeMultiBuffer(w.ctx, mb)
  187. longPadding := w.trafficState.IsTLS
  188. for i, b := range mb {
  189. if w.trafficState.IsTLS && b.Len() >= 6 && bytes.Equal(TlsApplicationDataStart, b.BytesTo(3)) {
  190. if w.trafficState.EnableXtls {
  191. w.trafficState.WriterSwitchToDirectCopy = true
  192. }
  193. var command byte = CommandPaddingContinue
  194. if i == len(mb) - 1 {
  195. command = CommandPaddingEnd
  196. if w.trafficState.EnableXtls {
  197. command = CommandPaddingDirect
  198. }
  199. }
  200. mb[i] = XtlsPadding(b, command, &w.writeOnceUserUUID, true, w.ctx)
  201. w.trafficState.IsPadding = false // padding going to end
  202. longPadding = false
  203. continue
  204. } else if !w.trafficState.IsTLS12orAbove && w.trafficState.NumberOfPacketToFilter <= 1 { // For compatibility with earlier vision receiver, we finish padding 1 packet early
  205. w.trafficState.IsPadding = false
  206. mb[i] = XtlsPadding(b, CommandPaddingEnd, &w.writeOnceUserUUID, longPadding, w.ctx)
  207. break
  208. }
  209. var command byte = CommandPaddingContinue
  210. if i == len(mb) - 1 && !w.trafficState.IsPadding {
  211. command = CommandPaddingEnd
  212. if w.trafficState.EnableXtls {
  213. command = CommandPaddingDirect
  214. }
  215. }
  216. mb[i] = XtlsPadding(b, command, &w.writeOnceUserUUID, longPadding, w.ctx)
  217. }
  218. }
  219. return w.Writer.WriteMultiBuffer(mb)
  220. }
  221. // ReshapeMultiBuffer prepare multi buffer for padding stucture (max 21 bytes)
  222. func ReshapeMultiBuffer(ctx context.Context, buffer buf.MultiBuffer) buf.MultiBuffer {
  223. needReshape := 0
  224. for _, b := range buffer {
  225. if b.Len() >= buf.Size-21 {
  226. needReshape += 1
  227. }
  228. }
  229. if needReshape == 0 {
  230. return buffer
  231. }
  232. mb2 := make(buf.MultiBuffer, 0, len(buffer)+needReshape)
  233. toPrint := ""
  234. for i, buffer1 := range buffer {
  235. if buffer1.Len() >= buf.Size-21 {
  236. index := int32(bytes.LastIndex(buffer1.Bytes(), TlsApplicationDataStart))
  237. if index < 21 || index > buf.Size-21 {
  238. index = buf.Size / 2
  239. }
  240. buffer2 := buf.New()
  241. buffer2.Write(buffer1.BytesFrom(index))
  242. buffer1.Resize(0, index)
  243. mb2 = append(mb2, buffer1, buffer2)
  244. toPrint += " " + strconv.Itoa(int(buffer1.Len())) + " " + strconv.Itoa(int(buffer2.Len()))
  245. } else {
  246. mb2 = append(mb2, buffer1)
  247. toPrint += " " + strconv.Itoa(int(buffer1.Len()))
  248. }
  249. buffer[i] = nil
  250. }
  251. buffer = buffer[:0]
  252. newError("ReshapeMultiBuffer ", toPrint).WriteToLog(session.ExportIDToError(ctx))
  253. return mb2
  254. }
  255. // XtlsPadding add padding to eliminate length siganature during tls handshake
  256. func XtlsPadding(b *buf.Buffer, command byte, userUUID *[]byte, longPadding bool, ctx context.Context) *buf.Buffer {
  257. var contentLen int32 = 0
  258. var paddingLen int32 = 0
  259. if b != nil {
  260. contentLen = b.Len()
  261. }
  262. if contentLen < 900 && longPadding {
  263. l, err := rand.Int(rand.Reader, big.NewInt(500))
  264. if err != nil {
  265. newError("failed to generate padding").Base(err).WriteToLog(session.ExportIDToError(ctx))
  266. }
  267. paddingLen = int32(l.Int64()) + 900 - contentLen
  268. } else {
  269. l, err := rand.Int(rand.Reader, big.NewInt(256))
  270. if err != nil {
  271. newError("failed to generate padding").Base(err).WriteToLog(session.ExportIDToError(ctx))
  272. }
  273. paddingLen = int32(l.Int64())
  274. }
  275. if paddingLen > buf.Size-21-contentLen {
  276. paddingLen = buf.Size - 21 - contentLen
  277. }
  278. newbuffer := buf.New()
  279. if userUUID != nil {
  280. newbuffer.Write(*userUUID)
  281. *userUUID = nil
  282. }
  283. newbuffer.Write([]byte{command, byte(contentLen >> 8), byte(contentLen), byte(paddingLen >> 8), byte(paddingLen)})
  284. if b != nil {
  285. newbuffer.Write(b.Bytes())
  286. b.Release()
  287. b = nil
  288. }
  289. newbuffer.Extend(paddingLen)
  290. newError("XtlsPadding ", contentLen, " ", paddingLen, " ", command).WriteToLog(session.ExportIDToError(ctx))
  291. return newbuffer
  292. }
  293. // XtlsUnpadding remove padding and parse command
  294. func XtlsUnpadding(b *buf.Buffer, s *TrafficState, ctx context.Context) *buf.Buffer {
  295. if s.RemainingCommand == -1 && s.RemainingContent == -1 && s.RemainingPadding == -1 { // inital state
  296. if b.Len() >= 21 && bytes.Equal(s.UserUUID, b.BytesTo(16)) {
  297. b.Advance(16)
  298. s.RemainingCommand = 5
  299. } else {
  300. return b
  301. }
  302. }
  303. newbuffer := buf.New()
  304. for b.Len() > 0 {
  305. if s.RemainingCommand > 0 {
  306. data, err := b.ReadByte()
  307. if err != nil {
  308. return newbuffer
  309. }
  310. switch s.RemainingCommand {
  311. case 5:
  312. s.CurrentCommand = int(data)
  313. case 4:
  314. s.RemainingContent = int32(data)<<8
  315. case 3:
  316. s.RemainingContent = s.RemainingContent | int32(data)
  317. case 2:
  318. s.RemainingPadding = int32(data)<<8
  319. case 1:
  320. s.RemainingPadding = s.RemainingPadding | int32(data)
  321. newError("Xtls Unpadding new block, content ", s.RemainingContent, " padding ", s.RemainingPadding, " command ", s.CurrentCommand).WriteToLog(session.ExportIDToError(ctx))
  322. }
  323. s.RemainingCommand--
  324. } else if s.RemainingContent > 0 {
  325. len := s.RemainingContent
  326. if b.Len() < len {
  327. len = b.Len()
  328. }
  329. data, err := b.ReadBytes(len)
  330. if err != nil {
  331. return newbuffer
  332. }
  333. newbuffer.Write(data)
  334. s.RemainingContent -= len
  335. } else { // remainingPadding > 0
  336. len := s.RemainingPadding
  337. if b.Len() < len {
  338. len = b.Len()
  339. }
  340. b.Advance(len)
  341. s.RemainingPadding -= len
  342. }
  343. if s.RemainingCommand <= 0 && s.RemainingContent <= 0 && s.RemainingPadding <= 0 { // this block done
  344. if s.CurrentCommand == 0 {
  345. s.RemainingCommand = 5
  346. } else {
  347. s.RemainingCommand = -1 // set to initial state
  348. s.RemainingContent = -1
  349. s.RemainingPadding = -1
  350. if b.Len() > 0 { // shouldn't happen
  351. newbuffer.Write(b.Bytes())
  352. }
  353. break
  354. }
  355. }
  356. }
  357. b.Release()
  358. b = nil
  359. return newbuffer
  360. }
  361. // XtlsFilterTls filter and recognize tls 1.3 and other info
  362. func XtlsFilterTls(buffer buf.MultiBuffer, trafficState *TrafficState, ctx context.Context) {
  363. for _, b := range buffer {
  364. if b == nil {
  365. continue
  366. }
  367. trafficState.NumberOfPacketToFilter--
  368. if b.Len() >= 6 {
  369. startsBytes := b.BytesTo(6)
  370. if bytes.Equal(TlsServerHandShakeStart, startsBytes[:3]) && startsBytes[5] == TlsHandshakeTypeServerHello {
  371. trafficState.RemainingServerHello = (int32(startsBytes[3])<<8 | int32(startsBytes[4])) + 5
  372. trafficState.IsTLS12orAbove = true
  373. trafficState.IsTLS = true
  374. if b.Len() >= 79 && trafficState.RemainingServerHello >= 79 {
  375. sessionIdLen := int32(b.Byte(43))
  376. cipherSuite := b.BytesRange(43+sessionIdLen+1, 43+sessionIdLen+3)
  377. trafficState.Cipher = uint16(cipherSuite[0])<<8 | uint16(cipherSuite[1])
  378. } else {
  379. newError("XtlsFilterTls short server hello, tls 1.2 or older? ", b.Len(), " ", trafficState.RemainingServerHello).WriteToLog(session.ExportIDToError(ctx))
  380. }
  381. } else if bytes.Equal(TlsClientHandShakeStart, startsBytes[:2]) && startsBytes[5] == TlsHandshakeTypeClientHello {
  382. trafficState.IsTLS = true
  383. newError("XtlsFilterTls found tls client hello! ", buffer.Len()).WriteToLog(session.ExportIDToError(ctx))
  384. }
  385. }
  386. if trafficState.RemainingServerHello > 0 {
  387. end := trafficState.RemainingServerHello
  388. if end > b.Len() {
  389. end = b.Len()
  390. }
  391. trafficState.RemainingServerHello -= b.Len()
  392. if bytes.Contains(b.BytesTo(end), Tls13SupportedVersions) {
  393. v, ok := Tls13CipherSuiteDic[trafficState.Cipher]
  394. if !ok {
  395. v = "Old cipher: " + strconv.FormatUint(uint64(trafficState.Cipher), 16)
  396. } else if v != "TLS_AES_128_CCM_8_SHA256" {
  397. trafficState.EnableXtls = true
  398. }
  399. newError("XtlsFilterTls found tls 1.3! ", b.Len(), " ", v).WriteToLog(session.ExportIDToError(ctx))
  400. trafficState.NumberOfPacketToFilter = 0
  401. return
  402. } else if trafficState.RemainingServerHello <= 0 {
  403. newError("XtlsFilterTls found tls 1.2! ", b.Len()).WriteToLog(session.ExportIDToError(ctx))
  404. trafficState.NumberOfPacketToFilter = 0
  405. return
  406. }
  407. newError("XtlsFilterTls inconclusive server hello ", b.Len(), " ", trafficState.RemainingServerHello).WriteToLog(session.ExportIDToError(ctx))
  408. }
  409. if trafficState.NumberOfPacketToFilter <= 0 {
  410. newError("XtlsFilterTls stop filtering", buffer.Len()).WriteToLog(session.ExportIDToError(ctx))
  411. }
  412. }
  413. }
  414. // UnwrapRawConn support unwrap stats, tls, utls, reality and proxyproto conn and get raw tcp conn from it
  415. func UnwrapRawConn(conn net.Conn) (net.Conn, stats.Counter, stats.Counter) {
  416. var readCounter, writerCounter stats.Counter
  417. if conn != nil {
  418. statConn, ok := conn.(*stat.CounterConnection)
  419. if ok {
  420. conn = statConn.Connection
  421. readCounter = statConn.ReadCounter
  422. writerCounter = statConn.WriteCounter
  423. }
  424. if xc, ok := conn.(*tls.Conn); ok {
  425. conn = xc.NetConn()
  426. } else if utlsConn, ok := conn.(*tls.UConn); ok {
  427. conn = utlsConn.NetConn()
  428. } else if realityConn, ok := conn.(*reality.Conn); ok {
  429. conn = realityConn.NetConn()
  430. } else if realityUConn, ok := conn.(*reality.UConn); ok {
  431. conn = realityUConn.NetConn()
  432. }
  433. if pc, ok := conn.(*proxyproto.Conn); ok {
  434. conn = pc.Raw()
  435. // 8192 > 4096, there is no need to process pc's bufReader
  436. }
  437. }
  438. return conn, readCounter, writerCounter
  439. }
  440. // CopyRawConnIfExist use the most efficient copy method.
  441. // - If caller don't want to turn on splice, do not pass in both reader conn and writer conn
  442. // - writer are from *transport.Link
  443. func CopyRawConnIfExist(ctx context.Context, readerConn net.Conn, writerConn net.Conn, writer buf.Writer, timer signal.ActivityUpdater) error {
  444. readerConn, readCounter, _ := UnwrapRawConn(readerConn)
  445. writerConn, _, writeCounter := UnwrapRawConn(writerConn)
  446. reader := buf.NewReader(readerConn)
  447. if inbound := session.InboundFromContext(ctx); inbound != nil {
  448. if tc, ok := writerConn.(*net.TCPConn); ok && readerConn != nil && writerConn != nil && (runtime.GOOS == "linux" || runtime.GOOS == "android") {
  449. for inbound.CanSpliceCopy != 3 {
  450. if inbound.CanSpliceCopy == 1 {
  451. newError("CopyRawConn splice").WriteToLog(session.ExportIDToError(ctx))
  452. //runtime.Gosched() // necessary
  453. time.Sleep(time.Millisecond) // without this, there will be a rare ssl error for freedom splice
  454. w, err := tc.ReadFrom(readerConn)
  455. if readCounter != nil {
  456. readCounter.Add(w)
  457. }
  458. if writeCounter != nil {
  459. writeCounter.Add(w)
  460. }
  461. if err != nil && errors.Cause(err) != io.EOF {
  462. return err
  463. }
  464. return nil
  465. }
  466. buffer, err := reader.ReadMultiBuffer()
  467. if !buffer.IsEmpty() {
  468. if readCounter != nil {
  469. readCounter.Add(int64(buffer.Len()))
  470. }
  471. timer.Update()
  472. if werr := writer.WriteMultiBuffer(buffer); werr != nil {
  473. return werr
  474. }
  475. }
  476. if err != nil {
  477. return err
  478. }
  479. }
  480. }
  481. }
  482. newError("CopyRawConn readv").WriteToLog(session.ExportIDToError(ctx))
  483. if err := buf.Copy(reader, writer, buf.UpdateActivity(timer), buf.AddToStatCounter(readCounter)); err != nil {
  484. return newError("failed to process response").Base(err)
  485. }
  486. return nil
  487. }