route.go 21 KB

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