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