mirror of
https://github.com/netbirdio/netbird.git
synced 2024-11-22 08:03:30 +01:00
feature: add Wireguard preshared-key support (#160)
This commit is contained in:
parent
edd4125742
commit
6b7d4cf644
@ -30,10 +30,9 @@ var (
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
config, err := internal.GetConfig(managementURL, configPath)
|
config, err := internal.GetConfig(managementURL, configPath, preSharedKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("failed getting config %s %v", configPath, err)
|
log.Errorf("failed getting config %s %v", configPath, err)
|
||||||
//os.Exit(ExitSetupFailed)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,7 +40,6 @@ var (
|
|||||||
myPrivateKey, err := wgtypes.ParseKey(config.PrivateKey)
|
myPrivateKey, err := wgtypes.ParseKey(config.PrivateKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("failed parsing Wireguard key %s: [%s]", config.PrivateKey, err.Error())
|
log.Errorf("failed parsing Wireguard key %s: [%s]", config.PrivateKey, err.Error())
|
||||||
//os.Exit(ExitSetupFailed)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,7 +54,6 @@ var (
|
|||||||
mgmClient, err := mgm.NewClient(ctx, config.ManagementURL.Host, myPrivateKey, mgmTlsEnabled)
|
mgmClient, err := mgm.NewClient(ctx, config.ManagementURL.Host, myPrivateKey, mgmTlsEnabled)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("failed connecting to Management Service %s %v", config.ManagementURL.String(), err)
|
log.Errorf("failed connecting to Management Service %s %v", config.ManagementURL.String(), err)
|
||||||
//os.Exit(ExitSetupFailed)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
log.Debugf("connected to anagement Service %s", config.ManagementURL.String())
|
log.Debugf("connected to anagement Service %s", config.ManagementURL.String())
|
||||||
@ -64,21 +61,18 @@ var (
|
|||||||
serverKey, err := mgmClient.GetServerPublicKey()
|
serverKey, err := mgmClient.GetServerPublicKey()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("failed while getting Management Service public key: %v", err)
|
log.Errorf("failed while getting Management Service public key: %v", err)
|
||||||
//os.Exit(ExitSetupFailed)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = loginPeer(*serverKey, mgmClient, setupKey)
|
_, err = loginPeer(*serverKey, mgmClient, setupKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("failed logging-in peer on Management Service : %v", err)
|
log.Errorf("failed logging-in peer on Management Service : %v", err)
|
||||||
//os.Exit(ExitSetupFailed)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = mgmClient.Close()
|
err = mgmClient.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("failed closing Management Service client: %v", err)
|
log.Errorf("failed closing Management Service client: %v", err)
|
||||||
//os.Exit(ExitSetupFailed)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ var (
|
|||||||
logFile string
|
logFile string
|
||||||
managementURL string
|
managementURL string
|
||||||
setupKey string
|
setupKey string
|
||||||
|
preSharedKey string
|
||||||
rootCmd = &cobra.Command{
|
rootCmd = &cobra.Command{
|
||||||
Use: "wiretrustee",
|
Use: "wiretrustee",
|
||||||
Short: "",
|
Short: "",
|
||||||
@ -53,6 +54,7 @@ func init() {
|
|||||||
rootCmd.PersistentFlags().StringVar(&logLevel, "log-level", "info", "sets Wiretrustee log level")
|
rootCmd.PersistentFlags().StringVar(&logLevel, "log-level", "info", "sets Wiretrustee log level")
|
||||||
rootCmd.PersistentFlags().StringVar(&logFile, "log-file", defaultLogFile, "sets Wiretrustee log path. If console is specified the the log will be output to stdout")
|
rootCmd.PersistentFlags().StringVar(&logFile, "log-file", defaultLogFile, "sets Wiretrustee log path. If console is specified the the log will be output to stdout")
|
||||||
rootCmd.PersistentFlags().StringVar(&setupKey, "setup-key", "", "Setup key obtained from the Management Service Dashboard (used to register peer)")
|
rootCmd.PersistentFlags().StringVar(&setupKey, "setup-key", "", "Setup key obtained from the Management Service Dashboard (used to register peer)")
|
||||||
|
rootCmd.PersistentFlags().StringVar(&preSharedKey, "preshared-key", "", "Sets Wireguard PreSharedKey property. If set, then only peers that have the same key can communicate.")
|
||||||
rootCmd.AddCommand(serviceCmd)
|
rootCmd.AddCommand(serviceCmd)
|
||||||
rootCmd.AddCommand(upCmd)
|
rootCmd.AddCommand(upCmd)
|
||||||
rootCmd.AddCommand(loginCmd)
|
rootCmd.AddCommand(loginCmd)
|
||||||
|
@ -63,12 +63,22 @@ func createEngineConfig(key wgtypes.Key, config *internal.Config, peerConfig *mg
|
|||||||
iFaceBlackList[config.IFaceBlackList[i]] = struct{}{}
|
iFaceBlackList[config.IFaceBlackList[i]] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &internal.EngineConfig{
|
engineConf := &internal.EngineConfig{
|
||||||
WgIface: config.WgIface,
|
WgIface: config.WgIface,
|
||||||
WgAddr: peerConfig.Address,
|
WgAddr: peerConfig.Address,
|
||||||
IFaceBlackList: iFaceBlackList,
|
IFaceBlackList: iFaceBlackList,
|
||||||
WgPrivateKey: key,
|
WgPrivateKey: key,
|
||||||
}, nil
|
}
|
||||||
|
|
||||||
|
if config.PreSharedKey != "" {
|
||||||
|
preSharedKey, err := wgtypes.ParseKey(config.PreSharedKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
engineConf.PreSharedKey = &preSharedKey
|
||||||
|
}
|
||||||
|
|
||||||
|
return engineConf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// connectToSignal creates Signal Service client and established a connection
|
// connectToSignal creates Signal Service client and established a connection
|
||||||
|
@ -28,13 +28,14 @@ func init() {
|
|||||||
type Config struct {
|
type Config struct {
|
||||||
// Wireguard private key of local peer
|
// Wireguard private key of local peer
|
||||||
PrivateKey string
|
PrivateKey string
|
||||||
|
PreSharedKey string
|
||||||
ManagementURL *url.URL
|
ManagementURL *url.URL
|
||||||
WgIface string
|
WgIface string
|
||||||
IFaceBlackList []string
|
IFaceBlackList []string
|
||||||
}
|
}
|
||||||
|
|
||||||
//createNewConfig creates a new config generating a new Wireguard key and saving to file
|
//createNewConfig creates a new config generating a new Wireguard key and saving to file
|
||||||
func createNewConfig(managementURL string, configPath string) (*Config, error) {
|
func createNewConfig(managementURL string, configPath string, preSharedKey string) (*Config, error) {
|
||||||
wgKey := generateKey()
|
wgKey := generateKey()
|
||||||
config := &Config{PrivateKey: wgKey, WgIface: iface.WgInterfaceDefault, IFaceBlackList: []string{}}
|
config := &Config{PrivateKey: wgKey, WgIface: iface.WgInterfaceDefault, IFaceBlackList: []string{}}
|
||||||
if managementURL != "" {
|
if managementURL != "" {
|
||||||
@ -47,6 +48,10 @@ func createNewConfig(managementURL string, configPath string) (*Config, error) {
|
|||||||
config.ManagementURL = managementURLDefault
|
config.ManagementURL = managementURLDefault
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if preSharedKey != "" {
|
||||||
|
config.PreSharedKey = preSharedKey
|
||||||
|
}
|
||||||
|
|
||||||
config.IFaceBlackList = []string{iface.WgInterfaceDefault, "tun0"}
|
config.IFaceBlackList = []string{iface.WgInterfaceDefault, "tun0"}
|
||||||
|
|
||||||
err := util.WriteJson(configPath, config)
|
err := util.WriteJson(configPath, config)
|
||||||
@ -93,11 +98,11 @@ func ReadConfig(managementURL string, configPath string) (*Config, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetConfig reads existing config or generates a new one
|
// GetConfig reads existing config or generates a new one
|
||||||
func GetConfig(managementURL string, configPath string) (*Config, error) {
|
func GetConfig(managementURL string, configPath string, preSharedKey string) (*Config, error) {
|
||||||
|
|
||||||
if _, err := os.Stat(configPath); os.IsNotExist(err) {
|
if _, err := os.Stat(configPath); os.IsNotExist(err) {
|
||||||
log.Infof("generating new config %s", configPath)
|
log.Infof("generating new config %s", configPath)
|
||||||
return createNewConfig(managementURL, configPath)
|
return createNewConfig(managementURL, configPath, preSharedKey)
|
||||||
} else {
|
} else {
|
||||||
return ReadConfig(managementURL, configPath)
|
return ReadConfig(managementURL, configPath)
|
||||||
}
|
}
|
||||||
|
@ -60,6 +60,8 @@ type ConnConfig struct {
|
|||||||
// Remote Wireguard public key
|
// Remote Wireguard public key
|
||||||
RemoteWgKey wgtypes.Key
|
RemoteWgKey wgtypes.Key
|
||||||
|
|
||||||
|
PreSharedKey *wgtypes.Key
|
||||||
|
|
||||||
StunTurnURLS []*ice.URL
|
StunTurnURLS []*ice.URL
|
||||||
|
|
||||||
iFaceBlackList map[string]struct{}
|
iFaceBlackList map[string]struct{}
|
||||||
@ -115,7 +117,7 @@ func NewConnection(config ConnConfig,
|
|||||||
closeCond: NewCond(),
|
closeCond: NewCond(),
|
||||||
connected: NewCond(),
|
connected: NewCond(),
|
||||||
agent: nil,
|
agent: nil,
|
||||||
wgProxy: NewWgProxy(config.WgIface, config.RemoteWgKey.String(), config.WgAllowedIPs, config.WgListenAddr),
|
wgProxy: NewWgProxy(config.WgIface, config.RemoteWgKey.String(), config.WgAllowedIPs, config.WgListenAddr, config.PreSharedKey),
|
||||||
Status: StatusDisconnected,
|
Status: StatusDisconnected,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,8 @@ type EngineConfig struct {
|
|||||||
WgPrivateKey wgtypes.Key
|
WgPrivateKey wgtypes.Key
|
||||||
// IFaceBlackList is a list of network interfaces to ignore when discovering connection candidates (ICE related)
|
// IFaceBlackList is a list of network interfaces to ignore when discovering connection candidates (ICE related)
|
||||||
IFaceBlackList map[string]struct{}
|
IFaceBlackList map[string]struct{}
|
||||||
|
|
||||||
|
PreSharedKey *wgtypes.Key
|
||||||
}
|
}
|
||||||
|
|
||||||
// Engine is a mechanism responsible for reacting on Signal and Management stream events and managing connections to the remote peers.
|
// Engine is a mechanism responsible for reacting on Signal and Management stream events and managing connections to the remote peers.
|
||||||
@ -238,6 +240,7 @@ func (e *Engine) openPeerConnection(wgPort int, myKey wgtypes.Key, peer Peer) (*
|
|||||||
RemoteWgKey: remoteKey,
|
RemoteWgKey: remoteKey,
|
||||||
StunTurnURLS: append(e.STUNs, e.TURNs...),
|
StunTurnURLS: append(e.STUNs, e.TURNs...),
|
||||||
iFaceBlackList: e.config.IFaceBlackList,
|
iFaceBlackList: e.config.IFaceBlackList,
|
||||||
|
PreSharedKey: e.config.PreSharedKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
signalOffer := func(uFrag string, pwd string) error {
|
signalOffer := func(uFrag string, pwd string) error {
|
||||||
|
@ -4,27 +4,30 @@ import (
|
|||||||
ice "github.com/pion/ice/v2"
|
ice "github.com/pion/ice/v2"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/wiretrustee/wiretrustee/iface"
|
"github.com/wiretrustee/wiretrustee/iface"
|
||||||
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
"net"
|
"net"
|
||||||
)
|
)
|
||||||
|
|
||||||
// WgProxy an instance of an instance of the Connection Wireguard Proxy
|
// WgProxy an instance of an instance of the Connection Wireguard Proxy
|
||||||
type WgProxy struct {
|
type WgProxy struct {
|
||||||
iface string
|
iface string
|
||||||
remoteKey string
|
remoteKey string
|
||||||
allowedIps string
|
allowedIps string
|
||||||
wgAddr string
|
wgAddr string
|
||||||
close chan struct{}
|
close chan struct{}
|
||||||
wgConn net.Conn
|
wgConn net.Conn
|
||||||
|
preSharedKey *wgtypes.Key
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewWgProxy creates a new Connection Wireguard Proxy
|
// NewWgProxy creates a new Connection Wireguard Proxy
|
||||||
func NewWgProxy(iface string, remoteKey string, allowedIps string, wgAddr string) *WgProxy {
|
func NewWgProxy(iface string, remoteKey string, allowedIps string, wgAddr string, preSharedKey *wgtypes.Key) *WgProxy {
|
||||||
return &WgProxy{
|
return &WgProxy{
|
||||||
iface: iface,
|
iface: iface,
|
||||||
remoteKey: remoteKey,
|
remoteKey: remoteKey,
|
||||||
allowedIps: allowedIps,
|
allowedIps: allowedIps,
|
||||||
wgAddr: wgAddr,
|
wgAddr: wgAddr,
|
||||||
close: make(chan struct{}),
|
close: make(chan struct{}),
|
||||||
|
preSharedKey: preSharedKey,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,7 +51,7 @@ func (p *WgProxy) Close() error {
|
|||||||
|
|
||||||
// StartLocal configure the interface with a peer using a direct IP:Port endpoint to the remote host
|
// StartLocal configure the interface with a peer using a direct IP:Port endpoint to the remote host
|
||||||
func (p *WgProxy) StartLocal(host string) error {
|
func (p *WgProxy) StartLocal(host string) error {
|
||||||
err := iface.UpdatePeer(p.iface, p.remoteKey, p.allowedIps, DefaultWgKeepAlive, host)
|
err := iface.UpdatePeer(p.iface, p.remoteKey, p.allowedIps, DefaultWgKeepAlive, host, p.preSharedKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("error while configuring Wireguard peer [%s] %s", p.remoteKey, err.Error())
|
log.Errorf("error while configuring Wireguard peer [%s] %s", p.remoteKey, err.Error())
|
||||||
return err
|
return err
|
||||||
@ -67,7 +70,7 @@ func (p *WgProxy) Start(remoteConn *ice.Conn) error {
|
|||||||
p.wgConn = wgConn
|
p.wgConn = wgConn
|
||||||
// add local proxy connection as a Wireguard peer
|
// add local proxy connection as a Wireguard peer
|
||||||
err = iface.UpdatePeer(p.iface, p.remoteKey, p.allowedIps, DefaultWgKeepAlive,
|
err = iface.UpdatePeer(p.iface, p.remoteKey, p.allowedIps, DefaultWgKeepAlive,
|
||||||
wgConn.LocalAddr().String())
|
wgConn.LocalAddr().String(), p.preSharedKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("error while configuring Wireguard peer [%s] %s", p.remoteKey, err.Error())
|
log.Errorf("error while configuring Wireguard peer [%s] %s", p.remoteKey, err.Error())
|
||||||
return err
|
return err
|
||||||
@ -92,13 +95,11 @@ func (p *WgProxy) proxyToRemotePeer(remoteConn *ice.Conn) {
|
|||||||
default:
|
default:
|
||||||
n, err := p.wgConn.Read(buf)
|
n, err := p.wgConn.Read(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
//log.Warnln("failed reading from peer: ", err.Error())
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = remoteConn.Write(buf[:n])
|
_, err = remoteConn.Write(buf[:n])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
//log.Warnln("failed writing to remote peer: ", err.Error())
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -118,13 +119,11 @@ func (p *WgProxy) proxyToLocalWireguard(remoteConn *ice.Conn) {
|
|||||||
default:
|
default:
|
||||||
n, err := remoteConn.Read(buf)
|
n, err := remoteConn.Read(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
//log.Errorf("failed reading from remote connection %s", err)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = p.wgConn.Write(buf[:n])
|
_, err = p.wgConn.Write(buf[:n])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
//log.Errorf("failed writing to local Wireguard instance %s", err)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -146,7 +146,7 @@ func GetListenPort(iface string) (*int, error) {
|
|||||||
|
|
||||||
// UpdatePeer updates existing Wireguard Peer or creates a new one if doesn't exist
|
// UpdatePeer updates existing Wireguard Peer or creates a new one if doesn't exist
|
||||||
// Endpoint is optional
|
// Endpoint is optional
|
||||||
func UpdatePeer(iface string, peerKey string, allowedIps string, keepAlive time.Duration, endpoint string) error {
|
func UpdatePeer(iface string, peerKey string, allowedIps string, keepAlive time.Duration, endpoint string, preSharedKey *wgtypes.Key) error {
|
||||||
|
|
||||||
log.Debugf("updating interface %s peer %s: endpoint %s ", iface, peerKey, endpoint)
|
log.Debugf("updating interface %s peer %s: endpoint %s ", iface, peerKey, endpoint)
|
||||||
|
|
||||||
@ -165,6 +165,7 @@ func UpdatePeer(iface string, peerKey string, allowedIps string, keepAlive time.
|
|||||||
ReplaceAllowedIPs: true,
|
ReplaceAllowedIPs: true,
|
||||||
AllowedIPs: []net.IPNet{*ipNet},
|
AllowedIPs: []net.IPNet{*ipNet},
|
||||||
PersistentKeepaliveInterval: &keepAlive,
|
PersistentKeepaliveInterval: &keepAlive,
|
||||||
|
PresharedKey: preSharedKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
config := wgtypes.Config{
|
config := wgtypes.Config{
|
||||||
|
@ -111,7 +111,7 @@ func Test_UpdatePeer(t *testing.T) {
|
|||||||
keepAlive := 15 * time.Second
|
keepAlive := 15 * time.Second
|
||||||
allowedIP := "10.99.99.2/32"
|
allowedIP := "10.99.99.2/32"
|
||||||
endpoint := "127.0.0.1:9900"
|
endpoint := "127.0.0.1:9900"
|
||||||
err = UpdatePeer(ifaceName, peerPubKey, allowedIP, keepAlive, endpoint)
|
err = UpdatePeer(ifaceName, peerPubKey, allowedIP, keepAlive, endpoint, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -163,7 +163,7 @@ func Test_UpdatePeerEndpoint(t *testing.T) {
|
|||||||
keepAlive := 15 * time.Second
|
keepAlive := 15 * time.Second
|
||||||
allowedIP := "10.99.99.2/32"
|
allowedIP := "10.99.99.2/32"
|
||||||
endpoint := "127.0.0.1:9900"
|
endpoint := "127.0.0.1:9900"
|
||||||
err = UpdatePeer(ifaceName, peerPubKey, allowedIP, keepAlive, endpoint)
|
err = UpdatePeer(ifaceName, peerPubKey, allowedIP, keepAlive, endpoint, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -204,7 +204,7 @@ func Test_RemovePeer(t *testing.T) {
|
|||||||
keepAlive := 15 * time.Second
|
keepAlive := 15 * time.Second
|
||||||
allowedIP := "10.99.99.2/32"
|
allowedIP := "10.99.99.2/32"
|
||||||
endpoint := "127.0.0.1:9900"
|
endpoint := "127.0.0.1:9900"
|
||||||
err = UpdatePeer(ifaceName, peerPubKey, allowedIP, keepAlive, endpoint)
|
err = UpdatePeer(ifaceName, peerPubKey, allowedIP, keepAlive, endpoint, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user