constellation/cli/vpn/vpn.go

102 lines
2.8 KiB
Go
Raw Normal View History

package vpn
import (
2022-03-29 05:38:14 -04:00
"fmt"
"net"
"time"
2022-03-29 05:38:14 -04:00
wgquick "github.com/nmiculinic/wg-quick-go"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
)
const (
interfaceName = "wg0"
wireguardPort = 51820
)
type ConfigHandler struct {
up func(cfg *wgquick.Config, iface string) error
}
func NewConfigHandler() *ConfigHandler {
return &ConfigHandler{up: wgquick.Up}
}
func (h *ConfigHandler) Create(coordinatorPubKey, coordinatorPubIP, clientPrivKey, clientVPNIP string, mtu int) (*wgquick.Config, error) {
return NewWGQuickConfig(coordinatorPubKey, coordinatorPubIP, clientPrivKey, clientVPNIP, mtu)
}
// Apply applies the generated WireGuard quick config.
func (h *ConfigHandler) Apply(conf *wgquick.Config) error {
return h.up(conf, interfaceName)
}
// GetBytes returns the the bytes of the config.
func (h *ConfigHandler) Marshal(conf *wgquick.Config) ([]byte, error) {
data, err := conf.MarshalText()
if err != nil {
return nil, fmt.Errorf("marshal wg-quick config: %w", err)
}
return data, nil
2022-03-29 05:38:14 -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)
}
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)
}
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)
}
listenPort := wireguardPort
keepAlive := 10 * time.Second
2022-03-29 05:38:14 -04:00
return wgtypes.Config{
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.
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
}
return &quickfile, nil
}