github.com/bepass-org/wireguard-go@v1.0.4-rc2.0.20240304192354-ebce6572bc24/wiresocks/config.go (about) 1 package wiresocks 2 3 import ( 4 "encoding/base64" 5 "encoding/hex" 6 "errors" 7 "strings" 8 9 "github.com/go-ini/ini" 10 11 "net/netip" 12 ) 13 14 type PeerConfig struct { 15 PublicKey string 16 PreSharedKey string 17 Endpoint *string 18 KeepAlive int 19 AllowedIPs []netip.Prefix 20 } 21 22 // DeviceConfig contains the information to initiate a wireguard connection 23 type DeviceConfig struct { 24 SecretKey string 25 Endpoint []netip.Addr 26 Peers []PeerConfig 27 DNS []netip.Addr 28 MTU int 29 ListenPort *int 30 Trick bool 31 } 32 33 type Configuration struct { 34 Device *DeviceConfig 35 } 36 37 var ( 38 dnsAddresses = []string{"8.8.8.8", "8.8.4.4"} 39 dc = 0 40 ) 41 42 func parseString(section *ini.Section, keyName string) (string, error) { 43 key := section.Key(strings.ToLower(keyName)) 44 if key == nil { 45 return "", errors.New(keyName + " should not be empty") 46 } 47 return key.String(), nil 48 } 49 50 func parseBase64KeyToHex(section *ini.Section, keyName string) (string, error) { 51 key, err := parseString(section, keyName) 52 if err != nil { 53 return "", err 54 } 55 result, err := encodeBase64ToHex(key) 56 if err != nil { 57 return result, err 58 } 59 60 return result, nil 61 } 62 63 func encodeBase64ToHex(key string) (string, error) { 64 decoded, err := base64.StdEncoding.DecodeString(key) 65 if err != nil { 66 return "", errors.New("invalid base64 string: " + key) 67 } 68 if len(decoded) != 32 { 69 return "", errors.New("key should be 32 bytes: " + key) 70 } 71 return hex.EncodeToString(decoded), nil 72 } 73 74 func parseNetIP(section *ini.Section, keyName string) ([]netip.Addr, error) { 75 key := section.Key(keyName) 76 if key == nil { 77 return []netip.Addr{}, nil 78 } 79 80 var ips []netip.Addr 81 for _, str := range key.StringsWithShadows(",") { 82 str = strings.TrimSpace(str) 83 if str == "1.1.1.1" { 84 str = dnsAddresses[dc%len(dnsAddresses)] 85 dc++ 86 } 87 ip, err := netip.ParseAddr(str) 88 if err != nil { 89 return nil, err 90 } 91 ips = append(ips, ip) 92 } 93 return ips, nil 94 } 95 96 func parseCIDRNetIP(section *ini.Section, keyName string) ([]netip.Addr, error) { 97 key := section.Key(keyName) 98 if key == nil { 99 return []netip.Addr{}, nil 100 } 101 102 var ips []netip.Addr 103 for _, str := range key.StringsWithShadows(",") { 104 prefix, err := netip.ParsePrefix(str) 105 if err != nil { 106 return nil, err 107 } 108 109 addr := prefix.Addr() 110 ips = append(ips, addr) 111 } 112 return ips, nil 113 } 114 115 func parseAllowedIPs(section *ini.Section) ([]netip.Prefix, error) { 116 key := section.Key("AllowedIPs") 117 if key == nil { 118 return []netip.Prefix{}, nil 119 } 120 121 var ips []netip.Prefix 122 for _, str := range key.StringsWithShadows(",") { 123 prefix, err := netip.ParsePrefix(str) 124 if err != nil { 125 return nil, err 126 } 127 128 ips = append(ips, prefix) 129 } 130 return ips, nil 131 } 132 133 // ParseInterface parses the [Interface] section and extract the information into `device` 134 func ParseInterface(cfg *ini.File, device *DeviceConfig) error { 135 sections, err := cfg.SectionsByName("Interface") 136 if len(sections) != 1 || err != nil { 137 return errors.New("one and only one [Interface] is expected") 138 } 139 section := sections[0] 140 141 address, err := parseCIDRNetIP(section, "Address") 142 if err != nil { 143 return err 144 } 145 146 device.Endpoint = address 147 148 privKey, err := parseBase64KeyToHex(section, "PrivateKey") 149 if err != nil { 150 return err 151 } 152 device.SecretKey = privKey 153 154 dns, err := parseNetIP(section, "DNS") 155 if err != nil { 156 return err 157 } 158 device.DNS = dns 159 160 if sectionKey, err := section.GetKey("MTU"); err == nil { 161 value, err := sectionKey.Int() 162 if err != nil { 163 return err 164 } 165 device.MTU = value 166 } else { 167 if dc == 0 { 168 device.MTU = 1420 169 } else { 170 device.MTU = 1300 171 } 172 } 173 174 if sectionKey, err := section.GetKey("ListenPort"); err == nil { 175 value, err := sectionKey.Int() 176 if err != nil { 177 return err 178 } 179 device.ListenPort = &value 180 } 181 182 return nil 183 } 184 185 // ParsePeers parses the [Peer] section and extract the information into `peers` 186 func ParsePeers(cfg *ini.File, peers *[]PeerConfig, endpoint string) error { 187 sections, err := cfg.SectionsByName("Peer") 188 if len(sections) < 1 || err != nil { 189 return errors.New("at least one [Peer] is expected") 190 } 191 192 for _, section := range sections { 193 peer := PeerConfig{ 194 PreSharedKey: "0000000000000000000000000000000000000000000000000000000000000000", 195 KeepAlive: 0, 196 } 197 198 decoded, err := parseBase64KeyToHex(section, "PublicKey") 199 if err != nil { 200 return err 201 } 202 peer.PublicKey = decoded 203 204 if sectionKey, err := section.GetKey("PreSharedKey"); err == nil { 205 value, err := encodeBase64ToHex(sectionKey.String()) 206 if err != nil { 207 return err 208 } 209 peer.PreSharedKey = value 210 } 211 212 if sectionKey, err := section.GetKey("PersistentKeepalive"); err == nil { 213 value, err := sectionKey.Int() 214 if err != nil { 215 return err 216 } 217 peer.KeepAlive = value 218 } 219 220 peer.AllowedIPs, err = parseAllowedIPs(section) 221 if err != nil { 222 return err 223 } 224 225 peer.Endpoint = &endpoint 226 227 *peers = append(*peers, peer) 228 } 229 return nil 230 } 231 232 // ParseConfig takes the path of a configuration file and parses it into Configuration 233 func ParseConfig(path string, endpoint string) (*Configuration, error) { 234 iniOpt := ini.LoadOptions{ 235 Insensitive: true, 236 AllowShadows: true, 237 AllowNonUniqueSections: true, 238 } 239 240 cfg, err := ini.LoadSources(iniOpt, path) 241 if err != nil { 242 return nil, err 243 } 244 245 device := &DeviceConfig{ 246 MTU: 1420, 247 } 248 249 root := cfg.Section("") 250 wgConf, err := root.GetKey("WGConfig") 251 wgCfg := cfg 252 if err == nil { 253 wgCfg, err = ini.LoadSources(iniOpt, wgConf.String()) 254 if err != nil { 255 return nil, err 256 } 257 } 258 259 err = ParseInterface(wgCfg, device) 260 if err != nil { 261 return nil, err 262 } 263 264 err = ParsePeers(wgCfg, &device.Peers, endpoint) 265 if err != nil { 266 return nil, err 267 } 268 269 return &Configuration{ 270 Device: device, 271 }, nil 272 }