instance.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. // Package amneziawg holds the AmneziaWG protocol's shared, DB-backed shapes
  2. // (Instance, Peer, Obfuscation31, ServerSettings/InboundSettings) and the
  3. // pure functions that derive an Instance from a stored inbound row. It no
  4. // longer manages any OS-level interface itself: that was the kernel-module
  5. // (DKMS) + awg-quick + TPROXY architecture this fork shipped originally,
  6. // retired in favor of an embedded, pure-Go one (amneziawg-go over a gVisor
  7. // netstack, see internal/amneziawgnet) in a hard cutover. This package's
  8. // remaining code is deliberately protocol-shape-only, with no OS dependency
  9. // at all, so both the (now-removed) kernel-module path and the embedded
  10. // path could read -- and, historically, did read -- it identically.
  11. package amneziawg
  12. import (
  13. "encoding/json"
  14. "fmt"
  15. "net/netip"
  16. "github.com/mhsanaei/3x-ui/v3/internal/database/model"
  17. )
  18. // InstanceFromInbound derives a desired Instance from an AmneziaWG inbound,
  19. // building one peer per active client. Returns false when the inbound is not
  20. // a usable AmneziaWG inbound (wrong protocol, unparseable settings, or no
  21. // server block) or has no enabled peer to serve — mirroring
  22. // mtproto.InstanceFromInbound, which skips the sidecar entirely rather than
  23. // run it with nothing to serve.
  24. func InstanceFromInbound(ib *model.Inbound) (Instance, bool) {
  25. if ib == nil || ib.Protocol != model.AmneziaWG {
  26. return Instance{}, false
  27. }
  28. var parsed InboundSettings
  29. if err := json.Unmarshal([]byte(ib.Settings), &parsed); err != nil || parsed.Server == nil {
  30. return Instance{}, false
  31. }
  32. server := parsed.Server
  33. peers := make([]Peer, 0, len(parsed.Clients))
  34. for _, c := range parsed.Clients {
  35. if !c.Enable || c.PublicKey == "" || len(c.AllowedIPs) == 0 {
  36. continue
  37. }
  38. peers = append(peers, Peer{
  39. Email: c.Email,
  40. PublicKey: c.PublicKey,
  41. PresharedKey: c.PreSharedKey,
  42. AllowedIPs: c.AllowedIPs,
  43. ForwardedPorts: c.ForwardedPorts,
  44. })
  45. }
  46. if len(peers) == 0 {
  47. return Instance{}, false
  48. }
  49. addresses := []string{serverAddress(server.SubnetIP, server.SubnetCIDR)}
  50. if server.IPv6Enabled {
  51. if v6, ok := serverAddressV6(server.IPv6Subnet); ok {
  52. addresses = append(addresses, v6)
  53. }
  54. }
  55. return Instance{
  56. Id: ib.Id,
  57. Tag: ib.Tag,
  58. InterfaceName: interfaceNameForID(ib.Id),
  59. ListenPort: ib.Port,
  60. PrivateKey: server.PrivateKey,
  61. PublicKey: server.PublicKey,
  62. Address: addresses,
  63. MTU: server.MTU,
  64. Obfuscation: server.Obfuscation(),
  65. Peers: peers,
  66. ExternalInterface: server.ExternalInterface,
  67. IPv6Enabled: server.IPv6Enabled,
  68. IPv6ExternalInterface: server.IPv6ExternalInterface,
  69. RouteThroughXray: server.RouteThroughXray,
  70. }, true
  71. }
  72. // interfaceNameForID derives the OS-level interface name for an inbound, e.g.
  73. // "awg42". Kept even though the embedded path has no real kernel interface
  74. // of its own: internal/amneziawgnet still uses the same name as a purely
  75. // cosmetic/log-friendly label, so an existing peer's identity/history
  76. // doesn't shift across the cutover.
  77. func interfaceNameForID(id int) string {
  78. return fmt.Sprintf("awg%d", id)
  79. }
  80. // serverAddress returns the server's own tunnel address for a subnet base,
  81. // e.g. "10.8.1.1/24" for base "10.8.1.0" or "10.8.1.5". The server always
  82. // holds the first usable host of the network subnetIP/cidr actually
  83. // describes -- derived via netip rather than assuming subnetIP already ends
  84. // in ".0", so a subnetIP that isn't a bare network address (a typo, or a
  85. // manually edited value) can never collide with peer addresses, which are
  86. // allocated starting from the network's second host upward (see
  87. // allocateWireguardAddress). Falls back to the previous literal behavior
  88. // only if subnetIP/cidr doesn't parse as an IPv4 network at all -- normal
  89. // saves never reach that path since ValidateSubnetIPv4 already rejects it.
  90. func serverAddress(subnetIP string, cidr int) string {
  91. if cidr <= 0 {
  92. cidr = 24
  93. }
  94. // A /32 has no host bits at all -- "first usable host" is meaningless,
  95. // and Next() would step outside the block entirely -- so a single-host
  96. // base is used exactly as given, same as before this fix.
  97. prefix, err := netip.ParsePrefix(fmt.Sprintf("%s/%d", subnetIP, cidr))
  98. if err != nil || !prefix.Addr().Is4() || cidr >= 32 {
  99. return fmt.Sprintf("%s/%d", subnetIP, cidr)
  100. }
  101. host := prefix.Masked().Addr().Next()
  102. return fmt.Sprintf("%s/%d", host, cidr)
  103. }
  104. // serverAddressV6 returns the server's own IPv6 tunnel address for a subnet
  105. // CIDR (e.g. "fd86:ea04:1115::1/64" for "fd86:ea04:1115::/64"), the first
  106. // usable host in the prefix. ok is false when subnetCIDR is empty or not a
  107. // valid IPv6 prefix.
  108. func serverAddressV6(subnetCIDR string) (addr string, ok bool) {
  109. prefix, err := netip.ParsePrefix(subnetCIDR)
  110. if err != nil || !prefix.Addr().Is6() {
  111. return "", false
  112. }
  113. host := prefix.Masked().Addr().Next()
  114. return fmt.Sprintf("%s/%d", host, prefix.Bits()), true
  115. }
  116. // FirstIPv4 returns the first IPv4 address (mask stripped) among allowedIPs,
  117. // or "" if none — used to derive a peer's tunnel IPv4 address.
  118. func FirstIPv4(allowedIPs []string) string {
  119. for _, a := range allowedIPs {
  120. if prefix, err := netip.ParsePrefix(a); err == nil {
  121. if prefix.Addr().Is4() {
  122. return prefix.Addr().String()
  123. }
  124. continue
  125. }
  126. if addr, err := netip.ParseAddr(a); err == nil && addr.Is4() {
  127. return addr.String()
  128. }
  129. }
  130. return ""
  131. }
  132. // FirstIPv6 returns the first IPv6 address (mask stripped) among allowedIPs,
  133. // or "" if none — the IPv6 counterpart of FirstIPv4, used by
  134. // internal/amneziawgnet's IPv6-address-alias mechanism to find which
  135. // address, if any, a peer wants aliased onto the host, and by
  136. // internal/web/service/xray.go's injectAmneziawgV6Egress to build that
  137. // peer's own freedom outbound (sendThrough). Only the first match is
  138. // returned, exactly like FirstIPv4 — more than one IPv6 AllowedIPs entry
  139. // per peer is not a supported configuration for either feature.
  140. func FirstIPv6(allowedIPs []string) string {
  141. for _, a := range allowedIPs {
  142. if prefix, err := netip.ParsePrefix(a); err == nil {
  143. if prefix.Addr().Is6() && !prefix.Addr().Is4In6() {
  144. return prefix.Addr().String()
  145. }
  146. continue
  147. }
  148. if addr, err := netip.ParseAddr(a); err == nil && addr.Is6() && !addr.Is4In6() {
  149. return addr.String()
  150. }
  151. }
  152. return ""
  153. }