diff --git a/logic/server.go b/logic/server.go index c2b738d2..a23c0ffa 100644 --- a/logic/server.go +++ b/logic/server.go @@ -136,7 +136,7 @@ func ServerJoin(network string, serverID string, privateKey string) error { return err } - err = initWireguard(node, privateKey, peers, hasGateway, gateways) + err = initWireguard(node, privateKey, peers, hasGateway, gateways, 0) if err != nil { return err } diff --git a/logic/wireguard.go b/logic/wireguard.go index bc578cb7..179f02c1 100644 --- a/logic/wireguard.go +++ b/logic/wireguard.go @@ -70,7 +70,7 @@ func setWGConfig(node models.Node, network string, peerupdate bool) error { return err } -func initWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig, hasGateway bool, gateways []string) error { +func initWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig, hasGateway bool, gateways []string, fwmark int32) error { key, err := wgtypes.ParseKey(privkey) if err != nil { @@ -108,7 +108,7 @@ func initWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig if !ncutils.IsKernel() { var newConf string - newConf, _ = ncutils.CreateUserSpaceConf(node.Address, key.String(), strconv.FormatInt(int64(node.ListenPort), 10), node.MTU, node.PersistentKeepalive, peers) + newConf, _ = ncutils.CreateUserSpaceConf(node.Address, key.String(), strconv.FormatInt(int64(node.ListenPort), 10), node.MTU, fwmark, node.PersistentKeepalive, peers) confPath := ncutils.GetNetclientPathSpecific() + ifacename + ".conf" Log("writing wg conf file to: "+confPath, 1) err = ioutil.WriteFile(confPath, []byte(newConf), 0644) @@ -290,7 +290,7 @@ func setServerPeers(iface string, keepalive int32, peers []wgtypes.PeerConfig) e return nil } -func setWGKeyConfig(node models.Node) error { +func setWGConfig(node models.Node) error { node.SetID() privatekey, err := wgtypes.GeneratePrivateKey() diff --git a/netclient/config/config.go b/netclient/config/config.go index d7d39d2f..53e87f69 100644 --- a/netclient/config/config.go +++ b/netclient/config/config.go @@ -30,6 +30,7 @@ type ClientConfig struct { Daemon string `yaml:"daemon"` OperatingSystem string `yaml:"operatingsystem"` DebugJoin bool `yaml:"debugjoin"` + FWMark int32 `yaml:"fwmark"` } // ServerConfig - struct for dealing with the server information for a netclient diff --git a/netclient/daemon/macos.go b/netclient/daemon/macos.go index 55ffc2ff..c00a618e 100644 --- a/netclient/daemon/macos.go +++ b/netclient/daemon/macos.go @@ -2,11 +2,12 @@ package daemon import ( "fmt" - "github.com/gravitl/netmaker/netclient/ncutils" "io/ioutil" "log" "os" "path/filepath" + + "github.com/gravitl/netmaker/netclient/ncutils" ) const MAC_SERVICE_NAME = "com.gravitl.netclient" @@ -20,7 +21,7 @@ func SetupMacDaemon(interval string) error { binarypath := dir + "/netclient" if !ncutils.FileExists("/etc/netclient/netclient") { - _, err = ncutils.Copy(binarypath, "/etc/netclient/netclient") + err = ncutils.Copy(binarypath, "/etc/netclient/netclient") if err != nil { log.Println(err) return err diff --git a/netclient/daemon/systemd.go b/netclient/daemon/systemd.go index 5fdea1e9..3bbcb4ce 100644 --- a/netclient/daemon/systemd.go +++ b/netclient/daemon/systemd.go @@ -35,7 +35,7 @@ func SetupSystemDDaemon(interval string) error { os.Symlink("/etc/netclient/netclient", "/usr/local/bin/netclient") } if !ncutils.FileExists("/etc/netclient/netclient") { - _, err = ncutils.Copy(binarypath, "/etc/netclient/netclient") + err = ncutils.Copy(binarypath, "/etc/netclient/netclient") if err != nil { log.Println(err) return err diff --git a/netclient/freebsd/peers.go b/netclient/freebsd/peers.go index dea81c82..fe94b3d8 100644 --- a/netclient/freebsd/peers.go +++ b/netclient/freebsd/peers.go @@ -1,21 +1,11 @@ package wireguard import ( - "fmt" - "io/ioutil" "log" - "os" - "os/exec" - "runtime" "strconv" "strings" - "time" - "github.com/gravitl/netmaker/models" - "github.com/gravitl/netmaker/netclient/config" - "github.com/gravitl/netmaker/netclient/local" "github.com/gravitl/netmaker/netclient/ncutils" - "github.com/gravitl/netmaker/netclient/server" "golang.zx2c4.com/wireguard/wgctrl/internal/wguser" "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) diff --git a/netclient/functions/join.go b/netclient/functions/join.go index d2767b07..2577c2e6 100644 --- a/netclient/functions/join.go +++ b/netclient/functions/join.go @@ -6,7 +6,9 @@ import ( "errors" "fmt" "log" + "math/rand" "os/exec" + "time" nodepb "github.com/gravitl/netmaker/grpc" "github.com/gravitl/netmaker/models" @@ -34,6 +36,13 @@ func JoinNetwork(cfg config.ClientConfig, privateKey string) error { err := errors.New("ALREADY_INSTALLED. Netclient appears to already be installed for " + cfg.Network + ". To re-install, please remove by executing 'sudo netclient leave -n " + cfg.Network + "'. Then re-run the install command.") return err } + if cfg.FWMark == 0 { + rand.Seed(time.Now().UnixNano()) + var min int32 = 1000 + var max int32 = 9999 + cfg.FWMark = rand.Int31n(max-min) + min + } + err = config.Write(&cfg, cfg.Network) if err != nil { return err diff --git a/netclient/ncutils/netclientutils.go b/netclient/ncutils/netclientutils.go index bc591266..9c90408e 100644 --- a/netclient/ncutils/netclientutils.go +++ b/netclient/ncutils/netclientutils.go @@ -2,7 +2,6 @@ package ncutils import ( "context" - "syscall" "crypto/tls" "errors" "fmt" @@ -17,7 +16,9 @@ import ( "runtime" "strconv" "strings" + "syscall" "time" + "golang.zx2c4.com/wireguard/wgctrl" "golang.zx2c4.com/wireguard/wgctrl/wgtypes" "google.golang.org/grpc" @@ -188,15 +189,19 @@ PersistentKeepAlive = %s } // CreateUserSpaceConf - creates a user space WireGuard conf -func CreateUserSpaceConf(address string, privatekey string, listenPort string, mtu int32, perskeepalive int32, peers []wgtypes.PeerConfig) (string, error) { +func CreateUserSpaceConf(address string, privatekey string, listenPort string, mtu int32, fwmark int32, perskeepalive int32, peers []wgtypes.PeerConfig) (string, error) { peersString, err := parsePeers(perskeepalive, peers) - listenPortString := "" + var listenPortString string + var fwmarkString string if mtu <= 0 { mtu = 1280 } if listenPort != "" { listenPortString += "ListenPort = " + listenPort } + if fwmark != 0 { + fwmarkString += "FWMark = " + strconv.Itoa(int(fwmark)) + } if err != nil { return "", err } @@ -205,6 +210,7 @@ Address = %s PrivateKey = %s MTU = %s %s +%s %s @@ -213,6 +219,7 @@ MTU = %s privatekey, strconv.Itoa(int(mtu)), listenPortString, + fwmarkString, peersString) return config, nil } @@ -342,44 +349,44 @@ func GRPCRequestOpts(isSecure string) grpc.DialOption { } // Copy - copies a src file to dest -func Copy(src, dst string) (int64, error) { +func Copy(src, dst string) error { sourceFileStat, err := os.Stat(src) if err != nil { - return 0, err + return err } if !sourceFileStat.Mode().IsRegular() { - return 0, errors.New(src + " is not a regular file") + return errors.New(src + " is not a regular file") } source, err := os.Open(src) if err != nil { - return 0, err + return err } defer source.Close() destination, err := os.Create(dst) if err != nil { - return 0, err + return err } defer destination.Close() - nBytes, err := io.Copy(destination, source) - err = os.Chmod(dst, 0755) + _, err = io.Copy(destination, source) if err != nil { - log.Println(err) + return err } - return nBytes, err + err = os.Chmod(dst, 0755) + return err } // RunCmd - runs a local command func RunCmd(command string, printerr bool) (string, error) { args := strings.Fields(command) ctx, cancel := context.WithTimeout(context.Background(), time.Second) - defer cancel() + defer cancel() cmd := exec.Command(args[0], args[1:]...) cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} go func() { - <- ctx.Done() + <-ctx.Done() _ = syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL) }() out, err := cmd.CombinedOutput() diff --git a/netclient/wireguard/common.go b/netclient/wireguard/common.go index 064fc181..a91f4043 100644 --- a/netclient/wireguard/common.go +++ b/netclient/wireguard/common.go @@ -6,6 +6,7 @@ import ( "log" "os" "os/exec" + "reflect" "runtime" "strconv" "strings" @@ -30,23 +31,23 @@ func SetPeers(iface string, keepalive int32, peers []wgtypes.PeerConfig) error { return err } } else { - client, err := wgctrl.New() - if err != nil { - ncutils.PrintLog("failed to start wgctrl", 0) - return err - } - device, err := client.Device(iface) - if err != nil { - ncutils.PrintLog("failed to parse interface", 0) - return err - } - devicePeers = device.Peers + client, err := wgctrl.New() + if err != nil { + ncutils.PrintLog("failed to start wgctrl", 0) + return err + } + device, err := client.Device(iface) + if err != nil { + ncutils.PrintLog("failed to parse interface", 0) + return err + } + devicePeers = device.Peers } if len(devicePeers) > 1 && len(peers) == 0 { ncutils.PrintLog("no peers pulled", 1) return err } - +PEERS: for _, peer := range peers { for _, currentPeer := range devicePeers { @@ -56,7 +57,13 @@ func SetPeers(iface string, keepalive int32, peers []wgtypes.PeerConfig) error { if err != nil { log.Println("error removing peer", peer.Endpoint.String()) } + } else if currentPeer.PublicKey.String() == peer.PublicKey.String() && + currentPeer.Endpoint.String() == peer.Endpoint.String() && + reflect.DeepEqual(currentPeer.AllowedIPs, peer.AllowedIPs) { + + continue PEERS } + } udpendpoint := peer.Endpoint.String() var allowedips string @@ -67,7 +74,7 @@ func SetPeers(iface string, keepalive int32, peers []wgtypes.PeerConfig) error { allowedips = strings.Join(iparr, ",") keepAliveString := strconv.Itoa(int(keepalive)) if keepAliveString == "0" { - keepAliveString = "5" + keepAliveString = "15" } if peer.Endpoint != nil { _, err = ncutils.RunCmd("wg set "+iface+" peer "+peer.PublicKey.String()+ @@ -119,7 +126,7 @@ func InitWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig if err != nil { return err } - + fwmark := modcfg.FWMark nodecfg := modcfg.Node servercfg := modcfg.Server @@ -174,9 +181,9 @@ func InitWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig if !ncutils.IsKernel() { var newConf string if node.UDPHolePunch != "yes" { - newConf, _ = ncutils.CreateUserSpaceConf(node.Address, key.String(), strconv.FormatInt(int64(node.ListenPort), 10), node.MTU, node.PersistentKeepalive, peers) + newConf, _ = ncutils.CreateUserSpaceConf(node.Address, key.String(), strconv.FormatInt(int64(node.ListenPort), 10), node.MTU, fwmark, node.PersistentKeepalive, peers) } else { - newConf, _ = ncutils.CreateUserSpaceConf(node.Address, key.String(), "", node.MTU, node.PersistentKeepalive, peers) + newConf, _ = ncutils.CreateUserSpaceConf(node.Address, key.String(), "", node.MTU, fwmark, node.PersistentKeepalive, peers) } confPath := ncutils.GetNetclientPathSpecific() + ifacename + ".conf" ncutils.PrintLog("writing wg conf file to: "+confPath, 1)