route.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702
  1. package route
  2. import (
  3. "context"
  4. "errors"
  5. "net"
  6. "net/netip"
  7. "os"
  8. "os/user"
  9. "strings"
  10. "time"
  11. "github.com/sagernet/sing-box/adapter"
  12. "github.com/sagernet/sing-box/common/conntrack"
  13. "github.com/sagernet/sing-box/common/process"
  14. "github.com/sagernet/sing-box/common/sniff"
  15. C "github.com/sagernet/sing-box/constant"
  16. "github.com/sagernet/sing-box/option"
  17. "github.com/sagernet/sing-box/route/rule"
  18. "github.com/sagernet/sing-mux"
  19. "github.com/sagernet/sing-tun"
  20. "github.com/sagernet/sing-vmess"
  21. "github.com/sagernet/sing/common"
  22. "github.com/sagernet/sing/common/buf"
  23. "github.com/sagernet/sing/common/bufio"
  24. "github.com/sagernet/sing/common/bufio/deadline"
  25. E "github.com/sagernet/sing/common/exceptions"
  26. F "github.com/sagernet/sing/common/format"
  27. M "github.com/sagernet/sing/common/metadata"
  28. N "github.com/sagernet/sing/common/network"
  29. "github.com/sagernet/sing/common/uot"
  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) {
  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. if r.pauseManager.IsDevicePaused() {
  59. return E.New("reject connection to ", metadata.Destination, " while device paused")
  60. }
  61. //nolint:staticcheck
  62. if metadata.InboundDetour != "" {
  63. if metadata.LastInbound == metadata.InboundDetour {
  64. return E.New("routing loop on detour: ", metadata.InboundDetour)
  65. }
  66. detour, loaded := r.inbound.Get(metadata.InboundDetour)
  67. if !loaded {
  68. return E.New("inbound detour not found: ", metadata.InboundDetour)
  69. }
  70. injectable, isInjectable := detour.(adapter.TCPInjectableInbound)
  71. if !isInjectable {
  72. return E.New("inbound detour is not TCP injectable: ", metadata.InboundDetour)
  73. }
  74. metadata.LastInbound = metadata.Inbound
  75. metadata.Inbound = metadata.InboundDetour
  76. metadata.InboundDetour = ""
  77. injectable.NewConnectionEx(ctx, conn, metadata, onClose)
  78. return nil
  79. }
  80. conntrack.KillerCheck()
  81. metadata.Network = N.NetworkTCP
  82. switch metadata.Destination.Fqdn {
  83. case mux.Destination.Fqdn:
  84. return E.New("global multiplex is deprecated since sing-box v1.7.0, enable multiplex in Inbound fields instead.")
  85. case vmess.MuxDestination.Fqdn:
  86. return E.New("global multiplex (v2ray legacy) not supported since sing-box v1.7.0.")
  87. case uot.MagicAddress:
  88. return E.New("global UoT not supported since sing-box v1.7.0.")
  89. case uot.LegacyMagicAddress:
  90. return E.New("global UoT (legacy) not supported since sing-box v1.7.0.")
  91. }
  92. if deadline.NeedAdditionalReadDeadline(conn) {
  93. conn = deadline.NewConn(conn)
  94. }
  95. selectedRule, _, buffers, _, err := r.matchRule(ctx, &metadata, false, conn, nil)
  96. if err != nil {
  97. return err
  98. }
  99. var selectedOutbound adapter.Outbound
  100. if selectedRule != nil {
  101. switch action := selectedRule.Action().(type) {
  102. case *rule.RuleActionRoute:
  103. var loaded bool
  104. selectedOutbound, loaded = r.outbound.Outbound(action.Outbound)
  105. if !loaded {
  106. buf.ReleaseMulti(buffers)
  107. return E.New("outbound not found: ", action.Outbound)
  108. }
  109. if !common.Contains(selectedOutbound.Network(), N.NetworkTCP) {
  110. buf.ReleaseMulti(buffers)
  111. return E.New("TCP is not supported by outbound: ", selectedOutbound.Tag())
  112. }
  113. case *rule.RuleActionReject:
  114. buf.ReleaseMulti(buffers)
  115. N.CloseOnHandshakeFailure(conn, onClose, action.Error(ctx))
  116. return nil
  117. case *rule.RuleActionHijackDNS:
  118. for _, buffer := range buffers {
  119. conn = bufio.NewCachedConn(conn, buffer)
  120. }
  121. r.hijackDNSStream(ctx, conn, metadata)
  122. return nil
  123. }
  124. }
  125. if selectedRule == nil {
  126. defaultOutbound := r.outbound.Default()
  127. if !common.Contains(defaultOutbound.Network(), N.NetworkTCP) {
  128. buf.ReleaseMulti(buffers)
  129. return E.New("TCP is not supported by default outbound: ", defaultOutbound.Tag())
  130. }
  131. selectedOutbound = defaultOutbound
  132. }
  133. for _, buffer := range buffers {
  134. conn = bufio.NewCachedConn(conn, buffer)
  135. }
  136. if r.tracker != nil {
  137. conn = r.tracker.RoutedConnection(ctx, conn, metadata, selectedRule, selectedOutbound)
  138. }
  139. if outboundHandler, isHandler := selectedOutbound.(adapter.ConnectionHandlerEx); isHandler {
  140. outboundHandler.NewConnectionEx(ctx, conn, metadata, onClose)
  141. } else {
  142. r.connection.NewConnection(ctx, selectedOutbound, conn, metadata, onClose)
  143. }
  144. return nil
  145. }
  146. func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
  147. done := make(chan interface{})
  148. err := r.routePacketConnection(ctx, conn, metadata, N.OnceClose(func(it error) {
  149. close(done)
  150. }))
  151. if err != nil {
  152. conn.Close()
  153. if E.IsClosedOrCanceled(err) {
  154. r.logger.DebugContext(ctx, "connection closed: ", err)
  155. } else {
  156. r.logger.ErrorContext(ctx, err)
  157. }
  158. }
  159. select {
  160. case <-done:
  161. case <-r.ctx.Done():
  162. }
  163. return nil
  164. }
  165. func (r *Router) RoutePacketConnectionEx(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) {
  166. err := r.routePacketConnection(ctx, conn, metadata, onClose)
  167. if err != nil {
  168. N.CloseOnHandshakeFailure(conn, onClose, err)
  169. if E.IsClosedOrCanceled(err) {
  170. r.logger.DebugContext(ctx, "connection closed: ", err)
  171. } else {
  172. r.logger.ErrorContext(ctx, err)
  173. }
  174. } else if onClose != nil {
  175. onClose(nil)
  176. }
  177. }
  178. func (r *Router) routePacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) error {
  179. if r.pauseManager.IsDevicePaused() {
  180. return E.New("reject packet connection to ", metadata.Destination, " while device paused")
  181. }
  182. //nolint:staticcheck
  183. if metadata.InboundDetour != "" {
  184. if metadata.LastInbound == metadata.InboundDetour {
  185. return E.New("routing loop on detour: ", metadata.InboundDetour)
  186. }
  187. detour, loaded := r.inbound.Get(metadata.InboundDetour)
  188. if !loaded {
  189. return E.New("inbound detour not found: ", metadata.InboundDetour)
  190. }
  191. injectable, isInjectable := detour.(adapter.UDPInjectableInbound)
  192. if !isInjectable {
  193. return E.New("inbound detour is not UDP injectable: ", metadata.InboundDetour)
  194. }
  195. metadata.LastInbound = metadata.Inbound
  196. metadata.Inbound = metadata.InboundDetour
  197. metadata.InboundDetour = ""
  198. injectable.NewPacketConnectionEx(ctx, conn, metadata, onClose)
  199. return nil
  200. }
  201. conntrack.KillerCheck()
  202. // TODO: move to UoT
  203. metadata.Network = N.NetworkUDP
  204. // Currently we don't have deadline usages for UDP connections
  205. /*if deadline.NeedAdditionalReadDeadline(conn) {
  206. conn = deadline.NewPacketConn(bufio.NewNetPacketConn(conn))
  207. }*/
  208. selectedRule, _, _, packetBuffers, err := r.matchRule(ctx, &metadata, false, nil, conn)
  209. if err != nil {
  210. return err
  211. }
  212. var selectedOutbound adapter.Outbound
  213. var selectReturn bool
  214. if selectedRule != nil {
  215. switch action := selectedRule.Action().(type) {
  216. case *rule.RuleActionRoute:
  217. var loaded bool
  218. selectedOutbound, loaded = r.outbound.Outbound(action.Outbound)
  219. if !loaded {
  220. N.ReleaseMultiPacketBuffer(packetBuffers)
  221. return E.New("outbound not found: ", action.Outbound)
  222. }
  223. if !common.Contains(selectedOutbound.Network(), N.NetworkUDP) {
  224. N.ReleaseMultiPacketBuffer(packetBuffers)
  225. return E.New("UDP is not supported by outbound: ", selectedOutbound.Tag())
  226. }
  227. case *rule.RuleActionReject:
  228. N.ReleaseMultiPacketBuffer(packetBuffers)
  229. N.CloseOnHandshakeFailure(conn, onClose, action.Error(ctx))
  230. return nil
  231. case *rule.RuleActionHijackDNS:
  232. r.hijackDNSPacket(ctx, conn, packetBuffers, metadata)
  233. return nil
  234. }
  235. }
  236. if selectedRule == nil || selectReturn {
  237. defaultOutbound := r.outbound.Default()
  238. if !common.Contains(defaultOutbound.Network(), N.NetworkUDP) {
  239. N.ReleaseMultiPacketBuffer(packetBuffers)
  240. return E.New("UDP is not supported by outbound: ", defaultOutbound.Tag())
  241. }
  242. selectedOutbound = defaultOutbound
  243. }
  244. for _, buffer := range packetBuffers {
  245. conn = bufio.NewCachedPacketConn(conn, buffer.Buffer, buffer.Destination)
  246. N.PutPacketBuffer(buffer)
  247. }
  248. if r.tracker != nil {
  249. conn = r.tracker.RoutedPacketConnection(ctx, conn, metadata, selectedRule, selectedOutbound)
  250. }
  251. if metadata.FakeIP {
  252. conn = bufio.NewNATPacketConn(bufio.NewNetPacketConn(conn), metadata.OriginDestination, metadata.Destination)
  253. }
  254. if outboundHandler, isHandler := selectedOutbound.(adapter.PacketConnectionHandlerEx); isHandler {
  255. outboundHandler.NewPacketConnectionEx(ctx, conn, metadata, onClose)
  256. } else {
  257. r.connection.NewPacketConnection(ctx, selectedOutbound, conn, metadata, onClose)
  258. }
  259. return nil
  260. }
  261. func (r *Router) PreMatch(metadata adapter.InboundContext, routeContext tun.DirectRouteContext) (tun.DirectRouteDestination, error) {
  262. selectedRule, _, _, _, err := r.matchRule(r.ctx, &metadata, true, nil, nil)
  263. if err != nil {
  264. return nil, err
  265. }
  266. if selectedRule == nil {
  267. defaultOutbound := r.outbound.Default()
  268. if !common.Contains(defaultOutbound.Network(), metadata.Network) {
  269. return nil, E.New(metadata.Network, " is not supported by default outbound: ", defaultOutbound.Tag())
  270. }
  271. return defaultOutbound.(adapter.DirectRouteOutbound).NewDirectRouteConnection(metadata, routeContext)
  272. }
  273. switch action := selectedRule.Action().(type) {
  274. case *rule.RuleActionReject:
  275. return nil, action.Error(context.Background())
  276. case *rule.RuleActionRoute:
  277. if routeContext == nil {
  278. return nil, nil
  279. }
  280. outbound, loaded := r.outbound.Outbound(action.Outbound)
  281. if !loaded {
  282. return nil, E.New("outbound not found: ", action.Outbound)
  283. }
  284. if !common.Contains(outbound.Network(), metadata.Network) {
  285. return nil, E.New(metadata.Network, " is not supported by outbound: ", action.Outbound)
  286. }
  287. return outbound.(adapter.DirectRouteOutbound).NewDirectRouteConnection(metadata, routeContext)
  288. default:
  289. return nil, nil
  290. }
  291. }
  292. func (r *Router) matchRule(
  293. ctx context.Context, metadata *adapter.InboundContext, preMatch bool,
  294. inputConn net.Conn, inputPacketConn N.PacketConn,
  295. ) (
  296. selectedRule adapter.Rule, selectedRuleIndex int,
  297. buffers []*buf.Buffer, packetBuffers []*N.PacketBuffer, fatalErr error,
  298. ) {
  299. if r.processSearcher != nil && metadata.ProcessInfo == nil {
  300. var originDestination netip.AddrPort
  301. if metadata.OriginDestination.IsValid() {
  302. originDestination = metadata.OriginDestination.AddrPort()
  303. } else if metadata.Destination.IsIP() {
  304. originDestination = metadata.Destination.AddrPort()
  305. }
  306. processInfo, fErr := process.FindProcessInfo(r.processSearcher, ctx, metadata.Network, metadata.Source.AddrPort(), originDestination)
  307. if fErr != nil {
  308. r.logger.InfoContext(ctx, "failed to search process: ", fErr)
  309. } else {
  310. if processInfo.ProcessPath != "" {
  311. r.logger.InfoContext(ctx, "found process path: ", processInfo.ProcessPath)
  312. } else if processInfo.PackageName != "" {
  313. r.logger.InfoContext(ctx, "found package name: ", processInfo.PackageName)
  314. } else if processInfo.UserId != -1 {
  315. if /*needUserName &&*/ true {
  316. osUser, _ := user.LookupId(F.ToString(processInfo.UserId))
  317. if osUser != nil {
  318. processInfo.User = osUser.Username
  319. }
  320. }
  321. if processInfo.User != "" {
  322. r.logger.InfoContext(ctx, "found user: ", processInfo.User)
  323. } else {
  324. r.logger.InfoContext(ctx, "found user id: ", processInfo.UserId)
  325. }
  326. }
  327. metadata.ProcessInfo = processInfo
  328. }
  329. }
  330. if metadata.Destination.Addr.IsValid() && r.dnsTransport.FakeIP() != nil && r.dnsTransport.FakeIP().Store().Contains(metadata.Destination.Addr) {
  331. domain, loaded := r.dnsTransport.FakeIP().Store().Lookup(metadata.Destination.Addr)
  332. if !loaded {
  333. fatalErr = E.New("missing fakeip record, try enable `experimental.cache_file`")
  334. return
  335. }
  336. if domain != "" {
  337. metadata.OriginDestination = metadata.Destination
  338. metadata.Destination = M.Socksaddr{
  339. Fqdn: domain,
  340. Port: metadata.Destination.Port,
  341. }
  342. metadata.FakeIP = true
  343. r.logger.DebugContext(ctx, "found fakeip domain: ", domain)
  344. }
  345. } else if metadata.Domain == "" {
  346. domain, loaded := r.dns.LookupReverseMapping(metadata.Destination.Addr)
  347. if loaded {
  348. metadata.Domain = domain
  349. r.logger.DebugContext(ctx, "found reserve mapped domain: ", metadata.Domain)
  350. }
  351. }
  352. if metadata.Destination.IsIPv4() {
  353. metadata.IPVersion = 4
  354. } else if metadata.Destination.IsIPv6() {
  355. metadata.IPVersion = 6
  356. }
  357. //nolint:staticcheck
  358. if metadata.InboundOptions != common.DefaultValue[option.InboundOptions]() {
  359. if !preMatch && metadata.InboundOptions.SniffEnabled {
  360. newBuffer, newPackerBuffers, newErr := r.actionSniff(ctx, metadata, &rule.RuleActionSniff{
  361. OverrideDestination: metadata.InboundOptions.SniffOverrideDestination,
  362. Timeout: time.Duration(metadata.InboundOptions.SniffTimeout),
  363. }, inputConn, inputPacketConn)
  364. if newErr != nil {
  365. fatalErr = newErr
  366. return
  367. }
  368. if newBuffer != nil {
  369. buffers = []*buf.Buffer{newBuffer}
  370. } else if len(newPackerBuffers) > 0 {
  371. packetBuffers = newPackerBuffers
  372. }
  373. }
  374. if C.DomainStrategy(metadata.InboundOptions.DomainStrategy) != C.DomainStrategyAsIS {
  375. fatalErr = r.actionResolve(ctx, metadata, &rule.RuleActionResolve{
  376. Strategy: C.DomainStrategy(metadata.InboundOptions.DomainStrategy),
  377. })
  378. if fatalErr != nil {
  379. return
  380. }
  381. }
  382. if metadata.InboundOptions.UDPDisableDomainUnmapping {
  383. metadata.UDPDisableDomainUnmapping = true
  384. }
  385. metadata.InboundOptions = option.InboundOptions{}
  386. }
  387. match:
  388. for currentRuleIndex, currentRule := range r.rules {
  389. metadata.ResetRuleCache()
  390. if !currentRule.Match(metadata) {
  391. continue
  392. }
  393. if !preMatch {
  394. ruleDescription := currentRule.String()
  395. if ruleDescription != "" {
  396. r.logger.DebugContext(ctx, "match[", currentRuleIndex, "] ", currentRule, " => ", currentRule.Action())
  397. } else {
  398. r.logger.DebugContext(ctx, "match[", currentRuleIndex, "] => ", currentRule.Action())
  399. }
  400. } else {
  401. switch currentRule.Action().Type() {
  402. case C.RuleActionTypeReject:
  403. ruleDescription := currentRule.String()
  404. if ruleDescription != "" {
  405. r.logger.DebugContext(ctx, "pre-match[", currentRuleIndex, "] ", currentRule, " => ", currentRule.Action())
  406. } else {
  407. r.logger.DebugContext(ctx, "pre-match[", currentRuleIndex, "] => ", currentRule.Action())
  408. }
  409. }
  410. }
  411. var routeOptions *rule.RuleActionRouteOptions
  412. switch action := currentRule.Action().(type) {
  413. case *rule.RuleActionRoute:
  414. routeOptions = &action.RuleActionRouteOptions
  415. case *rule.RuleActionRouteOptions:
  416. routeOptions = action
  417. }
  418. if routeOptions != nil {
  419. // TODO: add nat
  420. if (routeOptions.OverrideAddress.IsValid() || routeOptions.OverridePort > 0) && !metadata.RouteOriginalDestination.IsValid() {
  421. metadata.RouteOriginalDestination = metadata.Destination
  422. }
  423. if routeOptions.OverrideAddress.IsValid() {
  424. metadata.Destination = M.Socksaddr{
  425. Addr: routeOptions.OverrideAddress.Addr,
  426. Port: metadata.Destination.Port,
  427. Fqdn: routeOptions.OverrideAddress.Fqdn,
  428. }
  429. }
  430. if routeOptions.OverridePort > 0 {
  431. metadata.Destination = M.Socksaddr{
  432. Addr: metadata.Destination.Addr,
  433. Port: routeOptions.OverridePort,
  434. Fqdn: metadata.Destination.Fqdn,
  435. }
  436. }
  437. if routeOptions.NetworkStrategy != nil {
  438. metadata.NetworkStrategy = routeOptions.NetworkStrategy
  439. }
  440. if len(routeOptions.NetworkType) > 0 {
  441. metadata.NetworkType = routeOptions.NetworkType
  442. }
  443. if len(routeOptions.FallbackNetworkType) > 0 {
  444. metadata.FallbackNetworkType = routeOptions.FallbackNetworkType
  445. }
  446. if routeOptions.FallbackDelay != 0 {
  447. metadata.FallbackDelay = routeOptions.FallbackDelay
  448. }
  449. if routeOptions.UDPDisableDomainUnmapping {
  450. metadata.UDPDisableDomainUnmapping = true
  451. }
  452. if routeOptions.UDPConnect {
  453. metadata.UDPConnect = true
  454. }
  455. if routeOptions.UDPTimeout > 0 {
  456. metadata.UDPTimeout = routeOptions.UDPTimeout
  457. }
  458. if routeOptions.TLSFragment {
  459. metadata.TLSFragment = true
  460. metadata.TLSFragmentFallbackDelay = routeOptions.TLSFragmentFallbackDelay
  461. }
  462. }
  463. switch action := currentRule.Action().(type) {
  464. case *rule.RuleActionSniff:
  465. if !preMatch {
  466. newBuffer, newPacketBuffers, newErr := r.actionSniff(ctx, metadata, action, inputConn, inputPacketConn)
  467. if newErr != nil {
  468. fatalErr = newErr
  469. return
  470. }
  471. if newBuffer != nil {
  472. buffers = append(buffers, newBuffer)
  473. } else if len(newPacketBuffers) > 0 {
  474. packetBuffers = append(packetBuffers, newPacketBuffers...)
  475. }
  476. } else {
  477. selectedRule = currentRule
  478. selectedRuleIndex = currentRuleIndex
  479. break match
  480. }
  481. case *rule.RuleActionResolve:
  482. fatalErr = r.actionResolve(ctx, metadata, action)
  483. if fatalErr != nil {
  484. return
  485. }
  486. }
  487. actionType := currentRule.Action().Type()
  488. if actionType == C.RuleActionTypeRoute ||
  489. actionType == C.RuleActionTypeReject ||
  490. actionType == C.RuleActionTypeHijackDNS ||
  491. (actionType == C.RuleActionTypeSniff && preMatch) {
  492. selectedRule = currentRule
  493. selectedRuleIndex = currentRuleIndex
  494. break match
  495. }
  496. }
  497. if !preMatch && inputPacketConn != nil && (metadata.InboundType == C.TypeSOCKS || metadata.InboundType == C.TypeMixed) && !metadata.Destination.IsFqdn() && !metadata.Destination.Addr.IsGlobalUnicast() {
  498. newBuffer, newPacketBuffers, newErr := r.actionSniff(ctx, metadata, &rule.RuleActionSniff{Timeout: C.TCPTimeout}, inputConn, inputPacketConn)
  499. if newErr != nil {
  500. fatalErr = newErr
  501. return
  502. }
  503. if newBuffer != nil {
  504. buffers = append(buffers, newBuffer)
  505. } else if len(newPacketBuffers) > 0 {
  506. packetBuffers = append(packetBuffers, newPacketBuffers...)
  507. }
  508. }
  509. return
  510. }
  511. func (r *Router) actionSniff(
  512. ctx context.Context, metadata *adapter.InboundContext, action *rule.RuleActionSniff,
  513. inputConn net.Conn, inputPacketConn N.PacketConn,
  514. ) (buffer *buf.Buffer, packetBuffers []*N.PacketBuffer, fatalErr error) {
  515. if sniff.Skip(metadata) {
  516. return
  517. } else if inputConn != nil {
  518. sniffBuffer := buf.NewPacket()
  519. var streamSniffers []sniff.StreamSniffer
  520. if len(action.StreamSniffers) > 0 {
  521. streamSniffers = action.StreamSniffers
  522. } else {
  523. streamSniffers = []sniff.StreamSniffer{
  524. sniff.TLSClientHello,
  525. sniff.HTTPHost,
  526. sniff.StreamDomainNameQuery,
  527. sniff.BitTorrent,
  528. sniff.SSH,
  529. sniff.RDP,
  530. }
  531. }
  532. err := sniff.PeekStream(
  533. ctx,
  534. metadata,
  535. inputConn,
  536. sniffBuffer,
  537. action.Timeout,
  538. streamSniffers...,
  539. )
  540. if err == nil {
  541. //goland:noinspection GoDeprecation
  542. if action.OverrideDestination && M.IsDomainName(metadata.Domain) {
  543. metadata.Destination = M.Socksaddr{
  544. Fqdn: metadata.Domain,
  545. Port: metadata.Destination.Port,
  546. }
  547. }
  548. if metadata.Domain != "" && metadata.Client != "" {
  549. r.logger.DebugContext(ctx, "sniffed protocol: ", metadata.Protocol, ", domain: ", metadata.Domain, ", client: ", metadata.Client)
  550. } else if metadata.Domain != "" {
  551. r.logger.DebugContext(ctx, "sniffed protocol: ", metadata.Protocol, ", domain: ", metadata.Domain)
  552. } else {
  553. r.logger.DebugContext(ctx, "sniffed protocol: ", metadata.Protocol)
  554. }
  555. }
  556. if !sniffBuffer.IsEmpty() {
  557. buffer = sniffBuffer
  558. } else {
  559. sniffBuffer.Release()
  560. }
  561. } else if inputPacketConn != nil {
  562. for {
  563. var (
  564. sniffBuffer = buf.NewPacket()
  565. destination M.Socksaddr
  566. done = make(chan struct{})
  567. err error
  568. )
  569. go func() {
  570. sniffTimeout := C.ReadPayloadTimeout
  571. if action.Timeout > 0 {
  572. sniffTimeout = action.Timeout
  573. }
  574. inputPacketConn.SetReadDeadline(time.Now().Add(sniffTimeout))
  575. destination, err = inputPacketConn.ReadPacket(sniffBuffer)
  576. inputPacketConn.SetReadDeadline(time.Time{})
  577. close(done)
  578. }()
  579. select {
  580. case <-done:
  581. case <-ctx.Done():
  582. inputPacketConn.Close()
  583. fatalErr = ctx.Err()
  584. return
  585. }
  586. if err != nil {
  587. sniffBuffer.Release()
  588. if !errors.Is(err, os.ErrDeadlineExceeded) {
  589. fatalErr = err
  590. return
  591. }
  592. } else {
  593. if (metadata.InboundType == C.TypeSOCKS || metadata.InboundType == C.TypeMixed) && !metadata.Destination.IsFqdn() && !metadata.Destination.Addr.IsGlobalUnicast() && !metadata.RouteOriginalDestination.IsValid() {
  594. metadata.Destination = destination
  595. }
  596. if len(packetBuffers) > 0 {
  597. err = sniff.PeekPacket(
  598. ctx,
  599. metadata,
  600. sniffBuffer.Bytes(),
  601. sniff.QUICClientHello,
  602. )
  603. } else {
  604. var packetSniffers []sniff.PacketSniffer
  605. if len(action.PacketSniffers) > 0 {
  606. packetSniffers = action.PacketSniffers
  607. } else {
  608. packetSniffers = []sniff.PacketSniffer{
  609. sniff.DomainNameQuery,
  610. sniff.QUICClientHello,
  611. sniff.STUNMessage,
  612. sniff.UTP,
  613. sniff.UDPTracker,
  614. sniff.DTLSRecord,
  615. }
  616. }
  617. err = sniff.PeekPacket(
  618. ctx, metadata,
  619. sniffBuffer.Bytes(),
  620. packetSniffers...,
  621. )
  622. }
  623. packetBuffer := N.NewPacketBuffer()
  624. *packetBuffer = N.PacketBuffer{
  625. Buffer: sniffBuffer,
  626. Destination: destination,
  627. }
  628. packetBuffers = append(packetBuffers, packetBuffer)
  629. if E.IsMulti(err, sniff.ErrClientHelloFragmented) && len(packetBuffers) == 0 {
  630. r.logger.DebugContext(ctx, "attempt to sniff fragmented QUIC client hello")
  631. continue
  632. }
  633. if metadata.Protocol != "" {
  634. //goland:noinspection GoDeprecation
  635. if action.OverrideDestination && M.IsDomainName(metadata.Domain) {
  636. metadata.Destination = M.Socksaddr{
  637. Fqdn: metadata.Domain,
  638. Port: metadata.Destination.Port,
  639. }
  640. }
  641. if metadata.Domain != "" && metadata.Client != "" {
  642. r.logger.DebugContext(ctx, "sniffed packet protocol: ", metadata.Protocol, ", domain: ", metadata.Domain, ", client: ", metadata.Client)
  643. } else if metadata.Domain != "" {
  644. r.logger.DebugContext(ctx, "sniffed packet protocol: ", metadata.Protocol, ", domain: ", metadata.Domain)
  645. } else if metadata.Client != "" {
  646. r.logger.DebugContext(ctx, "sniffed packet protocol: ", metadata.Protocol, ", client: ", metadata.Client)
  647. } else {
  648. r.logger.DebugContext(ctx, "sniffed packet protocol: ", metadata.Protocol)
  649. }
  650. }
  651. }
  652. break
  653. }
  654. }
  655. return
  656. }
  657. func (r *Router) actionResolve(ctx context.Context, metadata *adapter.InboundContext, action *rule.RuleActionResolve) error {
  658. if metadata.Destination.IsFqdn() {
  659. var transport adapter.DNSTransport
  660. if action.Server != "" {
  661. var loaded bool
  662. transport, loaded = r.dnsTransport.Transport(action.Server)
  663. if !loaded {
  664. return E.New("DNS server not found: ", action.Server)
  665. }
  666. }
  667. addresses, err := r.dns.Lookup(adapter.WithContext(ctx, metadata), metadata.Destination.Fqdn, adapter.DNSQueryOptions{
  668. Transport: transport,
  669. Strategy: action.Strategy,
  670. })
  671. if err != nil {
  672. return err
  673. }
  674. metadata.DestinationAddresses = addresses
  675. r.logger.DebugContext(ctx, "resolved [", strings.Join(F.MapToString(metadata.DestinationAddresses), " "), "]")
  676. if metadata.Destination.IsIPv4() {
  677. metadata.IPVersion = 4
  678. } else if metadata.Destination.IsIPv6() {
  679. metadata.IPVersion = 6
  680. }
  681. }
  682. return nil
  683. }