router.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. package adapter
  2. import (
  3. "context"
  4. "crypto/tls"
  5. "net"
  6. "net/http"
  7. "sync"
  8. "time"
  9. C "github.com/sagernet/sing-box/constant"
  10. "github.com/sagernet/sing-tun"
  11. M "github.com/sagernet/sing/common/metadata"
  12. N "github.com/sagernet/sing/common/network"
  13. "github.com/sagernet/sing/common/ntp"
  14. "github.com/sagernet/sing/common/x/list"
  15. "go4.org/netipx"
  16. )
  17. type Router interface {
  18. Lifecycle
  19. ConnectionRouter
  20. PreMatch(metadata InboundContext, context tun.DirectRouteContext, timeout time.Duration) (tun.DirectRouteDestination, error)
  21. ConnectionRouterEx
  22. RuleSet(tag string) (RuleSet, bool)
  23. Rules() []Rule
  24. AppendTracker(tracker ConnectionTracker)
  25. ResetNetwork()
  26. }
  27. type ConnectionTracker interface {
  28. RoutedConnection(ctx context.Context, conn net.Conn, metadata InboundContext, matchedRule Rule, matchOutbound Outbound) net.Conn
  29. RoutedPacketConnection(ctx context.Context, conn N.PacketConn, metadata InboundContext, matchedRule Rule, matchOutbound Outbound) N.PacketConn
  30. }
  31. // Deprecated: Use ConnectionRouterEx instead.
  32. type ConnectionRouter interface {
  33. RouteConnection(ctx context.Context, conn net.Conn, metadata InboundContext) error
  34. RoutePacketConnection(ctx context.Context, conn N.PacketConn, metadata InboundContext) error
  35. }
  36. type ConnectionRouterEx interface {
  37. ConnectionRouter
  38. RouteConnectionEx(ctx context.Context, conn net.Conn, metadata InboundContext, onClose N.CloseHandlerFunc)
  39. RoutePacketConnectionEx(ctx context.Context, conn N.PacketConn, metadata InboundContext, onClose N.CloseHandlerFunc)
  40. }
  41. type RuleSet interface {
  42. Name() string
  43. StartContext(ctx context.Context, startContext *HTTPStartContext) error
  44. PostStart() error
  45. Metadata() RuleSetMetadata
  46. ExtractIPSet() []*netipx.IPSet
  47. IncRef()
  48. DecRef()
  49. Cleanup()
  50. RegisterCallback(callback RuleSetUpdateCallback) *list.Element[RuleSetUpdateCallback]
  51. UnregisterCallback(element *list.Element[RuleSetUpdateCallback])
  52. Close() error
  53. HeadlessRule
  54. }
  55. type RuleSetUpdateCallback func(it RuleSet)
  56. type RuleSetMetadata struct {
  57. ContainsProcessRule bool
  58. ContainsWIFIRule bool
  59. ContainsIPCIDRRule bool
  60. }
  61. type HTTPStartContext struct {
  62. ctx context.Context
  63. access sync.Mutex
  64. httpClientCache map[string]*http.Client
  65. }
  66. func NewHTTPStartContext(ctx context.Context) *HTTPStartContext {
  67. return &HTTPStartContext{
  68. ctx: ctx,
  69. httpClientCache: make(map[string]*http.Client),
  70. }
  71. }
  72. func (c *HTTPStartContext) HTTPClient(detour string, dialer N.Dialer) *http.Client {
  73. c.access.Lock()
  74. defer c.access.Unlock()
  75. if httpClient, loaded := c.httpClientCache[detour]; loaded {
  76. return httpClient
  77. }
  78. httpClient := &http.Client{
  79. Transport: &http.Transport{
  80. ForceAttemptHTTP2: true,
  81. TLSHandshakeTimeout: C.TCPTimeout,
  82. DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
  83. return dialer.DialContext(ctx, network, M.ParseSocksaddr(addr))
  84. },
  85. TLSClientConfig: &tls.Config{
  86. Time: ntp.TimeFuncFromContext(c.ctx),
  87. RootCAs: RootPoolFromContext(c.ctx),
  88. },
  89. },
  90. }
  91. c.httpClientCache[detour] = httpClient
  92. return httpClient
  93. }
  94. func (c *HTTPStartContext) Close() {
  95. c.access.Lock()
  96. defer c.access.Unlock()
  97. for _, client := range c.httpClientCache {
  98. client.CloseIdleConnections()
  99. }
  100. }