rule_action.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. package rule
  2. import (
  3. "net/netip"
  4. "os"
  5. "strings"
  6. "syscall"
  7. "time"
  8. "github.com/sagernet/sing-box/adapter"
  9. "github.com/sagernet/sing-box/common/sniff"
  10. C "github.com/sagernet/sing-box/constant"
  11. "github.com/sagernet/sing-box/option"
  12. "github.com/sagernet/sing-dns"
  13. "github.com/sagernet/sing-tun"
  14. E "github.com/sagernet/sing/common/exceptions"
  15. F "github.com/sagernet/sing/common/format"
  16. )
  17. func NewRuleAction(action option.RuleAction) (adapter.RuleAction, error) {
  18. switch action.Action {
  19. case C.RuleActionTypeRoute:
  20. return &RuleActionRoute{
  21. Outbound: action.RouteOptions.Outbound,
  22. UDPDisableDomainUnmapping: action.RouteOptions.UDPDisableDomainUnmapping,
  23. }, nil
  24. case C.RuleActionTypeReturn:
  25. return &RuleActionReturn{}, nil
  26. case C.RuleActionTypeReject:
  27. return &RuleActionReject{
  28. Method: action.RejectOptions.Method,
  29. }, nil
  30. case C.RuleActionTypeHijackDNS:
  31. return &RuleActionHijackDNS{}, nil
  32. case C.RuleActionTypeSniff:
  33. sniffAction := &RuleActionSniff{
  34. snifferNames: action.SniffOptions.Sniffer,
  35. Timeout: time.Duration(action.SniffOptions.Timeout),
  36. }
  37. return sniffAction, sniffAction.build()
  38. case C.RuleActionTypeResolve:
  39. return &RuleActionResolve{
  40. Strategy: dns.DomainStrategy(action.ResolveOptions.Strategy),
  41. Server: action.ResolveOptions.Server,
  42. }, nil
  43. default:
  44. panic(F.ToString("unknown rule action: ", action.Action))
  45. }
  46. }
  47. func NewDNSRuleAction(action option.DNSRuleAction) adapter.RuleAction {
  48. switch action.Action {
  49. case C.RuleActionTypeRoute:
  50. return &RuleActionDNSRoute{
  51. Server: action.RouteOptions.Server,
  52. DisableCache: action.RouteOptions.DisableCache,
  53. RewriteTTL: action.RouteOptions.RewriteTTL,
  54. ClientSubnet: action.RouteOptions.ClientSubnet.Build(),
  55. }
  56. case C.RuleActionTypeReturn:
  57. return &RuleActionReturn{}
  58. case C.RuleActionTypeReject:
  59. return &RuleActionReject{
  60. Method: action.RejectOptions.Method,
  61. }
  62. default:
  63. panic(F.ToString("unknown rule action: ", action.Action))
  64. }
  65. }
  66. type RuleActionRoute struct {
  67. Outbound string
  68. UDPDisableDomainUnmapping bool
  69. }
  70. func (r *RuleActionRoute) Type() string {
  71. return C.RuleActionTypeRoute
  72. }
  73. func (r *RuleActionRoute) String() string {
  74. return F.ToString("route(", r.Outbound, ")")
  75. }
  76. type RuleActionDNSRoute struct {
  77. Server string
  78. DisableCache bool
  79. RewriteTTL *uint32
  80. ClientSubnet netip.Prefix
  81. }
  82. func (r *RuleActionDNSRoute) Type() string {
  83. return C.RuleActionTypeRoute
  84. }
  85. func (r *RuleActionDNSRoute) String() string {
  86. return F.ToString("route(", r.Server, ")")
  87. }
  88. type RuleActionReturn struct{}
  89. func (r *RuleActionReturn) Type() string {
  90. return C.RuleActionTypeReturn
  91. }
  92. func (r *RuleActionReturn) String() string {
  93. return "return"
  94. }
  95. type RuleActionReject struct {
  96. Method string
  97. }
  98. func (r *RuleActionReject) Type() string {
  99. return C.RuleActionTypeReject
  100. }
  101. func (r *RuleActionReject) String() string {
  102. if r.Method == C.RuleActionRejectMethodDefault {
  103. return "reject"
  104. }
  105. return F.ToString("reject(", r.Method, ")")
  106. }
  107. func (r *RuleActionReject) Error() error {
  108. switch r.Method {
  109. case C.RuleActionRejectMethodReset:
  110. return os.ErrClosed
  111. case C.RuleActionRejectMethodNetworkUnreachable:
  112. return syscall.ENETUNREACH
  113. case C.RuleActionRejectMethodHostUnreachable:
  114. return syscall.EHOSTUNREACH
  115. case C.RuleActionRejectMethodDefault, C.RuleActionRejectMethodPortUnreachable:
  116. return syscall.ECONNREFUSED
  117. case C.RuleActionRejectMethodDrop:
  118. return tun.ErrDrop
  119. default:
  120. panic(F.ToString("unknown reject method: ", r.Method))
  121. }
  122. }
  123. type RuleActionHijackDNS struct{}
  124. func (r *RuleActionHijackDNS) Type() string {
  125. return C.RuleActionTypeHijackDNS
  126. }
  127. func (r *RuleActionHijackDNS) String() string {
  128. return "hijack-dns"
  129. }
  130. type RuleActionSniff struct {
  131. snifferNames []string
  132. StreamSniffers []sniff.StreamSniffer
  133. PacketSniffers []sniff.PacketSniffer
  134. Timeout time.Duration
  135. // Deprecated
  136. OverrideDestination bool
  137. }
  138. func (r *RuleActionSniff) Type() string {
  139. return C.RuleActionTypeSniff
  140. }
  141. func (r *RuleActionSniff) build() error {
  142. for _, name := range r.snifferNames {
  143. switch name {
  144. case C.ProtocolTLS:
  145. r.StreamSniffers = append(r.StreamSniffers, sniff.TLSClientHello)
  146. case C.ProtocolHTTP:
  147. r.StreamSniffers = append(r.StreamSniffers, sniff.HTTPHost)
  148. case C.ProtocolQUIC:
  149. r.PacketSniffers = append(r.PacketSniffers, sniff.QUICClientHello)
  150. case C.ProtocolDNS:
  151. r.StreamSniffers = append(r.StreamSniffers, sniff.StreamDomainNameQuery)
  152. r.PacketSniffers = append(r.PacketSniffers, sniff.DomainNameQuery)
  153. case C.ProtocolSTUN:
  154. r.PacketSniffers = append(r.PacketSniffers, sniff.STUNMessage)
  155. case C.ProtocolBitTorrent:
  156. r.StreamSniffers = append(r.StreamSniffers, sniff.BitTorrent)
  157. r.PacketSniffers = append(r.PacketSniffers, sniff.UTP)
  158. r.PacketSniffers = append(r.PacketSniffers, sniff.UDPTracker)
  159. case C.ProtocolDTLS:
  160. r.PacketSniffers = append(r.PacketSniffers, sniff.DTLSRecord)
  161. case C.ProtocolSSH:
  162. r.StreamSniffers = append(r.StreamSniffers, sniff.SSH)
  163. case C.ProtocolRDP:
  164. r.StreamSniffers = append(r.StreamSniffers, sniff.RDP)
  165. default:
  166. return E.New("unknown sniffer: ", name)
  167. }
  168. }
  169. return nil
  170. }
  171. func (r *RuleActionSniff) String() string {
  172. if len(r.snifferNames) == 0 && r.Timeout == 0 {
  173. return "sniff"
  174. } else if len(r.snifferNames) > 0 && r.Timeout == 0 {
  175. return F.ToString("sniff(", strings.Join(r.snifferNames, ","), ")")
  176. } else if len(r.snifferNames) == 0 && r.Timeout > 0 {
  177. return F.ToString("sniff(", r.Timeout.String(), ")")
  178. } else {
  179. return F.ToString("sniff(", strings.Join(r.snifferNames, ","), ",", r.Timeout.String(), ")")
  180. }
  181. }
  182. type RuleActionResolve struct {
  183. Strategy dns.DomainStrategy
  184. Server string
  185. }
  186. func (r *RuleActionResolve) Type() string {
  187. return C.RuleActionTypeResolve
  188. }
  189. func (r *RuleActionResolve) String() string {
  190. if r.Strategy == dns.DomainStrategyAsIS && r.Server == "" {
  191. return F.ToString("resolve")
  192. } else if r.Strategy != dns.DomainStrategyAsIS && r.Server == "" {
  193. return F.ToString("resolve(", option.DomainStrategy(r.Strategy).String(), ")")
  194. } else if r.Strategy == dns.DomainStrategyAsIS && r.Server != "" {
  195. return F.ToString("resolve(", r.Server, ")")
  196. } else {
  197. return F.ToString("resolve(", option.DomainStrategy(r.Strategy).String(), ",", r.Server, ")")
  198. }
  199. }