default.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. package outbound
  2. import (
  3. "context"
  4. "net"
  5. "net/netip"
  6. "os"
  7. "time"
  8. "github.com/sagernet/sing-box/adapter"
  9. "github.com/sagernet/sing-box/common/dialer"
  10. C "github.com/sagernet/sing-box/constant"
  11. "github.com/sagernet/sing/common"
  12. "github.com/sagernet/sing/common/buf"
  13. "github.com/sagernet/sing/common/bufio"
  14. "github.com/sagernet/sing/common/canceler"
  15. E "github.com/sagernet/sing/common/exceptions"
  16. M "github.com/sagernet/sing/common/metadata"
  17. N "github.com/sagernet/sing/common/network"
  18. )
  19. func NewConnection(ctx context.Context, this N.Dialer, conn net.Conn, metadata adapter.InboundContext) error {
  20. defer conn.Close()
  21. ctx = adapter.WithContext(ctx, &metadata)
  22. var outConn net.Conn
  23. var err error
  24. if len(metadata.DestinationAddresses) > 0 {
  25. outConn, err = dialer.DialSerialNetwork(ctx, this, N.NetworkTCP, metadata.Destination, metadata.DestinationAddresses, metadata.NetworkStrategy, metadata.NetworkType, metadata.FallbackNetworkType, metadata.FallbackDelay)
  26. } else {
  27. outConn, err = this.DialContext(ctx, N.NetworkTCP, metadata.Destination)
  28. }
  29. if err != nil {
  30. return N.ReportHandshakeFailure(conn, err)
  31. }
  32. err = N.ReportConnHandshakeSuccess(conn, outConn)
  33. if err != nil {
  34. outConn.Close()
  35. return err
  36. }
  37. return CopyEarlyConn(ctx, conn, outConn)
  38. }
  39. func NewPacketConnection(ctx context.Context, this N.Dialer, conn N.PacketConn, metadata adapter.InboundContext) error {
  40. defer conn.Close()
  41. ctx = adapter.WithContext(ctx, &metadata)
  42. var (
  43. outPacketConn net.PacketConn
  44. outConn net.Conn
  45. destinationAddress netip.Addr
  46. err error
  47. )
  48. if metadata.UDPConnect {
  49. if len(metadata.DestinationAddresses) > 0 {
  50. if parallelDialer, isParallelDialer := this.(dialer.ParallelInterfaceDialer); isParallelDialer {
  51. outConn, err = dialer.DialSerialNetwork(ctx, parallelDialer, N.NetworkUDP, metadata.Destination, metadata.DestinationAddresses, metadata.NetworkStrategy, metadata.NetworkType, metadata.FallbackNetworkType, metadata.FallbackDelay)
  52. } else {
  53. outConn, err = N.DialSerial(ctx, this, N.NetworkUDP, metadata.Destination, metadata.DestinationAddresses)
  54. }
  55. } else {
  56. outConn, err = this.DialContext(ctx, N.NetworkUDP, metadata.Destination)
  57. }
  58. if err != nil {
  59. return N.ReportHandshakeFailure(conn, err)
  60. }
  61. outPacketConn = bufio.NewUnbindPacketConn(outConn)
  62. connRemoteAddr := M.AddrFromNet(outConn.RemoteAddr())
  63. if connRemoteAddr != metadata.Destination.Addr {
  64. destinationAddress = connRemoteAddr
  65. }
  66. } else {
  67. if len(metadata.DestinationAddresses) > 0 {
  68. outPacketConn, destinationAddress, err = dialer.ListenSerialNetworkPacket(ctx, this, metadata.Destination, metadata.DestinationAddresses, metadata.NetworkStrategy, metadata.NetworkType, metadata.FallbackNetworkType, metadata.FallbackDelay)
  69. } else {
  70. outPacketConn, err = this.ListenPacket(ctx, metadata.Destination)
  71. }
  72. if err != nil {
  73. return N.ReportHandshakeFailure(conn, err)
  74. }
  75. }
  76. err = N.ReportPacketConnHandshakeSuccess(conn, outPacketConn)
  77. if err != nil {
  78. outPacketConn.Close()
  79. return err
  80. }
  81. if destinationAddress.IsValid() {
  82. var originDestination M.Socksaddr
  83. if metadata.RouteOriginalDestination.IsValid() {
  84. originDestination = metadata.RouteOriginalDestination
  85. } else {
  86. originDestination = metadata.Destination
  87. }
  88. if metadata.Destination != M.SocksaddrFrom(destinationAddress, metadata.Destination.Port) {
  89. if metadata.UDPDisableDomainUnmapping {
  90. outPacketConn = bufio.NewUnidirectionalNATPacketConn(bufio.NewPacketConn(outPacketConn), M.SocksaddrFrom(destinationAddress, metadata.Destination.Port), originDestination)
  91. } else {
  92. outPacketConn = bufio.NewNATPacketConn(bufio.NewPacketConn(outPacketConn), M.SocksaddrFrom(destinationAddress, metadata.Destination.Port), originDestination)
  93. }
  94. }
  95. if natConn, loaded := common.Cast[bufio.NATPacketConn](conn); loaded {
  96. natConn.UpdateDestination(destinationAddress)
  97. }
  98. }
  99. switch metadata.Protocol {
  100. case C.ProtocolSTUN:
  101. ctx, conn = canceler.NewPacketConn(ctx, conn, C.STUNTimeout)
  102. case C.ProtocolQUIC:
  103. ctx, conn = canceler.NewPacketConn(ctx, conn, C.QUICTimeout)
  104. case C.ProtocolDNS:
  105. ctx, conn = canceler.NewPacketConn(ctx, conn, C.DNSTimeout)
  106. }
  107. return bufio.CopyPacketConn(ctx, conn, bufio.NewPacketConn(outPacketConn))
  108. }
  109. func CopyEarlyConn(ctx context.Context, conn net.Conn, serverConn net.Conn) error {
  110. if cachedReader, isCached := conn.(N.CachedReader); isCached {
  111. payload := cachedReader.ReadCached()
  112. if payload != nil && !payload.IsEmpty() {
  113. _, err := serverConn.Write(payload.Bytes())
  114. payload.Release()
  115. if err != nil {
  116. serverConn.Close()
  117. return err
  118. }
  119. return bufio.CopyConn(ctx, conn, serverConn)
  120. }
  121. }
  122. if earlyConn, isEarlyConn := common.Cast[N.EarlyConn](serverConn); isEarlyConn && earlyConn.NeedHandshake() {
  123. payload := buf.NewPacket()
  124. err := conn.SetReadDeadline(time.Now().Add(C.ReadPayloadTimeout))
  125. if err != os.ErrInvalid {
  126. if err != nil {
  127. payload.Release()
  128. serverConn.Close()
  129. return err
  130. }
  131. _, err = payload.ReadOnceFrom(conn)
  132. if err != nil && !E.IsTimeout(err) {
  133. payload.Release()
  134. serverConn.Close()
  135. return E.Cause(err, "read payload")
  136. }
  137. err = conn.SetReadDeadline(time.Time{})
  138. if err != nil {
  139. payload.Release()
  140. serverConn.Close()
  141. return err
  142. }
  143. }
  144. _, err = serverConn.Write(payload.Bytes())
  145. payload.Release()
  146. if err != nil {
  147. serverConn.Close()
  148. return N.ReportHandshakeFailure(conn, err)
  149. }
  150. }
  151. return bufio.CopyConn(ctx, conn, serverConn)
  152. }