process_cache.go 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. package route
  2. import (
  3. "context"
  4. "net/netip"
  5. "strings"
  6. "github.com/sagernet/sing-box/adapter"
  7. "github.com/sagernet/sing-box/common/process"
  8. )
  9. type processCacheKey struct {
  10. Network string
  11. Source netip.AddrPort
  12. Destination netip.AddrPort
  13. }
  14. type processCacheEntry struct {
  15. result *adapter.ConnectionOwner
  16. err error
  17. }
  18. func (r *Router) findProcessInfoCached(ctx context.Context, network string, source netip.AddrPort, destination netip.AddrPort) (*adapter.ConnectionOwner, error) {
  19. key := processCacheKey{
  20. Network: network,
  21. Source: source,
  22. Destination: destination,
  23. }
  24. if entry, ok := r.processCache.Get(key); ok {
  25. return entry.result, entry.err
  26. }
  27. result, err := process.FindProcessInfo(r.processSearcher, ctx, network, source, destination)
  28. r.processCache.Add(key, processCacheEntry{result: result, err: err})
  29. return result, err
  30. }
  31. func (r *Router) searchProcessInfo(ctx context.Context, metadata *adapter.InboundContext) {
  32. if r.processSearcher == nil || metadata.ProcessInfo != nil || !r.isLocalSource(metadata.Source.Addr) {
  33. return
  34. }
  35. var originDestination netip.AddrPort
  36. if metadata.OriginDestination.IsValid() {
  37. originDestination = metadata.OriginDestination.AddrPort()
  38. } else if metadata.Destination.IsIP() {
  39. originDestination = metadata.Destination.AddrPort()
  40. }
  41. processInfo, err := r.findProcessInfoCached(ctx, metadata.Network, metadata.Source.AddrPort(), originDestination)
  42. if err != nil {
  43. r.logger.InfoContext(ctx, "failed to search process: ", err)
  44. return
  45. }
  46. metadata.ProcessInfo = processInfo
  47. if processInfo.ProcessPath != "" {
  48. if processInfo.UserName != "" {
  49. r.logger.InfoContext(ctx, "found process path: ", processInfo.ProcessPath, ", user: ", processInfo.UserName)
  50. } else if processInfo.UserId != -1 {
  51. r.logger.InfoContext(ctx, "found process path: ", processInfo.ProcessPath, ", user id: ", processInfo.UserId)
  52. } else {
  53. r.logger.InfoContext(ctx, "found process path: ", processInfo.ProcessPath)
  54. }
  55. return
  56. }
  57. if len(processInfo.AndroidPackageNames) > 0 {
  58. r.logger.InfoContext(ctx, "found package name: ", strings.Join(processInfo.AndroidPackageNames, ", "))
  59. return
  60. }
  61. if processInfo.UserId != -1 {
  62. if processInfo.UserName != "" {
  63. r.logger.InfoContext(ctx, "found user: ", processInfo.UserName)
  64. } else {
  65. r.logger.InfoContext(ctx, "found user id: ", processInfo.UserId)
  66. }
  67. }
  68. }
  69. func (r *Router) isLocalSource(source netip.Addr) bool {
  70. if !source.IsValid() {
  71. return false
  72. }
  73. source = source.Unmap()
  74. if source.IsLoopback() {
  75. return true
  76. }
  77. for _, netInterface := range r.network.InterfaceFinder().Interfaces() {
  78. for _, prefix := range netInterface.Addresses {
  79. if prefix.Addr().Unmap() == source {
  80. return true
  81. }
  82. }
  83. }
  84. return false
  85. }