route.go 22 KB

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