amneziawg_job.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. package job
  2. import (
  3. "encoding/json"
  4. "github.com/mhsanaei/3x-ui/v3/internal/amneziawg"
  5. "github.com/mhsanaei/3x-ui/v3/internal/amneziawgnet"
  6. "github.com/mhsanaei/3x-ui/v3/internal/logger"
  7. "github.com/mhsanaei/3x-ui/v3/internal/web/service"
  8. "github.com/mhsanaei/3x-ui/v3/internal/xray"
  9. )
  10. // AmneziaWGJob converges embedded AmneziaWG interfaces (inbounds AND the
  11. // template's "amneziawg" outbounds) every 10s; stats stay with Xray.
  12. type AmneziaWGJob struct {
  13. inboundService service.InboundService
  14. settingService service.SettingService
  15. xrayService service.XrayService
  16. }
  17. // NewAmneziaWGJob creates a new AmneziaWG reconcile job instance.
  18. func NewAmneziaWGJob() *AmneziaWGJob {
  19. return new(AmneziaWGJob)
  20. }
  21. // Run reconciles desired AmneziaWG inbounds with running embedded interfaces.
  22. func (j *AmneziaWGJob) Run() {
  23. desired, err := j.inboundService.DesiredAmneziaWGInstances()
  24. if err != nil {
  25. logger.Warning("amneziawg job: get desired instances failed:", err)
  26. return
  27. }
  28. wanted := make([]amneziawgnet.Desired, 0, len(desired))
  29. for _, inst := range desired {
  30. wanted = append(wanted, amneziawgnet.Desired{
  31. Instance: inst,
  32. Options: amneziawgnet.DeviceOptions{
  33. HeaderProtectionKey: inst.Obfuscation.HeaderProtectionKey,
  34. ContentPaddingAddition: inst.Obfuscation.ContentPaddingAddition,
  35. RekeyAfterTime: inst.Obfuscation.RekeyAfterTime,
  36. RekeyTimeout: inst.Obfuscation.RekeyTimeout,
  37. RejectAfterTime: inst.Obfuscation.RejectAfterTime,
  38. KeepaliveTimeout: inst.Obfuscation.KeepaliveTimeout,
  39. MaxHandshakeAttempts: inst.Obfuscation.MaxHandshakeAttempts,
  40. RandomTrailers: inst.Obfuscation.RandomTrailers,
  41. DisableCookies: inst.Obfuscation.DisableCookies,
  42. },
  43. })
  44. }
  45. amneziawgnet.GetManager().Reconcile(wanted)
  46. outboundDesired, err := j.desiredOutboundInstances()
  47. if err != nil {
  48. logger.Warning("amneziawg job: get desired outbound instances failed:", err)
  49. return
  50. }
  51. amneziawgnet.GetOutboundManager().Reconcile(outboundDesired)
  52. // Xray's bridges are generated apart from the listener; one that moved needs them regenerated.
  53. if amneziawgnet.BridgesStale() {
  54. j.xrayService.SetToNeedRestart()
  55. }
  56. }
  57. // desiredOutboundInstances derives client instances per template "amneziawg" outbound.
  58. func (j *AmneziaWGJob) desiredOutboundInstances() ([]amneziawgnet.OutboundDesired, error) {
  59. template, err := j.settingService.GetXrayConfigTemplate()
  60. if err != nil {
  61. return nil, err
  62. }
  63. if template == "" {
  64. return nil, nil
  65. }
  66. cfg := &xray.Config{}
  67. if err := json.Unmarshal([]byte(template), cfg); err != nil {
  68. return nil, err
  69. }
  70. if len(cfg.OutboundConfigs) == 0 {
  71. return nil, nil
  72. }
  73. var raws []json.RawMessage
  74. if err := json.Unmarshal(cfg.OutboundConfigs, &raws); err != nil {
  75. return nil, err
  76. }
  77. out := make([]amneziawgnet.OutboundDesired, 0, len(raws))
  78. for _, raw := range raws {
  79. if !amneziawg.IsAmneziaWGOutbound(raw) {
  80. continue
  81. }
  82. var probe struct {
  83. Tag string `json:"tag"`
  84. }
  85. if err := json.Unmarshal(raw, &probe); err != nil || probe.Tag == "" {
  86. continue
  87. }
  88. inst, ok := amneziawg.InstanceFromOutbound(probe.Tag, raw)
  89. if !ok {
  90. continue
  91. }
  92. out = append(out, amneziawgnet.OutboundDesired{
  93. Instance: inst,
  94. Options: amneziawgnet.DeviceOptions{
  95. HeaderProtectionKey: inst.Obfuscation.HeaderProtectionKey,
  96. ContentPaddingAddition: inst.Obfuscation.ContentPaddingAddition,
  97. RekeyAfterTime: inst.Obfuscation.RekeyAfterTime,
  98. RekeyTimeout: inst.Obfuscation.RekeyTimeout,
  99. RejectAfterTime: inst.Obfuscation.RejectAfterTime,
  100. KeepaliveTimeout: inst.Obfuscation.KeepaliveTimeout,
  101. MaxHandshakeAttempts: inst.Obfuscation.MaxHandshakeAttempts,
  102. RandomTrailers: inst.Obfuscation.RandomTrailers,
  103. DisableCookies: inst.Obfuscation.DisableCookies,
  104. },
  105. })
  106. }
  107. return out, nil
  108. }