route.go 22 KB

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