system_dialer.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. package internet
  2. import (
  3. "context"
  4. "math/rand"
  5. "syscall"
  6. "time"
  7. "github.com/sagernet/sing/common/control"
  8. "github.com/xtls/xray-core/common/errors"
  9. "github.com/xtls/xray-core/common/net"
  10. "github.com/xtls/xray-core/features/dns"
  11. "github.com/xtls/xray-core/features/outbound"
  12. )
  13. var effectiveSystemDialer SystemDialer = &DefaultSystemDialer{}
  14. type SystemDialer interface {
  15. Dial(ctx context.Context, source net.Address, destination net.Destination, sockopt *SocketConfig) (net.Conn, error)
  16. DestIpAddress() net.IP
  17. }
  18. type DefaultSystemDialer struct {
  19. controllers []control.Func
  20. dns dns.Client
  21. obm outbound.Manager
  22. }
  23. func resolveSrcAddr(network net.Network, src net.Address) net.Addr {
  24. if src == nil || src == net.AnyIP {
  25. return nil
  26. }
  27. if network == net.Network_TCP {
  28. return &net.TCPAddr{
  29. IP: src.IP(),
  30. Port: 0,
  31. }
  32. }
  33. return &net.UDPAddr{
  34. IP: src.IP(),
  35. Port: 0,
  36. }
  37. }
  38. func hasBindAddr(sockopt *SocketConfig) bool {
  39. return sockopt != nil && len(sockopt.BindAddress) > 0 && sockopt.BindPort > 0
  40. }
  41. func (d *DefaultSystemDialer) Dial(ctx context.Context, src net.Address, dest net.Destination, sockopt *SocketConfig) (net.Conn, error) {
  42. errors.LogDebug(ctx, "dialing to "+dest.String())
  43. if dest.Network == net.Network_UDP && !hasBindAddr(sockopt) {
  44. srcAddr := resolveSrcAddr(net.Network_UDP, src)
  45. if srcAddr == nil {
  46. srcAddr = &net.UDPAddr{
  47. IP: []byte{0, 0, 0, 0},
  48. Port: 0,
  49. }
  50. }
  51. packetConn, err := ListenSystemPacket(ctx, srcAddr, sockopt)
  52. if err != nil {
  53. return nil, err
  54. }
  55. destAddr, err := net.ResolveUDPAddr("udp", dest.NetAddr())
  56. if err != nil {
  57. return nil, err
  58. }
  59. if sockopt != nil {
  60. sys, err := packetConn.(*net.UDPConn).SyscallConn()
  61. if err != nil {
  62. return nil, err
  63. }
  64. sys.Control(func(fd uintptr) {
  65. if err := applyOutboundSocketOptions("udp", dest.NetAddr(), fd, sockopt); err != nil {
  66. errors.LogInfo(ctx, err, "failed to apply socket options")
  67. }
  68. })
  69. }
  70. return &PacketConnWrapper{
  71. Conn: packetConn,
  72. Dest: destAddr,
  73. }, nil
  74. }
  75. goStdKeepAlive := time.Duration(0)
  76. if sockopt != nil && (sockopt.TcpKeepAliveInterval != 0 || sockopt.TcpKeepAliveIdle != 0) {
  77. goStdKeepAlive = time.Duration(-1)
  78. }
  79. dialer := &net.Dialer{
  80. Timeout: time.Second * 16,
  81. LocalAddr: resolveSrcAddr(dest.Network, src),
  82. KeepAlive: goStdKeepAlive,
  83. }
  84. if sockopt != nil || len(d.controllers) > 0 {
  85. if sockopt != nil && sockopt.TcpMptcp {
  86. dialer.SetMultipathTCP(true)
  87. }
  88. dialer.Control = func(network, address string, c syscall.RawConn) error {
  89. for _, ctl := range d.controllers {
  90. if err := ctl(network, address, c); err != nil {
  91. errors.LogInfoInner(ctx, err, "failed to apply external controller")
  92. }
  93. }
  94. return c.Control(func(fd uintptr) {
  95. if sockopt != nil {
  96. if err := applyOutboundSocketOptions(network, address, fd, sockopt); err != nil {
  97. errors.LogInfoInner(ctx, err, "failed to apply socket options")
  98. }
  99. if dest.Network == net.Network_UDP && hasBindAddr(sockopt) {
  100. if err := bindAddr(fd, sockopt.BindAddress, sockopt.BindPort); err != nil {
  101. errors.LogInfoInner(ctx, err, "failed to bind source address to ", sockopt.BindAddress)
  102. }
  103. }
  104. }
  105. })
  106. }
  107. }
  108. return dialer.DialContext(ctx, dest.Network.SystemString(), dest.NetAddr())
  109. }
  110. func (d *DefaultSystemDialer) DestIpAddress() net.IP {
  111. return nil
  112. }
  113. type PacketConnWrapper struct {
  114. Conn net.PacketConn
  115. Dest net.Addr
  116. }
  117. func (c *PacketConnWrapper) Close() error {
  118. return c.Conn.Close()
  119. }
  120. func (c *PacketConnWrapper) LocalAddr() net.Addr {
  121. return c.Conn.LocalAddr()
  122. }
  123. func (c *PacketConnWrapper) RemoteAddr() net.Addr {
  124. return c.Dest
  125. }
  126. func (c *PacketConnWrapper) Write(p []byte) (int, error) {
  127. return c.Conn.WriteTo(p, c.Dest)
  128. }
  129. func (c *PacketConnWrapper) Read(p []byte) (int, error) {
  130. n, _, err := c.Conn.ReadFrom(p)
  131. return n, err
  132. }
  133. func (c *PacketConnWrapper) WriteTo(p []byte, d net.Addr) (int, error) {
  134. return c.Conn.WriteTo(p, d)
  135. }
  136. func (c *PacketConnWrapper) ReadFrom(p []byte) (int, net.Addr, error) {
  137. return c.Conn.ReadFrom(p)
  138. }
  139. func (c *PacketConnWrapper) SetDeadline(t time.Time) error {
  140. return c.Conn.SetDeadline(t)
  141. }
  142. func (c *PacketConnWrapper) SetReadDeadline(t time.Time) error {
  143. return c.Conn.SetReadDeadline(t)
  144. }
  145. func (c *PacketConnWrapper) SetWriteDeadline(t time.Time) error {
  146. return c.Conn.SetWriteDeadline(t)
  147. }
  148. type SystemDialerAdapter interface {
  149. Dial(network string, address string) (net.Conn, error)
  150. }
  151. type SimpleSystemDialer struct {
  152. adapter SystemDialerAdapter
  153. }
  154. func WithAdapter(dialer SystemDialerAdapter) SystemDialer {
  155. return &SimpleSystemDialer{
  156. adapter: dialer,
  157. }
  158. }
  159. func (v *SimpleSystemDialer) Dial(ctx context.Context, src net.Address, dest net.Destination, sockopt *SocketConfig) (net.Conn, error) {
  160. return v.adapter.Dial(dest.Network.SystemString(), dest.NetAddr())
  161. }
  162. func (d *SimpleSystemDialer) DestIpAddress() net.IP {
  163. return nil
  164. }
  165. // UseAlternativeSystemDialer replaces the current system dialer with a given one.
  166. // Caller must ensure there is no race condition.
  167. //
  168. // xray:api:stable
  169. func UseAlternativeSystemDialer(dialer SystemDialer) {
  170. if dialer == nil {
  171. dialer = &DefaultSystemDialer{}
  172. }
  173. effectiveSystemDialer = dialer
  174. }
  175. // RegisterDialerController adds a controller to the effective system dialer.
  176. // The controller can be used to operate on file descriptors before they are put into use.
  177. // It only works when effective dialer is the default dialer.
  178. //
  179. // xray:api:beta
  180. func RegisterDialerController(ctl control.Func) error {
  181. if ctl == nil {
  182. return errors.New("nil listener controller")
  183. }
  184. dialer, ok := effectiveSystemDialer.(*DefaultSystemDialer)
  185. if !ok {
  186. return errors.New("RegisterListenerController not supported in custom dialer")
  187. }
  188. dialer.controllers = append(dialer.controllers, ctl)
  189. return nil
  190. }
  191. type FakePacketConn struct {
  192. net.Conn
  193. }
  194. func (c *FakePacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
  195. n, err = c.Read(p)
  196. return n, c.RemoteAddr(), err
  197. }
  198. func (c *FakePacketConn) WriteTo(p []byte, _ net.Addr) (n int, err error) {
  199. return c.Write(p)
  200. }
  201. func (c *FakePacketConn) LocalAddr() net.Addr {
  202. return &net.TCPAddr{
  203. IP: net.IP{byte(rand.Intn(256)), byte(rand.Intn(256)), byte(rand.Intn(256)), byte(rand.Intn(256))},
  204. Port: rand.Intn(65536),
  205. }
  206. }
  207. func (c *FakePacketConn) SetReadBuffer(bytes int) error {
  208. // do nothing, this function is only there to suppress quic-go printing
  209. // random warnings about UDP buffers to stdout
  210. return nil
  211. }