wireguard.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. package conf
  2. import (
  3. "context"
  4. "encoding/base64"
  5. "encoding/hex"
  6. "strings"
  7. "github.com/xtls/xray-core/common/errors"
  8. "github.com/xtls/xray-core/proxy/wireguard"
  9. "google.golang.org/protobuf/proto"
  10. )
  11. type WireGuardPeerConfig struct {
  12. PublicKey string `json:"publicKey"`
  13. PreSharedKey string `json:"preSharedKey"`
  14. Endpoint string `json:"endpoint"`
  15. KeepAlive uint32 `json:"keepAlive"`
  16. AllowedIPs []string `json:"allowedIPs,omitempty"`
  17. }
  18. func (c *WireGuardPeerConfig) Build() (proto.Message, error) {
  19. var err error
  20. config := new(wireguard.PeerConfig)
  21. if c.PublicKey != "" {
  22. config.PublicKey, err = ParseWireGuardKey(c.PublicKey)
  23. if err != nil {
  24. return nil, err
  25. }
  26. }
  27. if c.PreSharedKey != "" {
  28. config.PreSharedKey, err = ParseWireGuardKey(c.PreSharedKey)
  29. if err != nil {
  30. return nil, err
  31. }
  32. }
  33. config.Endpoint = c.Endpoint
  34. // default 0
  35. config.KeepAlive = c.KeepAlive
  36. if c.AllowedIPs == nil {
  37. config.AllowedIps = []string{"0.0.0.0/0", "::0/0"}
  38. } else {
  39. config.AllowedIps = c.AllowedIPs
  40. }
  41. return config, nil
  42. }
  43. type WireGuardConfig struct {
  44. IsClient bool `json:""`
  45. KernelMode *bool `json:"kernelMode"`
  46. SecretKey string `json:"secretKey"`
  47. Address []string `json:"address"`
  48. Peers []*WireGuardPeerConfig `json:"peers"`
  49. MTU int32 `json:"mtu"`
  50. NumWorkers int32 `json:"workers"`
  51. Reserved []byte `json:"reserved"`
  52. DomainStrategy string `json:"domainStrategy"`
  53. }
  54. func (c *WireGuardConfig) Build() (proto.Message, error) {
  55. config := new(wireguard.DeviceConfig)
  56. var err error
  57. config.SecretKey, err = ParseWireGuardKey(c.SecretKey)
  58. if err != nil {
  59. return nil, err
  60. }
  61. if c.Address == nil {
  62. // bogon ips
  63. config.Endpoint = []string{"10.0.0.1", "fd59:7153:2388:b5fd:0000:0000:0000:0001"}
  64. } else {
  65. config.Endpoint = c.Address
  66. }
  67. if c.Peers != nil {
  68. config.Peers = make([]*wireguard.PeerConfig, len(c.Peers))
  69. for i, p := range c.Peers {
  70. msg, err := p.Build()
  71. if err != nil {
  72. return nil, err
  73. }
  74. config.Peers[i] = msg.(*wireguard.PeerConfig)
  75. }
  76. }
  77. if c.MTU == 0 {
  78. config.Mtu = 1420
  79. } else {
  80. config.Mtu = c.MTU
  81. }
  82. // these a fallback code exists in wireguard-go code,
  83. // we don't need to process fallback manually
  84. config.NumWorkers = c.NumWorkers
  85. if len(c.Reserved) != 0 && len(c.Reserved) != 3 {
  86. return nil, errors.New(`"reserved" should be empty or 3 bytes`)
  87. }
  88. config.Reserved = c.Reserved
  89. switch strings.ToLower(c.DomainStrategy) {
  90. case "forceip", "":
  91. config.DomainStrategy = wireguard.DeviceConfig_FORCE_IP
  92. case "forceipv4":
  93. config.DomainStrategy = wireguard.DeviceConfig_FORCE_IP4
  94. case "forceipv6":
  95. config.DomainStrategy = wireguard.DeviceConfig_FORCE_IP6
  96. case "forceipv4v6":
  97. config.DomainStrategy = wireguard.DeviceConfig_FORCE_IP46
  98. case "forceipv6v4":
  99. config.DomainStrategy = wireguard.DeviceConfig_FORCE_IP64
  100. default:
  101. return nil, errors.New("unsupported domain strategy: ", c.DomainStrategy)
  102. }
  103. config.IsClient = c.IsClient
  104. if c.KernelMode != nil {
  105. config.KernelMode = *c.KernelMode
  106. if config.KernelMode && !wireguard.KernelTunSupported() {
  107. errors.LogWarning(context.Background(), "kernel mode is not supported on your OS or permission is insufficient")
  108. }
  109. } else {
  110. config.KernelMode = wireguard.KernelTunSupported()
  111. if config.KernelMode {
  112. errors.LogDebug(context.Background(), "kernel mode is enabled as it's supported and permission is sufficient")
  113. }
  114. }
  115. return config, nil
  116. }
  117. func ParseWireGuardKey(str string) (string, error) {
  118. var err error
  119. if len(str)%2 == 0 {
  120. _, err = hex.DecodeString(str)
  121. if err == nil {
  122. return str, nil
  123. }
  124. }
  125. var dat []byte
  126. str = strings.TrimSuffix(str, "=")
  127. if strings.ContainsRune(str, '+') || strings.ContainsRune(str, '/') {
  128. dat, err = base64.RawStdEncoding.DecodeString(str)
  129. } else {
  130. dat, err = base64.RawURLEncoding.DecodeString(str)
  131. }
  132. if err == nil {
  133. return hex.EncodeToString(dat), nil
  134. }
  135. return "", errors.New("failed to deserialize key").Base(err)
  136. }