direct_loopback_detect.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. package outbound
  2. import (
  3. "net"
  4. "net/netip"
  5. "sync"
  6. M "github.com/sagernet/sing/common/metadata"
  7. N "github.com/sagernet/sing/common/network"
  8. )
  9. type loopBackDetector struct {
  10. connAccess sync.RWMutex
  11. packetConnAccess sync.RWMutex
  12. connMap map[netip.AddrPort]bool
  13. packetConnMap map[netip.AddrPort]bool
  14. }
  15. func newLoopBackDetector() *loopBackDetector {
  16. return &loopBackDetector{
  17. connMap: make(map[netip.AddrPort]bool),
  18. packetConnMap: make(map[netip.AddrPort]bool),
  19. }
  20. }
  21. func (l *loopBackDetector) NewConn(conn net.Conn) net.Conn {
  22. connAddr := M.AddrPortFromNet(conn.LocalAddr())
  23. if !connAddr.IsValid() {
  24. return conn
  25. }
  26. if udpConn, isUDPConn := conn.(abstractUDPConn); isUDPConn {
  27. l.packetConnAccess.Lock()
  28. l.packetConnMap[connAddr] = true
  29. l.packetConnAccess.Unlock()
  30. return &loopBackDetectUDPWrapper{abstractUDPConn: udpConn, detector: l, connAddr: connAddr}
  31. } else {
  32. l.connAccess.Lock()
  33. l.connMap[connAddr] = true
  34. l.connAccess.Unlock()
  35. return &loopBackDetectWrapper{Conn: conn, detector: l, connAddr: connAddr}
  36. }
  37. }
  38. func (l *loopBackDetector) NewPacketConn(conn N.NetPacketConn) N.NetPacketConn {
  39. connAddr := M.AddrPortFromNet(conn.LocalAddr())
  40. if !connAddr.IsValid() {
  41. return conn
  42. }
  43. l.packetConnAccess.Lock()
  44. l.packetConnMap[connAddr] = true
  45. l.packetConnAccess.Unlock()
  46. return &loopBackDetectPacketWrapper{NetPacketConn: conn, detector: l, connAddr: connAddr}
  47. }
  48. func (l *loopBackDetector) CheckConn(connAddr netip.AddrPort) bool {
  49. l.connAccess.RLock()
  50. defer l.connAccess.RUnlock()
  51. return l.connMap[connAddr]
  52. }
  53. func (l *loopBackDetector) CheckPacketConn(connAddr netip.AddrPort) bool {
  54. l.packetConnAccess.RLock()
  55. defer l.packetConnAccess.RUnlock()
  56. return l.packetConnMap[connAddr]
  57. }
  58. type loopBackDetectWrapper struct {
  59. net.Conn
  60. detector *loopBackDetector
  61. connAddr netip.AddrPort
  62. closeOnce sync.Once
  63. }
  64. func (w *loopBackDetectWrapper) Close() error {
  65. w.closeOnce.Do(func() {
  66. w.detector.connAccess.Lock()
  67. delete(w.detector.connMap, w.connAddr)
  68. w.detector.connAccess.Unlock()
  69. })
  70. return w.Conn.Close()
  71. }
  72. func (w *loopBackDetectWrapper) ReaderReplaceable() bool {
  73. return true
  74. }
  75. func (w *loopBackDetectWrapper) WriterReplaceable() bool {
  76. return true
  77. }
  78. func (w *loopBackDetectWrapper) Upstream() any {
  79. return w.Conn
  80. }
  81. type loopBackDetectPacketWrapper struct {
  82. N.NetPacketConn
  83. detector *loopBackDetector
  84. connAddr netip.AddrPort
  85. closeOnce sync.Once
  86. }
  87. func (w *loopBackDetectPacketWrapper) Close() error {
  88. w.closeOnce.Do(func() {
  89. w.detector.packetConnAccess.Lock()
  90. delete(w.detector.packetConnMap, w.connAddr)
  91. w.detector.packetConnAccess.Unlock()
  92. })
  93. return w.NetPacketConn.Close()
  94. }
  95. func (w *loopBackDetectPacketWrapper) ReaderReplaceable() bool {
  96. return true
  97. }
  98. func (w *loopBackDetectPacketWrapper) WriterReplaceable() bool {
  99. return true
  100. }
  101. func (w *loopBackDetectPacketWrapper) Upstream() any {
  102. return w.NetPacketConn
  103. }
  104. type abstractUDPConn interface {
  105. net.Conn
  106. net.PacketConn
  107. }
  108. type loopBackDetectUDPWrapper struct {
  109. abstractUDPConn
  110. detector *loopBackDetector
  111. connAddr netip.AddrPort
  112. closeOnce sync.Once
  113. }
  114. func (w *loopBackDetectUDPWrapper) Close() error {
  115. w.closeOnce.Do(func() {
  116. w.detector.packetConnAccess.Lock()
  117. delete(w.detector.packetConnMap, w.connAddr)
  118. w.detector.packetConnAccess.Unlock()
  119. })
  120. return w.abstractUDPConn.Close()
  121. }
  122. func (w *loopBackDetectUDPWrapper) ReaderReplaceable() bool {
  123. return true
  124. }
  125. func (w *loopBackDetectUDPWrapper) WriterReplaceable() bool {
  126. return true
  127. }
  128. func (w *loopBackDetectUDPWrapper) Upstream() any {
  129. return w.abstractUDPConn
  130. }