1
0

route.go 22 KB

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