identity.go 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. package amneziawgnet
  2. import (
  3. "net/netip"
  4. "github.com/mhsanaei/3x-ui/v3/internal/amneziawg"
  5. )
  6. // PeerIndex resolves a decapsulated connection's tunnel-internal source
  7. // address back to the peer it belongs to, the same role Xray-core's own
  8. // wireguard proxy's GetUserByAddr plays -- sourced here from an
  9. // amneziawg.Instance's own Peers (already carries Email per peer, no new
  10. // data needed) rather than a separate user table.
  11. type PeerIndex struct {
  12. entries []peerIndexEntry
  13. }
  14. type peerIndexEntry struct {
  15. prefix netip.Prefix
  16. peer amneziawg.Peer
  17. }
  18. // NewPeerIndex builds a lookup index from peers' AllowedIPs. Entries with an
  19. // unparseable AllowedIPs value are skipped rather than failing the whole
  20. // index -- by the time an Instance reaches this package, AllowedIPs has
  21. // already been accepted at save time (see internal/amneziawg's own
  22. // validation), so a bad entry here would only mean stale/manually-edited
  23. // data, not something worth refusing to serve the rest of the peers over.
  24. func NewPeerIndex(peers []amneziawg.Peer) *PeerIndex {
  25. idx := &PeerIndex{}
  26. for _, p := range peers {
  27. for _, a := range p.AllowedIPs {
  28. prefix, err := netip.ParsePrefix(a)
  29. if err != nil {
  30. continue
  31. }
  32. idx.entries = append(idx.entries, peerIndexEntry{prefix: prefix, peer: p})
  33. }
  34. }
  35. return idx
  36. }
  37. // Lookup returns the peer whose AllowedIPs most specifically contains addr --
  38. // the same longest-prefix-match rule a real AmneziaWG interface's own
  39. // AllowedIPs routing table uses for outbound packets, applied here in
  40. // reverse to attribute an inbound (tunnel-internal-source) packet back to
  41. // its owning peer.
  42. func (idx *PeerIndex) Lookup(addr netip.Addr) (amneziawg.Peer, bool) {
  43. bestBits := -1
  44. var bestPeer amneziawg.Peer
  45. for _, e := range idx.entries {
  46. if e.prefix.Bits() <= bestBits || !e.prefix.Contains(addr) {
  47. continue
  48. }
  49. bestBits = e.prefix.Bits()
  50. bestPeer = e.peer
  51. }
  52. if bestBits < 0 {
  53. return amneziawg.Peer{}, false
  54. }
  55. return bestPeer, true
  56. }