2022-03-22 11:03:15 -04:00
|
|
|
package vpn
|
|
|
|
|
|
|
|
import (
|
2022-03-29 05:38:14 -04:00
|
|
|
"fmt"
|
2022-03-22 11:03:15 -04:00
|
|
|
"net"
|
|
|
|
"time"
|
|
|
|
|
2022-03-29 05:38:14 -04:00
|
|
|
wgquick "github.com/nmiculinic/wg-quick-go"
|
2022-03-22 11:03:15 -04:00
|
|
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
interfaceName = "wg0"
|
|
|
|
wireguardPort = 51820
|
|
|
|
)
|
|
|
|
|
2022-04-12 08:20:46 -04:00
|
|
|
type ConfigHandler struct {
|
|
|
|
up func(cfg *wgquick.Config, iface string) error
|
2022-03-22 11:03:15 -04:00
|
|
|
}
|
|
|
|
|
2022-04-12 08:20:46 -04:00
|
|
|
func NewConfigHandler() *ConfigHandler {
|
|
|
|
return &ConfigHandler{up: wgquick.Up}
|
2022-03-22 11:03:15 -04:00
|
|
|
}
|
|
|
|
|
2022-04-12 08:20:46 -04:00
|
|
|
func (h *ConfigHandler) Create(coordinatorPubKey, coordinatorPubIP, clientPrivKey, clientVPNIP string, mtu int) (*wgquick.Config, error) {
|
|
|
|
return NewWGQuickConfig(coordinatorPubKey, coordinatorPubIP, clientPrivKey, clientVPNIP, mtu)
|
2022-03-22 11:03:15 -04:00
|
|
|
}
|
|
|
|
|
2022-04-12 08:20:46 -04:00
|
|
|
// Apply applies the generated WireGuard quick config.
|
|
|
|
func (h *ConfigHandler) Apply(conf *wgquick.Config) error {
|
|
|
|
return h.up(conf, interfaceName)
|
2022-03-22 11:03:15 -04:00
|
|
|
}
|
|
|
|
|
2022-04-12 08:20:46 -04:00
|
|
|
// GetBytes returns the the bytes of the config.
|
|
|
|
func (h *ConfigHandler) Marshal(conf *wgquick.Config) ([]byte, error) {
|
|
|
|
data, err := conf.MarshalText()
|
2022-03-22 11:03:15 -04:00
|
|
|
if err != nil {
|
2022-04-12 08:20:46 -04:00
|
|
|
return nil, fmt.Errorf("marshal wg-quick config: %w", err)
|
2022-03-22 11:03:15 -04:00
|
|
|
}
|
2022-04-12 08:20:46 -04:00
|
|
|
return data, nil
|
2022-03-29 05:38:14 -04:00
|
|
|
}
|
|
|
|
|
2022-04-12 08:20:46 -04:00
|
|
|
// newConfig creates a new WireGuard configuration.
|
|
|
|
func newConfig(coordinatorPubKey, coordinatorPubIP, clientPrivKey string) (wgtypes.Config, error) {
|
2022-03-29 05:38:14 -04:00
|
|
|
_, allowedIPs, err := net.ParseCIDR("10.118.0.1/32")
|
|
|
|
if err != nil {
|
|
|
|
return wgtypes.Config{}, fmt.Errorf("parsing CIDR: %w", err)
|
|
|
|
}
|
|
|
|
|
2022-03-22 11:03:15 -04:00
|
|
|
coordinatorPubKeyParsed, err := wgtypes.ParseKey(coordinatorPubKey)
|
|
|
|
if err != nil {
|
2022-03-29 05:38:14 -04:00
|
|
|
return wgtypes.Config{}, fmt.Errorf("parsing coordinator public key: %w", err)
|
2022-03-22 11:03:15 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
var endpoint *net.UDPAddr
|
|
|
|
if ip := net.ParseIP(coordinatorPubIP); ip != nil {
|
|
|
|
endpoint = &net.UDPAddr{IP: ip, Port: wireguardPort}
|
|
|
|
} else {
|
|
|
|
endpoint = nil
|
|
|
|
}
|
|
|
|
clientPrivKeyParsed, err := wgtypes.ParseKey(clientPrivKey)
|
|
|
|
if err != nil {
|
2022-03-29 05:38:14 -04:00
|
|
|
return wgtypes.Config{}, fmt.Errorf("parsing client private key: %w", err)
|
2022-03-22 11:03:15 -04:00
|
|
|
}
|
|
|
|
listenPort := wireguardPort
|
|
|
|
|
|
|
|
keepAlive := 10 * time.Second
|
2022-03-29 05:38:14 -04:00
|
|
|
return wgtypes.Config{
|
2022-03-22 11:03:15 -04:00
|
|
|
PrivateKey: &clientPrivKeyParsed,
|
|
|
|
ListenPort: &listenPort,
|
|
|
|
ReplacePeers: false,
|
|
|
|
Peers: []wgtypes.PeerConfig{
|
|
|
|
{
|
|
|
|
PublicKey: coordinatorPubKeyParsed,
|
|
|
|
UpdateOnly: false,
|
|
|
|
Endpoint: endpoint,
|
|
|
|
AllowedIPs: []net.IPNet{*allowedIPs},
|
|
|
|
PersistentKeepaliveInterval: &keepAlive,
|
|
|
|
},
|
|
|
|
},
|
2022-03-29 05:38:14 -04:00
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewWGQuickConfig create a new WireGuard wg-quick configuration file and mashals it to bytes.
|
2022-04-12 08:20:46 -04:00
|
|
|
func NewWGQuickConfig(coordinatorPubKey, coordinatorPubIP, clientPrivKey, clientVPNIP string, mtu int) (*wgquick.Config, error) {
|
|
|
|
config, err := newConfig(coordinatorPubKey, coordinatorPubIP, clientPrivKey)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2022-03-29 05:38:14 -04:00
|
|
|
clientIP := net.ParseIP(clientVPNIP)
|
|
|
|
if clientIP == nil {
|
|
|
|
return nil, fmt.Errorf("invalid client vpn ip '%s'", clientVPNIP)
|
|
|
|
}
|
|
|
|
quickfile := wgquick.Config{
|
|
|
|
Config: config,
|
|
|
|
Address: []net.IPNet{{IP: clientIP, Mask: []byte{255, 255, 0, 0}}},
|
2022-03-31 10:40:59 -04:00
|
|
|
MTU: mtu,
|
2022-03-29 05:38:14 -04:00
|
|
|
}
|
2022-04-12 08:20:46 -04:00
|
|
|
return &quickfile, nil
|
2022-03-22 11:03:15 -04:00
|
|
|
}
|