route.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689
  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-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) || R.IsRejected(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. //nolint:staticcheck
  58. if metadata.InboundDetour != "" {
  59. if metadata.LastInbound == metadata.InboundDetour {
  60. return E.New("routing loop on detour: ", metadata.InboundDetour)
  61. }
  62. detour, loaded := r.inbound.Get(metadata.InboundDetour)
  63. if !loaded {
  64. return E.New("inbound detour not found: ", metadata.InboundDetour)
  65. }
  66. injectable, isInjectable := detour.(adapter.TCPInjectableInbound)
  67. if !isInjectable {
  68. return E.New("inbound detour is not TCP injectable: ", metadata.InboundDetour)
  69. }
  70. metadata.LastInbound = metadata.Inbound
  71. metadata.Inbound = metadata.InboundDetour
  72. metadata.InboundDetour = ""
  73. injectable.NewConnectionEx(ctx, conn, metadata, onClose)
  74. return nil
  75. }
  76. conntrack.KillerCheck()
  77. metadata.Network = N.NetworkTCP
  78. switch metadata.Destination.Fqdn {
  79. case mux.Destination.Fqdn:
  80. return E.New("global multiplex is deprecated since sing-box v1.7.0, enable multiplex in Inbound fields instead.")
  81. case vmess.MuxDestination.Fqdn:
  82. return E.New("global multiplex (v2ray legacy) not supported since sing-box v1.7.0.")
  83. case uot.MagicAddress:
  84. return E.New("global UoT not supported since sing-box v1.7.0.")
  85. case uot.LegacyMagicAddress:
  86. return E.New("global UoT (legacy) not supported since sing-box v1.7.0.")
  87. }
  88. if deadline.NeedAdditionalReadDeadline(conn) {
  89. conn = deadline.NewConn(conn)
  90. }
  91. selectedRule, _, buffers, _, err := r.matchRule(ctx, &metadata, false, conn, nil)
  92. if err != nil {
  93. return err
  94. }
  95. var selectedOutbound adapter.Outbound
  96. if selectedRule != nil {
  97. switch action := selectedRule.Action().(type) {
  98. case *R.RuleActionRoute:
  99. var loaded bool
  100. selectedOutbound, loaded = r.outbound.Outbound(action.Outbound)
  101. if !loaded {
  102. buf.ReleaseMulti(buffers)
  103. return E.New("outbound not found: ", action.Outbound)
  104. }
  105. if !common.Contains(selectedOutbound.Network(), N.NetworkTCP) {
  106. buf.ReleaseMulti(buffers)
  107. return E.New("TCP is not supported by outbound: ", selectedOutbound.Tag())
  108. }
  109. case *R.RuleActionReject:
  110. buf.ReleaseMulti(buffers)
  111. N.CloseOnHandshakeFailure(conn, onClose, action.Error(ctx))
  112. return nil
  113. case *R.RuleActionHijackDNS:
  114. for _, buffer := range buffers {
  115. conn = bufio.NewCachedConn(conn, buffer)
  116. }
  117. N.CloseOnHandshakeFailure(conn, onClose, r.hijackDNSStream(ctx, conn, metadata))
  118. return nil
  119. }
  120. }
  121. if selectedRule == nil {
  122. defaultOutbound := r.outbound.Default()
  123. if !common.Contains(defaultOutbound.Network(), N.NetworkTCP) {
  124. buf.ReleaseMulti(buffers)
  125. return E.New("TCP is not supported by default outbound: ", defaultOutbound.Tag())
  126. }
  127. selectedOutbound = defaultOutbound
  128. }
  129. for _, buffer := range buffers {
  130. conn = bufio.NewCachedConn(conn, buffer)
  131. }
  132. for _, tracker := range r.trackers {
  133. conn = tracker.RoutedConnection(ctx, conn, metadata, selectedRule, selectedOutbound)
  134. }
  135. if outboundHandler, isHandler := selectedOutbound.(adapter.ConnectionHandlerEx); isHandler {
  136. outboundHandler.NewConnectionEx(ctx, conn, metadata, onClose)
  137. } else {
  138. r.connection.NewConnection(ctx, selectedOutbound, conn, metadata, onClose)
  139. }
  140. return nil
  141. }
  142. func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
  143. done := make(chan interface{})
  144. err := r.routePacketConnection(ctx, conn, metadata, N.OnceClose(func(it error) {
  145. close(done)
  146. }))
  147. if err != nil {
  148. conn.Close()
  149. if E.IsClosedOrCanceled(err) || R.IsRejected(err) {
  150. r.logger.DebugContext(ctx, "connection closed: ", err)
  151. } else {
  152. r.logger.ErrorContext(ctx, err)
  153. }
  154. }
  155. select {
  156. case <-done:
  157. case <-r.ctx.Done():
  158. }
  159. return nil
  160. }
  161. func (r *Router) RoutePacketConnectionEx(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) {
  162. err := r.routePacketConnection(ctx, conn, metadata, onClose)
  163. if err != nil {
  164. N.CloseOnHandshakeFailure(conn, onClose, err)
  165. if E.IsClosedOrCanceled(err) || R.IsRejected(err) {
  166. r.logger.DebugContext(ctx, "connection closed: ", err)
  167. } else {
  168. r.logger.ErrorContext(ctx, err)
  169. }
  170. }
  171. }
  172. func (r *Router) routePacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) error {
  173. //nolint:staticcheck
  174. if metadata.InboundDetour != "" {
  175. if metadata.LastInbound == metadata.InboundDetour {
  176. return E.New("routing loop on detour: ", metadata.InboundDetour)
  177. }
  178. detour, loaded := r.inbound.Get(metadata.InboundDetour)
  179. if !loaded {
  180. return E.New("inbound detour not found: ", metadata.InboundDetour)
  181. }
  182. injectable, isInjectable := detour.(adapter.UDPInjectableInbound)
  183. if !isInjectable {
  184. return E.New("inbound detour is not UDP injectable: ", metadata.InboundDetour)
  185. }
  186. metadata.LastInbound = metadata.Inbound
  187. metadata.Inbound = metadata.InboundDetour
  188. metadata.InboundDetour = ""
  189. injectable.NewPacketConnectionEx(ctx, conn, metadata, onClose)
  190. return nil
  191. }
  192. conntrack.KillerCheck()
  193. // TODO: move to UoT
  194. metadata.Network = N.NetworkUDP
  195. // Currently we don't have deadline usages for UDP connections
  196. /*if deadline.NeedAdditionalReadDeadline(conn) {
  197. conn = deadline.NewPacketConn(bufio.NewNetPacketConn(conn))
  198. }*/
  199. selectedRule, _, _, packetBuffers, err := r.matchRule(ctx, &metadata, false, nil, conn)
  200. if err != nil {
  201. return err
  202. }
  203. var selectedOutbound adapter.Outbound
  204. var selectReturn bool
  205. if selectedRule != nil {
  206. switch action := selectedRule.Action().(type) {
  207. case *R.RuleActionRoute:
  208. var loaded bool
  209. selectedOutbound, loaded = r.outbound.Outbound(action.Outbound)
  210. if !loaded {
  211. N.ReleaseMultiPacketBuffer(packetBuffers)
  212. return E.New("outbound not found: ", action.Outbound)
  213. }
  214. if !common.Contains(selectedOutbound.Network(), N.NetworkUDP) {
  215. N.ReleaseMultiPacketBuffer(packetBuffers)
  216. return E.New("UDP is not supported by outbound: ", selectedOutbound.Tag())
  217. }
  218. case *R.RuleActionReject:
  219. N.ReleaseMultiPacketBuffer(packetBuffers)
  220. N.CloseOnHandshakeFailure(conn, onClose, action.Error(ctx))
  221. return nil
  222. case *R.RuleActionHijackDNS:
  223. r.hijackDNSPacket(ctx, conn, packetBuffers, metadata, onClose)
  224. return nil
  225. }
  226. }
  227. if selectedRule == nil || selectReturn {
  228. defaultOutbound := r.outbound.Default()
  229. if !common.Contains(defaultOutbound.Network(), N.NetworkUDP) {
  230. N.ReleaseMultiPacketBuffer(packetBuffers)
  231. return E.New("UDP is not supported by outbound: ", defaultOutbound.Tag())
  232. }
  233. selectedOutbound = defaultOutbound
  234. }
  235. for _, buffer := range packetBuffers {
  236. conn = bufio.NewCachedPacketConn(conn, buffer.Buffer, buffer.Destination)
  237. N.PutPacketBuffer(buffer)
  238. }
  239. for _, tracker := range r.trackers {
  240. conn = tracker.RoutedPacketConnection(ctx, conn, metadata, selectedRule, selectedOutbound)
  241. }
  242. if metadata.FakeIP {
  243. conn = bufio.NewNATPacketConn(bufio.NewNetPacketConn(conn), metadata.OriginDestination, metadata.Destination)
  244. }
  245. if outboundHandler, isHandler := selectedOutbound.(adapter.PacketConnectionHandlerEx); isHandler {
  246. outboundHandler.NewPacketConnectionEx(ctx, conn, metadata, onClose)
  247. } else {
  248. r.connection.NewPacketConnection(ctx, selectedOutbound, conn, metadata, onClose)
  249. }
  250. return nil
  251. }
  252. func (r *Router) PreMatch(metadata adapter.InboundContext) error {
  253. selectedRule, _, _, _, err := r.matchRule(r.ctx, &metadata, true, nil, nil)
  254. if err != nil {
  255. return err
  256. }
  257. if selectedRule == nil {
  258. return nil
  259. }
  260. rejectAction, isReject := selectedRule.Action().(*R.RuleActionReject)
  261. if !isReject {
  262. return nil
  263. }
  264. return rejectAction.Error(context.Background())
  265. }
  266. func (r *Router) matchRule(
  267. ctx context.Context, metadata *adapter.InboundContext, preMatch bool,
  268. inputConn net.Conn, inputPacketConn N.PacketConn,
  269. ) (
  270. selectedRule adapter.Rule, selectedRuleIndex int,
  271. buffers []*buf.Buffer, packetBuffers []*N.PacketBuffer, fatalErr error,
  272. ) {
  273. if r.processSearcher != nil && metadata.ProcessInfo == nil {
  274. var originDestination netip.AddrPort
  275. if metadata.OriginDestination.IsValid() {
  276. originDestination = metadata.OriginDestination.AddrPort()
  277. } else if metadata.Destination.IsIP() {
  278. originDestination = metadata.Destination.AddrPort()
  279. }
  280. processInfo, fErr := process.FindProcessInfo(r.processSearcher, ctx, metadata.Network, metadata.Source.AddrPort(), originDestination)
  281. if fErr != nil {
  282. r.logger.InfoContext(ctx, "failed to search process: ", fErr)
  283. } else {
  284. if processInfo.ProcessPath != "" {
  285. r.logger.InfoContext(ctx, "found process path: ", processInfo.ProcessPath)
  286. } else if processInfo.PackageName != "" {
  287. r.logger.InfoContext(ctx, "found package name: ", processInfo.PackageName)
  288. } else if processInfo.UserId != -1 {
  289. if /*needUserName &&*/ true {
  290. osUser, _ := user.LookupId(F.ToString(processInfo.UserId))
  291. if osUser != nil {
  292. processInfo.User = osUser.Username
  293. }
  294. }
  295. if processInfo.User != "" {
  296. r.logger.InfoContext(ctx, "found user: ", processInfo.User)
  297. } else {
  298. r.logger.InfoContext(ctx, "found user id: ", processInfo.UserId)
  299. }
  300. }
  301. metadata.ProcessInfo = processInfo
  302. }
  303. }
  304. if metadata.Destination.Addr.IsValid() && r.dnsTransport.FakeIP() != nil && r.dnsTransport.FakeIP().Store().Contains(metadata.Destination.Addr) {
  305. domain, loaded := r.dnsTransport.FakeIP().Store().Lookup(metadata.Destination.Addr)
  306. if !loaded {
  307. fatalErr = E.New("missing fakeip record, try enable `experimental.cache_file`")
  308. return
  309. }
  310. if domain != "" {
  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. } else if metadata.Domain == "" {
  320. domain, loaded := r.dns.LookupReverseMapping(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 C.DomainStrategy(metadata.InboundOptions.DomainStrategy) != C.DomainStrategyAsIS {
  349. fatalErr = r.actionResolve(ctx, metadata, &R.RuleActionResolve{
  350. Strategy: C.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. if routeOptions.TLSFragment {
  434. metadata.TLSFragment = true
  435. metadata.TLSFragmentFallbackDelay = routeOptions.TLSFragmentFallbackDelay
  436. }
  437. if routeOptions.TLSRecordFragment {
  438. metadata.TLSRecordFragment = true
  439. }
  440. }
  441. switch action := currentRule.Action().(type) {
  442. case *R.RuleActionSniff:
  443. if !preMatch {
  444. newBuffer, newPacketBuffers, newErr := r.actionSniff(ctx, metadata, action, inputConn, inputPacketConn, buffers)
  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 *R.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. return
  476. }
  477. func (r *Router) actionSniff(
  478. ctx context.Context, metadata *adapter.InboundContext, action *R.RuleActionSniff,
  479. inputConn net.Conn, inputPacketConn N.PacketConn, inputBuffers []*buf.Buffer,
  480. ) (buffer *buf.Buffer, packetBuffers []*N.PacketBuffer, fatalErr error) {
  481. if sniff.Skip(metadata) {
  482. r.logger.DebugContext(ctx, "sniff skipped due to port considered as server-first")
  483. return
  484. } else if metadata.Protocol != "" {
  485. r.logger.DebugContext(ctx, "duplicate sniff skipped")
  486. return
  487. }
  488. if inputConn != nil {
  489. if len(action.StreamSniffers) == 0 && len(action.PacketSniffers) > 0 {
  490. return
  491. } else if metadata.SniffError != nil && !errors.Is(metadata.SniffError, sniff.ErrNeedMoreData) {
  492. r.logger.DebugContext(ctx, "packet sniff skipped due to previous error: ", metadata.SniffError)
  493. return
  494. }
  495. var streamSniffers []sniff.StreamSniffer
  496. if len(action.StreamSniffers) > 0 {
  497. streamSniffers = action.StreamSniffers
  498. } else {
  499. streamSniffers = []sniff.StreamSniffer{
  500. sniff.TLSClientHello,
  501. sniff.HTTPHost,
  502. sniff.StreamDomainNameQuery,
  503. sniff.BitTorrent,
  504. sniff.SSH,
  505. sniff.RDP,
  506. }
  507. }
  508. sniffBuffer := buf.NewPacket()
  509. err := sniff.PeekStream(
  510. ctx,
  511. metadata,
  512. inputConn,
  513. inputBuffers,
  514. sniffBuffer,
  515. action.Timeout,
  516. streamSniffers...,
  517. )
  518. metadata.SniffError = err
  519. if err == nil {
  520. //goland:noinspection GoDeprecation
  521. if action.OverrideDestination && M.IsDomainName(metadata.Domain) {
  522. metadata.Destination = M.Socksaddr{
  523. Fqdn: metadata.Domain,
  524. Port: metadata.Destination.Port,
  525. }
  526. }
  527. if metadata.Domain != "" && metadata.Client != "" {
  528. r.logger.DebugContext(ctx, "sniffed protocol: ", metadata.Protocol, ", domain: ", metadata.Domain, ", client: ", metadata.Client)
  529. } else if metadata.Domain != "" {
  530. r.logger.DebugContext(ctx, "sniffed protocol: ", metadata.Protocol, ", domain: ", metadata.Domain)
  531. } else {
  532. r.logger.DebugContext(ctx, "sniffed protocol: ", metadata.Protocol)
  533. }
  534. }
  535. if !sniffBuffer.IsEmpty() {
  536. buffer = sniffBuffer
  537. } else {
  538. sniffBuffer.Release()
  539. }
  540. } else if inputPacketConn != nil {
  541. if len(action.PacketSniffers) == 0 && len(action.StreamSniffers) > 0 {
  542. return
  543. } else if metadata.SniffError != nil && !errors.Is(metadata.SniffError, sniff.ErrNeedMoreData) {
  544. r.logger.DebugContext(ctx, "packet sniff skipped due to previous error: ", metadata.SniffError)
  545. return
  546. }
  547. var packetSniffers []sniff.PacketSniffer
  548. if len(action.PacketSniffers) > 0 {
  549. packetSniffers = action.PacketSniffers
  550. } else {
  551. packetSniffers = []sniff.PacketSniffer{
  552. sniff.DomainNameQuery,
  553. sniff.QUICClientHello,
  554. sniff.STUNMessage,
  555. sniff.UTP,
  556. sniff.UDPTracker,
  557. sniff.DTLSRecord,
  558. sniff.NTP,
  559. }
  560. }
  561. for {
  562. var (
  563. sniffBuffer = buf.NewPacket()
  564. destination M.Socksaddr
  565. done = make(chan struct{})
  566. err error
  567. )
  568. go func() {
  569. sniffTimeout := C.ReadPayloadTimeout
  570. if action.Timeout > 0 {
  571. sniffTimeout = action.Timeout
  572. }
  573. inputPacketConn.SetReadDeadline(time.Now().Add(sniffTimeout))
  574. destination, err = inputPacketConn.ReadPacket(sniffBuffer)
  575. inputPacketConn.SetReadDeadline(time.Time{})
  576. close(done)
  577. }()
  578. select {
  579. case <-done:
  580. case <-ctx.Done():
  581. inputPacketConn.Close()
  582. fatalErr = ctx.Err()
  583. return
  584. }
  585. if err != nil {
  586. sniffBuffer.Release()
  587. if !errors.Is(err, os.ErrDeadlineExceeded) {
  588. fatalErr = err
  589. return
  590. }
  591. } else {
  592. if len(packetBuffers) > 0 || metadata.SniffError != nil {
  593. err = sniff.PeekPacket(
  594. ctx,
  595. metadata,
  596. sniffBuffer.Bytes(),
  597. sniff.QUICClientHello,
  598. )
  599. } else {
  600. err = sniff.PeekPacket(
  601. ctx, metadata,
  602. sniffBuffer.Bytes(),
  603. packetSniffers...,
  604. )
  605. }
  606. packetBuffer := N.NewPacketBuffer()
  607. *packetBuffer = N.PacketBuffer{
  608. Buffer: sniffBuffer,
  609. Destination: destination,
  610. }
  611. packetBuffers = append(packetBuffers, packetBuffer)
  612. metadata.SniffError = err
  613. if errors.Is(err, sniff.ErrNeedMoreData) {
  614. // TODO: replace with generic message when there are more multi-packet protocols
  615. r.logger.DebugContext(ctx, "attempt to sniff fragmented QUIC client hello")
  616. continue
  617. }
  618. if metadata.Protocol != "" {
  619. //goland:noinspection GoDeprecation
  620. if action.OverrideDestination && M.IsDomainName(metadata.Domain) {
  621. metadata.Destination = M.Socksaddr{
  622. Fqdn: metadata.Domain,
  623. Port: metadata.Destination.Port,
  624. }
  625. }
  626. if metadata.Domain != "" && metadata.Client != "" {
  627. r.logger.DebugContext(ctx, "sniffed packet protocol: ", metadata.Protocol, ", domain: ", metadata.Domain, ", client: ", metadata.Client)
  628. } else if metadata.Domain != "" {
  629. r.logger.DebugContext(ctx, "sniffed packet protocol: ", metadata.Protocol, ", domain: ", metadata.Domain)
  630. } else if metadata.Client != "" {
  631. r.logger.DebugContext(ctx, "sniffed packet protocol: ", metadata.Protocol, ", client: ", metadata.Client)
  632. } else {
  633. r.logger.DebugContext(ctx, "sniffed packet protocol: ", metadata.Protocol)
  634. }
  635. }
  636. }
  637. break
  638. }
  639. }
  640. return
  641. }
  642. func (r *Router) actionResolve(ctx context.Context, metadata *adapter.InboundContext, action *R.RuleActionResolve) error {
  643. if metadata.Destination.IsFqdn() {
  644. var transport adapter.DNSTransport
  645. if action.Server != "" {
  646. var loaded bool
  647. transport, loaded = r.dnsTransport.Transport(action.Server)
  648. if !loaded {
  649. return E.New("DNS server not found: ", action.Server)
  650. }
  651. }
  652. addresses, err := r.dns.Lookup(adapter.WithContext(ctx, metadata), metadata.Destination.Fqdn, adapter.DNSQueryOptions{
  653. Transport: transport,
  654. Strategy: action.Strategy,
  655. DisableCache: action.DisableCache,
  656. RewriteTTL: action.RewriteTTL,
  657. ClientSubnet: action.ClientSubnet,
  658. })
  659. if err != nil {
  660. return err
  661. }
  662. metadata.DestinationAddresses = addresses
  663. r.logger.DebugContext(ctx, "resolved [", strings.Join(F.MapToString(metadata.DestinationAddresses), " "), "]")
  664. if metadata.Destination.IsIPv4() {
  665. metadata.IPVersion = 4
  666. } else if metadata.Destination.IsIPv6() {
  667. metadata.IPVersion = 6
  668. }
  669. }
  670. return nil
  671. }