route.go 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852
  1. package route
  2. import (
  3. "context"
  4. "errors"
  5. "net"
  6. "net/netip"
  7. "strings"
  8. "time"
  9. "github.com/sagernet/sing-box/adapter"
  10. "github.com/sagernet/sing-box/common/conntrack"
  11. "github.com/sagernet/sing-box/common/process"
  12. "github.com/sagernet/sing-box/common/sniff"
  13. C "github.com/sagernet/sing-box/constant"
  14. "github.com/sagernet/sing-box/option"
  15. R "github.com/sagernet/sing-box/route/rule"
  16. "github.com/sagernet/sing-mux"
  17. "github.com/sagernet/sing-tun"
  18. "github.com/sagernet/sing-tun/ping"
  19. "github.com/sagernet/sing-vmess"
  20. "github.com/sagernet/sing/common"
  21. "github.com/sagernet/sing/common/buf"
  22. "github.com/sagernet/sing/common/bufio"
  23. "github.com/sagernet/sing/common/bufio/deadline"
  24. E "github.com/sagernet/sing/common/exceptions"
  25. F "github.com/sagernet/sing/common/format"
  26. M "github.com/sagernet/sing/common/metadata"
  27. N "github.com/sagernet/sing/common/network"
  28. "github.com/sagernet/sing/common/uot"
  29. "golang.org/x/exp/slices"
  30. )
  31. // Deprecated: use RouteConnectionEx instead.
  32. func (r *Router) RouteConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
  33. done := make(chan interface{})
  34. err := r.routeConnection(ctx, conn, metadata, N.OnceClose(func(it error) {
  35. close(done)
  36. }))
  37. if err != nil {
  38. return err
  39. }
  40. select {
  41. case <-done:
  42. case <-r.ctx.Done():
  43. }
  44. return nil
  45. }
  46. func (r *Router) RouteConnectionEx(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) {
  47. err := r.routeConnection(ctx, conn, metadata, onClose)
  48. if err != nil {
  49. N.CloseOnHandshakeFailure(conn, onClose, err)
  50. if E.IsClosedOrCanceled(err) || R.IsRejected(err) {
  51. r.logger.DebugContext(ctx, "connection closed: ", err)
  52. } else {
  53. r.logger.ErrorContext(ctx, err)
  54. }
  55. }
  56. }
  57. func (r *Router) routeConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) error {
  58. //nolint:staticcheck
  59. if metadata.InboundDetour != "" {
  60. if metadata.LastInbound == metadata.InboundDetour {
  61. return E.New("routing loop on detour: ", metadata.InboundDetour)
  62. }
  63. detour, loaded := r.inbound.Get(metadata.InboundDetour)
  64. if !loaded {
  65. return E.New("inbound detour not found: ", metadata.InboundDetour)
  66. }
  67. injectable, isInjectable := detour.(adapter.TCPInjectableInbound)
  68. if !isInjectable {
  69. return E.New("inbound detour is not TCP injectable: ", metadata.InboundDetour)
  70. }
  71. metadata.LastInbound = metadata.Inbound
  72. metadata.Inbound = metadata.InboundDetour
  73. metadata.InboundDetour = ""
  74. injectable.NewConnectionEx(ctx, conn, metadata, onClose)
  75. return nil
  76. }
  77. conntrack.KillerCheck()
  78. metadata.Network = N.NetworkTCP
  79. switch metadata.Destination.Fqdn {
  80. case mux.Destination.Fqdn:
  81. return E.New("global multiplex is deprecated since sing-box v1.7.0, enable multiplex in Inbound fields instead.")
  82. case vmess.MuxDestination.Fqdn:
  83. return E.New("global multiplex (v2ray legacy) not supported since sing-box v1.7.0.")
  84. case uot.MagicAddress:
  85. return E.New("global UoT not supported since sing-box v1.7.0.")
  86. case uot.LegacyMagicAddress:
  87. return E.New("global UoT (legacy) not supported since sing-box v1.7.0.")
  88. }
  89. if deadline.NeedAdditionalReadDeadline(conn) {
  90. conn = deadline.NewConn(conn)
  91. }
  92. selectedRule, _, buffers, _, err := r.matchRule(ctx, &metadata, false, false, conn, nil)
  93. if err != nil {
  94. return err
  95. }
  96. var selectedOutbound adapter.Outbound
  97. if selectedRule != nil {
  98. switch action := selectedRule.Action().(type) {
  99. case *R.RuleActionRoute:
  100. var loaded bool
  101. selectedOutbound, loaded = r.outbound.Outbound(action.Outbound)
  102. if !loaded {
  103. buf.ReleaseMulti(buffers)
  104. return E.New("outbound not found: ", action.Outbound)
  105. }
  106. if !common.Contains(selectedOutbound.Network(), N.NetworkTCP) {
  107. buf.ReleaseMulti(buffers)
  108. return E.New("TCP is not supported by outbound: ", selectedOutbound.Tag())
  109. }
  110. case *R.RuleActionBypass:
  111. if action.Outbound == "" {
  112. break
  113. }
  114. var loaded bool
  115. selectedOutbound, loaded = r.outbound.Outbound(action.Outbound)
  116. if !loaded {
  117. buf.ReleaseMulti(buffers)
  118. return E.New("outbound not found: ", action.Outbound)
  119. }
  120. if !common.Contains(selectedOutbound.Network(), N.NetworkTCP) {
  121. buf.ReleaseMulti(buffers)
  122. return E.New("TCP is not supported by outbound: ", selectedOutbound.Tag())
  123. }
  124. case *R.RuleActionReject:
  125. buf.ReleaseMulti(buffers)
  126. if action.Method == C.RuleActionRejectMethodReply {
  127. return E.New("reject method `reply` is not supported for TCP connections")
  128. }
  129. return action.Error(ctx)
  130. case *R.RuleActionHijackDNS:
  131. for _, buffer := range buffers {
  132. conn = bufio.NewCachedConn(conn, buffer)
  133. }
  134. N.CloseOnHandshakeFailure(conn, onClose, r.hijackDNSStream(ctx, conn, metadata))
  135. return nil
  136. }
  137. }
  138. if selectedRule == nil {
  139. defaultOutbound := r.outbound.Default()
  140. if !common.Contains(defaultOutbound.Network(), N.NetworkTCP) {
  141. buf.ReleaseMulti(buffers)
  142. return E.New("TCP is not supported by default outbound: ", defaultOutbound.Tag())
  143. }
  144. selectedOutbound = defaultOutbound
  145. }
  146. for _, buffer := range buffers {
  147. conn = bufio.NewCachedConn(conn, buffer)
  148. }
  149. for _, tracker := range r.trackers {
  150. conn = tracker.RoutedConnection(ctx, conn, metadata, selectedRule, selectedOutbound)
  151. }
  152. if outboundHandler, isHandler := selectedOutbound.(adapter.ConnectionHandlerEx); isHandler {
  153. outboundHandler.NewConnectionEx(ctx, conn, metadata, onClose)
  154. } else {
  155. r.connection.NewConnection(ctx, selectedOutbound, conn, metadata, onClose)
  156. }
  157. return nil
  158. }
  159. func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
  160. done := make(chan interface{})
  161. err := r.routePacketConnection(ctx, conn, metadata, N.OnceClose(func(it error) {
  162. close(done)
  163. }))
  164. if err != nil {
  165. conn.Close()
  166. if E.IsClosedOrCanceled(err) || R.IsRejected(err) {
  167. r.logger.DebugContext(ctx, "connection closed: ", err)
  168. } else {
  169. r.logger.ErrorContext(ctx, err)
  170. }
  171. }
  172. select {
  173. case <-done:
  174. case <-r.ctx.Done():
  175. }
  176. return nil
  177. }
  178. func (r *Router) RoutePacketConnectionEx(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) {
  179. err := r.routePacketConnection(ctx, conn, metadata, onClose)
  180. if err != nil {
  181. N.CloseOnHandshakeFailure(conn, onClose, err)
  182. if E.IsClosedOrCanceled(err) || R.IsRejected(err) {
  183. r.logger.DebugContext(ctx, "connection closed: ", err)
  184. } else {
  185. r.logger.ErrorContext(ctx, err)
  186. }
  187. }
  188. }
  189. func (r *Router) routePacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) error {
  190. //nolint:staticcheck
  191. if metadata.InboundDetour != "" {
  192. if metadata.LastInbound == metadata.InboundDetour {
  193. return E.New("routing loop on detour: ", metadata.InboundDetour)
  194. }
  195. detour, loaded := r.inbound.Get(metadata.InboundDetour)
  196. if !loaded {
  197. return E.New("inbound detour not found: ", metadata.InboundDetour)
  198. }
  199. injectable, isInjectable := detour.(adapter.UDPInjectableInbound)
  200. if !isInjectable {
  201. return E.New("inbound detour is not UDP injectable: ", metadata.InboundDetour)
  202. }
  203. metadata.LastInbound = metadata.Inbound
  204. metadata.Inbound = metadata.InboundDetour
  205. metadata.InboundDetour = ""
  206. injectable.NewPacketConnectionEx(ctx, conn, metadata, onClose)
  207. return nil
  208. }
  209. conntrack.KillerCheck()
  210. // TODO: move to UoT
  211. metadata.Network = N.NetworkUDP
  212. // Currently we don't have deadline usages for UDP connections
  213. /*if deadline.NeedAdditionalReadDeadline(conn) {
  214. conn = deadline.NewPacketConn(bufio.NewNetPacketConn(conn))
  215. }*/
  216. selectedRule, _, _, packetBuffers, err := r.matchRule(ctx, &metadata, false, false, nil, conn)
  217. if err != nil {
  218. return err
  219. }
  220. var selectedOutbound adapter.Outbound
  221. var selectReturn bool
  222. if selectedRule != nil {
  223. switch action := selectedRule.Action().(type) {
  224. case *R.RuleActionRoute:
  225. var loaded bool
  226. selectedOutbound, loaded = r.outbound.Outbound(action.Outbound)
  227. if !loaded {
  228. N.ReleaseMultiPacketBuffer(packetBuffers)
  229. return E.New("outbound not found: ", action.Outbound)
  230. }
  231. if !common.Contains(selectedOutbound.Network(), N.NetworkUDP) {
  232. N.ReleaseMultiPacketBuffer(packetBuffers)
  233. return E.New("UDP is not supported by outbound: ", selectedOutbound.Tag())
  234. }
  235. case *R.RuleActionBypass:
  236. if action.Outbound == "" {
  237. break
  238. }
  239. var loaded bool
  240. selectedOutbound, loaded = r.outbound.Outbound(action.Outbound)
  241. if !loaded {
  242. N.ReleaseMultiPacketBuffer(packetBuffers)
  243. return E.New("outbound not found: ", action.Outbound)
  244. }
  245. if !common.Contains(selectedOutbound.Network(), N.NetworkUDP) {
  246. N.ReleaseMultiPacketBuffer(packetBuffers)
  247. return E.New("UDP is not supported by outbound: ", selectedOutbound.Tag())
  248. }
  249. case *R.RuleActionReject:
  250. N.ReleaseMultiPacketBuffer(packetBuffers)
  251. if action.Method == C.RuleActionRejectMethodReply {
  252. return E.New("reject method `reply` is not supported for UDP connections")
  253. }
  254. return action.Error(ctx)
  255. case *R.RuleActionHijackDNS:
  256. return r.hijackDNSPacket(ctx, conn, packetBuffers, metadata, onClose)
  257. }
  258. }
  259. if selectedRule == nil || selectReturn {
  260. defaultOutbound := r.outbound.Default()
  261. if !common.Contains(defaultOutbound.Network(), N.NetworkUDP) {
  262. N.ReleaseMultiPacketBuffer(packetBuffers)
  263. return E.New("UDP is not supported by outbound: ", defaultOutbound.Tag())
  264. }
  265. selectedOutbound = defaultOutbound
  266. }
  267. for _, buffer := range packetBuffers {
  268. conn = bufio.NewCachedPacketConn(conn, buffer.Buffer, buffer.Destination)
  269. N.PutPacketBuffer(buffer)
  270. }
  271. for _, tracker := range r.trackers {
  272. conn = tracker.RoutedPacketConnection(ctx, conn, metadata, selectedRule, selectedOutbound)
  273. }
  274. if metadata.FakeIP {
  275. conn = bufio.NewNATPacketConn(bufio.NewNetPacketConn(conn), metadata.OriginDestination, metadata.Destination)
  276. }
  277. if outboundHandler, isHandler := selectedOutbound.(adapter.PacketConnectionHandlerEx); isHandler {
  278. outboundHandler.NewPacketConnectionEx(ctx, conn, metadata, onClose)
  279. } else {
  280. r.connection.NewPacketConnection(ctx, selectedOutbound, conn, metadata, onClose)
  281. }
  282. return nil
  283. }
  284. func (r *Router) PreMatch(metadata adapter.InboundContext, routeContext tun.DirectRouteContext, timeout time.Duration, supportBypass bool) (tun.DirectRouteDestination, error) {
  285. selectedRule, _, _, _, err := r.matchRule(r.ctx, &metadata, true, supportBypass, nil, nil)
  286. if err != nil {
  287. return nil, err
  288. }
  289. var directRouteOutbound adapter.DirectRouteOutbound
  290. if selectedRule != nil {
  291. switch action := selectedRule.Action().(type) {
  292. case *R.RuleActionReject:
  293. switch metadata.Network {
  294. case N.NetworkTCP:
  295. if action.Method == C.RuleActionRejectMethodReply {
  296. return nil, E.New("reject method `reply` is not supported for TCP connections")
  297. }
  298. case N.NetworkUDP:
  299. if action.Method == C.RuleActionRejectMethodReply {
  300. return nil, E.New("reject method `reply` is not supported for UDP connections")
  301. }
  302. }
  303. return nil, action.Error(context.Background())
  304. case *R.RuleActionBypass:
  305. if supportBypass {
  306. return nil, &R.BypassedError{Cause: tun.ErrBypass}
  307. }
  308. if routeContext == nil {
  309. return nil, nil
  310. }
  311. outbound, loaded := r.outbound.Outbound(action.Outbound)
  312. if !loaded {
  313. return nil, E.New("outbound not found: ", action.Outbound)
  314. }
  315. if !common.Contains(outbound.Network(), metadata.Network) {
  316. return nil, E.New(metadata.Network, " is not supported by outbound: ", action.Outbound)
  317. }
  318. directRouteOutbound = outbound.(adapter.DirectRouteOutbound)
  319. case *R.RuleActionRoute:
  320. if routeContext == nil {
  321. return nil, nil
  322. }
  323. outbound, loaded := r.outbound.Outbound(action.Outbound)
  324. if !loaded {
  325. return nil, E.New("outbound not found: ", action.Outbound)
  326. }
  327. if !common.Contains(outbound.Network(), metadata.Network) {
  328. return nil, E.New(metadata.Network, " is not supported by outbound: ", action.Outbound)
  329. }
  330. directRouteOutbound = outbound.(adapter.DirectRouteOutbound)
  331. }
  332. }
  333. if directRouteOutbound == nil {
  334. if selectedRule != nil || metadata.Network != N.NetworkICMP {
  335. return nil, nil
  336. }
  337. defaultOutbound := r.outbound.Default()
  338. if !common.Contains(defaultOutbound.Network(), metadata.Network) {
  339. return nil, E.New(metadata.Network, " is not supported by default outbound: ", defaultOutbound.Tag())
  340. }
  341. directRouteOutbound = defaultOutbound.(adapter.DirectRouteOutbound)
  342. }
  343. if metadata.Destination.IsFqdn() {
  344. if len(metadata.DestinationAddresses) == 0 {
  345. var strategy C.DomainStrategy
  346. if metadata.Source.IsIPv4() {
  347. strategy = C.DomainStrategyIPv4Only
  348. } else {
  349. strategy = C.DomainStrategyIPv6Only
  350. }
  351. err = r.actionResolve(r.ctx, &metadata, &R.RuleActionResolve{
  352. Strategy: strategy,
  353. })
  354. if err != nil {
  355. return nil, err
  356. }
  357. }
  358. var newDestination netip.Addr
  359. if metadata.Source.IsIPv4() {
  360. for _, address := range metadata.DestinationAddresses {
  361. if address.Is4() {
  362. newDestination = address
  363. break
  364. }
  365. }
  366. } else {
  367. for _, address := range metadata.DestinationAddresses {
  368. if address.Is6() {
  369. newDestination = address
  370. break
  371. }
  372. }
  373. }
  374. if !newDestination.IsValid() {
  375. if metadata.Source.IsIPv4() {
  376. return nil, E.New("no IPv4 address found for domain: ", metadata.Destination.Fqdn)
  377. } else {
  378. return nil, E.New("no IPv6 address found for domain: ", metadata.Destination.Fqdn)
  379. }
  380. }
  381. metadata.Destination = M.Socksaddr{
  382. Addr: newDestination,
  383. }
  384. routeContext = ping.NewContextDestinationWriter(routeContext, metadata.OriginDestination.Addr)
  385. var routeDestination tun.DirectRouteDestination
  386. routeDestination, err = directRouteOutbound.NewDirectRouteConnection(metadata, routeContext, timeout)
  387. if err != nil {
  388. return nil, err
  389. }
  390. return ping.NewDestinationWriter(routeDestination, newDestination), nil
  391. }
  392. return directRouteOutbound.NewDirectRouteConnection(metadata, routeContext, timeout)
  393. }
  394. func (r *Router) matchRule(
  395. ctx context.Context, metadata *adapter.InboundContext, preMatch bool, supportBypass bool,
  396. inputConn net.Conn, inputPacketConn N.PacketConn,
  397. ) (
  398. selectedRule adapter.Rule, selectedRuleIndex int,
  399. buffers []*buf.Buffer, packetBuffers []*N.PacketBuffer, fatalErr error,
  400. ) {
  401. if r.processSearcher != nil && metadata.ProcessInfo == nil {
  402. var originDestination netip.AddrPort
  403. if metadata.OriginDestination.IsValid() {
  404. originDestination = metadata.OriginDestination.AddrPort()
  405. } else if metadata.Destination.IsIP() {
  406. originDestination = metadata.Destination.AddrPort()
  407. }
  408. processInfo, fErr := process.FindProcessInfo(r.processSearcher, ctx, metadata.Network, metadata.Source.AddrPort(), originDestination)
  409. if fErr != nil {
  410. r.logger.InfoContext(ctx, "failed to search process: ", fErr)
  411. } else {
  412. if processInfo.ProcessPath != "" {
  413. if processInfo.UserName != "" {
  414. r.logger.InfoContext(ctx, "found process path: ", processInfo.ProcessPath, ", user: ", processInfo.UserName)
  415. } else if processInfo.UserId != -1 {
  416. r.logger.InfoContext(ctx, "found process path: ", processInfo.ProcessPath, ", user id: ", processInfo.UserId)
  417. } else {
  418. r.logger.InfoContext(ctx, "found process path: ", processInfo.ProcessPath)
  419. }
  420. } else if processInfo.AndroidPackageName != "" {
  421. r.logger.InfoContext(ctx, "found package name: ", processInfo.AndroidPackageName)
  422. } else if processInfo.UserId != -1 {
  423. if processInfo.UserName != "" {
  424. r.logger.InfoContext(ctx, "found user: ", processInfo.UserName)
  425. } else {
  426. r.logger.InfoContext(ctx, "found user id: ", processInfo.UserId)
  427. }
  428. }
  429. metadata.ProcessInfo = processInfo
  430. }
  431. }
  432. if metadata.Destination.Addr.IsValid() && r.dnsTransport.FakeIP() != nil && r.dnsTransport.FakeIP().Store().Contains(metadata.Destination.Addr) {
  433. domain, loaded := r.dnsTransport.FakeIP().Store().Lookup(metadata.Destination.Addr)
  434. if !loaded {
  435. fatalErr = E.New("missing fakeip record, try enable `experimental.cache_file`")
  436. return
  437. }
  438. if domain != "" {
  439. metadata.OriginDestination = metadata.Destination
  440. metadata.Destination = M.Socksaddr{
  441. Fqdn: domain,
  442. Port: metadata.Destination.Port,
  443. }
  444. metadata.FakeIP = true
  445. r.logger.DebugContext(ctx, "found fakeip domain: ", domain)
  446. }
  447. } else if metadata.Domain == "" {
  448. domain, loaded := r.dns.LookupReverseMapping(metadata.Destination.Addr)
  449. if loaded {
  450. metadata.Domain = domain
  451. r.logger.DebugContext(ctx, "found reserve mapped domain: ", metadata.Domain)
  452. }
  453. }
  454. if metadata.Destination.IsIPv4() {
  455. metadata.IPVersion = 4
  456. } else if metadata.Destination.IsIPv6() {
  457. metadata.IPVersion = 6
  458. }
  459. //nolint:staticcheck
  460. if metadata.InboundOptions != common.DefaultValue[option.InboundOptions]() {
  461. if !preMatch && metadata.InboundOptions.SniffEnabled {
  462. newBuffer, newPackerBuffers, newErr := r.actionSniff(ctx, metadata, &R.RuleActionSniff{
  463. OverrideDestination: metadata.InboundOptions.SniffOverrideDestination,
  464. Timeout: time.Duration(metadata.InboundOptions.SniffTimeout),
  465. }, inputConn, inputPacketConn, nil, nil)
  466. if newBuffer != nil {
  467. buffers = []*buf.Buffer{newBuffer}
  468. } else if len(newPackerBuffers) > 0 {
  469. packetBuffers = newPackerBuffers
  470. }
  471. if newErr != nil {
  472. fatalErr = newErr
  473. return
  474. }
  475. }
  476. if C.DomainStrategy(metadata.InboundOptions.DomainStrategy) != C.DomainStrategyAsIS {
  477. fatalErr = r.actionResolve(ctx, metadata, &R.RuleActionResolve{
  478. Strategy: C.DomainStrategy(metadata.InboundOptions.DomainStrategy),
  479. })
  480. if fatalErr != nil {
  481. return
  482. }
  483. }
  484. if metadata.InboundOptions.UDPDisableDomainUnmapping {
  485. metadata.UDPDisableDomainUnmapping = true
  486. }
  487. metadata.InboundOptions = option.InboundOptions{}
  488. }
  489. match:
  490. for currentRuleIndex, currentRule := range r.rules {
  491. metadata.ResetRuleCache()
  492. if !currentRule.Match(metadata) {
  493. continue
  494. }
  495. if !preMatch {
  496. ruleDescription := currentRule.String()
  497. if ruleDescription != "" {
  498. r.logger.DebugContext(ctx, "match[", currentRuleIndex, "] ", currentRule, " => ", currentRule.Action())
  499. } else {
  500. r.logger.DebugContext(ctx, "match[", currentRuleIndex, "] => ", currentRule.Action())
  501. }
  502. } else {
  503. switch currentRule.Action().Type() {
  504. case C.RuleActionTypeReject:
  505. ruleDescription := currentRule.String()
  506. if ruleDescription != "" {
  507. r.logger.DebugContext(ctx, "pre-match[", currentRuleIndex, "] ", currentRule, " => ", currentRule.Action())
  508. } else {
  509. r.logger.DebugContext(ctx, "pre-match[", currentRuleIndex, "] => ", currentRule.Action())
  510. }
  511. }
  512. }
  513. var routeOptions *R.RuleActionRouteOptions
  514. switch action := currentRule.Action().(type) {
  515. case *R.RuleActionRoute:
  516. routeOptions = &action.RuleActionRouteOptions
  517. case *R.RuleActionRouteOptions:
  518. routeOptions = action
  519. }
  520. if routeOptions != nil {
  521. // TODO: add nat
  522. if (routeOptions.OverrideAddress.IsValid() || routeOptions.OverridePort > 0) && !metadata.RouteOriginalDestination.IsValid() {
  523. metadata.RouteOriginalDestination = metadata.Destination
  524. }
  525. if routeOptions.OverrideAddress.IsValid() {
  526. metadata.Destination = M.Socksaddr{
  527. Addr: routeOptions.OverrideAddress.Addr,
  528. Port: metadata.Destination.Port,
  529. Fqdn: routeOptions.OverrideAddress.Fqdn,
  530. }
  531. metadata.DestinationAddresses = nil
  532. }
  533. if routeOptions.OverridePort > 0 {
  534. metadata.Destination = M.Socksaddr{
  535. Addr: metadata.Destination.Addr,
  536. Port: routeOptions.OverridePort,
  537. Fqdn: metadata.Destination.Fqdn,
  538. }
  539. }
  540. if routeOptions.NetworkStrategy != nil {
  541. metadata.NetworkStrategy = routeOptions.NetworkStrategy
  542. }
  543. if len(routeOptions.NetworkType) > 0 {
  544. metadata.NetworkType = routeOptions.NetworkType
  545. }
  546. if len(routeOptions.FallbackNetworkType) > 0 {
  547. metadata.FallbackNetworkType = routeOptions.FallbackNetworkType
  548. }
  549. if routeOptions.FallbackDelay != 0 {
  550. metadata.FallbackDelay = routeOptions.FallbackDelay
  551. }
  552. if routeOptions.UDPDisableDomainUnmapping {
  553. metadata.UDPDisableDomainUnmapping = true
  554. }
  555. if routeOptions.UDPConnect {
  556. metadata.UDPConnect = true
  557. }
  558. if routeOptions.UDPTimeout > 0 {
  559. metadata.UDPTimeout = routeOptions.UDPTimeout
  560. }
  561. if routeOptions.TLSFragment {
  562. metadata.TLSFragment = true
  563. metadata.TLSFragmentFallbackDelay = routeOptions.TLSFragmentFallbackDelay
  564. }
  565. if routeOptions.TLSRecordFragment {
  566. metadata.TLSRecordFragment = true
  567. }
  568. }
  569. switch action := currentRule.Action().(type) {
  570. case *R.RuleActionSniff:
  571. if !preMatch {
  572. newBuffer, newPacketBuffers, newErr := r.actionSniff(ctx, metadata, action, inputConn, inputPacketConn, buffers, packetBuffers)
  573. if newBuffer != nil {
  574. buffers = append(buffers, newBuffer)
  575. } else if len(newPacketBuffers) > 0 {
  576. packetBuffers = append(packetBuffers, newPacketBuffers...)
  577. }
  578. if newErr != nil {
  579. fatalErr = newErr
  580. return
  581. }
  582. } else if metadata.Network != N.NetworkICMP {
  583. selectedRule = currentRule
  584. selectedRuleIndex = currentRuleIndex
  585. break match
  586. }
  587. case *R.RuleActionResolve:
  588. fatalErr = r.actionResolve(ctx, metadata, action)
  589. if fatalErr != nil {
  590. return
  591. }
  592. }
  593. actionType := currentRule.Action().Type()
  594. if actionType == C.RuleActionTypeRoute ||
  595. actionType == C.RuleActionTypeReject ||
  596. actionType == C.RuleActionTypeHijackDNS {
  597. selectedRule = currentRule
  598. selectedRuleIndex = currentRuleIndex
  599. break match
  600. }
  601. if actionType == C.RuleActionTypeBypass {
  602. bypassAction := currentRule.Action().(*R.RuleActionBypass)
  603. if !supportBypass && bypassAction.Outbound == "" {
  604. continue match
  605. }
  606. selectedRule = currentRule
  607. selectedRuleIndex = currentRuleIndex
  608. break match
  609. }
  610. }
  611. return
  612. }
  613. func (r *Router) actionSniff(
  614. ctx context.Context, metadata *adapter.InboundContext, action *R.RuleActionSniff,
  615. inputConn net.Conn, inputPacketConn N.PacketConn, inputBuffers []*buf.Buffer, inputPacketBuffers []*N.PacketBuffer,
  616. ) (buffer *buf.Buffer, packetBuffers []*N.PacketBuffer, fatalErr error) {
  617. if sniff.Skip(metadata) {
  618. r.logger.DebugContext(ctx, "sniff skipped due to port considered as server-first")
  619. return
  620. } else if metadata.Protocol != "" {
  621. r.logger.DebugContext(ctx, "duplicate sniff skipped")
  622. return
  623. }
  624. if inputConn != nil {
  625. if len(action.StreamSniffers) == 0 && len(action.PacketSniffers) > 0 {
  626. return
  627. } else if slices.Equal(metadata.SnifferNames, action.SnifferNames) && metadata.SniffError != nil && !errors.Is(metadata.SniffError, sniff.ErrNeedMoreData) {
  628. r.logger.DebugContext(ctx, "packet sniff skipped due to previous error: ", metadata.SniffError)
  629. return
  630. }
  631. var streamSniffers []sniff.StreamSniffer
  632. if len(action.StreamSniffers) > 0 {
  633. streamSniffers = action.StreamSniffers
  634. } else {
  635. streamSniffers = []sniff.StreamSniffer{
  636. sniff.TLSClientHello,
  637. sniff.HTTPHost,
  638. sniff.StreamDomainNameQuery,
  639. sniff.BitTorrent,
  640. sniff.SSH,
  641. sniff.RDP,
  642. }
  643. }
  644. sniffBuffer := buf.NewPacket()
  645. err := sniff.PeekStream(
  646. ctx,
  647. metadata,
  648. inputConn,
  649. inputBuffers,
  650. sniffBuffer,
  651. action.Timeout,
  652. streamSniffers...,
  653. )
  654. metadata.SnifferNames = action.SnifferNames
  655. metadata.SniffError = err
  656. if err == nil {
  657. //goland:noinspection GoDeprecation
  658. if action.OverrideDestination && M.IsDomainName(metadata.Domain) {
  659. metadata.Destination = M.Socksaddr{
  660. Fqdn: metadata.Domain,
  661. Port: metadata.Destination.Port,
  662. }
  663. }
  664. if metadata.Domain != "" && metadata.Client != "" {
  665. r.logger.DebugContext(ctx, "sniffed protocol: ", metadata.Protocol, ", domain: ", metadata.Domain, ", client: ", metadata.Client)
  666. } else if metadata.Domain != "" {
  667. r.logger.DebugContext(ctx, "sniffed protocol: ", metadata.Protocol, ", domain: ", metadata.Domain)
  668. } else {
  669. r.logger.DebugContext(ctx, "sniffed protocol: ", metadata.Protocol)
  670. }
  671. }
  672. if !sniffBuffer.IsEmpty() {
  673. buffer = sniffBuffer
  674. } else {
  675. sniffBuffer.Release()
  676. }
  677. } else if inputPacketConn != nil {
  678. if len(action.PacketSniffers) == 0 && len(action.StreamSniffers) > 0 {
  679. return
  680. } else if slices.Equal(metadata.SnifferNames, action.SnifferNames) && metadata.SniffError != nil && !errors.Is(metadata.SniffError, sniff.ErrNeedMoreData) {
  681. r.logger.DebugContext(ctx, "packet sniff skipped due to previous error: ", metadata.SniffError)
  682. return
  683. }
  684. quicMoreData := func() bool {
  685. return slices.Equal(metadata.SnifferNames, action.SnifferNames) && errors.Is(metadata.SniffError, sniff.ErrNeedMoreData)
  686. }
  687. var packetSniffers []sniff.PacketSniffer
  688. if len(action.PacketSniffers) > 0 {
  689. packetSniffers = action.PacketSniffers
  690. } else {
  691. packetSniffers = []sniff.PacketSniffer{
  692. sniff.DomainNameQuery,
  693. sniff.QUICClientHello,
  694. sniff.STUNMessage,
  695. sniff.UTP,
  696. sniff.UDPTracker,
  697. sniff.DTLSRecord,
  698. sniff.NTP,
  699. }
  700. }
  701. var err error
  702. for _, packetBuffer := range inputPacketBuffers {
  703. if quicMoreData() {
  704. err = sniff.PeekPacket(
  705. ctx,
  706. metadata,
  707. packetBuffer.Buffer.Bytes(),
  708. sniff.QUICClientHello,
  709. )
  710. } else {
  711. err = sniff.PeekPacket(
  712. ctx, metadata,
  713. packetBuffer.Buffer.Bytes(),
  714. packetSniffers...,
  715. )
  716. }
  717. metadata.SnifferNames = action.SnifferNames
  718. metadata.SniffError = err
  719. if errors.Is(err, sniff.ErrNeedMoreData) {
  720. // TODO: replace with generic message when there are more multi-packet protocols
  721. r.logger.DebugContext(ctx, "attempt to sniff fragmented QUIC client hello")
  722. continue
  723. }
  724. goto finally
  725. }
  726. packetBuffers = inputPacketBuffers
  727. for {
  728. var (
  729. sniffBuffer = buf.NewPacket()
  730. destination M.Socksaddr
  731. done = make(chan struct{})
  732. )
  733. go func() {
  734. sniffTimeout := C.ReadPayloadTimeout
  735. if action.Timeout > 0 {
  736. sniffTimeout = action.Timeout
  737. }
  738. inputPacketConn.SetReadDeadline(time.Now().Add(sniffTimeout))
  739. destination, err = inputPacketConn.ReadPacket(sniffBuffer)
  740. inputPacketConn.SetReadDeadline(time.Time{})
  741. close(done)
  742. }()
  743. select {
  744. case <-done:
  745. case <-ctx.Done():
  746. inputPacketConn.Close()
  747. fatalErr = ctx.Err()
  748. return
  749. }
  750. if err != nil {
  751. sniffBuffer.Release()
  752. if !errors.Is(err, context.DeadlineExceeded) {
  753. fatalErr = err
  754. return
  755. }
  756. } else {
  757. if quicMoreData() {
  758. err = sniff.PeekPacket(
  759. ctx,
  760. metadata,
  761. sniffBuffer.Bytes(),
  762. sniff.QUICClientHello,
  763. )
  764. } else {
  765. err = sniff.PeekPacket(
  766. ctx, metadata,
  767. sniffBuffer.Bytes(),
  768. packetSniffers...,
  769. )
  770. }
  771. packetBuffer := N.NewPacketBuffer()
  772. *packetBuffer = N.PacketBuffer{
  773. Buffer: sniffBuffer,
  774. Destination: destination,
  775. }
  776. packetBuffers = append(packetBuffers, packetBuffer)
  777. metadata.SnifferNames = action.SnifferNames
  778. metadata.SniffError = err
  779. if errors.Is(err, sniff.ErrNeedMoreData) {
  780. // TODO: replace with generic message when there are more multi-packet protocols
  781. r.logger.DebugContext(ctx, "attempt to sniff fragmented QUIC client hello")
  782. continue
  783. }
  784. }
  785. goto finally
  786. }
  787. finally:
  788. if err == nil {
  789. //goland:noinspection GoDeprecation
  790. if action.OverrideDestination && M.IsDomainName(metadata.Domain) {
  791. metadata.Destination = M.Socksaddr{
  792. Fqdn: metadata.Domain,
  793. Port: metadata.Destination.Port,
  794. }
  795. }
  796. if metadata.Domain != "" && metadata.Client != "" {
  797. r.logger.DebugContext(ctx, "sniffed packet protocol: ", metadata.Protocol, ", domain: ", metadata.Domain, ", client: ", metadata.Client)
  798. } else if metadata.Domain != "" {
  799. r.logger.DebugContext(ctx, "sniffed packet protocol: ", metadata.Protocol, ", domain: ", metadata.Domain)
  800. } else if metadata.Client != "" {
  801. r.logger.DebugContext(ctx, "sniffed packet protocol: ", metadata.Protocol, ", client: ", metadata.Client)
  802. } else {
  803. r.logger.DebugContext(ctx, "sniffed packet protocol: ", metadata.Protocol)
  804. }
  805. }
  806. }
  807. return
  808. }
  809. func (r *Router) actionResolve(ctx context.Context, metadata *adapter.InboundContext, action *R.RuleActionResolve) error {
  810. if metadata.Destination.IsFqdn() {
  811. var transport adapter.DNSTransport
  812. if action.Server != "" {
  813. var loaded bool
  814. transport, loaded = r.dnsTransport.Transport(action.Server)
  815. if !loaded {
  816. return E.New("DNS server not found: ", action.Server)
  817. }
  818. }
  819. addresses, err := r.dns.Lookup(adapter.WithContext(ctx, metadata), metadata.Destination.Fqdn, adapter.DNSQueryOptions{
  820. Transport: transport,
  821. Strategy: action.Strategy,
  822. DisableCache: action.DisableCache,
  823. RewriteTTL: action.RewriteTTL,
  824. ClientSubnet: action.ClientSubnet,
  825. })
  826. if err != nil {
  827. return err
  828. }
  829. metadata.DestinationAddresses = addresses
  830. r.logger.DebugContext(ctx, "resolved [", strings.Join(F.MapToString(metadata.DestinationAddresses), " "), "]")
  831. }
  832. return nil
  833. }