route.go 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815
  1. package route
  2. import (
  3. "context"
  4. "errors"
  5. "net"
  6. "net/netip"
  7. "strings"
  8. "time"
  9. "github.com/sagernet/sing-box/adapter"
  10. "github.com/sagernet/sing-box/common/sniff"
  11. C "github.com/sagernet/sing-box/constant"
  12. R "github.com/sagernet/sing-box/route/rule"
  13. "github.com/sagernet/sing-mux"
  14. "github.com/sagernet/sing-tun"
  15. "github.com/sagernet/sing-tun/ping"
  16. "github.com/sagernet/sing-vmess"
  17. "github.com/sagernet/sing/common"
  18. "github.com/sagernet/sing/common/buf"
  19. "github.com/sagernet/sing/common/bufio"
  20. "github.com/sagernet/sing/common/bufio/deadline"
  21. E "github.com/sagernet/sing/common/exceptions"
  22. F "github.com/sagernet/sing/common/format"
  23. M "github.com/sagernet/sing/common/metadata"
  24. N "github.com/sagernet/sing/common/network"
  25. "github.com/sagernet/sing/common/uot"
  26. "golang.org/x/exp/slices"
  27. )
  28. // Deprecated: use RouteConnectionEx instead.
  29. func (r *Router) RouteConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
  30. done := make(chan interface{})
  31. err := r.routeConnection(ctx, conn, metadata, N.OnceClose(func(it error) {
  32. close(done)
  33. }))
  34. if err != nil {
  35. return err
  36. }
  37. select {
  38. case <-done:
  39. case <-r.ctx.Done():
  40. }
  41. return nil
  42. }
  43. func (r *Router) RouteConnectionEx(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) {
  44. err := r.routeConnection(ctx, conn, metadata, onClose)
  45. if err != nil {
  46. N.CloseOnHandshakeFailure(conn, onClose, err)
  47. if E.IsClosedOrCanceled(err) || R.IsRejected(err) {
  48. r.logger.DebugContext(ctx, "connection closed: ", err)
  49. } else {
  50. r.logger.ErrorContext(ctx, err)
  51. }
  52. }
  53. }
  54. func (r *Router) routeConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) error {
  55. //nolint:staticcheck
  56. if metadata.InboundDetour != "" {
  57. if metadata.LastInbound == metadata.InboundDetour {
  58. return E.New("routing loop on detour: ", metadata.InboundDetour)
  59. }
  60. detour, loaded := r.inbound.Get(metadata.InboundDetour)
  61. if !loaded {
  62. return E.New("inbound detour not found: ", metadata.InboundDetour)
  63. }
  64. injectable, isInjectable := detour.(adapter.TCPInjectableInbound)
  65. if !isInjectable {
  66. return E.New("inbound detour is not TCP injectable: ", metadata.InboundDetour)
  67. }
  68. metadata.LastInbound = metadata.Inbound
  69. metadata.Inbound = metadata.InboundDetour
  70. metadata.InboundDetour = ""
  71. injectable.NewConnectionEx(ctx, conn, metadata, onClose)
  72. return nil
  73. }
  74. metadata.Network = N.NetworkTCP
  75. switch metadata.Destination.Fqdn {
  76. case mux.Destination.Fqdn:
  77. return E.New("global multiplex is deprecated since sing-box v1.7.0, enable multiplex in Inbound fields instead.")
  78. case vmess.MuxDestination.Fqdn:
  79. return E.New("global multiplex (v2ray legacy) not supported since sing-box v1.7.0.")
  80. case uot.MagicAddress:
  81. return E.New("global UoT not supported since sing-box v1.7.0.")
  82. case uot.LegacyMagicAddress:
  83. return E.New("global UoT (legacy) not supported since sing-box v1.7.0.")
  84. }
  85. if deadline.NeedAdditionalReadDeadline(conn) {
  86. conn = deadline.NewConn(conn)
  87. }
  88. selectedRule, _, buffers, _, err := r.matchRule(ctx, &metadata, false, false, conn, nil)
  89. if err != nil {
  90. return err
  91. }
  92. var selectedOutbound adapter.Outbound
  93. if selectedRule != nil {
  94. switch action := selectedRule.Action().(type) {
  95. case *R.RuleActionRoute:
  96. var loaded bool
  97. selectedOutbound, loaded = r.outbound.Outbound(action.Outbound)
  98. if !loaded {
  99. buf.ReleaseMulti(buffers)
  100. return E.New("outbound not found: ", action.Outbound)
  101. }
  102. if !common.Contains(selectedOutbound.Network(), N.NetworkTCP) {
  103. buf.ReleaseMulti(buffers)
  104. return E.New("TCP is not supported by outbound: ", selectedOutbound.Tag())
  105. }
  106. case *R.RuleActionBypass:
  107. if action.Outbound == "" {
  108. break
  109. }
  110. var loaded bool
  111. selectedOutbound, loaded = r.outbound.Outbound(action.Outbound)
  112. if !loaded {
  113. buf.ReleaseMulti(buffers)
  114. return E.New("outbound not found: ", action.Outbound)
  115. }
  116. if !common.Contains(selectedOutbound.Network(), N.NetworkTCP) {
  117. buf.ReleaseMulti(buffers)
  118. return E.New("TCP is not supported by outbound: ", selectedOutbound.Tag())
  119. }
  120. case *R.RuleActionReject:
  121. buf.ReleaseMulti(buffers)
  122. if action.Method == C.RuleActionRejectMethodReply {
  123. return E.New("reject method `reply` is not supported for TCP connections")
  124. }
  125. return action.Error(ctx)
  126. case *R.RuleActionHijackDNS:
  127. for _, buffer := range buffers {
  128. conn = bufio.NewCachedConn(conn, buffer)
  129. }
  130. N.CloseOnHandshakeFailure(conn, onClose, r.hijackDNSStream(ctx, conn, metadata))
  131. return nil
  132. }
  133. }
  134. if selectedRule == nil {
  135. defaultOutbound := r.outbound.Default()
  136. if !common.Contains(defaultOutbound.Network(), N.NetworkTCP) {
  137. buf.ReleaseMulti(buffers)
  138. return E.New("TCP is not supported by default outbound: ", defaultOutbound.Tag())
  139. }
  140. selectedOutbound = defaultOutbound
  141. }
  142. for _, buffer := range buffers {
  143. conn = bufio.NewCachedConn(conn, buffer)
  144. }
  145. for _, tracker := range r.trackers {
  146. conn = tracker.RoutedConnection(ctx, conn, metadata, selectedRule, selectedOutbound)
  147. }
  148. if outboundHandler, isHandler := selectedOutbound.(adapter.ConnectionHandlerEx); isHandler {
  149. outboundHandler.NewConnectionEx(ctx, conn, metadata, onClose)
  150. } else {
  151. r.connection.NewConnection(ctx, selectedOutbound, conn, metadata, onClose)
  152. }
  153. return nil
  154. }
  155. func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
  156. done := make(chan interface{})
  157. err := r.routePacketConnection(ctx, conn, metadata, N.OnceClose(func(it error) {
  158. close(done)
  159. }))
  160. if err != nil {
  161. conn.Close()
  162. if E.IsClosedOrCanceled(err) || R.IsRejected(err) {
  163. r.logger.DebugContext(ctx, "connection closed: ", err)
  164. } else {
  165. r.logger.ErrorContext(ctx, err)
  166. }
  167. }
  168. select {
  169. case <-done:
  170. case <-r.ctx.Done():
  171. }
  172. return nil
  173. }
  174. func (r *Router) RoutePacketConnectionEx(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) {
  175. err := r.routePacketConnection(ctx, conn, metadata, onClose)
  176. if err != nil {
  177. N.CloseOnHandshakeFailure(conn, onClose, err)
  178. if E.IsClosedOrCanceled(err) || R.IsRejected(err) {
  179. r.logger.DebugContext(ctx, "connection closed: ", err)
  180. } else {
  181. r.logger.ErrorContext(ctx, err)
  182. }
  183. }
  184. }
  185. func (r *Router) routePacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) error {
  186. //nolint:staticcheck
  187. if metadata.InboundDetour != "" {
  188. if metadata.LastInbound == metadata.InboundDetour {
  189. return E.New("routing loop on detour: ", metadata.InboundDetour)
  190. }
  191. detour, loaded := r.inbound.Get(metadata.InboundDetour)
  192. if !loaded {
  193. return E.New("inbound detour not found: ", metadata.InboundDetour)
  194. }
  195. injectable, isInjectable := detour.(adapter.UDPInjectableInbound)
  196. if !isInjectable {
  197. return E.New("inbound detour is not UDP injectable: ", metadata.InboundDetour)
  198. }
  199. metadata.LastInbound = metadata.Inbound
  200. metadata.Inbound = metadata.InboundDetour
  201. metadata.InboundDetour = ""
  202. injectable.NewPacketConnectionEx(ctx, conn, metadata, onClose)
  203. return nil
  204. }
  205. // TODO: move to UoT
  206. metadata.Network = N.NetworkUDP
  207. // Currently we don't have deadline usages for UDP connections
  208. /*if deadline.NeedAdditionalReadDeadline(conn) {
  209. conn = deadline.NewPacketConn(bufio.NewNetPacketConn(conn))
  210. }*/
  211. selectedRule, _, _, packetBuffers, err := r.matchRule(ctx, &metadata, false, false, nil, conn)
  212. if err != nil {
  213. return err
  214. }
  215. var selectedOutbound adapter.Outbound
  216. var selectReturn bool
  217. if selectedRule != nil {
  218. switch action := selectedRule.Action().(type) {
  219. case *R.RuleActionRoute:
  220. var loaded bool
  221. selectedOutbound, loaded = r.outbound.Outbound(action.Outbound)
  222. if !loaded {
  223. N.ReleaseMultiPacketBuffer(packetBuffers)
  224. return E.New("outbound not found: ", action.Outbound)
  225. }
  226. if !common.Contains(selectedOutbound.Network(), N.NetworkUDP) {
  227. N.ReleaseMultiPacketBuffer(packetBuffers)
  228. return E.New("UDP is not supported by outbound: ", selectedOutbound.Tag())
  229. }
  230. case *R.RuleActionBypass:
  231. if action.Outbound == "" {
  232. break
  233. }
  234. var loaded bool
  235. selectedOutbound, loaded = r.outbound.Outbound(action.Outbound)
  236. if !loaded {
  237. N.ReleaseMultiPacketBuffer(packetBuffers)
  238. return E.New("outbound not found: ", action.Outbound)
  239. }
  240. if !common.Contains(selectedOutbound.Network(), N.NetworkUDP) {
  241. N.ReleaseMultiPacketBuffer(packetBuffers)
  242. return E.New("UDP is not supported by outbound: ", selectedOutbound.Tag())
  243. }
  244. case *R.RuleActionReject:
  245. N.ReleaseMultiPacketBuffer(packetBuffers)
  246. if action.Method == C.RuleActionRejectMethodReply {
  247. return E.New("reject method `reply` is not supported for UDP connections")
  248. }
  249. return action.Error(ctx)
  250. case *R.RuleActionHijackDNS:
  251. return r.hijackDNSPacket(ctx, conn, packetBuffers, metadata, onClose)
  252. }
  253. }
  254. if selectedRule == nil || selectReturn {
  255. defaultOutbound := r.outbound.Default()
  256. if !common.Contains(defaultOutbound.Network(), N.NetworkUDP) {
  257. N.ReleaseMultiPacketBuffer(packetBuffers)
  258. return E.New("UDP is not supported by outbound: ", defaultOutbound.Tag())
  259. }
  260. selectedOutbound = defaultOutbound
  261. }
  262. for _, buffer := range packetBuffers {
  263. conn = bufio.NewCachedPacketConn(conn, buffer.Buffer, buffer.Destination)
  264. N.PutPacketBuffer(buffer)
  265. }
  266. for _, tracker := range r.trackers {
  267. conn = tracker.RoutedPacketConnection(ctx, conn, metadata, selectedRule, selectedOutbound)
  268. }
  269. if metadata.FakeIP {
  270. conn = bufio.NewNATPacketConn(bufio.NewNetPacketConn(conn), metadata.OriginDestination, metadata.Destination)
  271. }
  272. if outboundHandler, isHandler := selectedOutbound.(adapter.PacketConnectionHandlerEx); isHandler {
  273. outboundHandler.NewPacketConnectionEx(ctx, conn, metadata, onClose)
  274. } else {
  275. r.connection.NewPacketConnection(ctx, selectedOutbound, conn, metadata, onClose)
  276. }
  277. return nil
  278. }
  279. func (r *Router) PreMatch(metadata adapter.InboundContext, routeContext tun.DirectRouteContext, timeout time.Duration, supportBypass bool) (tun.DirectRouteDestination, error) {
  280. selectedRule, _, _, _, err := r.matchRule(r.ctx, &metadata, true, supportBypass, nil, nil)
  281. if err != nil {
  282. return nil, err
  283. }
  284. var directRouteOutbound adapter.DirectRouteOutbound
  285. if selectedRule != nil {
  286. switch action := selectedRule.Action().(type) {
  287. case *R.RuleActionReject:
  288. switch metadata.Network {
  289. case N.NetworkTCP:
  290. if action.Method == C.RuleActionRejectMethodReply {
  291. return nil, E.New("reject method `reply` is not supported for TCP connections")
  292. }
  293. case N.NetworkUDP:
  294. if action.Method == C.RuleActionRejectMethodReply {
  295. return nil, E.New("reject method `reply` is not supported for UDP connections")
  296. }
  297. }
  298. return nil, action.Error(context.Background())
  299. case *R.RuleActionBypass:
  300. if supportBypass {
  301. return nil, &R.BypassedError{Cause: tun.ErrBypass}
  302. }
  303. if routeContext == nil {
  304. return nil, nil
  305. }
  306. outbound, loaded := r.outbound.Outbound(action.Outbound)
  307. if !loaded {
  308. return nil, E.New("outbound not found: ", action.Outbound)
  309. }
  310. if !common.Contains(outbound.Network(), metadata.Network) {
  311. return nil, E.New(metadata.Network, " is not supported by outbound: ", action.Outbound)
  312. }
  313. directRouteOutbound = outbound.(adapter.DirectRouteOutbound)
  314. case *R.RuleActionRoute:
  315. if routeContext == nil {
  316. return nil, nil
  317. }
  318. outbound, loaded := r.outbound.Outbound(action.Outbound)
  319. if !loaded {
  320. return nil, E.New("outbound not found: ", action.Outbound)
  321. }
  322. if !common.Contains(outbound.Network(), metadata.Network) {
  323. return nil, E.New(metadata.Network, " is not supported by outbound: ", action.Outbound)
  324. }
  325. directRouteOutbound = outbound.(adapter.DirectRouteOutbound)
  326. }
  327. }
  328. if directRouteOutbound == nil {
  329. if selectedRule != nil || metadata.Network != N.NetworkICMP {
  330. return nil, nil
  331. }
  332. defaultOutbound := r.outbound.Default()
  333. if !common.Contains(defaultOutbound.Network(), metadata.Network) {
  334. return nil, E.New(metadata.Network, " is not supported by default outbound: ", defaultOutbound.Tag())
  335. }
  336. directRouteOutbound = defaultOutbound.(adapter.DirectRouteOutbound)
  337. }
  338. if metadata.Destination.IsDomain() {
  339. if len(metadata.DestinationAddresses) == 0 {
  340. var strategy C.DomainStrategy
  341. if metadata.Source.IsIPv4() {
  342. strategy = C.DomainStrategyIPv4Only
  343. } else {
  344. strategy = C.DomainStrategyIPv6Only
  345. }
  346. err = r.actionResolve(r.ctx, &metadata, &R.RuleActionResolve{
  347. Strategy: strategy,
  348. })
  349. if err != nil {
  350. return nil, err
  351. }
  352. }
  353. var newDestination netip.Addr
  354. if metadata.Source.IsIPv4() {
  355. for _, address := range metadata.DestinationAddresses {
  356. if address.Is4() {
  357. newDestination = address
  358. break
  359. }
  360. }
  361. } else {
  362. for _, address := range metadata.DestinationAddresses {
  363. if address.Is6() {
  364. newDestination = address
  365. break
  366. }
  367. }
  368. }
  369. if !newDestination.IsValid() {
  370. if metadata.Source.IsIPv4() {
  371. return nil, E.New("no IPv4 address found for domain: ", metadata.Destination.Fqdn)
  372. } else {
  373. return nil, E.New("no IPv6 address found for domain: ", metadata.Destination.Fqdn)
  374. }
  375. }
  376. metadata.Destination = M.Socksaddr{
  377. Addr: newDestination,
  378. }
  379. routeContext = ping.NewContextDestinationWriter(routeContext, metadata.OriginDestination.Addr)
  380. var routeDestination tun.DirectRouteDestination
  381. routeDestination, err = directRouteOutbound.NewDirectRouteConnection(metadata, routeContext, timeout)
  382. if err != nil {
  383. return nil, err
  384. }
  385. return ping.NewDestinationWriter(routeDestination, newDestination), nil
  386. }
  387. return directRouteOutbound.NewDirectRouteConnection(metadata, routeContext, timeout)
  388. }
  389. func (r *Router) matchRule(
  390. ctx context.Context, metadata *adapter.InboundContext, preMatch bool, supportBypass bool,
  391. inputConn net.Conn, inputPacketConn N.PacketConn,
  392. ) (
  393. selectedRule adapter.Rule, selectedRuleIndex int,
  394. buffers []*buf.Buffer, packetBuffers []*N.PacketBuffer, fatalErr error,
  395. ) {
  396. if r.processSearcher != nil && metadata.ProcessInfo == nil {
  397. var originDestination netip.AddrPort
  398. if metadata.OriginDestination.IsValid() {
  399. originDestination = metadata.OriginDestination.AddrPort()
  400. } else if metadata.Destination.IsIP() {
  401. originDestination = metadata.Destination.AddrPort()
  402. }
  403. processInfo, fErr := r.findProcessInfoCached(ctx, metadata.Network, metadata.Source.AddrPort(), originDestination)
  404. if fErr != nil {
  405. r.logger.InfoContext(ctx, "failed to search process: ", fErr)
  406. } else {
  407. if processInfo.ProcessPath != "" {
  408. if processInfo.UserName != "" {
  409. r.logger.InfoContext(ctx, "found process path: ", processInfo.ProcessPath, ", user: ", processInfo.UserName)
  410. } else if processInfo.UserId != -1 {
  411. r.logger.InfoContext(ctx, "found process path: ", processInfo.ProcessPath, ", user id: ", processInfo.UserId)
  412. } else {
  413. r.logger.InfoContext(ctx, "found process path: ", processInfo.ProcessPath)
  414. }
  415. } else if len(processInfo.AndroidPackageNames) > 0 {
  416. r.logger.InfoContext(ctx, "found package name: ", strings.Join(processInfo.AndroidPackageNames, ", "))
  417. } else if processInfo.UserId != -1 {
  418. if processInfo.UserName != "" {
  419. r.logger.InfoContext(ctx, "found user: ", processInfo.UserName)
  420. } else {
  421. r.logger.InfoContext(ctx, "found user id: ", processInfo.UserId)
  422. }
  423. }
  424. metadata.ProcessInfo = processInfo
  425. }
  426. }
  427. if metadata.Destination.Addr.IsValid() && r.dnsTransport.FakeIP() != nil && r.dnsTransport.FakeIP().Store().Contains(metadata.Destination.Addr) {
  428. domain, loaded := r.dnsTransport.FakeIP().Store().Lookup(metadata.Destination.Addr)
  429. if !loaded {
  430. fatalErr = E.New("missing fakeip record, try enable `experimental.cache_file`")
  431. return
  432. }
  433. if domain != "" {
  434. metadata.OriginDestination = metadata.Destination
  435. metadata.Destination = M.Socksaddr{
  436. Fqdn: domain,
  437. Port: metadata.Destination.Port,
  438. }
  439. metadata.FakeIP = true
  440. r.logger.DebugContext(ctx, "found fakeip domain: ", domain)
  441. }
  442. } else if metadata.Domain == "" {
  443. domain, loaded := r.dns.LookupReverseMapping(metadata.Destination.Addr)
  444. if loaded {
  445. metadata.Domain = domain
  446. r.logger.DebugContext(ctx, "found reserve mapped domain: ", metadata.Domain)
  447. }
  448. }
  449. if metadata.Destination.IsIPv4() {
  450. metadata.IPVersion = 4
  451. } else if metadata.Destination.IsIPv6() {
  452. metadata.IPVersion = 6
  453. }
  454. match:
  455. for currentRuleIndex, currentRule := range r.rules {
  456. metadata.ResetRuleCache()
  457. if !currentRule.Match(metadata) {
  458. continue
  459. }
  460. if !preMatch {
  461. ruleDescription := currentRule.String()
  462. if ruleDescription != "" {
  463. r.logger.DebugContext(ctx, "match[", currentRuleIndex, "] ", currentRule, " => ", currentRule.Action())
  464. } else {
  465. r.logger.DebugContext(ctx, "match[", currentRuleIndex, "] => ", currentRule.Action())
  466. }
  467. } else {
  468. switch currentRule.Action().Type() {
  469. case C.RuleActionTypeReject:
  470. ruleDescription := currentRule.String()
  471. if ruleDescription != "" {
  472. r.logger.DebugContext(ctx, "pre-match[", currentRuleIndex, "] ", currentRule, " => ", currentRule.Action())
  473. } else {
  474. r.logger.DebugContext(ctx, "pre-match[", currentRuleIndex, "] => ", currentRule.Action())
  475. }
  476. }
  477. }
  478. var routeOptions *R.RuleActionRouteOptions
  479. switch action := currentRule.Action().(type) {
  480. case *R.RuleActionRoute:
  481. routeOptions = &action.RuleActionRouteOptions
  482. case *R.RuleActionRouteOptions:
  483. routeOptions = action
  484. }
  485. if routeOptions != nil {
  486. // TODO: add nat
  487. if (routeOptions.OverrideAddress.IsValid() || routeOptions.OverridePort > 0) && !metadata.RouteOriginalDestination.IsValid() {
  488. metadata.RouteOriginalDestination = metadata.Destination
  489. }
  490. if routeOptions.OverrideAddress.IsValid() {
  491. metadata.Destination = M.Socksaddr{
  492. Addr: routeOptions.OverrideAddress.Addr,
  493. Port: metadata.Destination.Port,
  494. Fqdn: routeOptions.OverrideAddress.Fqdn,
  495. }
  496. metadata.DestinationAddresses = nil
  497. }
  498. if routeOptions.OverridePort > 0 {
  499. metadata.Destination = M.Socksaddr{
  500. Addr: metadata.Destination.Addr,
  501. Port: routeOptions.OverridePort,
  502. Fqdn: metadata.Destination.Fqdn,
  503. }
  504. }
  505. if routeOptions.NetworkStrategy != nil {
  506. metadata.NetworkStrategy = routeOptions.NetworkStrategy
  507. }
  508. if len(routeOptions.NetworkType) > 0 {
  509. metadata.NetworkType = routeOptions.NetworkType
  510. }
  511. if len(routeOptions.FallbackNetworkType) > 0 {
  512. metadata.FallbackNetworkType = routeOptions.FallbackNetworkType
  513. }
  514. if routeOptions.FallbackDelay != 0 {
  515. metadata.FallbackDelay = routeOptions.FallbackDelay
  516. }
  517. if routeOptions.UDPDisableDomainUnmapping {
  518. metadata.UDPDisableDomainUnmapping = true
  519. }
  520. if routeOptions.UDPConnect {
  521. metadata.UDPConnect = true
  522. }
  523. if routeOptions.UDPTimeout > 0 {
  524. metadata.UDPTimeout = routeOptions.UDPTimeout
  525. }
  526. if routeOptions.TLSFragment {
  527. metadata.TLSFragment = true
  528. metadata.TLSFragmentFallbackDelay = routeOptions.TLSFragmentFallbackDelay
  529. }
  530. if routeOptions.TLSRecordFragment {
  531. metadata.TLSRecordFragment = true
  532. }
  533. }
  534. switch action := currentRule.Action().(type) {
  535. case *R.RuleActionSniff:
  536. if !preMatch {
  537. newBuffer, newPacketBuffers, newErr := r.actionSniff(ctx, metadata, action, inputConn, inputPacketConn, buffers, packetBuffers)
  538. if newBuffer != nil {
  539. buffers = append(buffers, newBuffer)
  540. } else if len(newPacketBuffers) > 0 {
  541. packetBuffers = append(packetBuffers, newPacketBuffers...)
  542. }
  543. if newErr != nil {
  544. fatalErr = newErr
  545. return
  546. }
  547. } else if metadata.Network != N.NetworkICMP {
  548. selectedRule = currentRule
  549. selectedRuleIndex = currentRuleIndex
  550. break match
  551. }
  552. case *R.RuleActionResolve:
  553. fatalErr = r.actionResolve(ctx, metadata, action)
  554. if fatalErr != nil {
  555. return
  556. }
  557. }
  558. actionType := currentRule.Action().Type()
  559. if actionType == C.RuleActionTypeRoute ||
  560. actionType == C.RuleActionTypeReject ||
  561. actionType == C.RuleActionTypeHijackDNS {
  562. selectedRule = currentRule
  563. selectedRuleIndex = currentRuleIndex
  564. break match
  565. }
  566. if actionType == C.RuleActionTypeBypass {
  567. bypassAction := currentRule.Action().(*R.RuleActionBypass)
  568. if !supportBypass && bypassAction.Outbound == "" {
  569. continue match
  570. }
  571. selectedRule = currentRule
  572. selectedRuleIndex = currentRuleIndex
  573. break match
  574. }
  575. }
  576. return
  577. }
  578. func (r *Router) actionSniff(
  579. ctx context.Context, metadata *adapter.InboundContext, action *R.RuleActionSniff,
  580. inputConn net.Conn, inputPacketConn N.PacketConn, inputBuffers []*buf.Buffer, inputPacketBuffers []*N.PacketBuffer,
  581. ) (buffer *buf.Buffer, packetBuffers []*N.PacketBuffer, fatalErr error) {
  582. if sniff.Skip(metadata) {
  583. r.logger.DebugContext(ctx, "sniff skipped due to port considered as server-first")
  584. return
  585. } else if metadata.Protocol != "" {
  586. r.logger.DebugContext(ctx, "duplicate sniff skipped")
  587. return
  588. }
  589. if inputConn != nil {
  590. if len(action.StreamSniffers) == 0 && len(action.PacketSniffers) > 0 {
  591. return
  592. } else if slices.Equal(metadata.SnifferNames, action.SnifferNames) && metadata.SniffError != nil && !errors.Is(metadata.SniffError, sniff.ErrNeedMoreData) {
  593. r.logger.DebugContext(ctx, "packet sniff skipped due to previous error: ", metadata.SniffError)
  594. return
  595. }
  596. var streamSniffers []sniff.StreamSniffer
  597. if len(action.StreamSniffers) > 0 {
  598. streamSniffers = action.StreamSniffers
  599. } else {
  600. streamSniffers = []sniff.StreamSniffer{
  601. sniff.TLSClientHello,
  602. sniff.HTTPHost,
  603. sniff.StreamDomainNameQuery,
  604. sniff.BitTorrent,
  605. sniff.SSH,
  606. sniff.RDP,
  607. }
  608. }
  609. sniffBuffer := buf.NewPacket()
  610. err := sniff.PeekStream(
  611. ctx,
  612. metadata,
  613. inputConn,
  614. inputBuffers,
  615. sniffBuffer,
  616. action.Timeout,
  617. streamSniffers...,
  618. )
  619. metadata.SnifferNames = action.SnifferNames
  620. metadata.SniffError = err
  621. if err == nil {
  622. //goland:noinspection GoDeprecation
  623. if action.OverrideDestination && M.IsDomainName(metadata.Domain) {
  624. metadata.Destination = M.Socksaddr{
  625. Fqdn: metadata.Domain,
  626. Port: metadata.Destination.Port,
  627. }
  628. }
  629. if metadata.Domain != "" && metadata.Client != "" {
  630. r.logger.DebugContext(ctx, "sniffed protocol: ", metadata.Protocol, ", domain: ", metadata.Domain, ", client: ", metadata.Client)
  631. } else if metadata.Domain != "" {
  632. r.logger.DebugContext(ctx, "sniffed protocol: ", metadata.Protocol, ", domain: ", metadata.Domain)
  633. } else {
  634. r.logger.DebugContext(ctx, "sniffed protocol: ", metadata.Protocol)
  635. }
  636. }
  637. if !sniffBuffer.IsEmpty() {
  638. buffer = sniffBuffer
  639. } else {
  640. sniffBuffer.Release()
  641. }
  642. } else if inputPacketConn != nil {
  643. if len(action.PacketSniffers) == 0 && len(action.StreamSniffers) > 0 {
  644. return
  645. } else if slices.Equal(metadata.SnifferNames, action.SnifferNames) && metadata.SniffError != nil && !errors.Is(metadata.SniffError, sniff.ErrNeedMoreData) {
  646. r.logger.DebugContext(ctx, "packet sniff skipped due to previous error: ", metadata.SniffError)
  647. return
  648. }
  649. quicMoreData := func() bool {
  650. return slices.Equal(metadata.SnifferNames, action.SnifferNames) && errors.Is(metadata.SniffError, sniff.ErrNeedMoreData)
  651. }
  652. var packetSniffers []sniff.PacketSniffer
  653. if len(action.PacketSniffers) > 0 {
  654. packetSniffers = action.PacketSniffers
  655. } else {
  656. packetSniffers = []sniff.PacketSniffer{
  657. sniff.DomainNameQuery,
  658. sniff.QUICClientHello,
  659. sniff.STUNMessage,
  660. sniff.UTP,
  661. sniff.UDPTracker,
  662. sniff.DTLSRecord,
  663. sniff.NTP,
  664. }
  665. }
  666. var err error
  667. for _, packetBuffer := range inputPacketBuffers {
  668. if quicMoreData() {
  669. err = sniff.PeekPacket(
  670. ctx,
  671. metadata,
  672. packetBuffer.Buffer.Bytes(),
  673. sniff.QUICClientHello,
  674. )
  675. } else {
  676. err = sniff.PeekPacket(
  677. ctx, metadata,
  678. packetBuffer.Buffer.Bytes(),
  679. packetSniffers...,
  680. )
  681. }
  682. metadata.SnifferNames = action.SnifferNames
  683. metadata.SniffError = err
  684. if errors.Is(err, sniff.ErrNeedMoreData) {
  685. // TODO: replace with generic message when there are more multi-packet protocols
  686. r.logger.DebugContext(ctx, "attempt to sniff fragmented QUIC client hello")
  687. continue
  688. }
  689. goto finally
  690. }
  691. packetBuffers = inputPacketBuffers
  692. for {
  693. var (
  694. sniffBuffer = buf.NewPacket()
  695. destination M.Socksaddr
  696. done = make(chan struct{})
  697. )
  698. go func() {
  699. sniffTimeout := C.ReadPayloadTimeout
  700. if action.Timeout > 0 {
  701. sniffTimeout = action.Timeout
  702. }
  703. inputPacketConn.SetReadDeadline(time.Now().Add(sniffTimeout))
  704. destination, err = inputPacketConn.ReadPacket(sniffBuffer)
  705. inputPacketConn.SetReadDeadline(time.Time{})
  706. close(done)
  707. }()
  708. select {
  709. case <-done:
  710. case <-ctx.Done():
  711. inputPacketConn.Close()
  712. fatalErr = ctx.Err()
  713. return
  714. }
  715. if err != nil {
  716. sniffBuffer.Release()
  717. if !errors.Is(err, context.DeadlineExceeded) {
  718. fatalErr = err
  719. return
  720. }
  721. } else {
  722. if quicMoreData() {
  723. err = sniff.PeekPacket(
  724. ctx,
  725. metadata,
  726. sniffBuffer.Bytes(),
  727. sniff.QUICClientHello,
  728. )
  729. } else {
  730. err = sniff.PeekPacket(
  731. ctx, metadata,
  732. sniffBuffer.Bytes(),
  733. packetSniffers...,
  734. )
  735. }
  736. packetBuffer := N.NewPacketBuffer()
  737. *packetBuffer = N.PacketBuffer{
  738. Buffer: sniffBuffer,
  739. Destination: destination,
  740. }
  741. packetBuffers = append(packetBuffers, packetBuffer)
  742. metadata.SnifferNames = action.SnifferNames
  743. metadata.SniffError = err
  744. if errors.Is(err, sniff.ErrNeedMoreData) {
  745. // TODO: replace with generic message when there are more multi-packet protocols
  746. r.logger.DebugContext(ctx, "attempt to sniff fragmented QUIC client hello")
  747. continue
  748. }
  749. }
  750. goto finally
  751. }
  752. finally:
  753. if err == nil {
  754. //goland:noinspection GoDeprecation
  755. if action.OverrideDestination && M.IsDomainName(metadata.Domain) {
  756. metadata.Destination = M.Socksaddr{
  757. Fqdn: metadata.Domain,
  758. Port: metadata.Destination.Port,
  759. }
  760. }
  761. if metadata.Domain != "" && metadata.Client != "" {
  762. r.logger.DebugContext(ctx, "sniffed packet protocol: ", metadata.Protocol, ", domain: ", metadata.Domain, ", client: ", metadata.Client)
  763. } else if metadata.Domain != "" {
  764. r.logger.DebugContext(ctx, "sniffed packet protocol: ", metadata.Protocol, ", domain: ", metadata.Domain)
  765. } else if metadata.Client != "" {
  766. r.logger.DebugContext(ctx, "sniffed packet protocol: ", metadata.Protocol, ", client: ", metadata.Client)
  767. } else {
  768. r.logger.DebugContext(ctx, "sniffed packet protocol: ", metadata.Protocol)
  769. }
  770. }
  771. }
  772. return
  773. }
  774. func (r *Router) actionResolve(ctx context.Context, metadata *adapter.InboundContext, action *R.RuleActionResolve) error {
  775. if metadata.Destination.IsDomain() {
  776. var transport adapter.DNSTransport
  777. if action.Server != "" {
  778. var loaded bool
  779. transport, loaded = r.dnsTransport.Transport(action.Server)
  780. if !loaded {
  781. return E.New("DNS server not found: ", action.Server)
  782. }
  783. }
  784. addresses, err := r.dns.Lookup(adapter.WithContext(ctx, metadata), metadata.Destination.Fqdn, adapter.DNSQueryOptions{
  785. Transport: transport,
  786. Strategy: action.Strategy,
  787. DisableCache: action.DisableCache,
  788. RewriteTTL: action.RewriteTTL,
  789. ClientSubnet: action.ClientSubnet,
  790. })
  791. if err != nil {
  792. return err
  793. }
  794. metadata.DestinationAddresses = addresses
  795. r.logger.DebugContext(ctx, "resolved [", strings.Join(F.MapToString(metadata.DestinationAddresses), " "), "]")
  796. }
  797. return nil
  798. }