2021-08-31 03:58:23 +08:00
//go:generate goversioninfo -icon=windowsdata/resource/netmaker.ico -manifest=netclient.exe.manifest.xml -64=true -o=netclient.syso
2021-03-26 00:17:52 +08:00
package main
import (
2021-07-26 02:22:20 +08:00
"errors"
"log"
"os"
"os/exec"
2021-08-31 03:58:23 +08:00
"os/signal"
2021-09-20 02:03:47 +08:00
"runtime/debug"
2021-07-26 02:22:20 +08:00
"strconv"
2021-08-31 03:58:23 +08:00
"syscall"
2021-09-20 02:03:47 +08:00
2021-07-26 02:22:20 +08:00
"github.com/gravitl/netmaker/netclient/command"
"github.com/gravitl/netmaker/netclient/config"
2021-08-03 06:06:26 +08:00
"github.com/gravitl/netmaker/netclient/local"
2021-09-20 02:03:47 +08:00
"github.com/gravitl/netmaker/netclient/ncutils"
2021-08-31 03:58:23 +08:00
"github.com/gravitl/netmaker/netclient/ncwindows"
2021-07-26 02:22:20 +08:00
"github.com/urfave/cli/v2"
2021-03-26 00:17:52 +08:00
)
func main ( ) {
2021-07-26 02:22:20 +08:00
app := cli . NewApp ( )
app . Name = "Netclient CLI"
app . Usage = "Netmaker's netclient agent and CLI. Used to perform interactions with Netmaker server and set local WireGuard config."
2021-11-09 01:15:20 +08:00
app . Version = "v0.8.6"
2021-03-26 00:17:52 +08:00
2021-10-20 03:53:01 +08:00
hostname , err := os . Hostname ( )
if err != nil {
hostname = ""
}
2021-03-26 00:17:52 +08:00
2021-07-26 02:22:20 +08:00
cliFlags := [ ] cli . Flag {
& cli . StringFlag {
Name : "network" ,
Aliases : [ ] string { "n" } ,
EnvVars : [ ] string { "NETCLIENT_NETWORK" } ,
Value : "all" ,
Usage : "Network to perform specified action against." ,
} ,
& cli . StringFlag {
Name : "password" ,
Aliases : [ ] string { "p" } ,
EnvVars : [ ] string { "NETCLIENT_PASSWORD" } ,
2021-08-06 01:19:55 +08:00
Value : "" ,
2021-07-26 02:22:20 +08:00
Usage : "Password for authenticating with netmaker." ,
} ,
& cli . StringFlag {
Name : "endpoint" ,
Aliases : [ ] string { "e" } ,
EnvVars : [ ] string { "NETCLIENT_ENDPOINT" } ,
Value : "" ,
Usage : "Reachable (usually public) address for WireGuard (not the private WG address)." ,
} ,
& cli . StringFlag {
Name : "macaddress" ,
Aliases : [ ] string { "m" } ,
EnvVars : [ ] string { "NETCLIENT_MACADDRESS" } ,
Value : "" ,
Usage : "Mac Address for this machine. Used as a unique identifier within Netmaker network." ,
} ,
& cli . StringFlag {
Name : "publickey" ,
Aliases : [ ] string { "pubkey" } ,
EnvVars : [ ] string { "NETCLIENT_PUBLICKEY" } ,
Value : "" ,
Usage : "Public Key for WireGuard Interface." ,
} ,
& cli . StringFlag {
Name : "privatekey" ,
Aliases : [ ] string { "privkey" } ,
EnvVars : [ ] string { "NETCLIENT_PRIVATEKEY" } ,
Value : "" ,
Usage : "Private Key for WireGuard Interface." ,
} ,
& cli . StringFlag {
Name : "port" ,
EnvVars : [ ] string { "NETCLIENT_PORT" } ,
Value : "" ,
Usage : "Port for WireGuard Interface." ,
} ,
& cli . IntFlag {
Name : "keepalive" ,
EnvVars : [ ] string { "NETCLIENT_KEEPALIVE" } ,
Value : 0 ,
Usage : "Default PersistentKeepAlive for Peers in WireGuard Interface." ,
} ,
& cli . StringFlag {
Name : "operatingsystem" ,
Aliases : [ ] string { "os" } ,
EnvVars : [ ] string { "NETCLIENT_OS" } ,
Value : "" ,
Usage : "Identifiable name for machine within Netmaker network." ,
} ,
& cli . StringFlag {
Name : "name" ,
EnvVars : [ ] string { "NETCLIENT_NAME" } ,
2021-10-15 17:47:13 +08:00
Value : hostname ,
2021-07-26 02:22:20 +08:00
Usage : "Identifiable name for machine within Netmaker network." ,
} ,
& cli . StringFlag {
Name : "localaddress" ,
EnvVars : [ ] string { "NETCLIENT_LOCALADDRESS" } ,
Value : "" ,
Usage : "Local address for machine. Can be used in place of Endpoint for machines on the same LAN." ,
} ,
& cli . StringFlag {
Name : "address" ,
Aliases : [ ] string { "a" } ,
EnvVars : [ ] string { "NETCLIENT_ADDRESS" } ,
Value : "" ,
Usage : "WireGuard address for machine within Netmaker network." ,
} ,
& cli . StringFlag {
Name : "addressIPv6" ,
Aliases : [ ] string { "a6" } ,
EnvVars : [ ] string { "NETCLIENT_ADDRESSIPV6" } ,
Value : "" ,
Usage : "WireGuard address for machine within Netmaker network." ,
} ,
& cli . StringFlag {
Name : "interface" ,
Aliases : [ ] string { "i" } ,
EnvVars : [ ] string { "NETCLIENT_INTERFACE" } ,
Value : "" ,
Usage : "WireGuard local network interface name." ,
} ,
& cli . StringFlag {
Name : "apiserver" ,
EnvVars : [ ] string { "NETCLIENT_API_SERVER" } ,
Value : "" ,
Usage : "Address + GRPC Port (e.g. 1.2.3.4:50051) of Netmaker server." ,
} ,
& cli . StringFlag {
Name : "grpcserver" ,
EnvVars : [ ] string { "NETCLIENT_GRPC_SERVER" } ,
Value : "" ,
Usage : "Address + API Port (e.g. 1.2.3.4:8081) of Netmaker server." ,
} ,
& cli . StringFlag {
Name : "key" ,
Aliases : [ ] string { "k" } ,
EnvVars : [ ] string { "NETCLIENT_ACCESSKEY" } ,
Value : "" ,
Usage : "Access Key for signing up machine with Netmaker server during initial 'add'." ,
} ,
& cli . StringFlag {
Name : "token" ,
Aliases : [ ] string { "t" } ,
EnvVars : [ ] string { "NETCLIENT_ACCESSTOKEN" } ,
Value : "" ,
Usage : "Access Token for signing up machine with Netmaker server during initial 'add'." ,
} ,
& cli . StringFlag {
Name : "localrange" ,
EnvVars : [ ] string { "NETCLIENT_LOCALRANGE" } ,
Value : "" ,
Usage : "Local Range if network is local, for instance 192.168.1.0/24." ,
} ,
& cli . StringFlag {
2021-08-12 00:19:28 +08:00
Name : "dnson" ,
2021-07-26 02:22:20 +08:00
EnvVars : [ ] string { "NETCLIENT_DNS" } ,
2021-08-12 00:19:28 +08:00
Value : "yes" ,
Usage : "Sets private dns if 'yes'. Ignores if 'no'. Will retrieve from network if unset." ,
2021-07-26 02:22:20 +08:00
} ,
& cli . StringFlag {
Name : "islocal" ,
EnvVars : [ ] string { "NETCLIENT_IS_LOCAL" } ,
Value : "" ,
Usage : "Sets endpoint to local address if 'yes'. Ignores if 'no'. Will retrieve from network if unset." ,
} ,
& cli . StringFlag {
Name : "isdualstack" ,
EnvVars : [ ] string { "NETCLIENT_IS_DUALSTACK" } ,
Value : "" ,
Usage : "Sets ipv6 address if 'yes'. Ignores if 'no'. Will retrieve from network if unset." ,
} ,
& cli . StringFlag {
Name : "udpholepunch" ,
EnvVars : [ ] string { "NETCLIENT_UDP_HOLEPUNCH" } ,
Value : "" ,
Usage : "Turns on udp holepunching if 'yes'. Ignores if 'no'. Will retrieve from network if unset." ,
} ,
& cli . StringFlag {
Name : "ipforwarding" ,
EnvVars : [ ] string { "NETCLIENT_IPFORWARDING" } ,
Value : "on" ,
Usage : "Sets ip forwarding on if 'on'. Ignores if 'off'. On by default." ,
} ,
& cli . StringFlag {
Name : "postup" ,
EnvVars : [ ] string { "NETCLIENT_POSTUP" } ,
Value : "" ,
Usage : "Sets PostUp command for WireGuard." ,
} ,
& cli . StringFlag {
Name : "postdown" ,
EnvVars : [ ] string { "NETCLIENT_POSTDOWN" } ,
Value : "" ,
Usage : "Sets PostDown command for WireGuard." ,
} ,
& cli . StringFlag {
Name : "daemon" ,
EnvVars : [ ] string { "NETCLIENT_DAEMON" } ,
Value : "on" ,
Usage : "Installs daemon if 'on'. Ignores if 'off'. On by default." ,
} ,
& cli . StringFlag {
Name : "roaming" ,
EnvVars : [ ] string { "NETCLIENT_ROAMING" } ,
Value : "on" ,
Usage : "Checks for IP changes if 'on'. Ignores if 'off'. On by default." ,
} ,
}
2021-03-28 00:50:27 +08:00
2021-07-26 02:22:20 +08:00
app . Commands = [ ] * cli . Command {
{
Name : "join" ,
Usage : "Join a Netmaker network." ,
Flags : cliFlags ,
Action : func ( c * cli . Context ) error {
2021-08-03 06:06:26 +08:00
cfg , pvtKey , err := config . GetCLIConfig ( c )
2021-07-26 02:22:20 +08:00
if err != nil {
return err
}
if cfg . Network == "all" {
err = errors . New ( "No network provided." )
return err
}
if cfg . Server . GRPCAddress == "" {
err = errors . New ( "No server address provided." )
return err
}
2021-08-03 06:06:26 +08:00
err = command . Join ( cfg , pvtKey )
2021-07-26 02:22:20 +08:00
return err
} ,
} ,
{
Name : "leave" ,
Usage : "Leave a Netmaker network." ,
Flags : cliFlags ,
// the action, or code that will be executed when
// we execute our `ns` command
Action : func ( c * cli . Context ) error {
2021-08-03 06:06:26 +08:00
cfg , _ , err := config . GetCLIConfig ( c )
2021-07-26 02:22:20 +08:00
if err != nil {
return err
}
err = command . Leave ( cfg )
return err
} ,
} ,
{
Name : "checkin" ,
Usage : "Checks for local changes and then checks into the specified Netmaker network to ask about remote changes." ,
Flags : cliFlags ,
// the action, or code that will be executed when
// we execute our `ns` command
Action : func ( c * cli . Context ) error {
2021-08-03 06:06:26 +08:00
cfg , _ , err := config . GetCLIConfig ( c )
2021-07-26 02:22:20 +08:00
if err != nil {
return err
}
err = command . CheckIn ( cfg )
return err
} ,
} ,
{
Name : "push" ,
Usage : "Push configuration changes to server." ,
Flags : cliFlags ,
// the action, or code that will be executed when
// we execute our `ns` command
Action : func ( c * cli . Context ) error {
2021-08-03 06:06:26 +08:00
cfg , _ , err := config . GetCLIConfig ( c )
2021-07-26 02:22:20 +08:00
if err != nil {
return err
}
err = command . Push ( cfg )
return err
} ,
} ,
{
Name : "pull" ,
Usage : "Pull latest configuration and peers from server." ,
Flags : cliFlags ,
// the action, or code that will be executed when
// we execute our `ns` command
Action : func ( c * cli . Context ) error {
2021-08-03 06:06:26 +08:00
cfg , _ , err := config . GetCLIConfig ( c )
2021-07-26 02:22:20 +08:00
if err != nil {
return err
}
err = command . Pull ( cfg )
return err
} ,
} ,
{
Name : "list" ,
Usage : "Get list of networks." ,
Flags : cliFlags ,
// the action, or code that will be executed when
// we execute our `ns` command
Action : func ( c * cli . Context ) error {
2021-08-03 06:06:26 +08:00
cfg , _ , err := config . GetCLIConfig ( c )
2021-07-26 02:22:20 +08:00
if err != nil {
return err
}
err = command . List ( cfg )
return err
} ,
} ,
{
Name : "uninstall" ,
Usage : "Uninstall the netclient system service." ,
Flags : cliFlags ,
// the action, or code that will be executed when
// we execute our `ns` command
Action : func ( c * cli . Context ) error {
2021-08-10 05:42:32 +08:00
err := command . Uninstall ( )
2021-07-26 02:22:20 +08:00
return err
} ,
} ,
}
2021-03-28 00:50:27 +08:00
2021-09-11 03:48:18 +08:00
setGarbageCollection ( )
2021-09-20 02:03:47 +08:00
if ncutils . IsWindows ( ) {
2021-08-31 03:58:23 +08:00
ncwindows . InitWindows ( )
} else {
// start our application
2021-09-20 02:03:47 +08:00
out , err := ncutils . RunCmd ( "id -u" , true )
2021-03-28 00:50:27 +08:00
2021-08-31 03:58:23 +08:00
if err != nil {
log . Fatal ( out , err )
}
id , err := strconv . Atoi ( string ( out [ : len ( out ) - 1 ] ) )
2021-03-28 00:50:27 +08:00
2021-08-31 03:58:23 +08:00
if err != nil {
log . Fatal ( err )
}
2021-03-28 00:50:27 +08:00
2021-08-31 03:58:23 +08:00
if id != 0 {
log . Fatal ( "This program must be run with elevated privileges (sudo). This program installs a SystemD service and configures WireGuard and networking rules. Please re-run with sudo/root." )
}
2021-03-28 00:50:27 +08:00
2021-08-31 03:58:23 +08:00
_ , err = exec . LookPath ( "wg" )
2021-09-22 09:35:52 +08:00
uspace := ncutils . GetWireGuard ( )
2021-08-31 03:58:23 +08:00
if err != nil {
2021-09-22 09:35:52 +08:00
if uspace == "wg" {
2021-09-22 08:50:32 +08:00
log . Println ( err )
log . Fatal ( "WireGuard not installed. Please install WireGuard (wireguard-tools) and try again." )
2021-10-02 20:54:46 +08:00
}
2021-09-22 09:35:52 +08:00
ncutils . PrintLog ( "Running with userspace wireguard: " + uspace , 0 )
} else if uspace != "wg" {
2021-10-02 20:54:46 +08:00
log . Println ( "running userspace WireGuard with " + uspace )
}
2021-07-26 02:22:20 +08:00
}
2021-09-20 02:03:47 +08:00
if ! ncutils . IsKernel ( ) {
if ! local . IsWGInstalled ( ) {
2021-09-22 08:32:09 +08:00
log . Fatal ( "Please install WireGuard before using Gravitl Netclient. https://download.wireguard.com" )
2021-08-31 03:58:23 +08:00
}
}
2021-09-20 02:03:47 +08:00
if len ( os . Args ) == 1 && ncutils . IsWindows ( ) {
2021-10-03 00:28:17 +08:00
2021-08-31 03:58:23 +08:00
c := make ( chan os . Signal )
signal . Notify ( c , os . Interrupt , syscall . SIGTERM )
go func ( ) {
<- c
log . Println ( "closing Gravitl Netclient" )
os . Exit ( 0 )
} ( )
command . RunUserspaceDaemon ( )
} else {
err := app . Run ( os . Args )
if err != nil {
log . Fatal ( err )
}
2021-07-26 02:22:20 +08:00
}
2021-03-26 00:17:52 +08:00
}
2021-09-11 03:48:18 +08:00
2021-09-20 02:03:47 +08:00
func setGarbageCollection ( ) {
_ , gcset := os . LookupEnv ( "GOGC" )
2021-09-11 03:48:18 +08:00
if ! gcset {
2021-09-20 02:03:47 +08:00
debug . SetGCPercent ( ncutils . DEFAULT_GC_PERCENT )
2021-09-11 03:48:18 +08:00
}
2021-09-20 02:03:47 +08:00
}