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  }