From 815ce3cf24a77f60b5ee66139f03fe928d4e1211 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Sat, 1 Jan 2022 15:30:39 +0000 Subject: [PATCH 001/116] update compose file and scripts to use mosquitto broker. Includes insecure config file for mosquitto --- compose/docker-compose.contained.yml | 11 +++++++++++ docker/mosquitto.conf | 10 ++++++++++ scripts/install-netmaker.sh | 3 +++ scripts/nm-quick.sh | 4 ++++ 4 files changed, 28 insertions(+) create mode 100644 docker/mosquitto.conf diff --git a/compose/docker-compose.contained.yml b/compose/docker-compose.contained.yml index aa3ea175..2d2ef308 100644 --- a/compose/docker-compose.contained.yml +++ b/compose/docker-compose.contained.yml @@ -68,9 +68,20 @@ services: # - $PWD/site:/srv # you could also serve a static site in site folder - caddy_data:/data - caddy_conf:/config + mosquitto: + image: eclipse-mosquitto:2.0.14 + container_name: broker + restart: unless-stopped + network_mode: host + volumes: + - /root/mosquitto.conf:/mosquitto/config/mosquitto.conf + - mosquitto_data:/var/lib/mosquitto + - mosquitto_logs:/var/log/mosquitto/mosquitto.log volumes: caddy_data: {} caddy_conf: {} sqldata: {} dnsconfig: {} + mosquitto_data: {} + mosquitto_logs: {} diff --git a/docker/mosquitto.conf b/docker/mosquitto.conf new file mode 100644 index 00000000..20ab6597 --- /dev/null +++ b/docker/mosquitto.conf @@ -0,0 +1,10 @@ +persitance true +persistance_location /var/lib/mosquitto/ + +log_dest_file /var/log/mosquitto/mosquitto.log + +per_listener_settings true +listener 1883 +allow_anonymous true +bind_interface SERVER_PUBLIC_IP + diff --git a/scripts/install-netmaker.sh b/scripts/install-netmaker.sh index 52232d9a..547dca88 100644 --- a/scripts/install-netmaker.sh +++ b/scripts/install-netmaker.sh @@ -136,6 +136,9 @@ echo "Setting Caddyfile..." sed -i "s/NETMAKER_BASE_DOMAIN/$NETMAKER_BASE_DOMAIN/g" /root/Caddyfile sed -i "s/YOUR_EMAIL/$EMAIL/g" /root/Caddyfile +echo "Setting Broker..." +sed -i "s/SERVER_PBLIC_IP/$SERVER_PUBLIC_IP/g" /root/mosquitto.conf + echo "Setting docker-compose..." sed -i "s/NETMAKER_BASE_DOMAIN/$NETMAKER_BASE_DOMAIN/g" /root/docker-compose.yml diff --git a/scripts/nm-quick.sh b/scripts/nm-quick.sh index 507e6258..8a9bead4 100755 --- a/scripts/nm-quick.sh +++ b/scripts/nm-quick.sh @@ -135,6 +135,10 @@ wget -q -O /root/Caddyfile https://raw.githubusercontent.com/gravitl/netmaker/ma sed -i "s/NETMAKER_BASE_DOMAIN/$NETMAKER_BASE_DOMAIN/g" /root/Caddyfile sed -i "s/YOUR_EMAIL/$EMAIL/g" /root/Caddyfile +echo "setting mosquitto.conf..." + +wget -q -O /root/mosquitto.conf https://raw.githubusercontent.com/gravil/netmaker/master/docker/mosquitto.conf +sed -i "s/SERVER_PUBLIC_IP/$SERVER_PUBLIC_IP/g" /root/mosquitto.conf echo "setting docker-compose..." From 533965b77b79851e637c8754741dc88e8c9c6145 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Sat, 1 Jan 2022 15:43:55 +0000 Subject: [PATCH 002/116] fix typo --- docker/mosquitto.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/mosquitto.conf b/docker/mosquitto.conf index 20ab6597..3594af29 100644 --- a/docker/mosquitto.conf +++ b/docker/mosquitto.conf @@ -1,4 +1,4 @@ -persitance true +persistance true persistance_location /var/lib/mosquitto/ log_dest_file /var/log/mosquitto/mosquitto.log From 07bf9252827220eb3c568b8e002f5979b6bcd073 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Sat, 1 Jan 2022 18:22:06 +0000 Subject: [PATCH 003/116] update mosquitto broker conf and volume info --- compose/docker-compose.contained.yml | 4 ++-- docker/mosquitto.conf | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/compose/docker-compose.contained.yml b/compose/docker-compose.contained.yml index 2d2ef308..61512717 100644 --- a/compose/docker-compose.contained.yml +++ b/compose/docker-compose.contained.yml @@ -75,8 +75,8 @@ services: network_mode: host volumes: - /root/mosquitto.conf:/mosquitto/config/mosquitto.conf - - mosquitto_data:/var/lib/mosquitto - - mosquitto_logs:/var/log/mosquitto/mosquitto.log + - mosquitto_data:/mosquitto/data + - mosquitto_logs:/mosquitto/log volumes: caddy_data: {} caddy_conf: {} diff --git a/docker/mosquitto.conf b/docker/mosquitto.conf index 3594af29..85914bad 100644 --- a/docker/mosquitto.conf +++ b/docker/mosquitto.conf @@ -1,10 +1,11 @@ -persistance true -persistance_location /var/lib/mosquitto/ +persistence true +persistence file mosquitto.db +persistance_location mosquitto/data -log_dest_file /var/log/mosquitto/mosquitto.log +log_dest_file mosquitto/log/mosquitto.log per_listener_settings true listener 1883 allow_anonymous true -bind_interface SERVER_PUBLIC_IP +#bind_interface SERVER_PUBLIC_IP From 3e1a85b4b9edbef17f2230b620ee3343b2356c5b Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Sat, 1 Jan 2022 15:30:39 +0000 Subject: [PATCH 004/116] update compose file and scripts to use mosquitto broker. Includes insecure config file for mosquitto --- compose/docker-compose.contained.yml | 11 +++++++++++ docker/mosquitto.conf | 10 ++++++++++ scripts/install-netmaker.sh | 3 +++ scripts/nm-quick.sh | 4 ++++ 4 files changed, 28 insertions(+) create mode 100644 docker/mosquitto.conf diff --git a/compose/docker-compose.contained.yml b/compose/docker-compose.contained.yml index aa3ea175..2d2ef308 100644 --- a/compose/docker-compose.contained.yml +++ b/compose/docker-compose.contained.yml @@ -68,9 +68,20 @@ services: # - $PWD/site:/srv # you could also serve a static site in site folder - caddy_data:/data - caddy_conf:/config + mosquitto: + image: eclipse-mosquitto:2.0.14 + container_name: broker + restart: unless-stopped + network_mode: host + volumes: + - /root/mosquitto.conf:/mosquitto/config/mosquitto.conf + - mosquitto_data:/var/lib/mosquitto + - mosquitto_logs:/var/log/mosquitto/mosquitto.log volumes: caddy_data: {} caddy_conf: {} sqldata: {} dnsconfig: {} + mosquitto_data: {} + mosquitto_logs: {} diff --git a/docker/mosquitto.conf b/docker/mosquitto.conf new file mode 100644 index 00000000..20ab6597 --- /dev/null +++ b/docker/mosquitto.conf @@ -0,0 +1,10 @@ +persitance true +persistance_location /var/lib/mosquitto/ + +log_dest_file /var/log/mosquitto/mosquitto.log + +per_listener_settings true +listener 1883 +allow_anonymous true +bind_interface SERVER_PUBLIC_IP + diff --git a/scripts/install-netmaker.sh b/scripts/install-netmaker.sh index 52232d9a..547dca88 100644 --- a/scripts/install-netmaker.sh +++ b/scripts/install-netmaker.sh @@ -136,6 +136,9 @@ echo "Setting Caddyfile..." sed -i "s/NETMAKER_BASE_DOMAIN/$NETMAKER_BASE_DOMAIN/g" /root/Caddyfile sed -i "s/YOUR_EMAIL/$EMAIL/g" /root/Caddyfile +echo "Setting Broker..." +sed -i "s/SERVER_PBLIC_IP/$SERVER_PUBLIC_IP/g" /root/mosquitto.conf + echo "Setting docker-compose..." sed -i "s/NETMAKER_BASE_DOMAIN/$NETMAKER_BASE_DOMAIN/g" /root/docker-compose.yml diff --git a/scripts/nm-quick.sh b/scripts/nm-quick.sh index 6e253a09..ebe78b65 100755 --- a/scripts/nm-quick.sh +++ b/scripts/nm-quick.sh @@ -135,6 +135,10 @@ wget -q -O /root/Caddyfile https://raw.githubusercontent.com/gravitl/netmaker/ma sed -i "s/NETMAKER_BASE_DOMAIN/$NETMAKER_BASE_DOMAIN/g" /root/Caddyfile sed -i "s/YOUR_EMAIL/$EMAIL/g" /root/Caddyfile +echo "setting mosquitto.conf..." + +wget -q -O /root/mosquitto.conf https://raw.githubusercontent.com/gravil/netmaker/master/docker/mosquitto.conf +sed -i "s/SERVER_PUBLIC_IP/$SERVER_PUBLIC_IP/g" /root/mosquitto.conf echo "setting docker-compose..." From e337d877281d46095320995dc1dce3ea135aa70f Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Sat, 1 Jan 2022 15:43:55 +0000 Subject: [PATCH 005/116] fix typo --- docker/mosquitto.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/mosquitto.conf b/docker/mosquitto.conf index 20ab6597..3594af29 100644 --- a/docker/mosquitto.conf +++ b/docker/mosquitto.conf @@ -1,4 +1,4 @@ -persitance true +persistance true persistance_location /var/lib/mosquitto/ log_dest_file /var/log/mosquitto/mosquitto.log From bc974859ad611a284270900df5f4fe0c47ba2eaf Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Sat, 1 Jan 2022 18:22:06 +0000 Subject: [PATCH 006/116] update mosquitto broker conf and volume info --- compose/docker-compose.contained.yml | 4 ++-- docker/mosquitto.conf | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/compose/docker-compose.contained.yml b/compose/docker-compose.contained.yml index 2d2ef308..61512717 100644 --- a/compose/docker-compose.contained.yml +++ b/compose/docker-compose.contained.yml @@ -75,8 +75,8 @@ services: network_mode: host volumes: - /root/mosquitto.conf:/mosquitto/config/mosquitto.conf - - mosquitto_data:/var/lib/mosquitto - - mosquitto_logs:/var/log/mosquitto/mosquitto.log + - mosquitto_data:/mosquitto/data + - mosquitto_logs:/mosquitto/log volumes: caddy_data: {} caddy_conf: {} diff --git a/docker/mosquitto.conf b/docker/mosquitto.conf index 3594af29..85914bad 100644 --- a/docker/mosquitto.conf +++ b/docker/mosquitto.conf @@ -1,10 +1,11 @@ -persistance true -persistance_location /var/lib/mosquitto/ +persistence true +persistence file mosquitto.db +persistance_location mosquitto/data -log_dest_file /var/log/mosquitto/mosquitto.log +log_dest_file mosquitto/log/mosquitto.log per_listener_settings true listener 1883 allow_anonymous true -bind_interface SERVER_PUBLIC_IP +#bind_interface SERVER_PUBLIC_IP From d11bb575be85f55074b71ca4ab3a34b143188c9c Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Sun, 2 Jan 2022 16:02:59 +0000 Subject: [PATCH 007/116] work in progress for message queue --- go.mod | 6 + go.sum | 13 +++ netclient/cli_options/cmds.go | 9 ++ netclient/command/commands.go | 5 + netclient/functions/daemon.go | 214 ++++++++++++++++++++++++++++++++++ 5 files changed, 247 insertions(+) create mode 100644 netclient/functions/daemon.go diff --git a/go.mod b/go.mod index 4c86fb3f..8c49b6bb 100644 --- a/go.mod +++ b/go.mod @@ -31,10 +31,15 @@ require ( require ( cloud.google.com/go v0.34.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/eclipse/paho.mqtt.golang v1.3.5 // indirect github.com/felixge/httpsnoop v1.0.1 // indirect + github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534 // indirect github.com/go-playground/locales v0.14.0 // indirect github.com/go-playground/universal-translator v0.18.0 // indirect github.com/google/go-cmp v0.5.5 // indirect + github.com/google/uuid v1.2.0 // indirect + github.com/gorilla/websocket v1.4.2 // indirect github.com/josharian/native v0.0.0-20200817173448-b6b71def0850 // indirect github.com/leodido/go-urn v1.2.1 // indirect github.com/mdlayher/genetlink v1.0.0 // indirect @@ -42,5 +47,6 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/russross/blackfriday/v2 v2.0.1 // indirect github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect + golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect google.golang.org/appengine v1.4.0 // indirect ) diff --git a/go.sum b/go.sum index 867461fc..5b8fecb5 100644 --- a/go.sum +++ b/go.sum @@ -24,6 +24,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/eclipse/paho.mqtt.golang v1.3.5 h1:sWtmgNxYM9P2sP+xEItMozsR3w0cqZFlqnNN1bdl41Y= +github.com/eclipse/paho.mqtt.golang v1.3.5/go.mod h1:eTzb4gxwwyWpqBUHGQZ4ABAV7+Jgm1PklsYT/eo8Hcc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -34,6 +36,8 @@ github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8S github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534 h1:dhy9OQKGBh4zVXbjwbxxHjRxMJtLXj3zfgpBYQaR4Q4= +github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk= github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= @@ -70,10 +74,14 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -178,6 +186,7 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -185,6 +194,7 @@ golang.org/x/net v0.0.0-20201216054612-986b41b23924/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210504132125-bbd867fde50d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985 h1:4CSI6oo7cOjJKajidEljs9h+uP0rRZBPPPhcCbj5mw8= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -195,6 +205,8 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -216,6 +228,7 @@ golang.org/x/sys v0.0.0-20210123111255-9b0068b26619/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210216163648-f7da38b97c65/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210309040221-94ec62e08169/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210503173754-0981d6026fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/netclient/cli_options/cmds.go b/netclient/cli_options/cmds.go index a43a88c3..5f90c1a8 100644 --- a/netclient/cli_options/cmds.go +++ b/netclient/cli_options/cmds.go @@ -118,5 +118,14 @@ func GetCommands(cliFlags []cli.Flag) []*cli.Command { return err }, }, + { + Name: "daemon", + Usage: "run netclient as daemon", + Flags: cliFlags, + Action: func(c *cli.Context) error { + err := command.Daemon() + return err + }, + }, } } diff --git a/netclient/command/commands.go b/netclient/command/commands.go index 940eb67b..fa8013df 100644 --- a/netclient/command/commands.go +++ b/netclient/command/commands.go @@ -209,3 +209,8 @@ func Uninstall() error { err := functions.Uninstall() return err } + +func Daemon() error { + err := functions.Daemon() + return err +} diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go new file mode 100644 index 00000000..72c7998c --- /dev/null +++ b/netclient/functions/daemon.go @@ -0,0 +1,214 @@ +package functions + +import ( + "encoding/json" + "fmt" + "log" + "time" + + mqtt "github.com/eclipse/paho.mqtt.golang" + "github.com/go-ping/ping" + "github.com/gravitl/netmaker/netclient/config" + "github.com/gravitl/netmaker/netclient/ncutils" + "golang.zx2c4.com/wireguard/wgctrl" +) + +func Daemon() error { + networks, err := ncutils.GetSystemNetworks() + if err != nil { + return err + } + for _, network := range networks { + go Netclient(network) + } + for { + } + return nil +} + +func Netclient(network string) { + var cfg config.ClientConfig + cfg.Network = network + cfg.ReadConfig() + ncutils.Log("daemon started for network:" + network) + //setup MQTT + opts := mqtt.NewClientOptions() + ncutils.Log("setting broker to " + cfg.Server.CoreDNSAddr + ":1883") + opts.AddBroker(cfg.Server.CoreDNSAddr + ":1883") + opts.SetDefaultPublishHandler(All) + opts.SetClientID("netclient-mqttt") + client := mqtt.NewClient(opts) + if token := client.Connect(); token.Wait() && token.Error() != nil { + log.Fatal(token.Error()) + } + if token := client.Subscribe("#", 0, nil); token.Wait() && token.Error() != nil { + log.Fatal(token.Error()) + } + client.AddRoute("update/"+network+"/"+cfg.Node.MacAddress, NodeUpdate) + client.AddRoute("update/"+network+"/peers", UpdatePeers) + client.AddRoute("update/"+network+"/keys", UpdateKeys) + client.AddRoute("update/"+network+"/keys/"+cfg.Node.MacAddress, UpdateKeys) + defer client.Disconnect(250) + go Checkin(client, network) + //go Metrics(client, network) + //go Connectivity(client, network) + for { + } +} + +var All mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { + ncutils.Log("Topic: " + string(msg.Topic())) + ncutils.Log("Message: " + string(msg.Payload())) +} + +var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { + ncutils.Log("received message to update node " + string(msg.Payload())) +} + +var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { + ncutils.Log("received message to update peers " + string(msg.Payload())) +} + +var UpdateKeys mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { + ncutils.Log("received message to update keys " + string(msg.Payload())) +} + +func Checkin(client mqtt.Client, network string) { + var cfg config.ClientConfig + cfg.Network = network + cfg.ReadConfig() + for { + time.Sleep(time.Duration(cfg.Node.NetworkSettings.DefaultCheckInInterval) * time.Second) + ncutils.Log("Checkin running") + if cfg.Node.Roaming == "yes" && cfg.Node.IsStatic != "yes" { + extIP, err := ncutils.GetPublicIP() + if err != nil { + ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) + } + if cfg.Node.Endpoint != extIP && extIP != "" { + ncutils.PrintLog("endpoint has changed from "+cfg.Node.Endpoint+" to "+extIP, 1) + UpdateEndpoint(client, network, extIP) + } + intIP, err := getPrivateAddr() + if err != nil { + ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) + } + if cfg.Node.LocalAddress != intIP && intIP != "" { + ncutils.PrintLog("local Address has changed from "+cfg.Node.LocalAddress+" to "+intIP, 1) + UpdateLocalAddress(client, network, intIP) + } + } else { + localIP, err := ncutils.GetLocalIP(cfg.Node.LocalRange) + if err != nil { + ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) + } + if cfg.Node.Endpoint != localIP && localIP != "" { + ncutils.PrintLog("endpoint has changed from "+cfg.Node.Endpoint+" to "+localIP, 1) + UpdateEndpoint(client, network, localIP) + } + } + Ping(client, network) + } +} + +func Ping(client mqtt.Client, network string) { + var cfg config.ClientConfig + cfg.Network = network + cfg.ReadConfig() + if token := client.Publish("ping/"+network+"/"+cfg.Node.ID, 0, false, []byte("ping")); token.Wait() && token.Error() != nil { + ncutils.Log("error publishing ping " + token.Error().Error()) + } +} + +func Metrics(client mqtt.Client, network string) { + if token := client.Connect(); token.Wait() && token.Error() != nil { + log.Fatal(token.Error()) + } + var cfg config.ClientConfig + cfg.Network = network + cfg.ReadConfig() + for { + time.Sleep(time.Second * 60) + ncutils.Log("Metrics running") + wg, err := wgctrl.New() + if err != nil { + ncutils.Log("error getting devices " + err.Error()) + break + } + device, err := wg.Device(cfg.Node.Interface) + if err != nil { + ncutils.Log("error readind wg device " + err.Error()) + break + } + bytes, err := json.Marshal(device.Peers) + if err != nil { + ncutils.Log("error marshaling peers " + err.Error()) + break + } + if token := client.Publish("metrics/"+network+"/"+cfg.Node.ID, 1, false, bytes); token.Wait() && token.Error() != nil { + ncutils.Log("error publishing metrics " + token.Error().Error()) + break + } + wg.Close() + } +} + +type PingStat struct { + Name string + Reachable bool +} + +func Connectivity(client mqtt.Client, network string) { + if token := client.Connect(); token.Wait() && token.Error() != nil { + log.Fatal(token.Error()) + } + var cfg config.ClientConfig + cfg.Network = network + cfg.ReadConfig() + for { + time.Sleep(time.Duration(cfg.NetworkSettings.DefaultCheckInInterval) * time.Second) + ncutils.Log("Connectivity running") + var pingStats []PingStat + peers, err := ncutils.GetPeers(cfg.Node.Interface) + if err != nil { + ncutils.Log("error retriving peers " + err.Error()) + break + } + for _, peer := range peers { + var pingStat PingStat + pingStat.Name = peer.PublicKey.String() + pingStat.Reachable = true + ip := peer.Endpoint.IP.String() + fmt.Println("----------", peer.Endpoint.IP, ip) + pinger, err := ping.NewPinger(ip) + if err != nil { + ncutils.Log("error creating pinger " + err.Error()) + break + } + pinger.Timeout = 2 * time.Second + pinger.Run() + stats := pinger.Statistics() + if stats.PacketLoss == 100 { + pingStat.Reachable = false + } + pingStats = append(pingStats, pingStat) + } + bytes, err := json.Marshal(pingStats) + if err != nil { + ncutils.Log("error marshaling stats" + err.Error()) + break + } + if token := client.Publish("connectivity/"+network+"/"+cfg.Node.ID, 1, false, bytes); token.Wait() && token.Error() != nil { + ncutils.Log("error publishing ping stats " + token.Error().Error()) + break + } + } +} + +func UpdateEndpoint(client mqtt.Client, network, ip string) { + ncutils.Log("Updating endpoint") +} + +func UpdateLocalAddress(client mqtt.Client, network, ip string) { + ncutils.Log("Updating local address") +} From 5cd57400ce87a8b84ae42ac50d9c11c7f6f1949a Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Mon, 3 Jan 2022 15:22:26 -0500 Subject: [PATCH 008/116] Replaced ### with - in Node.ID (local copy) to fix mqtt publishing errors added context to all go routines removed connectivity function --- netclient/functions/daemon.go | 191 ++++++++++++++++------------------ 1 file changed, 87 insertions(+), 104 deletions(-) diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index 72c7998c..2e31d37a 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -1,18 +1,22 @@ package functions import ( + "context" "encoding/json" - "fmt" "log" + "os" + "os/signal" + "strings" + "syscall" "time" mqtt "github.com/eclipse/paho.mqtt.golang" - "github.com/go-ping/ping" "github.com/gravitl/netmaker/netclient/config" "github.com/gravitl/netmaker/netclient/ncutils" "golang.zx2c4.com/wireguard/wgctrl" ) +//Daemon runs netclient daemon from command line func Daemon() error { networks, err := ncutils.GetSystemNetworks() if err != nil { @@ -26,59 +30,75 @@ func Daemon() error { return nil } -func Netclient(network string) { - var cfg config.ClientConfig - cfg.Network = network - cfg.ReadConfig() - ncutils.Log("daemon started for network:" + network) - //setup MQTT +//SetupMQTT creates a connection to broker and return client +func SetupMQTT(cfg config.ClientConfig) mqtt.Client { opts := mqtt.NewClientOptions() ncutils.Log("setting broker to " + cfg.Server.CoreDNSAddr + ":1883") opts.AddBroker(cfg.Server.CoreDNSAddr + ":1883") opts.SetDefaultPublishHandler(All) - opts.SetClientID("netclient-mqttt") client := mqtt.NewClient(opts) if token := client.Connect(); token.Wait() && token.Error() != nil { log.Fatal(token.Error()) } + return client +} + +//Netclient sets up Message Queue and subsribes/publishes updates to/from server +func Netclient(network string) { + ctx, cancel := context.WithCancel(context.Background()) + var cfg config.ClientConfig + cfg.Network = network + cfg.ReadConfig() + //fix NodeID to remove ### so NodeID can be used as message topic + //remove with GRA-73 + cfg.Node.ID = strings.ReplaceAll(cfg.Node.ID, "###", "-") + ncutils.Log("daemon started for network:" + network) + client := SetupMQTT(cfg) if token := client.Subscribe("#", 0, nil); token.Wait() && token.Error() != nil { log.Fatal(token.Error()) } - client.AddRoute("update/"+network+"/"+cfg.Node.MacAddress, NodeUpdate) - client.AddRoute("update/"+network+"/peers", UpdatePeers) - client.AddRoute("update/"+network+"/keys", UpdateKeys) - client.AddRoute("update/"+network+"/keys/"+cfg.Node.MacAddress, UpdateKeys) + client.AddRoute("update/"+cfg.Node.ID, NodeUpdate) + client.AddRoute("update/peers/"+cfg.Node.ID, UpdatePeers) + client.AddRoute("update/keys/"+cfg.Node.ID, UpdateKeys) defer client.Disconnect(250) - go Checkin(client, network) - //go Metrics(client, network) - //go Connectivity(client, network) - for { - } + go Checkin(ctx, cfg, network) + go Metrics(ctx, cfg, network) + quit := make(chan os.Signal, 1) + signal.Notify(quit, syscall.SIGTERM, os.Interrupt) + <-quit + cancel() } +//All -- mqtt message hander for all ('#') topics var All mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("Topic: " + string(msg.Topic())) ncutils.Log("Message: " + string(msg.Payload())) } +//NodeUpdate -- mqtt message handler for /update/ topic var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update node " + string(msg.Payload())) } +//NodeUpdate -- mqtt message handler for /update/peers/ topic var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update peers " + string(msg.Payload())) } +//NodeUpdate -- mqtt message handler for /update/keys/ topic var UpdateKeys mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update keys " + string(msg.Payload())) } -func Checkin(client mqtt.Client, network string) { - var cfg config.ClientConfig - cfg.Network = network - cfg.ReadConfig() - for { - time.Sleep(time.Duration(cfg.Node.NetworkSettings.DefaultCheckInInterval) * time.Second) +//Checkin -- go routine that checks for public or local ip changes, publishes changes +// if there are no updates, simply "pings" the server as a checkin +func Checkin(ctx context.Context, cfg config.ClientConfig, network string) { + select { + case <-ctx.Done(): + ncutils.Log("Checkin cancelled") + return + //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? + case <-time.After(time.Second * 10): ncutils.Log("Checkin running") if cfg.Node.Roaming == "yes" && cfg.Node.IsStatic != "yes" { extIP, err := ncutils.GetPublicIP() @@ -87,7 +107,7 @@ func Checkin(client mqtt.Client, network string) { } if cfg.Node.Endpoint != extIP && extIP != "" { ncutils.PrintLog("endpoint has changed from "+cfg.Node.Endpoint+" to "+extIP, 1) - UpdateEndpoint(client, network, extIP) + UpdateEndpoint(cfg, network, extIP) } intIP, err := getPrivateAddr() if err != nil { @@ -95,7 +115,7 @@ func Checkin(client mqtt.Client, network string) { } if cfg.Node.LocalAddress != intIP && intIP != "" { ncutils.PrintLog("local Address has changed from "+cfg.Node.LocalAddress+" to "+intIP, 1) - UpdateLocalAddress(client, network, intIP) + UpdateLocalAddress(cfg, network, intIP) } } else { localIP, err := ncutils.GetLocalIP(cfg.Node.LocalRange) @@ -104,31 +124,52 @@ func Checkin(client mqtt.Client, network string) { } if cfg.Node.Endpoint != localIP && localIP != "" { ncutils.PrintLog("endpoint has changed from "+cfg.Node.Endpoint+" to "+localIP, 1) - UpdateEndpoint(client, network, localIP) + UpdateEndpoint(cfg, network, localIP) } } - Ping(client, network) + Hello(cfg, network) + ncutils.Log("Checkin complete") } } -func Ping(client mqtt.Client, network string) { - var cfg config.ClientConfig - cfg.Network = network - cfg.ReadConfig() - if token := client.Publish("ping/"+network+"/"+cfg.Node.ID, 0, false, []byte("ping")); token.Wait() && token.Error() != nil { +//UpdateEndpoint -- publishes an endpoint update to broker +func UpdateEndpoint(cfg config.ClientConfig, network, ip string) { + ncutils.Log("Updating endpoint") + client := SetupMQTT(cfg) + if token := client.Publish("update/ip/"+cfg.Node.ID, 0, false, ip); token.Wait() && token.Error() != nil { + ncutils.Log("error publishing endpoint update " + token.Error().Error()) + } + client.Disconnect(250) +} + +//UpdateLocalAddress -- publishes a local address update to broker +func UpdateLocalAddress(cfg config.ClientConfig, network, ip string) { + ncutils.Log("Updating local address") + client := SetupMQTT(cfg) + if token := client.Publish("update/localaddress/"+cfg.Node.ID, 0, false, ip); token.Wait() && token.Error() != nil { + ncutils.Log("error publishing local address update " + token.Error().Error()) + } + client.Disconnect(250) +} + +//Hello -- ping the broker to let server know node is alive and doing fine +func Hello(cfg config.ClientConfig, network string) { + client := SetupMQTT(cfg) + if token := client.Publish("ping/"+network+"/"+cfg.Node.ID, 0, false, "hello world!"); token.Wait() && token.Error() != nil { ncutils.Log("error publishing ping " + token.Error().Error()) } + client.Disconnect(250) } -func Metrics(client mqtt.Client, network string) { - if token := client.Connect(); token.Wait() && token.Error() != nil { - log.Fatal(token.Error()) - } - var cfg config.ClientConfig - cfg.Network = network - cfg.ReadConfig() - for { - time.Sleep(time.Second * 60) +//Metics -- go routine that collects wireguard metrics and publishes to broker +func Metrics(ctx context.Context, cfg config.ClientConfig, network string) { + select { + case <-ctx.Done(): + ncutils.Log("Metrics collection cancelled") + return + //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? + case <-time.After(time.Second * 60): + ncutils.Log("Metrics collection running") ncutils.Log("Metrics running") wg, err := wgctrl.New() if err != nil { @@ -145,70 +186,12 @@ func Metrics(client mqtt.Client, network string) { ncutils.Log("error marshaling peers " + err.Error()) break } - if token := client.Publish("metrics/"+network+"/"+cfg.Node.ID, 1, false, bytes); token.Wait() && token.Error() != nil { + client := SetupMQTT(cfg) + if token := client.Publish("metrics/"+cfg.Node.ID, 1, false, bytes); token.Wait() && token.Error() != nil { ncutils.Log("error publishing metrics " + token.Error().Error()) - break } wg.Close() + client.Disconnect(250) + ncutils.Log("metrics collection complete") } } - -type PingStat struct { - Name string - Reachable bool -} - -func Connectivity(client mqtt.Client, network string) { - if token := client.Connect(); token.Wait() && token.Error() != nil { - log.Fatal(token.Error()) - } - var cfg config.ClientConfig - cfg.Network = network - cfg.ReadConfig() - for { - time.Sleep(time.Duration(cfg.NetworkSettings.DefaultCheckInInterval) * time.Second) - ncutils.Log("Connectivity running") - var pingStats []PingStat - peers, err := ncutils.GetPeers(cfg.Node.Interface) - if err != nil { - ncutils.Log("error retriving peers " + err.Error()) - break - } - for _, peer := range peers { - var pingStat PingStat - pingStat.Name = peer.PublicKey.String() - pingStat.Reachable = true - ip := peer.Endpoint.IP.String() - fmt.Println("----------", peer.Endpoint.IP, ip) - pinger, err := ping.NewPinger(ip) - if err != nil { - ncutils.Log("error creating pinger " + err.Error()) - break - } - pinger.Timeout = 2 * time.Second - pinger.Run() - stats := pinger.Statistics() - if stats.PacketLoss == 100 { - pingStat.Reachable = false - } - pingStats = append(pingStats, pingStat) - } - bytes, err := json.Marshal(pingStats) - if err != nil { - ncutils.Log("error marshaling stats" + err.Error()) - break - } - if token := client.Publish("connectivity/"+network+"/"+cfg.Node.ID, 1, false, bytes); token.Wait() && token.Error() != nil { - ncutils.Log("error publishing ping stats " + token.Error().Error()) - break - } - } -} - -func UpdateEndpoint(client mqtt.Client, network, ip string) { - ncutils.Log("Updating endpoint") -} - -func UpdateLocalAddress(client mqtt.Client, network, ip string) { - ncutils.Log("Updating local address") -} From 7bc99d3076a17f66b0956cf78e012d5309bf1c1c Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Mon, 3 Jan 2022 16:26:40 -0500 Subject: [PATCH 009/116] move context up a level --- netclient/functions/daemon.go | 58 +++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index 2e31d37a..43dae42f 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -18,15 +18,18 @@ import ( //Daemon runs netclient daemon from command line func Daemon() error { + ctx, cancel := context.WithCancel(context.Background()) networks, err := ncutils.GetSystemNetworks() if err != nil { return err } for _, network := range networks { - go Netclient(network) - } - for { + go Netclient(ctx, network) } + quit := make(chan os.Signal, 1) + signal.Notify(quit, syscall.SIGTERM, os.Interrupt) + <-quit + cancel() return nil } @@ -44,29 +47,30 @@ func SetupMQTT(cfg config.ClientConfig) mqtt.Client { } //Netclient sets up Message Queue and subsribes/publishes updates to/from server -func Netclient(network string) { - ctx, cancel := context.WithCancel(context.Background()) - var cfg config.ClientConfig - cfg.Network = network - cfg.ReadConfig() - //fix NodeID to remove ### so NodeID can be used as message topic - //remove with GRA-73 - cfg.Node.ID = strings.ReplaceAll(cfg.Node.ID, "###", "-") - ncutils.Log("daemon started for network:" + network) - client := SetupMQTT(cfg) - if token := client.Subscribe("#", 0, nil); token.Wait() && token.Error() != nil { - log.Fatal(token.Error()) +func Netclient(ctx context.Context, network string) { + select { + case <-ctx.Done(): + ncutils.Log("shutting down daemon") + return + default: + var cfg config.ClientConfig + cfg.Network = network + cfg.ReadConfig() + //fix NodeID to remove ### so NodeID can be used as message topic + //remove with GRA-73 + cfg.Node.ID = strings.ReplaceAll(cfg.Node.ID, "###", "-") + ncutils.Log("daemon started for network:" + network) + client := SetupMQTT(cfg) + if token := client.Subscribe("#", 0, nil); token.Wait() && token.Error() != nil { + log.Fatal(token.Error()) + } + client.AddRoute("update/"+cfg.Node.ID, NodeUpdate) + client.AddRoute("update/peers/"+cfg.Node.ID, UpdatePeers) + client.AddRoute("update/keys/"+cfg.Node.ID, UpdateKeys) + defer client.Disconnect(250) + go Checkin(ctx, cfg, network) + go Metrics(ctx, cfg, network) } - client.AddRoute("update/"+cfg.Node.ID, NodeUpdate) - client.AddRoute("update/peers/"+cfg.Node.ID, UpdatePeers) - client.AddRoute("update/keys/"+cfg.Node.ID, UpdateKeys) - defer client.Disconnect(250) - go Checkin(ctx, cfg, network) - go Metrics(ctx, cfg, network) - quit := make(chan os.Signal, 1) - signal.Notify(quit, syscall.SIGTERM, os.Interrupt) - <-quit - cancel() } //All -- mqtt message hander for all ('#') topics @@ -80,12 +84,12 @@ var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) ncutils.Log("received message to update node " + string(msg.Payload())) } -//NodeUpdate -- mqtt message handler for /update/peers/ topic +//UpdatePeers -- mqtt message handler for /update/peers/ topic var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update peers " + string(msg.Payload())) } -//NodeUpdate -- mqtt message handler for /update/keys/ topic +//UpdateKeys -- mqtt message handler for /update/keys/ topic var UpdateKeys mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update keys " + string(msg.Payload())) } From f5aa383541c2892a1a9fdfd86a41982527a5c6a2 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Mon, 3 Jan 2022 22:21:52 +0000 Subject: [PATCH 010/116] go routines now run forever like they are supposed to --- netclient/functions/daemon.go | 176 +++++++++++++++++----------------- 1 file changed, 90 insertions(+), 86 deletions(-) diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index 43dae42f..e48e8c19 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -30,6 +30,7 @@ func Daemon() error { signal.Notify(quit, syscall.SIGTERM, os.Interrupt) <-quit cancel() + ncutils.Log("all done") return nil } @@ -48,29 +49,28 @@ func SetupMQTT(cfg config.ClientConfig) mqtt.Client { //Netclient sets up Message Queue and subsribes/publishes updates to/from server func Netclient(ctx context.Context, network string) { - select { - case <-ctx.Done(): - ncutils.Log("shutting down daemon") - return - default: - var cfg config.ClientConfig - cfg.Network = network - cfg.ReadConfig() - //fix NodeID to remove ### so NodeID can be used as message topic - //remove with GRA-73 - cfg.Node.ID = strings.ReplaceAll(cfg.Node.ID, "###", "-") - ncutils.Log("daemon started for network:" + network) - client := SetupMQTT(cfg) - if token := client.Subscribe("#", 0, nil); token.Wait() && token.Error() != nil { - log.Fatal(token.Error()) - } - client.AddRoute("update/"+cfg.Node.ID, NodeUpdate) - client.AddRoute("update/peers/"+cfg.Node.ID, UpdatePeers) - client.AddRoute("update/keys/"+cfg.Node.ID, UpdateKeys) - defer client.Disconnect(250) - go Checkin(ctx, cfg, network) - go Metrics(ctx, cfg, network) + ncutils.Log("netclient go routine started for " + network) + var cfg config.ClientConfig + cfg.Network = network + cfg.ReadConfig() + //fix NodeID to remove ### so NodeID can be used as message topic + //remove with GRA-73 + cfg.Node.ID = strings.ReplaceAll(cfg.Node.ID, "###", "-") + ncutils.Log("daemon started for network:" + network) + client := SetupMQTT(cfg) + if token := client.Subscribe("#", 0, nil); token.Wait() && token.Error() != nil { + log.Fatal(token.Error()) } + client.AddRoute("update/"+cfg.Node.ID, NodeUpdate) + client.AddRoute("update/peers/"+cfg.Node.ID, UpdatePeers) + client.AddRoute("update/keys/"+cfg.Node.ID, UpdateKeys) + defer client.Disconnect(250) + go Checkin(ctx, cfg, network) + go Metrics(ctx, cfg, network) + <-ctx.Done() + ncutils.Log("shutting down daemon") + return + ncutils.Log("netclient go routine ended for " + network) } //All -- mqtt message hander for all ('#') topics @@ -97,42 +97,44 @@ var UpdateKeys mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) //Checkin -- go routine that checks for public or local ip changes, publishes changes // if there are no updates, simply "pings" the server as a checkin func Checkin(ctx context.Context, cfg config.ClientConfig, network string) { - select { - case <-ctx.Done(): - ncutils.Log("Checkin cancelled") - return - //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? - case <-time.After(time.Second * 10): - ncutils.Log("Checkin running") - if cfg.Node.Roaming == "yes" && cfg.Node.IsStatic != "yes" { - extIP, err := ncutils.GetPublicIP() - if err != nil { - ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) - } - if cfg.Node.Endpoint != extIP && extIP != "" { - ncutils.PrintLog("endpoint has changed from "+cfg.Node.Endpoint+" to "+extIP, 1) - UpdateEndpoint(cfg, network, extIP) - } - intIP, err := getPrivateAddr() - if err != nil { - ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) - } - if cfg.Node.LocalAddress != intIP && intIP != "" { - ncutils.PrintLog("local Address has changed from "+cfg.Node.LocalAddress+" to "+intIP, 1) - UpdateLocalAddress(cfg, network, intIP) - } - } else { - localIP, err := ncutils.GetLocalIP(cfg.Node.LocalRange) - if err != nil { - ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) - } - if cfg.Node.Endpoint != localIP && localIP != "" { - ncutils.PrintLog("endpoint has changed from "+cfg.Node.Endpoint+" to "+localIP, 1) - UpdateEndpoint(cfg, network, localIP) + for { + select { + case <-ctx.Done(): + ncutils.Log("Checkin cancelled") + return + //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? + case <-time.After(time.Second * 10): + ncutils.Log("Checkin running") + if cfg.Node.Roaming == "yes" && cfg.Node.IsStatic != "yes" { + extIP, err := ncutils.GetPublicIP() + if err != nil { + ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) + } + if cfg.Node.Endpoint != extIP && extIP != "" { + ncutils.PrintLog("endpoint has changed from "+cfg.Node.Endpoint+" to "+extIP, 1) + UpdateEndpoint(cfg, network, extIP) + } + intIP, err := getPrivateAddr() + if err != nil { + ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) + } + if cfg.Node.LocalAddress != intIP && intIP != "" { + ncutils.PrintLog("local Address has changed from "+cfg.Node.LocalAddress+" to "+intIP, 1) + UpdateLocalAddress(cfg, network, intIP) + } + } else { + localIP, err := ncutils.GetLocalIP(cfg.Node.LocalRange) + if err != nil { + ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) + } + if cfg.Node.Endpoint != localIP && localIP != "" { + ncutils.PrintLog("endpoint has changed from "+cfg.Node.Endpoint+" to "+localIP, 1) + UpdateEndpoint(cfg, network, localIP) + } } + Hello(cfg, network) + ncutils.Log("Checkin complete") } - Hello(cfg, network) - ncutils.Log("Checkin complete") } } @@ -159,7 +161,7 @@ func UpdateLocalAddress(cfg config.ClientConfig, network, ip string) { //Hello -- ping the broker to let server know node is alive and doing fine func Hello(cfg config.ClientConfig, network string) { client := SetupMQTT(cfg) - if token := client.Publish("ping/"+network+"/"+cfg.Node.ID, 0, false, "hello world!"); token.Wait() && token.Error() != nil { + if token := client.Publish("ping/"+cfg.Node.ID, 0, false, "hello world!"); token.Wait() && token.Error() != nil { ncutils.Log("error publishing ping " + token.Error().Error()) } client.Disconnect(250) @@ -167,35 +169,37 @@ func Hello(cfg config.ClientConfig, network string) { //Metics -- go routine that collects wireguard metrics and publishes to broker func Metrics(ctx context.Context, cfg config.ClientConfig, network string) { - select { - case <-ctx.Done(): - ncutils.Log("Metrics collection cancelled") - return - //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? - case <-time.After(time.Second * 60): - ncutils.Log("Metrics collection running") - ncutils.Log("Metrics running") - wg, err := wgctrl.New() - if err != nil { - ncutils.Log("error getting devices " + err.Error()) - break + for { + select { + case <-ctx.Done(): + ncutils.Log("Metrics collection cancelled") + return + //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? + case <-time.After(time.Second * 60): + ncutils.Log("Metrics collection running") + ncutils.Log("Metrics running") + wg, err := wgctrl.New() + if err != nil { + ncutils.Log("error getting devices " + err.Error()) + break + } + device, err := wg.Device(cfg.Node.Interface) + if err != nil { + ncutils.Log("error readind wg device " + err.Error()) + break + } + bytes, err := json.Marshal(device.Peers) + if err != nil { + ncutils.Log("error marshaling peers " + err.Error()) + break + } + client := SetupMQTT(cfg) + if token := client.Publish("metrics/"+cfg.Node.ID, 1, false, bytes); token.Wait() && token.Error() != nil { + ncutils.Log("error publishing metrics " + token.Error().Error()) + } + wg.Close() + client.Disconnect(250) + ncutils.Log("metrics collection complete") } - device, err := wg.Device(cfg.Node.Interface) - if err != nil { - ncutils.Log("error readind wg device " + err.Error()) - break - } - bytes, err := json.Marshal(device.Peers) - if err != nil { - ncutils.Log("error marshaling peers " + err.Error()) - break - } - client := SetupMQTT(cfg) - if token := client.Publish("metrics/"+cfg.Node.ID, 1, false, bytes); token.Wait() && token.Error() != nil { - ncutils.Log("error publishing metrics " + token.Error().Error()) - } - wg.Close() - client.Disconnect(250) - ncutils.Log("metrics collection complete") } } From 5e5d97627d1edab44364e3edbb51d0a155f19801 Mon Sep 17 00:00:00 2001 From: 0xdcarns Date: Mon, 3 Jan 2022 18:27:13 -0500 Subject: [PATCH 011/116] linting fixes --- netclient/functions/daemon.go | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index e48e8c19..45a49d9b 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -16,11 +16,12 @@ import ( "golang.zx2c4.com/wireguard/wgctrl" ) -//Daemon runs netclient daemon from command line +// Daemon runs netclient daemon from command line func Daemon() error { ctx, cancel := context.WithCancel(context.Background()) networks, err := ncutils.GetSystemNetworks() if err != nil { + cancel() return err } for _, network := range networks { @@ -34,7 +35,7 @@ func Daemon() error { return nil } -//SetupMQTT creates a connection to broker and return client +// SetupMQTT creates a connection to broker and return client func SetupMQTT(cfg config.ClientConfig) mqtt.Client { opts := mqtt.NewClientOptions() ncutils.Log("setting broker to " + cfg.Server.CoreDNSAddr + ":1883") @@ -47,7 +48,7 @@ func SetupMQTT(cfg config.ClientConfig) mqtt.Client { return client } -//Netclient sets up Message Queue and subsribes/publishes updates to/from server +// Netclient sets up Message Queue and subsribes/publishes updates to/from server func Netclient(ctx context.Context, network string) { ncutils.Log("netclient go routine started for " + network) var cfg config.ClientConfig @@ -55,7 +56,7 @@ func Netclient(ctx context.Context, network string) { cfg.ReadConfig() //fix NodeID to remove ### so NodeID can be used as message topic //remove with GRA-73 - cfg.Node.ID = strings.ReplaceAll(cfg.Node.ID, "###", "-") + cfg.Node.ID = strings.Replace(cfg.Node.ID, "###", "-", 1) ncutils.Log("daemon started for network:" + network) client := SetupMQTT(cfg) if token := client.Subscribe("#", 0, nil); token.Wait() && token.Error() != nil { @@ -69,32 +70,30 @@ func Netclient(ctx context.Context, network string) { go Metrics(ctx, cfg, network) <-ctx.Done() ncutils.Log("shutting down daemon") - return - ncutils.Log("netclient go routine ended for " + network) } -//All -- mqtt message hander for all ('#') topics +// All -- mqtt message hander for all ('#') topics var All mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("Topic: " + string(msg.Topic())) ncutils.Log("Message: " + string(msg.Payload())) } -//NodeUpdate -- mqtt message handler for /update/ topic +// NodeUpdate -- mqtt message handler for /update/ topic var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update node " + string(msg.Payload())) } -//UpdatePeers -- mqtt message handler for /update/peers/ topic +// UpdatePeers -- mqtt message handler for /update/peers/ topic var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update peers " + string(msg.Payload())) } -//UpdateKeys -- mqtt message handler for /update/keys/ topic +// UpdateKeys -- mqtt message handler for /update/keys/ topic var UpdateKeys mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update keys " + string(msg.Payload())) } -//Checkin -- go routine that checks for public or local ip changes, publishes changes +// Checkin -- go routine that checks for public or local ip changes, publishes changes // if there are no updates, simply "pings" the server as a checkin func Checkin(ctx context.Context, cfg config.ClientConfig, network string) { for { @@ -138,7 +137,7 @@ func Checkin(ctx context.Context, cfg config.ClientConfig, network string) { } } -//UpdateEndpoint -- publishes an endpoint update to broker +// UpdateEndpoint -- publishes an endpoint update to broker func UpdateEndpoint(cfg config.ClientConfig, network, ip string) { ncutils.Log("Updating endpoint") client := SetupMQTT(cfg) @@ -148,7 +147,7 @@ func UpdateEndpoint(cfg config.ClientConfig, network, ip string) { client.Disconnect(250) } -//UpdateLocalAddress -- publishes a local address update to broker +// UpdateLocalAddress -- publishes a local address update to broker func UpdateLocalAddress(cfg config.ClientConfig, network, ip string) { ncutils.Log("Updating local address") client := SetupMQTT(cfg) @@ -158,7 +157,7 @@ func UpdateLocalAddress(cfg config.ClientConfig, network, ip string) { client.Disconnect(250) } -//Hello -- ping the broker to let server know node is alive and doing fine +// Hello -- ping the broker to let server know node is alive and doing fine func Hello(cfg config.ClientConfig, network string) { client := SetupMQTT(cfg) if token := client.Publish("ping/"+cfg.Node.ID, 0, false, "hello world!"); token.Wait() && token.Error() != nil { @@ -167,7 +166,7 @@ func Hello(cfg config.ClientConfig, network string) { client.Disconnect(250) } -//Metics -- go routine that collects wireguard metrics and publishes to broker +// Metics -- go routine that collects wireguard metrics and publishes to broker func Metrics(ctx context.Context, cfg config.ClientConfig, network string) { for { select { From b4deb65cfb041997d7ba2fae3c11122768154bc7 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Tue, 4 Jan 2022 17:24:50 -0500 Subject: [PATCH 012/116] Rebase to develop (#4) * add nameserver in call to CreateUserSpaceConf * fixed user deletion * changed log * go mod tidy and conver azure tenant to env/conf var * added egress relayed addrs to relayed nodes * added post commands for wg quick * refactored ncutils x-platform * log fix * adding egress to relay * fixing egress on relay Co-authored-by: dcarns <75687250+0xdcarns@users.noreply.github.com> Co-authored-by: 0xdcarns Co-authored-by: afeiszli --- .gitignore | 1 + auth/azure-ad.go | 3 +- config/config.go | 15 +++-- controllers/user.go | 2 +- logic/util.go | 71 +++++++++++++++++---- logic/wireguard.go | 3 +- main.go | 2 +- netclient/command/commands.go | 3 +- netclient/ncutils/netclientutils_darwin.go | 15 +++-- netclient/ncutils/netclientutils_freebsd.go | 18 +++--- netclient/ncutils/netclientutils_linux.go | 29 ++++++--- netclient/ncutils/netclientutils_windows.go | 15 +++-- netclient/wireguard/common.go | 6 +- netclient/wireguard/unix.go | 3 +- servercfg/serverconf.go | 11 ++++ 15 files changed, 136 insertions(+), 61 deletions(-) diff --git a/.gitignore b/.gitignore index 995aa2bc..defe793f 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ netclient/netclient32 netclient/netclient.exe config/dnsconfig/ data/ +.vscode/ diff --git a/auth/azure-ad.go b/auth/azure-ad.go index 8ad9a8e3..ffe1a173 100644 --- a/auth/azure-ad.go +++ b/auth/azure-ad.go @@ -5,7 +5,6 @@ import ( "fmt" "io/ioutil" "net/http" - "os" "github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/logic" @@ -36,7 +35,7 @@ func initAzureAD(redirectURL string, clientID string, clientSecret string) { ClientID: clientID, ClientSecret: clientSecret, Scopes: []string{"User.Read"}, - Endpoint: microsoft.AzureADEndpoint(os.Getenv("AZURE_TENANT")), + Endpoint: microsoft.AzureADEndpoint(servercfg.GetAzureTenant()), } } diff --git a/config/config.go b/config/config.go index c3b2fbd5..044d1a88 100644 --- a/config/config.go +++ b/config/config.go @@ -12,7 +12,7 @@ import ( "gopkg.in/yaml.v3" ) -//setting dev by default +// setting dev by default func getEnv() string { env := os.Getenv("NETMAKER_ENV") @@ -27,13 +27,13 @@ func getEnv() string { // Config : application config stored as global variable var Config *EnvironmentConfig -// EnvironmentConfig : +// EnvironmentConfig - environment conf struct type EnvironmentConfig struct { Server ServerConfig `yaml:"server"` SQL SQLConfig `yaml:"sql"` } -// ServerConfig : +// ServerConfig - server conf struct type ServerConfig struct { CoreDNSAddr string `yaml:"corednsaddr"` APIConnString string `yaml:"apiconn"` @@ -58,8 +58,8 @@ type ServerConfig struct { Version string `yaml:"version"` SQLConn string `yaml:"sqlconn"` Platform string `yaml:"platform"` - Database string `yaml:database` - CheckinInterval string `yaml:checkininterval` + Database string `yaml:"database"` + CheckinInterval string `yaml:"checkininterval"` DefaultNodeLimit int32 `yaml:"defaultnodelimit"` Verbosity int32 `yaml:"verbosity"` ServerCheckinInterval int64 `yaml:"servercheckininterval"` @@ -68,9 +68,10 @@ type ServerConfig struct { ClientSecret string `yaml:"clientsecret"` FrontendURL string `yaml:"frontendurl"` DisplayKeys string `yaml:"displaykeys"` + AzureTenant string `yaml:"azuretenant"` } -// Generic SQL Config +// SQLConfig - Generic SQL Config type SQLConfig struct { Host string `yaml:"host"` Port int32 `yaml:"port"` @@ -80,7 +81,7 @@ type SQLConfig struct { SSLMode string `yaml:"sslmode"` } -//reading in the env file +// reading in the env file func readConfig() *EnvironmentConfig { file := fmt.Sprintf("config/environments/%s.yaml", getEnv()) f, err := os.Open(file) diff --git a/controllers/user.go b/controllers/user.go index f08328c7..c9e387e3 100644 --- a/controllers/user.go +++ b/controllers/user.go @@ -23,7 +23,7 @@ func userHandlers(r *mux.Router) { r.HandleFunc("/api/users/networks/{username}", securityCheck(true, http.HandlerFunc(updateUserNetworks))).Methods("PUT") r.HandleFunc("/api/users/{username}/adm", securityCheck(true, http.HandlerFunc(updateUserAdm))).Methods("PUT") r.HandleFunc("/api/users/{username}", securityCheck(true, http.HandlerFunc(createUser))).Methods("POST") - r.HandleFunc("/api/users/{username}", securityCheck(false, continueIfUserMatch(http.HandlerFunc(deleteUser)))).Methods("DELETE") + r.HandleFunc("/api/users/{username}", securityCheck(true, http.HandlerFunc(deleteUser))).Methods("DELETE") r.HandleFunc("/api/users/{username}", securityCheck(false, continueIfUserMatch(http.HandlerFunc(getUser)))).Methods("GET") r.HandleFunc("/api/users", securityCheck(true, http.HandlerFunc(getUsers))).Methods("GET") r.HandleFunc("/api/oauth/login", auth.HandleAuthLogin).Methods("GET") diff --git a/logic/util.go b/logic/util.go index d7ce5534..989bff4e 100644 --- a/logic/util.go +++ b/logic/util.go @@ -184,26 +184,18 @@ func GetNode(macaddress string, network string) (models.Node, error) { // GetNodePeers - fetches peers for a given node func GetNodePeers(networkName string, excludeRelayed bool) ([]models.Node, error) { var peers []models.Node - collection, err := database.FetchRecords(database.NODES_TABLE_NAME) + var networkNodes, egressNetworkNodes, err = getNetworkEgressAndNodes(networkName) if err != nil { - if database.IsEmptyRecord(err) { - return peers, nil - } - logger.Log(2, err.Error()) - return nil, err + return peers, nil } + udppeers, errN := database.GetPeers(networkName) if errN != nil { logger.Log(2, errN.Error()) } - for _, value := range collection { - var node = &models.Node{} + + for _, node := range networkNodes { var peer = models.Node{} - err := json.Unmarshal([]byte(value), node) - if err != nil { - logger.Log(2, err.Error()) - continue - } if node.IsEgressGateway == "yes" { // handle egress stuff peer.EgressGatewayRanges = node.EgressGatewayRanges peer.IsEgressGateway = node.IsEgressGateway @@ -211,7 +203,7 @@ func GetNodePeers(networkName string, excludeRelayed bool) ([]models.Node, error allow := node.IsRelayed != "yes" || !excludeRelayed if node.Network == networkName && node.IsPending != "yes" && allow { - peer = setPeerInfo(node) + peer = setPeerInfo(&node) if node.UDPHolePunch == "yes" && errN == nil && CheckEndpoint(udppeers[node.PublicKey]) { endpointstring := udppeers[node.PublicKey] endpointarr := strings.Split(endpointstring, ":") @@ -230,6 +222,11 @@ func GetNodePeers(networkName string, excludeRelayed bool) ([]models.Node, error } else { peer.AllowedIPs = append(peer.AllowedIPs, node.RelayAddrs...) } + for _, egressNode := range egressNetworkNodes { + if egressNode.IsRelayed == "yes" && StringSliceContains(node.RelayAddrs, egressNode.Address) { + peer.AllowedIPs = append(peer.AllowedIPs, egressNode.EgressGatewayRanges...) + } + } } peers = append(peers, peer) } @@ -252,6 +249,14 @@ func GetPeersList(networkName string, excludeRelayed bool, relayedNodeAddr strin network, err := GetNetwork(networkName) if err == nil { peerNode.AllowedIPs = append(peerNode.AllowedIPs, network.AddressRange) + var _, egressNetworkNodes, err = getNetworkEgressAndNodes(networkName) + if err == nil { + for _, egress := range egressNetworkNodes { + if egress.Address != relayedNodeAddr { + peerNode.AllowedIPs = append(peerNode.AllowedIPs, egress.EgressGatewayRanges...) + } + } + } } else { peerNode.AllowedIPs = append(peerNode.AllowedIPs, peerNode.RelayAddrs...) } @@ -286,6 +291,34 @@ func RandomString(length int) string { // == Private Methods == +func getNetworkEgressAndNodes(networkName string) ([]models.Node, []models.Node, error) { + var networkNodes, egressNetworkNodes []models.Node + collection, err := database.FetchRecords(database.NODES_TABLE_NAME) + if err != nil { + if database.IsEmptyRecord(err) { + return networkNodes, egressNetworkNodes, nil + } + logger.Log(2, err.Error()) + return nil, nil, err + } + + for _, value := range collection { + var node = models.Node{} + err := json.Unmarshal([]byte(value), &node) + if err != nil { + logger.Log(2, err.Error()) + continue + } + if node.Network == networkName { + networkNodes = append(networkNodes, node) + if node.IsEgressGateway == "yes" { + egressNetworkNodes = append(egressNetworkNodes, node) + } + } + } + return networkNodes, egressNetworkNodes, nil +} + func setPeerInfo(node *models.Node) models.Node { var peer models.Node peer.RelayAddrs = node.RelayAddrs @@ -326,3 +359,13 @@ func setIPForwardingLinux() error { } return nil } + +// StringSliceContains - sees if a string slice contains a string element +func StringSliceContains(slice []string, item string) bool { + for _, s := range slice { + if s == item { + return true + } + } + return false +} diff --git a/logic/wireguard.go b/logic/wireguard.go index 2090ec18..f903ae43 100644 --- a/logic/wireguard.go +++ b/logic/wireguard.go @@ -87,7 +87,8 @@ func initWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig if !ncutils.IsKernel() { var newConf string - newConf, _ = ncutils.CreateWireGuardConf(node.Address, key.String(), strconv.FormatInt(int64(node.ListenPort), 10), node.MTU, servercfg.GetCoreDNSAddr(), node.PersistentKeepalive, peers) + var nameserver string + newConf, _ = ncutils.CreateWireGuardConf(node.Address, key.String(), strconv.FormatInt(int64(node.ListenPort), 10), node.MTU, nameserver, servercfg.GetCoreDNSAddr(), node.PersistentKeepalive, peers) confPath := ncutils.GetNetclientPathSpecific() + ifacename + ".conf" logger.Log(1, "writing wg conf file to:", confPath) err = ioutil.WriteFile(confPath, []byte(newConf), 0644) diff --git a/main.go b/main.go index 384302d7..c908c5bb 100644 --- a/main.go +++ b/main.go @@ -43,7 +43,7 @@ func initialize() { // Client Mode Prereq Check var authProvider = auth.InitializeAuthProvider() if authProvider != "" { - logger.Log(0, "OAuth provider, ", authProvider, ", initialized") + logger.Log(0, "OAuth provider,", authProvider+",", "initialized") } else { logger.Log(0, "no OAuth provider found or not configured, continuing without OAuth") } diff --git a/netclient/command/commands.go b/netclient/command/commands.go index fa8013df..1aecdb4b 100644 --- a/netclient/command/commands.go +++ b/netclient/command/commands.go @@ -205,8 +205,9 @@ func List(cfg config.ClientConfig) error { // Uninstall - runs uninstall command from cli func Uninstall() error { - ncutils.PrintLog("uninstalling netclient", 0) + ncutils.PrintLog("uninstalling netclient...", 0) err := functions.Uninstall() + ncutils.PrintLog("uninstalled netclient", 0) return err } diff --git a/netclient/ncutils/netclientutils_darwin.go b/netclient/ncutils/netclientutils_darwin.go index 79fc85d7..a073f989 100644 --- a/netclient/ncutils/netclientutils_darwin.go +++ b/netclient/ncutils/netclientutils_darwin.go @@ -7,6 +7,7 @@ import ( "strconv" "strings" + "github.com/gravitl/netmaker/models" "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) @@ -33,12 +34,12 @@ func GetEmbedded() error { return nil } -// CreateUserSpaceConf - creates a user space WireGuard conf -func CreateUserSpaceConf(address string, privatekey string, listenPort string, mtu int32, perskeepalive int32, peers []wgtypes.PeerConfig) (string, error) { - peersString, err := parsePeers(perskeepalive, peers) +// CreateWireGuardConf - creates a WireGuard conf string +func CreateWireGuardConf(node *models.Node, privatekey string, listenPort string, dns string, peers []wgtypes.PeerConfig) (string, error) { + peersString, err := parsePeers(node.PersistentKeepalive, peers) var listenPortString string - if mtu <= 0 { - mtu = 1280 + if node.MTU <= 0 { + node.MTU = 1280 } if listenPort != "" { listenPortString += "ListenPort = " + listenPort @@ -55,9 +56,9 @@ MTU = %s %s `, - address+"/32", + node.Address+"/32", privatekey, - strconv.Itoa(int(mtu)), + strconv.Itoa(int(node.MTU)), listenPortString, peersString) return config, nil diff --git a/netclient/ncutils/netclientutils_freebsd.go b/netclient/ncutils/netclientutils_freebsd.go index 19d3aa19..bbacdc6c 100644 --- a/netclient/ncutils/netclientutils_freebsd.go +++ b/netclient/ncutils/netclientutils_freebsd.go @@ -3,13 +3,15 @@ package ncutils import ( "context" "fmt" - "golang.zx2c4.com/wireguard/wgctrl/wgtypes" "log" "os/exec" "strconv" "strings" "syscall" "time" + + "github.com/gravitl/netmaker/models" + "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) // RunCmdFormatted - run a command formatted for freebsd @@ -41,12 +43,12 @@ func RunCmd(command string, printerr bool) (string, error) { return string(out), err } -// CreateUserSpaceConf - creates a user space WireGuard conf -func CreateUserSpaceConf(address string, privatekey string, listenPort string, mtu int32, perskeepalive int32, peers []wgtypes.PeerConfig) (string, error) { - peersString, err := parsePeers(perskeepalive, peers) +// CreateWireGuardConf - creates a WireGuard conf string +func CreateWireGuardConf(node *models.Node, privatekey string, listenPort string, dns string, peers []wgtypes.PeerConfig) (string, error) { + peersString, err := parsePeers(node.PersistentKeepalive, peers) var listenPortString string - if mtu <= 0 { - mtu = 1280 + if node.MTU <= 0 { + node.MTU = 1280 } if listenPort != "" { listenPortString += "ListenPort = " + listenPort @@ -63,9 +65,9 @@ MTU = %s %s `, - address+"/32", + node.Address+"/32", privatekey, - strconv.Itoa(int(mtu)), + strconv.Itoa(int(node.MTU)), listenPortString, peersString) return config, nil diff --git a/netclient/ncutils/netclientutils_linux.go b/netclient/ncutils/netclientutils_linux.go index ae40c292..bc4c399e 100644 --- a/netclient/ncutils/netclientutils_linux.go +++ b/netclient/ncutils/netclientutils_linux.go @@ -6,6 +6,7 @@ import ( "strconv" "strings" + "github.com/gravitl/netmaker/models" "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) @@ -33,15 +34,23 @@ func GetEmbedded() error { } // CreateWireGuardConf - creates a user space WireGuard conf -func CreateWireGuardConf(address string, privatekey string, listenPort string, mtu int32, dns string, perskeepalive int32, peers []wgtypes.PeerConfig) (string, error) { - peersString, err := parsePeers(perskeepalive, peers) - var listenPortString string - if mtu <= 0 { - mtu = 1280 +func CreateWireGuardConf(node *models.Node, privatekey string, listenPort string, dns string, peers []wgtypes.PeerConfig) (string, error) { + peersString, err := parsePeers(node.PersistentKeepalive, peers) + var listenPortString, postDownString, postUpString string + if node.MTU <= 0 { + node.MTU = 1280 } + if node.PostDown != "" { + postDownString = fmt.Sprintf("PostDown = %s", node.PostDown) + } + if node.PostUp != "" { + postUpString = fmt.Sprintf("PostUp = %s", node.PostUp) + } + if listenPort != "" { - listenPortString += "ListenPort = " + listenPort + listenPortString = fmt.Sprintf("ListenPort = %s", listenPort) } + if err != nil { return "", err } @@ -51,14 +60,18 @@ DNS = %s PrivateKey = %s MTU = %s %s +%s +%s %s `, - address+"/32", + node.Address+"/32", dns, privatekey, - strconv.Itoa(int(mtu)), + strconv.Itoa(int(node.MTU)), + postDownString, + postUpString, listenPortString, peersString) return config, nil diff --git a/netclient/ncutils/netclientutils_windows.go b/netclient/ncutils/netclientutils_windows.go index 45974297..5acf73a7 100644 --- a/netclient/ncutils/netclientutils_windows.go +++ b/netclient/ncutils/netclientutils_windows.go @@ -10,6 +10,7 @@ import ( "strings" "syscall" + "github.com/gravitl/netmaker/models" "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) @@ -47,12 +48,12 @@ func RunCmdFormatted(command string, printerr bool) (string, error) { return string(out), err } -// CreateUserSpaceConf - creates a user space WireGuard conf -func CreateUserSpaceConf(address string, privatekey string, listenPort string, mtu int32, perskeepalive int32, peers []wgtypes.PeerConfig) (string, error) { - peersString, err := parsePeers(perskeepalive, peers) +// CreateWireGuardConf - creates a WireGuard conf string +func CreateWireGuardConf(node *models.Node, privatekey string, listenPort string, dns string, peers []wgtypes.PeerConfig) (string, error) { + peersString, err := parsePeers(node.PersistentKeepalive, peers) var listenPortString string - if mtu <= 0 { - mtu = 1280 + if node.MTU <= 0 { + node.MTU = 1280 } if listenPort != "" { listenPortString += "ListenPort = " + listenPort @@ -69,9 +70,9 @@ MTU = %s %s `, - address+"/32", + node.Address+"/32", privatekey, - strconv.Itoa(int(mtu)), + strconv.Itoa(int(node.MTU)), listenPortString, peersString) return config, nil diff --git a/netclient/wireguard/common.go b/netclient/wireguard/common.go index 53613790..f65016dd 100644 --- a/netclient/wireguard/common.go +++ b/netclient/wireguard/common.go @@ -149,9 +149,9 @@ func InitWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig } var newConf string if node.UDPHolePunch != "yes" { - newConf, _ = ncutils.CreateWireGuardConf(node.Address, key.String(), strconv.FormatInt(int64(node.ListenPort), 10), node.MTU, nameserver, node.PersistentKeepalive, peers) + newConf, _ = ncutils.CreateWireGuardConf(node, key.String(), strconv.FormatInt(int64(node.ListenPort), 10), nameserver, peers) } else { - newConf, _ = ncutils.CreateWireGuardConf(node.Address, key.String(), "", node.MTU, nameserver, node.PersistentKeepalive, peers) + newConf, _ = ncutils.CreateWireGuardConf(node, key.String(), "", nameserver, peers) } confPath := ncutils.GetNetclientPathSpecific() + ifacename + ".conf" ncutils.PrintLog("writing wg conf file to: "+confPath, 1) @@ -182,7 +182,7 @@ func InitWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig } else { d, _ := wgclient.Device(deviceiface) for d != nil && d.Name == deviceiface { - _ = RemoveConf(ifacename, false) // remove interface first + RemoveConf(ifacename, false) // remove interface first time.Sleep(time.Second >> 2) d, _ = wgclient.Device(deviceiface) } diff --git a/netclient/wireguard/unix.go b/netclient/wireguard/unix.go index 8b557d0a..6e9e52af 100644 --- a/netclient/wireguard/unix.go +++ b/netclient/wireguard/unix.go @@ -1,6 +1,7 @@ package wireguard import ( + "fmt" "io/ioutil" "log" "os" @@ -86,7 +87,7 @@ func SyncWGQuickConf(iface string, confPath string) error { // RemoveWGQuickConf - calls wg-quick down func RemoveWGQuickConf(confPath string, printlog bool) error { - _, err := ncutils.RunCmd("wg-quick down "+confPath, printlog) + _, err := ncutils.RunCmd(fmt.Sprintf("wg-quick down %s", confPath), printlog) return err } diff --git a/servercfg/serverconf.go b/servercfg/serverconf.go index fb7a67cb..7c1ebd74 100644 --- a/servercfg/serverconf.go +++ b/servercfg/serverconf.go @@ -502,6 +502,17 @@ func GetAuthProviderInfo() []string { return []string{"", "", ""} } +// GetAzureTenant - retrieve the azure tenant ID from env variable or config file +func GetAzureTenant() string { + var azureTenant = "" + if os.Getenv("AZURE_TENANT") != "" { + azureTenant = os.Getenv("AZURE_TENANT") + } else if config.Config.Server.AzureTenant != "" { + azureTenant = config.Config.Server.AzureTenant + } + return azureTenant +} + // GetMacAddr - get's mac address func getMacAddr() string { ifas, err := net.Interfaces() From d9ff00d4b155f9f0762d2bb4ac7c536cb1e24229 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Wed, 5 Jan 2022 10:05:51 -0500 Subject: [PATCH 013/116] subscribed message handlers implemented --- go.mod | 1 + go.sum | 2 + models/mqtt.go | 14 ++++ netclient/functions/daemon.go | 75 +++++++++++++++++++++ netclient/wireguard/common.go | 123 ++++++++++++++++++++++++++++++++++ 5 files changed, 215 insertions(+) create mode 100644 models/mqtt.go diff --git a/go.mod b/go.mod index 8c49b6bb..781d86a6 100644 --- a/go.mod +++ b/go.mod @@ -49,4 +49,5 @@ require ( github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect google.golang.org/appengine v1.4.0 // indirect + gopkg.in/ini.v1 v1.66.2 // indirect ) diff --git a/go.sum b/go.sum index 5b8fecb5..a1efc4e7 100644 --- a/go.sum +++ b/go.sum @@ -292,6 +292,8 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/ini.v1 v1.66.2 h1:XfR1dOYubytKy4Shzc2LHrrGhU0lDCfDGG1yLPmpgsI= +gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/models/mqtt.go b/models/mqtt.go new file mode 100644 index 00000000..a7e87e1f --- /dev/null +++ b/models/mqtt.go @@ -0,0 +1,14 @@ +package models + +import "golang.zx2c4.com/wireguard/wgctrl/wgtypes" + +type PeerUpdate struct { + Network string + Interface string + Peers []wgtypes.Peer +} + +type KeyUpdate struct { + Network string + Interface string +} diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index 45a49d9b..fc926bda 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -11,9 +11,12 @@ import ( "time" mqtt "github.com/eclipse/paho.mqtt.golang" + "github.com/gravitl/netmaker/models" "github.com/gravitl/netmaker/netclient/config" "github.com/gravitl/netmaker/netclient/ncutils" + "github.com/gravitl/netmaker/netclient/wireguard" "golang.zx2c4.com/wireguard/wgctrl" + "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) // Daemon runs netclient daemon from command line @@ -81,16 +84,88 @@ var All mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { // NodeUpdate -- mqtt message handler for /update/ topic var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update node " + string(msg.Payload())) + //potentiall blocking i/o so do this in a go routine + go func() { + var data models.Node + err := json.Unmarshal(msg.Payload(), &data) + if err != nil { + ncutils.Log("error unmarshalling node update data" + err.Error()) + return + } + var cfg config.ClientConfig + cfg.Network = data.Network + cfg.ReadConfig() + nameserver := cfg.Server.CoreDNSAddr + privateKey, err := wireguard.RetrievePrivKey(data.Network) + if err := wireguard.UpdateWgInterface(cfg.Node.Interface, privateKey, nameserver, data); err != nil { + ncutils.Log("error updating wireguard config " + err.Error()) + return + } + // path hardcoded for now... should be updated + err = wireguard.ApplyWGQuickConf("/etc/netclient/config/" + cfg.Node.Interface + ".conf") + if err != nil { + ncutils.Log("error restarting wg after peer update " + err.Error()) + return + } + }() } // UpdatePeers -- mqtt message handler for /update/peers/ topic var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update peers " + string(msg.Payload())) + //potentiall blocking i/o so do this in a go routine + go func() { + var peerUpdate models.PeerUpdate + err := json.Unmarshal(msg.Payload(), &peerUpdate) + if err != nil { + ncutils.Log("error unmarshalling peer data") + return + } + var cfg config.ClientConfig + cfg.Network = peerUpdate.Network + cfg.ReadConfig() + err = wireguard.UpdateWgPeers(cfg.Node.Interface, peerUpdate.Peers) + if err != nil { + ncutils.Log("error updating peers" + err.Error()) + return + } + // path hardcoded for now... should be updated + err = wireguard.ApplyWGQuickConf("/etc/netclient/config/" + cfg.Node.Interface + ".conf") + if err != nil { + ncutils.Log("error restarting wg after peer update " + err.Error()) + return + } + }() } // UpdateKeys -- mqtt message handler for /update/keys/ topic var UpdateKeys mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update keys " + string(msg.Payload())) + //potentiall blocking i/o so do this in a go routine + go func() { + var data models.KeyUpdate + if err := json.Unmarshal(msg.Payload(), &data); err != nil { + ncutils.Log("error unmarshalling key update data" + err.Error()) + return + } + var cfg config.ClientConfig + cfg.Network = data.Network + cfg.ReadConfig() + key, err := wgtypes.GeneratePrivateKey() + if err != nil { + ncutils.Log("error generating privatekey " + err.Error()) + return + } + if err := wireguard.UpdatePrivateKey(data.Interface, key.String()); err != nil { + ncutils.Log("error updating wireguard key " + err.Error()) + return + } + publicKey := key.PublicKey() + if token := client.Publish("update/publickey/"+cfg.Node.ID, 0, false, publicKey.String()); token.Wait() && token.Error() != nil { + ncutils.Log("error publishing publickey update " + token.Error().Error()) + } + client.Disconnect(250) + }() } // Checkin -- go routine that checks for public or local ip changes, publishes changes diff --git a/netclient/wireguard/common.go b/netclient/wireguard/common.go index f65016dd..56c1f241 100644 --- a/netclient/wireguard/common.go +++ b/netclient/wireguard/common.go @@ -17,6 +17,7 @@ import ( "github.com/gravitl/netmaker/netclient/server" "golang.zx2c4.com/wireguard/wgctrl" "golang.zx2c4.com/wireguard/wgctrl/wgtypes" + "gopkg.in/ini.v1" ) // SetPeers - sets peers on a given WireGuard interface @@ -290,3 +291,125 @@ func ApplyConf(confPath string) error { } return err } + +// WriteWgConfig - creates a wireguard config file +func WriteWgConfig(cfg config.ClientConfig, privateKey string, peers []wgtypes.Peer) error { + options := ini.LoadOptions{ + AllowNonUniqueSections: true, + AllowShadows: true, + } + wireguard := ini.Empty(options) + wireguard.Section("Interface").Key("PrivateKey").SetValue(privateKey) + wireguard.Section("Interface").Key("ListenPort").SetValue(strconv.Itoa(int(cfg.Node.ListenPort))) + if cfg.Node.Address != "" { + wireguard.Section("Interface").Key("Address").SetValue(cfg.Node.Address) + } + if cfg.Node.Address6 != "" { + wireguard.Section("Interface").Key("Address").SetValue(cfg.Node.Address6) + } + if cfg.Node.DNSOn == "yes" { + wireguard.Section("Interface").Key("DNS").SetValue(cfg.Server.CoreDNSAddr) + } + if cfg.Node.PostUp != "" { + wireguard.Section("Interface").Key("PostUp").SetValue(cfg.Node.PostUp) + } + if cfg.Node.PostDown != "" { + wireguard.Section("Interface").Key("PostDown").SetValue(cfg.Node.PostDown) + } + for i, peer := range peers { + wireguard.SectionWithIndex("Peer", i).Key("PublicKey").SetValue(peer.PublicKey.String()) + if peer.PresharedKey.String() != "" { + wireguard.SectionWithIndex("Peer", i).Key("PreSharedKey").SetValue(peer.PresharedKey.String()) + } + if peer.AllowedIPs != nil { + var allowedIPs string + for _, ip := range peer.AllowedIPs { + allowedIPs = allowedIPs + ", " + ip.String() + } + wireguard.SectionWithIndex("Peer", i).Key("AllowedIps").SetValue(allowedIPs) + } + if peer.Endpoint != nil { + wireguard.SectionWithIndex("Peer", i).Key("Endpoint").SetValue(peer.Endpoint.String()) + } + } + if err := wireguard.SaveTo("/etc/netclient/config" + cfg.Node.Interface + ".conf"); err != nil { + return err + } + return nil +} + +// UpdateWgPeers - updates the peers of a network +func UpdateWgPeers(wgInterface string, peers []wgtypes.Peer) error { + //update to get path properly + file := "/etc/netclient/config/" + wgInterface + ".conf" + wireguard, err := ini.ShadowLoad(file) + if err != nil { + return err + } + for i, peer := range peers { + wireguard.SectionWithIndex("Peer", i).Key("PublicKey").SetValue(peer.PublicKey.String()) + if peer.PresharedKey.String() != "" { + wireguard.SectionWithIndex("Peer", i).Key("PreSharedKey").SetValue(peer.PresharedKey.String()) + } + if peer.AllowedIPs != nil { + var allowedIPs string + for _, ip := range peer.AllowedIPs { + allowedIPs = allowedIPs + ", " + ip.String() + } + wireguard.SectionWithIndex("Peer", i).Key("AllowedIps").SetValue(allowedIPs) + } + if peer.Endpoint != nil { + wireguard.SectionWithIndex("Peer", i).Key("Endpoint").SetValue(peer.Endpoint.String()) + } + } + if err := wireguard.SaveTo(file); err != nil { + return err + } + return nil +} + +// UpdateWgInterface - updates the interface section of a wireguard config file +func UpdateWgInterface(wgInterface, privateKey, nameserver string, node models.Node) error { + //update to get path properly + file := "/etc/netclient/config/" + wgInterface + ".conf" + wireguard, err := ini.ShadowLoad(file) + if err != nil { + return err + } + wireguard.Section("Interface").Key("PrivateKey").SetValue(privateKey) + wireguard.Section("Interface").Key("ListenPort").SetValue(strconv.Itoa(int(node.ListenPort))) + if node.Address != "" { + wireguard.Section("Interface").Key("Address").SetValue(node.Address) + } + if node.Address6 != "" { + wireguard.Section("Interface").Key("Address").SetValue(node.Address6) + } + if node.DNSOn == "yes" { + wireguard.Section("Interface").Key("DNS").SetValue(nameserver) + } + if node.PostUp != "" { + wireguard.Section("Interface").Key("PostUp").SetValue(node.PostUp) + } + if node.PostDown != "" { + wireguard.Section("Interface").Key("PostDown").SetValue(node.PostDown) + } + if err := wireguard.SaveTo(file); err != nil { + return err + } + return nil +} + +// UpdatePrivateKey - updates the private key of a wireguard config file +func UpdatePrivateKey(wgInterface, privateKey string) error { + //update to get path properly + file := "/etc/netclient/config/" + wgInterface + ".conf" + wireguard, err := ini.ShadowLoad(file) + if err != nil { + return err + } + wireguard.Section("Interface").Key("PrivateKey").SetValue(privateKey) + if err := wireguard.SaveTo(file); err != nil { + return err + } + return nil +} From 81b75c78bd1cf53db5a7da727a3835c69bddc631 Mon Sep 17 00:00:00 2001 From: 0xdcarns Date: Wed, 5 Jan 2022 10:32:20 -0500 Subject: [PATCH 014/116] constants --- netclient/wireguard/common.go | 59 +++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/netclient/wireguard/common.go b/netclient/wireguard/common.go index 56c1f241..cb83c166 100644 --- a/netclient/wireguard/common.go +++ b/netclient/wireguard/common.go @@ -20,6 +20,11 @@ import ( "gopkg.in/ini.v1" ) +const ( + section_interface = "Interface" + section_peers = "Peer" +) + // SetPeers - sets peers on a given WireGuard interface func SetPeers(iface string, keepalive int32, peers []wgtypes.PeerConfig) error { @@ -299,40 +304,40 @@ func WriteWgConfig(cfg config.ClientConfig, privateKey string, peers []wgtypes.P AllowShadows: true, } wireguard := ini.Empty(options) - wireguard.Section("Interface").Key("PrivateKey").SetValue(privateKey) - wireguard.Section("Interface").Key("ListenPort").SetValue(strconv.Itoa(int(cfg.Node.ListenPort))) + wireguard.Section(section_interface).Key("PrivateKey").SetValue(privateKey) + wireguard.Section(section_interface).Key("ListenPort").SetValue(strconv.Itoa(int(cfg.Node.ListenPort))) if cfg.Node.Address != "" { - wireguard.Section("Interface").Key("Address").SetValue(cfg.Node.Address) + wireguard.Section(section_interface).Key("Address").SetValue(cfg.Node.Address) } if cfg.Node.Address6 != "" { - wireguard.Section("Interface").Key("Address").SetValue(cfg.Node.Address6) + wireguard.Section(section_interface).Key("Address").SetValue(cfg.Node.Address6) } if cfg.Node.DNSOn == "yes" { - wireguard.Section("Interface").Key("DNS").SetValue(cfg.Server.CoreDNSAddr) + wireguard.Section(section_interface).Key("DNS").SetValue(cfg.Server.CoreDNSAddr) } if cfg.Node.PostUp != "" { - wireguard.Section("Interface").Key("PostUp").SetValue(cfg.Node.PostUp) + wireguard.Section(section_interface).Key("PostUp").SetValue(cfg.Node.PostUp) } if cfg.Node.PostDown != "" { - wireguard.Section("Interface").Key("PostDown").SetValue(cfg.Node.PostDown) + wireguard.Section(section_interface).Key("PostDown").SetValue(cfg.Node.PostDown) } for i, peer := range peers { - wireguard.SectionWithIndex("Peer", i).Key("PublicKey").SetValue(peer.PublicKey.String()) + wireguard.SectionWithIndex(section_peers, i).Key("PublicKey").SetValue(peer.PublicKey.String()) if peer.PresharedKey.String() != "" { - wireguard.SectionWithIndex("Peer", i).Key("PreSharedKey").SetValue(peer.PresharedKey.String()) + wireguard.SectionWithIndex(section_peers, i).Key("PreSharedKey").SetValue(peer.PresharedKey.String()) } if peer.AllowedIPs != nil { var allowedIPs string for _, ip := range peer.AllowedIPs { allowedIPs = allowedIPs + ", " + ip.String() } - wireguard.SectionWithIndex("Peer", i).Key("AllowedIps").SetValue(allowedIPs) + wireguard.SectionWithIndex(section_peers, i).Key("AllowedIps").SetValue(allowedIPs) } if peer.Endpoint != nil { - wireguard.SectionWithIndex("Peer", i).Key("Endpoint").SetValue(peer.Endpoint.String()) + wireguard.SectionWithIndex(section_peers, i).Key("Endpoint").SetValue(peer.Endpoint.String()) } } - if err := wireguard.SaveTo("/etc/netclient/config" + cfg.Node.Interface + ".conf"); err != nil { + if err := wireguard.SaveTo(ncutils.GetNetclientPathSpecific() + cfg.Node.Interface + ".conf"); err != nil { return err } return nil @@ -341,25 +346,25 @@ func WriteWgConfig(cfg config.ClientConfig, privateKey string, peers []wgtypes.P // UpdateWgPeers - updates the peers of a network func UpdateWgPeers(wgInterface string, peers []wgtypes.Peer) error { //update to get path properly - file := "/etc/netclient/config/" + wgInterface + ".conf" + file := ncutils.GetNetclientPathSpecific() + wgInterface + ".conf" wireguard, err := ini.ShadowLoad(file) if err != nil { return err } for i, peer := range peers { - wireguard.SectionWithIndex("Peer", i).Key("PublicKey").SetValue(peer.PublicKey.String()) + wireguard.SectionWithIndex(section_peers, i).Key("PublicKey").SetValue(peer.PublicKey.String()) if peer.PresharedKey.String() != "" { - wireguard.SectionWithIndex("Peer", i).Key("PreSharedKey").SetValue(peer.PresharedKey.String()) + wireguard.SectionWithIndex(section_peers, i).Key("PreSharedKey").SetValue(peer.PresharedKey.String()) } if peer.AllowedIPs != nil { var allowedIPs string for _, ip := range peer.AllowedIPs { allowedIPs = allowedIPs + ", " + ip.String() } - wireguard.SectionWithIndex("Peer", i).Key("AllowedIps").SetValue(allowedIPs) + wireguard.SectionWithIndex(section_peers, i).Key("AllowedIps").SetValue(allowedIPs) } if peer.Endpoint != nil { - wireguard.SectionWithIndex("Peer", i).Key("Endpoint").SetValue(peer.Endpoint.String()) + wireguard.SectionWithIndex(section_peers, i).Key("Endpoint").SetValue(peer.Endpoint.String()) } } if err := wireguard.SaveTo(file); err != nil { @@ -371,27 +376,27 @@ func UpdateWgPeers(wgInterface string, peers []wgtypes.Peer) error { // UpdateWgInterface - updates the interface section of a wireguard config file func UpdateWgInterface(wgInterface, privateKey, nameserver string, node models.Node) error { //update to get path properly - file := "/etc/netclient/config/" + wgInterface + ".conf" + file := ncutils.GetNetclientPathSpecific() + wgInterface + ".conf" wireguard, err := ini.ShadowLoad(file) if err != nil { return err } - wireguard.Section("Interface").Key("PrivateKey").SetValue(privateKey) - wireguard.Section("Interface").Key("ListenPort").SetValue(strconv.Itoa(int(node.ListenPort))) + wireguard.Section(section_interface).Key("PrivateKey").SetValue(privateKey) + wireguard.Section(section_interface).Key("ListenPort").SetValue(strconv.Itoa(int(node.ListenPort))) if node.Address != "" { - wireguard.Section("Interface").Key("Address").SetValue(node.Address) + wireguard.Section(section_interface).Key("Address").SetValue(node.Address) } if node.Address6 != "" { - wireguard.Section("Interface").Key("Address").SetValue(node.Address6) + wireguard.Section(section_interface).Key("Address").SetValue(node.Address6) } if node.DNSOn == "yes" { - wireguard.Section("Interface").Key("DNS").SetValue(nameserver) + wireguard.Section(section_interface).Key("DNS").SetValue(nameserver) } if node.PostUp != "" { - wireguard.Section("Interface").Key("PostUp").SetValue(node.PostUp) + wireguard.Section(section_interface).Key("PostUp").SetValue(node.PostUp) } if node.PostDown != "" { - wireguard.Section("Interface").Key("PostDown").SetValue(node.PostDown) + wireguard.Section(section_interface).Key("PostDown").SetValue(node.PostDown) } if err := wireguard.SaveTo(file); err != nil { return err @@ -402,12 +407,12 @@ func UpdateWgInterface(wgInterface, privateKey, nameserver string, node models.N // UpdatePrivateKey - updates the private key of a wireguard config file func UpdatePrivateKey(wgInterface, privateKey string) error { //update to get path properly - file := "/etc/netclient/config/" + wgInterface + ".conf" + file := ncutils.GetNetclientPathSpecific() + wgInterface + ".conf" wireguard, err := ini.ShadowLoad(file) if err != nil { return err } - wireguard.Section("Interface").Key("PrivateKey").SetValue(privateKey) + wireguard.Section(section_interface).Key("PrivateKey").SetValue(privateKey) if err := wireguard.SaveTo(file); err != nil { return err } From 2531af49f24c36ccae090efce7fd55361221b35f Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Wed, 5 Jan 2022 11:07:09 -0500 Subject: [PATCH 015/116] add error handling on failed key generation --- netclient/functions/daemon.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index fc926bda..8baaa392 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -97,6 +97,10 @@ var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) cfg.ReadConfig() nameserver := cfg.Server.CoreDNSAddr privateKey, err := wireguard.RetrievePrivKey(data.Network) + if err != nil { + ncutils.Log("error generating PrivateKey " + err.Error()) + return + } if err := wireguard.UpdateWgInterface(cfg.Node.Interface, privateKey, nameserver, data); err != nil { ncutils.Log("error updating wireguard config " + err.Error()) return From f8a01dfac006f44c5fd6a84bc9177d16cebd51a7 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Mon, 10 Jan 2022 14:35:53 -0500 Subject: [PATCH 016/116] refactor NodeUpdate message queue handler --- netclient/functions/daemon.go | 89 +++++++++++++++++++++-------------- 1 file changed, 54 insertions(+), 35 deletions(-) diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index 8baaa392..639436ae 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -6,6 +6,7 @@ import ( "log" "os" "os/signal" + "runtime" "strings" "syscall" "time" @@ -67,7 +68,8 @@ func Netclient(ctx context.Context, network string) { } client.AddRoute("update/"+cfg.Node.ID, NodeUpdate) client.AddRoute("update/peers/"+cfg.Node.ID, UpdatePeers) - client.AddRoute("update/keys/"+cfg.Node.ID, UpdateKeys) + //handle key updates in node update + //client.AddRoute("update/keys/"+cfg.Node.ID, UpdateKeys) defer client.Disconnect(250) go Checkin(ctx, cfg, network) go Metrics(ctx, cfg, network) @@ -86,19 +88,44 @@ var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) ncutils.Log("received message to update node " + string(msg.Payload())) //potentiall blocking i/o so do this in a go routine go func() { - var data models.Node - err := json.Unmarshal(msg.Payload(), &data) + var newNode models.Node + var cfg config.ClientConfig + cfg.Network = newNode.Network + cfg.ReadConfig() + err := json.Unmarshal(msg.Payload(), &newNode) if err != nil { ncutils.Log("error unmarshalling node update data" + err.Error()) return } - var cfg config.ClientConfig - cfg.Network = data.Network - cfg.ReadConfig() + //check if interface name has changed if so delete. + if cfg.Node.Interface != newNode.Interface { + if err = wireguard.RemoveConf(cfg.Node.Interface, true); err != nil { + ncutils.PrintLog("could not delete old interface "+cfg.Node.Interface+": ", err.Error(), 1) + } + } + newNode.PullChanges = "no" + //ensure that OS never changes + newNode.OS = runtime.GOOS + cfg.Node = newNode + switch newNode.Action { + case models.NODE_DELETE: + if err := RemoveLocalInstance(cfg, cfg.Network); err != nil { + ncutils.Printlog("error deleting local instance: "+err.Error(), 1) + return + } + case models.NODE_UPDATE_KEY: + UpdateKeys(cfg) + case models.NODE_NOOP: + default: + } + //Save new config + if err := config.Write(&cfg, cfg.Network); err != nil { + ncutils.PrintLog("error updating node configuration: "+err.Error(), 1) + } nameserver := cfg.Server.CoreDNSAddr privateKey, err := wireguard.RetrievePrivKey(data.Network) if err != nil { - ncutils.Log("error generating PrivateKey " + err.Error()) + ncutils.Log("error reading PrivateKey " + err.Error()) return } if err := wireguard.UpdateWgInterface(cfg.Node.Interface, privateKey, nameserver, data); err != nil { @@ -108,7 +135,7 @@ var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) // path hardcoded for now... should be updated err = wireguard.ApplyWGQuickConf("/etc/netclient/config/" + cfg.Node.Interface + ".conf") if err != nil { - ncutils.Log("error restarting wg after peer update " + err.Error()) + ncutils.Log("error restarting wg after node update " + err.Error()) return } }() @@ -117,7 +144,6 @@ var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) // UpdatePeers -- mqtt message handler for /update/peers/ topic var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update peers " + string(msg.Payload())) - //potentiall blocking i/o so do this in a go routine go func() { var peerUpdate models.PeerUpdate err := json.Unmarshal(msg.Payload(), &peerUpdate) @@ -142,34 +168,27 @@ var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) }() } -// UpdateKeys -- mqtt message handler for /update/keys/ topic -var UpdateKeys mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { - ncutils.Log("received message to update keys " + string(msg.Payload())) +// UpdateKeys -- updates private key and returns new publickey +func UpdateKeys(cfg *config.ClientConfig, client mqtt.Client) (*config.ClientConfig, error) { + ncutils.Log("received message to update keys") //potentiall blocking i/o so do this in a go routine - go func() { - var data models.KeyUpdate - if err := json.Unmarshal(msg.Payload(), &data); err != nil { - ncutils.Log("error unmarshalling key update data" + err.Error()) - return - } - var cfg config.ClientConfig - cfg.Network = data.Network - cfg.ReadConfig() - key, err := wgtypes.GeneratePrivateKey() - if err != nil { - ncutils.Log("error generating privatekey " + err.Error()) - return - } - if err := wireguard.UpdatePrivateKey(data.Interface, key.String()); err != nil { - ncutils.Log("error updating wireguard key " + err.Error()) - return - } - publicKey := key.PublicKey() - if token := client.Publish("update/publickey/"+cfg.Node.ID, 0, false, publicKey.String()); token.Wait() && token.Error() != nil { - ncutils.Log("error publishing publickey update " + token.Error().Error()) - } + key, err := wgtypes.GeneratePrivateKey() + if err != nil { + ncutils.Log("error generating privatekey " + err.Error()) + return cfg, err + } + if err := wireguard.UpdatePrivateKey(data.Interface, key.String()); err != nil { + ncutils.Log("error updating wireguard key " + err.Error()) + return cfg, err + } + publicKey := key.PublicKey() + if token := client.Publish("update/publickey/"+cfg.Node.ID, 0, false, publicKey.String()); token.Wait() && token.Error() != nil { + ncutils.Log("error publishing publickey update " + token.Error().Error()) client.Disconnect(250) - }() + return cfg, err + } + client.Disconnect(250) + return cfg, nil } // Checkin -- go routine that checks for public or local ip changes, publishes changes From 206c542c7066b54cc8371a8ca3d9ff7830839289 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Wed, 12 Jan 2022 16:23:34 -0500 Subject: [PATCH 017/116] WIP commit --- .gitignore | 1 + config/config.go | 2 + go.mod | 7 +- go.sum | 8 -- main.go | 57 +++++++++- models/mqtt.go | 5 +- mq/mq.go | 197 ++++++++++++++++++++++++++++++++++ netclient/functions/daemon.go | 14 +-- servercfg/serverconf.go | 27 +++++ 9 files changed, 293 insertions(+), 25 deletions(-) create mode 100644 mq/mq.go diff --git a/.gitignore b/.gitignore index 16721cb9..bf873a65 100644 --- a/.gitignore +++ b/.gitignore @@ -16,4 +16,5 @@ netclient/netclient.exe config/dnsconfig/ data/ .idea/ +.vscode/ diff --git a/config/config.go b/config/config.go index fc1bcbf2..649ef1b9 100644 --- a/config/config.go +++ b/config/config.go @@ -43,12 +43,14 @@ type ServerConfig struct { GRPCHost string `yaml:"grpchost"` GRPCPort string `yaml:"grpcport"` GRPCSecure string `yaml:"grpcsecure"` + MQHOST string `yaml:"mqhost"` MasterKey string `yaml:"masterkey"` DNSKey string `yaml:"dnskey"` AllowedOrigin string `yaml:"allowedorigin"` NodeID string `yaml:"nodeid"` RestBackend string `yaml:"restbackend"` AgentBackend string `yaml:"agentbackend"` + MessageQueueBackend string `yaml:"messagequeuebackend"` ClientMode string `yaml:"clientmode"` DNSMode string `yaml:"dnsmode"` SplitDNS string `yaml:"splitdns"` diff --git a/go.mod b/go.mod index e4df37a3..e4cead57 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/gravitl/netmaker go 1.17 require ( + github.com/eclipse/paho.mqtt.golang v1.3.5 github.com/go-playground/validator/v10 v10.10.0 github.com/golang-jwt/jwt/v4 v4.2.0 github.com/golang/protobuf v1.5.2 // indirect @@ -25,6 +26,7 @@ require ( google.golang.org/genproto v0.0.0-20210201151548-94839c025ad4 // indirect google.golang.org/grpc v1.43.0 google.golang.org/protobuf v1.27.1 + gopkg.in/ini.v1 v1.66.2 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b ) @@ -32,13 +34,10 @@ require ( cloud.google.com/go v0.34.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/eclipse/paho.mqtt.golang v1.3.5 // indirect github.com/felixge/httpsnoop v1.0.1 // indirect - github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534 // indirect github.com/go-playground/locales v0.14.0 // indirect github.com/go-playground/universal-translator v0.18.0 // indirect github.com/google/go-cmp v0.5.5 // indirect - github.com/google/uuid v1.2.0 // indirect github.com/gorilla/websocket v1.4.2 // indirect github.com/josharian/native v0.0.0-20200817173448-b6b71def0850 // indirect github.com/leodido/go-urn v1.2.1 // indirect @@ -47,7 +46,5 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/russross/blackfriday/v2 v2.0.1 // indirect github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect - golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect google.golang.org/appengine v1.4.0 // indirect - gopkg.in/ini.v1 v1.66.2 // indirect ) diff --git a/go.sum b/go.sum index 5ffce809..995a9322 100644 --- a/go.sum +++ b/go.sum @@ -36,8 +36,6 @@ github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8S github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534 h1:dhy9OQKGBh4zVXbjwbxxHjRxMJtLXj3zfgpBYQaR4Q4= -github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk= github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= @@ -74,8 +72,6 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= -github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= @@ -194,7 +190,6 @@ golang.org/x/net v0.0.0-20201216054612-986b41b23924/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210504132125-bbd867fde50d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985 h1:4CSI6oo7cOjJKajidEljs9h+uP0rRZBPPPhcCbj5mw8= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -205,8 +200,6 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -228,7 +221,6 @@ golang.org/x/sys v0.0.0-20210123111255-9b0068b26619/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210216163648-f7da38b97c65/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210309040221-94ec62e08169/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210503173754-0981d6026fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/main.go b/main.go index fd9aad97..52243051 100644 --- a/main.go +++ b/main.go @@ -11,6 +11,7 @@ import ( "sync" "time" + mqtt "github.com/eclipse/paho.mqtt.golang" "github.com/gravitl/netmaker/auth" controller "github.com/gravitl/netmaker/controllers" "github.com/gravitl/netmaker/database" @@ -19,6 +20,7 @@ import ( "github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/logic" "github.com/gravitl/netmaker/models" + "github.com/gravitl/netmaker/mq" "github.com/gravitl/netmaker/netclient/ncutils" "github.com/gravitl/netmaker/servercfg" "github.com/gravitl/netmaker/serverctl" @@ -106,8 +108,14 @@ func startControllers() { go controller.HandleRESTRequests(&waitnetwork) } - if !servercfg.IsAgentBackend() && !servercfg.IsRestBackend() { - logger.Log(0, "No Server Mode selected, so nothing is being served! Set either Agent mode (AGENT_BACKEND) or Rest mode (REST_BACKEND) to 'true'.") + //Run MessageQueue + if servercfg.IsMessageQueueBackend() { + waitnetwork.Add(1) + go runMessageQueue(&waitnetwork) + } + + if !servercfg.IsAgentBackend() && !servercfg.IsRestBackend() && !servercfg.IsMessageQueueBackend() { + logger.Log(0, "No Server Mode selected, so nothing is being served! Set Agent mode (AGENT_BACKEND) or Rest mode (REST_BACKEND) or MessageQueue (MESSAGEQUEUE_BACKEND) to 'true'.") } if servercfg.IsClientMode() == "on" { @@ -175,6 +183,51 @@ func runGRPC(wg *sync.WaitGroup) { logger.Log(0, "Closed DB connection.") } +// Should we be using a context vice a waitgroup???????????? +func runMessageQueue(wg *sync.WaitGroup) { + defer wg.Done() + //refactor netclient.functions.SetupMQTT so can be called from here + //setupMQTT + opts := mqtt.NewClientOptions() + opts.AddBroker(servercfg.GetMessageQueueEndpoint()) + logger.Log(0, "setting broker "+servercfg.GetMessageQueueEndpoint()) + opts.SetDefaultPublishHandler(mq.DefaultHandler) + client := mqtt.NewClient(opts) + if token := client.Connect(); token.Wait() && token.Error() != nil { + logger.Log(0, "unable to connect to message queue broker, closing down") + return + } + //Set up Subscriptions + if token := client.Subscribe("#", 0, nil); token.Wait() && token.Error() != nil { + //should make constant for disconnect wait period + client.Disconnect(250) + logger.Log(0, "could not subscribe to message queue ...") + return + } + if token := client.Subscribe("ping/#", 0, mq.Ping); token.Wait() && token.Error() != nil { + client.Disconnect(240) + logger.Log(0, "ping sub failed") + } + if token := client.Subscribe("metrics/#", 0, mq.Metrics); token.Wait() && token.Error() != nil { + client.Disconnect(240) + logger.Log(0, "metrics sub failed") + } + if token := client.Subscribe("update/localaddress/#", 0, mq.LocalAddressUpdate); token.Wait() && token.Error() != nil { + client.Disconnect(240) + logger.Log(0, "metrics sub failed") + } + if token := client.Subscribe("update/ip/#", 0, mq.IPUpdate); token.Wait() && token.Error() != nil { + client.Disconnect(240) + logger.Log(0, "metrics sub failed") + } + if token := client.Subscribe("update/publickey/#", 0, mq.PublicKeyUpdate); token.Wait() && token.Error() != nil { + client.Disconnect(240) + logger.Log(0, "metrics sub failed") + } + for { + } +} + func authServerUnaryInterceptor() grpc.ServerOption { return grpc.UnaryInterceptor(controller.AuthServerUnaryInterceptor) } diff --git a/models/mqtt.go b/models/mqtt.go index a7e87e1f..da7265f3 100644 --- a/models/mqtt.go +++ b/models/mqtt.go @@ -3,9 +3,8 @@ package models import "golang.zx2c4.com/wireguard/wgctrl/wgtypes" type PeerUpdate struct { - Network string - Interface string - Peers []wgtypes.Peer + Network string + Peers []wgtypes.Peer } type KeyUpdate struct { diff --git a/mq/mq.go b/mq/mq.go new file mode 100644 index 00000000..3620b215 --- /dev/null +++ b/mq/mq.go @@ -0,0 +1,197 @@ +package mq + +import ( + "encoding/json" + "errors" + "log" + "net" + "strings" + "time" + + mqtt "github.com/eclipse/paho.mqtt.golang" + "github.com/gravitl/netmaker/database" + "github.com/gravitl/netmaker/logger" + "github.com/gravitl/netmaker/logic" + "github.com/gravitl/netmaker/models" + "golang.zx2c4.com/wireguard/wgctrl/wgtypes" +) + +var DefaultHandler mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { + logger.Log(0, "MQTT Message: Topic: "+string(msg.Topic())+" Message: "+string(msg.Payload())) +} + +var Metrics mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { + logger.Log(0, "Metrics Handler") +} + +var Ping mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { + logger.Log(0, "Ping Handler") + //test code --- create a node if it doesn't exit for testing only + createnode := models.Node{PublicKey: "DM5qhLAE20PG9BbfBCger+Ac9D2NDOwCtY1rbYDLf34=", Name: "testnode", + Endpoint: "10.0.0.1", MacAddress: "01:02:03:04:05:06", Password: "password", Network: "skynet"} + if _, err := logic.GetNode("01:02:03:04:05:06", "skynet"); err != nil { + err := logic.CreateNode(&createnode) + if err != nil { + log.Println(err) + } + } + //end of test code + go func() { + mac, net, err := GetMacNetwork(msg.Topic()) + if err != nil { + logger.Log(0, "error getting node.ID sent on ping topic ") + return + } + logger.Log(0, "ping recieved from "+mac+" on net "+net) + node, err := logic.GetNodeByMacAddress(net, mac) + if err != nil { + logger.Log(0, "mq-ping error getting node: "+err.Error()) + record, err := database.FetchRecord(database.NODES_TABLE_NAME, mac+"###"+net) + if err != nil { + logger.Log(0, "error reading database ", err.Error()) + return + } + logger.Log(0, "record from database") + logger.Log(0, record) + return + } + node.SetLastCheckIn() + // --TODO --set client version once feature is implemented. + //node.SetClientVersion(msg.Payload()) + }() +} + +var PublicKeyUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { + logger.Log(0, "PublicKey Handler") + go func() { + logger.Log(0, "public key update "+msg.Topic()) + key := string(msg.Payload()) + mac, network, err := GetMacNetwork(msg.Topic()) + if err != nil { + logger.Log(0, "error getting node.ID sent on "+msg.Topic()+" "+err.Error()) + } + node, err := logic.GetNode(mac, network) + if err != nil { + logger.Log(0, "error retrieving node "+msg.Topic()+" "+err.Error()) + } + node.PublicKey = key + node.SetLastCheckIn() + UpdatePeers(&node, client) + }() +} + +var IPUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { + go func() { + ip := string(msg.Payload()) + logger.Log(0, "IPUpdate Handler") + mac, network, err := GetMacNetwork(msg.Topic()) + logger.Log(0, "ipUpdate recieved from "+mac+" on net "+network) + if err != nil { + logger.Log(0, "error getting node.ID sent on update/ip topic ") + return + } + node, err := logic.GetNode(mac, network) + if err != nil { + logger.Log(0, "invalid ID recieved on update/ip topic: "+err.Error()) + return + } + node.Endpoint = ip + node.SetLastCheckIn() + UpdatePeers(&node, client) + }() +} + +func UpdatePeers(node *models.Node, client mqtt.Client) { + peersToUpdate, err := logic.GetPeers(node) + if err != nil { + logger.Log(0, "error retrieving peers") + return + } + for _, peerToUpdate := range peersToUpdate { + var peerUpdate models.PeerUpdate + peerUpdate.Network = node.Network + + myPeers, err := logic.GetPeers(&peerToUpdate) + if err != nil { + logger.Log(0, "uable to get peers "+err.Error()) + continue + } + for i, myPeer := range myPeers { + var allowedIPs []net.IPNet + var allowedIP net.IPNet + endpoint, err := net.ResolveUDPAddr("udp", myPeer.Address+":"+string(myPeer.ListenPort)) + if err != nil { + logger.Log(0, "error setting endpoint for peer "+err.Error()) + } + for _, ipString := range myPeer.AllowedIPs { + _, ipNet, _ := net.ParseCIDR(ipString) + allowedIP = *ipNet + allowedIPs = append(allowedIPs, allowedIP) + } + key, err := wgtypes.ParseKey(myPeer.PublicKey) + if err != nil { + logger.Log(0, "err parsing publickey") + continue + } + peerUpdate.Peers[i].PublicKey = key + peerUpdate.Peers[i].Endpoint = endpoint + peerUpdate.Peers[i].PersistentKeepaliveInterval = time.Duration(myPeer.PersistentKeepalive) + peerUpdate.Peers[i].AllowedIPs = allowedIPs + peerUpdate.Peers[i].ProtocolVersion = 0 + } + //PublishPeerUpdate(my) + data, err := json.Marshal(peerUpdate) + if err != nil { + logger.Log(0, "err marshalling data for peer update "+err.Error()) + } + if token := client.Publish("update/peers/"+peerToUpdate.ID, 0, false, data); token.Wait() && token.Error() != nil { + logger.Log(0, "error publishing peer update "+token.Error().Error()) + } + client.Disconnect(250) + } +} + +var LocalAddressUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { + logger.Log(0, "LocalAddressUpdate Handler") + go func() { + logger.Log(0, "LocalAddressUpdate handler") + mac, net, err := GetMacNetwork(msg.Topic()) + if err != nil { + logger.Log(0, "error getting node.ID "+msg.Topic()) + return + } + node, err := logic.GetNode(mac, net) + if err != nil { + logger.Log(0, "error get node "+msg.Topic()) + return + } + node.LocalAddress = string(msg.Payload()) + node.SetLastCheckIn() + }() +} + +func GetMacNetwork(topic string) (string, string, error) { + parts := strings.Split(topic, "/") + count := len(parts) + if count == 1 { + return "", "", errors.New("invalid topic") + } + macnet := strings.Split(parts[count-1], "---") + if len(macnet) != 2 { + return "", "", errors.New("topic id not in mac---network format") + } + return macnet[0], macnet[1], nil +} + +func GetID(topic string) (string, error) { + parts := strings.Split(topic, "/") + count := len(parts) + if count == 1 { + return "", errors.New("invalid topic") + } + macnet := strings.Split(parts[count-1], "---") + if len(macnet) != 2 { + return "", errors.New("topic id not in mac---network format") + } + return macnet[0] + "###" + macnet[1], nil +} diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index 639436ae..a5360319 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -100,7 +100,7 @@ var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) //check if interface name has changed if so delete. if cfg.Node.Interface != newNode.Interface { if err = wireguard.RemoveConf(cfg.Node.Interface, true); err != nil { - ncutils.PrintLog("could not delete old interface "+cfg.Node.Interface+": ", err.Error(), 1) + ncutils.PrintLog("could not delete old interface "+cfg.Node.Interface+": "+err.Error(), 1) } } newNode.PullChanges = "no" @@ -109,12 +109,12 @@ var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) cfg.Node = newNode switch newNode.Action { case models.NODE_DELETE: - if err := RemoveLocalInstance(cfg, cfg.Network); err != nil { - ncutils.Printlog("error deleting local instance: "+err.Error(), 1) + if err := RemoveLocalInstance(&cfg, cfg.Network); err != nil { + ncutils.PrintLog("error deleting local instance: "+err.Error(), 1) return } case models.NODE_UPDATE_KEY: - UpdateKeys(cfg) + UpdateKeys(&cfg, client) case models.NODE_NOOP: default: } @@ -123,12 +123,12 @@ var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) ncutils.PrintLog("error updating node configuration: "+err.Error(), 1) } nameserver := cfg.Server.CoreDNSAddr - privateKey, err := wireguard.RetrievePrivKey(data.Network) + privateKey, err := wireguard.RetrievePrivKey(newNode.Network) if err != nil { ncutils.Log("error reading PrivateKey " + err.Error()) return } - if err := wireguard.UpdateWgInterface(cfg.Node.Interface, privateKey, nameserver, data); err != nil { + if err := wireguard.UpdateWgInterface(cfg.Node.Interface, privateKey, nameserver, newNode); err != nil { ncutils.Log("error updating wireguard config " + err.Error()) return } @@ -177,7 +177,7 @@ func UpdateKeys(cfg *config.ClientConfig, client mqtt.Client) (*config.ClientCon ncutils.Log("error generating privatekey " + err.Error()) return cfg, err } - if err := wireguard.UpdatePrivateKey(data.Interface, key.String()); err != nil { + if err := wireguard.UpdatePrivateKey(cfg.Node.Interface, key.String()); err != nil { ncutils.Log("error updating wireguard key " + err.Error()) return cfg, err } diff --git a/servercfg/serverconf.go b/servercfg/serverconf.go index d15af77a..885ca45f 100644 --- a/servercfg/serverconf.go +++ b/servercfg/serverconf.go @@ -244,6 +244,18 @@ func GetGRPCPort() string { return grpcport } +// GetMessageQueueEndpoint - gets the message queue endpoint +func GetMessageQueueEndpoint() string { + host, _ := GetPublicIP() + if os.Getenv("MQ_HOST") != "" { + host = os.Getenv("MQ_HOST") + } else if config.Config.Server.MQHOST != "" { + host = config.Config.Server.MQHOST + } + //Do we want MQ port configurable??? + return host + ":1883" +} + // GetMasterKey - gets the configured master key of server func GetMasterKey() string { key := "secretkey" @@ -307,6 +319,21 @@ func IsAgentBackend() bool { return isagent } +// IsMessageQueueBackend - checks if message queue is on or off +func IsMessageQueueBackend() bool { + ismessagequeue := true + if os.Getenv("MESSAGEQUEUE_BACKEND") != "" { + if os.Getenv("MESSAGEQUEUE_BACKEND") == "off" { + ismessagequeue = false + } + } else if config.Config.Server.MessageQueueBackend != "" { + if config.Config.Server.MessageQueueBackend == "off" { + ismessagequeue = false + } + } + return ismessagequeue +} + // IsClientMode - checks if it should run in client mode func IsClientMode() string { isclient := "on" From 3e693361a58fd5ba710becf35da5771a8c81c2d7 Mon Sep 17 00:00:00 2001 From: 0xdcarns Date: Mon, 10 Jan 2022 10:55:05 -0500 Subject: [PATCH 018/116] began transition --- go.mod | 1 + go.sum | 2 ++ logic/networks.go | 5 ----- logic/nodes.go | 15 +++++++++++++-- logic/relay.go | 1 - logic/server.go | 2 -- logic/util.go | 11 +++++------ logic/wireguard.go | 2 -- models/node.go | 24 ++++++++++-------------- netclient/config/config.go | 3 --- netclient/functions/common.go | 21 --------------------- 11 files changed, 31 insertions(+), 56 deletions(-) diff --git a/go.mod b/go.mod index 1aecf9c9..70f37dc5 100644 --- a/go.mod +++ b/go.mod @@ -36,6 +36,7 @@ require ( github.com/go-playground/locales v0.14.0 // indirect github.com/go-playground/universal-translator v0.18.0 // indirect github.com/google/go-cmp v0.5.5 // indirect + github.com/google/uuid v1.3.0 // indirect github.com/josharian/native v0.0.0-20200817173448-b6b71def0850 // indirect github.com/leodido/go-urn v1.2.1 // indirect github.com/mdlayher/genetlink v1.0.0 // indirect diff --git a/go.sum b/go.sum index b613ac12..1843eb9d 100644 --- a/go.sum +++ b/go.sum @@ -70,6 +70,8 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= diff --git a/logic/networks.go b/logic/networks.go index 2398a85a..d5798d5f 100644 --- a/logic/networks.go +++ b/logic/networks.go @@ -110,7 +110,6 @@ func NetworkNodesUpdatePullChanges(networkName string) error { if err != nil { return err } - node.SetID() database.Insert(node.ID, string(data), database.NODES_TABLE_NAME) } } @@ -355,7 +354,6 @@ func UpdateNetworkLocalAddresses(networkName string) error { fmt.Println("error in node address assignment!") return err } - node.SetID() database.Insert(node.ID, string(newNodeData), database.NODES_TABLE_NAME) } } @@ -387,7 +385,6 @@ func RemoveNetworkNodeIPv6Addresses(networkName string) error { if err != nil { return err } - node.SetID() database.Insert(node.ID, string(data), database.NODES_TABLE_NAME) } } @@ -424,7 +421,6 @@ func UpdateNetworkNodeAddresses(networkName string) error { if err != nil { return err } - node.SetID() database.Insert(node.ID, string(data), database.NODES_TABLE_NAME) } } @@ -630,7 +626,6 @@ func networkNodesUpdateAction(networkName string, action string) error { if err != nil { return err } - node.SetID() database.Insert(node.ID, string(data), database.NODES_TABLE_NAME) } } diff --git a/logic/nodes.go b/logic/nodes.go index c2e804b1..61dea4cd 100644 --- a/logic/nodes.go +++ b/logic/nodes.go @@ -125,7 +125,6 @@ func UpdateNode(currentNode *models.Node, newNode *models.Node) error { if err := ValidateNode(newNode, true); err != nil { return err } - newNode.SetID() if newNode.ID == currentNode.ID { newNode.SetLastModified() if data, err := json.Marshal(newNode); err != nil { @@ -285,7 +284,6 @@ func SetNodeDefaults(node *models.Node) { node.SetRoamingDefault() node.SetPullChangesDefault() node.SetDefaultAction() - node.SetID() node.SetIsServerDefault() node.SetIsStaticDefault() node.SetDefaultEgressGateway() @@ -380,3 +378,16 @@ func GetNodeRelay(network string, relayedNodeAddr string) (models.Node, error) { } return relay, errors.New("could not find relay for node " + relayedNodeAddr) } + +// GetNodeByID - get node by uuid, should have been set by create +func GetNodeByID(uuid string) (models.Node, error) { + var record, err = database.FetchRecord(database.NODES_TABLE_NAME, uuid) + if err != nil { + return models.Node{}, err + } + var node models.Node + if err = json.Unmarshal([]byte(record), &node); err != nil { + return models.Node{}, err + } + return node, nil +} diff --git a/logic/relay.go b/logic/relay.go index 4b3f7ab8..06b8fc67 100644 --- a/logic/relay.go +++ b/logic/relay.go @@ -73,7 +73,6 @@ func SetRelayedNodes(yesOrno string, networkName string, addrs []string) error { if err != nil { return err } - node.SetID() database.Insert(node.ID, string(data), database.NODES_TABLE_NAME) } } diff --git a/logic/server.go b/logic/server.go index 8184f9cc..4319c5b1 100644 --- a/logic/server.go +++ b/logic/server.go @@ -113,7 +113,6 @@ func ServerJoin(networkSettings *models.Network, serverID string) error { node.Endpoint = node.LocalAddress } - node.SetID() if err = StorePrivKey(node.ID, privateKey); err != nil { return err } @@ -215,7 +214,6 @@ func ServerLeave(mac string, network string) error { if err != nil { return err } - serverNode.SetID() return DeleteNode(&serverNode, true) } diff --git a/logic/util.go b/logic/util.go index 989bff4e..7b63fdfe 100644 --- a/logic/util.go +++ b/logic/util.go @@ -9,6 +9,7 @@ import ( "strings" "time" + "github.com/google/uuid" "github.com/gravitl/netmaker/database" "github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/models" @@ -44,7 +45,6 @@ func SetNetworkServerPeers(node *models.Node) { // DeleteNode - deletes a node from database or moves into delete nodes table func DeleteNode(node *models.Node, exterminate bool) error { var err error - node.SetID() var key = node.ID if !exterminate { args := strings.Split(key, "###") @@ -114,15 +114,14 @@ func CreateNode(node *models.Node) error { if err != nil { return err } - key, err := GetRecordKey(node.MacAddress, node.Network) - if err != nil { - return err - } + + node.ID = uuid.NewString() + nodebytes, err := json.Marshal(&node) if err != nil { return err } - err = database.Insert(key, string(nodebytes), database.NODES_TABLE_NAME) + err = database.Insert(node.ID, string(nodebytes), database.NODES_TABLE_NAME) if err != nil { return err } diff --git a/logic/wireguard.go b/logic/wireguard.go index c8b53a54..b796894a 100644 --- a/logic/wireguard.go +++ b/logic/wireguard.go @@ -283,7 +283,6 @@ func setServerPeers(iface string, keepalive int32, peers []wgtypes.PeerConfig) e func setWGConfig(node *models.Node, peerupdate bool) error { - node.SetID() peers, hasGateway, gateways, err := GetServerPeers(node) if err != nil { return err @@ -305,7 +304,6 @@ func setWGConfig(node *models.Node, peerupdate bool) error { func setWGKeyConfig(node *models.Node) error { - node.SetID() privatekey, err := wgtypes.GeneratePrivateKey() if err != nil { return err diff --git a/models/node.go b/models/node.go index c6dc623b..4ed0ee63 100644 --- a/models/node.go +++ b/models/node.go @@ -2,7 +2,6 @@ package models import ( "bytes" - "errors" "math/rand" "net" "strings" @@ -75,11 +74,17 @@ type Node struct { MTU int32 `json:"mtu" bson:"mtu" yaml:"mtu"` } +// NodesArray - used for node sorting type NodesArray []Node -func (a NodesArray) Len() int { return len(a) } +// NodesArray.Len - gets length of node array +func (a NodesArray) Len() int { return len(a) } + +// NodesArray.Less - gets returns lower rank of two node addresses func (a NodesArray) Less(i, j int) bool { return isLess(a[i].Address, a[j].Address) } -func (a NodesArray) Swap(i, j int) { a[i], a[j] = a[j], a[i] } + +// NodesArray.Swap - swaps two nodes in array +func (a NodesArray) Swap(i, j int) { a[i], a[j] = a[j], a[i] } func isLess(ipA string, ipB string) bool { ipNetA := net.ParseIP(ipA) @@ -87,12 +92,14 @@ func isLess(ipA string, ipB string) bool { return bytes.Compare(ipNetA, ipNetB) < 0 } +// Node.SetDefaultMTU - sets default MTU of a node func (node *Node) SetDefaultMTU() { if node.MTU == 0 { node.MTU = 1280 } } +// Node.SetDefaulIsPending - sets ispending default func (node *Node) SetDefaulIsPending() { if node.IsPending == "" { node.IsPending = "no" @@ -191,10 +198,6 @@ func (node *Node) SetLastPeerUpdate() { node.LastPeerUpdate = time.Now().Unix() } -func (node *Node) SetID() { - node.ID = node.MacAddress + "###" + node.Network -} - func (node *Node) SetExpirationDateTime() { node.ExpirationDateTime = time.Now().Unix() + TEN_YEARS_IN_SECONDS } @@ -379,10 +382,3 @@ func (node *Node) NameInNodeCharSet() bool { } return true } - -func (node *Node) GetID() (string, error) { - if node.MacAddress == "" || node.Network == "" { - return "", errors.New("unable to get record key") - } - return node.MacAddress + "###" + node.Network, nil -} diff --git a/netclient/config/config.go b/netclient/config/config.go index c343ccb5..b582c27b 100644 --- a/netclient/config/config.go +++ b/netclient/config/config.go @@ -97,9 +97,6 @@ func (config *ClientConfig) ReadConfig() { fmt.Println("no config or invalid") fmt.Println(err) log.Fatal(err) - } else { - config.Node.SetID() - //config = cfg } } } diff --git a/netclient/functions/common.go b/netclient/functions/common.go index 385af71b..34798a45 100644 --- a/netclient/functions/common.go +++ b/netclient/functions/common.go @@ -101,26 +101,6 @@ func getPrivateAddrBackup() (string, error) { return local, err } -// DEPRECATED -// func needInterfaceUpdate(ctx context.Context, mac string, network string, iface string) (bool, string, error) { -// var header metadata.MD -// req := &nodepb.Object{ -// Data: mac + "###" + network, -// Type: nodepb.STRING_TYPE, -// } -// readres, err := wcclient.ReadNode(ctx, req, grpc.Header(&header)) -// if err != nil { -// return false, "", err -// } -// var resNode models.Node -// if err := json.Unmarshal([]byte(readres.Data), &resNode); err != nil { -// return false, iface, err -// } -// oldiface := resNode.Interface - -// return iface != oldiface, oldiface, err -// } - // GetNode - gets node locally func GetNode(network string) models.Node { @@ -183,7 +163,6 @@ func LeaveNetwork(network string) error { if err != nil { log.Printf("Failed to authenticate: %v", err) } else { // handle client side - node.SetID() var header metadata.MD _, err = wcclient.DeleteNode( ctx, From 92f9dafd2ecf5792241c8c8e98f4c63fc14e07a2 Mon Sep 17 00:00:00 2001 From: 0xdcarns Date: Mon, 10 Jan 2022 17:52:21 -0500 Subject: [PATCH 019/116] restructuring continued --- controllers/auth_grpc.go | 18 +++++----- controllers/ext_client.go | 16 ++++----- controllers/node.go | 75 ++++++++++++++++++++------------------- controllers/node_grpc.go | 22 +++++++----- controllers/node_test.go | 13 +++---- controllers/relay.go | 8 ++--- logic/gateway.go | 12 +++---- logic/jwts.go | 13 +++---- logic/nodes.go | 46 ++++++++++++++++++++++-- logic/relay.go | 13 +++---- logic/server.go | 2 +- logic/util.go | 38 +++++++++++++++++--- models/structs.go | 7 ++-- 13 files changed, 178 insertions(+), 105 deletions(-) diff --git a/controllers/auth_grpc.go b/controllers/auth_grpc.go index d457a2d1..6f890803 100644 --- a/controllers/auth_grpc.go +++ b/controllers/auth_grpc.go @@ -72,7 +72,7 @@ func grpcAuthorize(ctx context.Context) error { authToken := authHeader[0] - mac, network, err := logic.VerifyToken(authToken) + nodeID, mac, network, err := logic.VerifyToken(authToken) if err != nil { return err } @@ -83,9 +83,10 @@ func grpcAuthorize(ctx context.Context) error { return status.Errorf(codes.Unauthenticated, "Unauthorized. Network does not exist: "+network) } emptynode := models.Node{} - node, err := logic.GetNodeByMacAddress(network, mac) + node, err := logic.GetNodeByIDorMacAddress(nodeID, mac, network) if database.IsEmptyRecord(err) { - if node, err = logic.GetDeletedNodeByMacAddress(network, mac); err == nil { + // == DELETE replace logic after 2 major version updates == + if node, err = logic.GetDeletedNodeByID(node.ID); err == nil { if functions.RemoveDeletedNode(node.ID) { return status.Errorf(codes.Unauthenticated, models.NODE_DELETE) } @@ -112,17 +113,18 @@ func (s *NodeServiceServer) Login(ctx context.Context, req *nodepb.Object) (*nod return nil, err } - macaddress := reqNode.MacAddress + nodeID := reqNode.ID network := reqNode.Network password := reqNode.Password + macaddress := reqNode.MacAddress var result models.NodeAuth var err error // err := errors.New("generic server error") - if macaddress == "" { + if nodeID == "" { //TODO: Set Error response - err = errors.New("missing mac address") + err = errors.New("missing node ID") return nil, err } else if password == "" { err = errors.New("missing password") @@ -137,7 +139,7 @@ func (s *NodeServiceServer) Login(ctx context.Context, req *nodepb.Object) (*nod if err = json.Unmarshal([]byte(value), &result); err != nil { continue // finish going through nodes } - if result.MacAddress == macaddress && result.Network == network { + if result.ID == nodeID && result.Network == network { break } } @@ -150,7 +152,7 @@ func (s *NodeServiceServer) Login(ctx context.Context, req *nodepb.Object) (*nod return nil, err } else { //Create a new JWT for the node - tokenString, err := logic.CreateJWT(macaddress, result.Network) + tokenString, err := logic.CreateJWT(result.ID, macaddress, result.Network) if err != nil { return nil, err diff --git a/controllers/ext_client.go b/controllers/ext_client.go index d27f299b..beb4f814 100644 --- a/controllers/ext_client.go +++ b/controllers/ext_client.go @@ -25,11 +25,11 @@ func extClientHandlers(r *mux.Router) { r.HandleFunc("/api/extclients/{network}/{clientid}/{type}", securityCheck(false, http.HandlerFunc(getExtClientConf))).Methods("GET") r.HandleFunc("/api/extclients/{network}/{clientid}", securityCheck(false, http.HandlerFunc(updateExtClient))).Methods("PUT") r.HandleFunc("/api/extclients/{network}/{clientid}", securityCheck(false, http.HandlerFunc(deleteExtClient))).Methods("DELETE") - r.HandleFunc("/api/extclients/{network}/{macaddress}", securityCheck(false, http.HandlerFunc(createExtClient))).Methods("POST") + r.HandleFunc("/api/extclients/{network}/{nodeid}", securityCheck(false, http.HandlerFunc(createExtClient))).Methods("POST") } -func checkIngressExists(network string, macaddress string) bool { - node, err := logic.GetNodeByMacAddress(network, macaddress) +func checkIngressExists(nodeID string) bool { + node, err := logic.GetNodeByID(nodeID) if err != nil { return false } @@ -122,7 +122,7 @@ func getExtClientConf(w http.ResponseWriter, r *http.Request) { return } - gwnode, err := logic.GetNodeByMacAddress(client.Network, client.IngressGatewayID) + gwnode, err := logic.GetNodeByID(client.IngressGatewayID) if err != nil { logger.Log(1, fmt.Sprintf("%s %s %s", r.Header.Get("user"), "Could not retrieve Ingress Gateway Node", client.IngressGatewayID)) returnErrorResponse(w, r, formatError(err, "internal")) @@ -211,8 +211,8 @@ func createExtClient(w http.ResponseWriter, r *http.Request) { var params = mux.Vars(r) networkName := params["network"] - macaddress := params["macaddress"] - ingressExists := checkIngressExists(networkName, macaddress) + nodeid := params["nodeid"] + ingressExists := checkIngressExists(nodeid) if !ingressExists { returnErrorResponse(w, r, formatError(errors.New("ingress does not exist"), "internal")) return @@ -220,8 +220,8 @@ func createExtClient(w http.ResponseWriter, r *http.Request) { var extclient models.ExtClient extclient.Network = networkName - extclient.IngressGatewayID = macaddress - node, err := logic.GetNodeByMacAddress(networkName, macaddress) + extclient.IngressGatewayID = nodeid + node, err := logic.GetNodeByIDorMacAddress(nodeid, nodeid, networkName) if err != nil { returnErrorResponse(w, r, formatError(err, "internal")) return diff --git a/controllers/node.go b/controllers/node.go index 605ceec3..e6156382 100644 --- a/controllers/node.go +++ b/controllers/node.go @@ -19,17 +19,17 @@ func nodeHandlers(r *mux.Router) { r.HandleFunc("/api/nodes", authorize(false, "user", http.HandlerFunc(getAllNodes))).Methods("GET") r.HandleFunc("/api/nodes/{network}", authorize(true, "network", http.HandlerFunc(getNetworkNodes))).Methods("GET") - r.HandleFunc("/api/nodes/{network}/{macaddress}", authorize(true, "node", http.HandlerFunc(getNode))).Methods("GET") - r.HandleFunc("/api/nodes/{network}/{macaddress}", authorize(true, "node", http.HandlerFunc(updateNode))).Methods("PUT") - r.HandleFunc("/api/nodes/{network}/{macaddress}", authorize(true, "node", http.HandlerFunc(deleteNode))).Methods("DELETE") - r.HandleFunc("/api/nodes/{network}/{macaddress}/createrelay", authorize(true, "user", http.HandlerFunc(createRelay))).Methods("POST") - r.HandleFunc("/api/nodes/{network}/{macaddress}/deleterelay", authorize(true, "user", http.HandlerFunc(deleteRelay))).Methods("DELETE") - r.HandleFunc("/api/nodes/{network}/{macaddress}/creategateway", authorize(true, "user", http.HandlerFunc(createEgressGateway))).Methods("POST") - r.HandleFunc("/api/nodes/{network}/{macaddress}/deletegateway", authorize(true, "user", http.HandlerFunc(deleteEgressGateway))).Methods("DELETE") - r.HandleFunc("/api/nodes/{network}/{macaddress}/createingress", securityCheck(false, http.HandlerFunc(createIngressGateway))).Methods("POST") - r.HandleFunc("/api/nodes/{network}/{macaddress}/deleteingress", securityCheck(false, http.HandlerFunc(deleteIngressGateway))).Methods("DELETE") - r.HandleFunc("/api/nodes/{network}/{macaddress}/approve", authorize(true, "user", http.HandlerFunc(uncordonNode))).Methods("POST") - r.HandleFunc("/api/nodes/{network}", createNode).Methods("POST") + r.HandleFunc("/api/nodes/{network}/{nodeid}", authorize(true, "node", http.HandlerFunc(getNode))).Methods("GET") + r.HandleFunc("/api/nodes/{network}/{nodeid}", authorize(true, "node", http.HandlerFunc(updateNode))).Methods("PUT") + r.HandleFunc("/api/nodes/{network}/{nodeid}", authorize(true, "node", http.HandlerFunc(deleteNode))).Methods("DELETE") + r.HandleFunc("/api/nodes/{network}/{nodeid}/createrelay", authorize(true, "user", http.HandlerFunc(createRelay))).Methods("POST") + r.HandleFunc("/api/nodes/{network}/{nodeid}/deleterelay", authorize(true, "user", http.HandlerFunc(deleteRelay))).Methods("DELETE") + r.HandleFunc("/api/nodes/{network}/{nodeid}/creategateway", authorize(true, "user", http.HandlerFunc(createEgressGateway))).Methods("POST") + r.HandleFunc("/api/nodes/{network}/{nodeid}/deletegateway", authorize(true, "user", http.HandlerFunc(deleteEgressGateway))).Methods("DELETE") + r.HandleFunc("/api/nodes/{network}/{nodeid}/createingress", securityCheck(false, http.HandlerFunc(createIngressGateway))).Methods("POST") + r.HandleFunc("/api/nodes/{network}/{nodeid}/deleteingress", securityCheck(false, http.HandlerFunc(deleteIngressGateway))).Methods("DELETE") + r.HandleFunc("/api/nodes/{network}/{nodeid}/approve", authorize(true, "user", http.HandlerFunc(uncordonNode))).Methods("POST") + // r.HandleFunc("/api/nodes/{network}", createNode).Methods("POST") r.HandleFunc("/api/nodes/adm/{network}/lastmodified", authorize(true, "network", http.HandlerFunc(getLastModified))).Methods("GET") r.HandleFunc("/api/nodes/adm/{network}/authenticate", authenticate).Methods("POST") @@ -78,7 +78,7 @@ func authenticate(response http.ResponseWriter, request *http.Request) { if err := json.Unmarshal([]byte(value), &result); err != nil { continue } - if result.MacAddress == authRequest.MacAddress && result.IsPending != "yes" && result.Network == networkname { + if (result.ID == authRequest.ID || result.MacAddress == authRequest.MacAddress) && result.IsPending != "yes" && result.Network == networkname { break } } @@ -97,7 +97,7 @@ func authenticate(response http.ResponseWriter, request *http.Request) { returnErrorResponse(response, request, errorResponse) return } else { - tokenString, _ := logic.CreateJWT(authRequest.MacAddress, result.Network) + tokenString, _ := logic.CreateJWT(authRequest.ID, authRequest.MacAddress, result.Network) if tokenString == "" { errorResponse.Code = http.StatusBadRequest @@ -177,11 +177,11 @@ func authorize(networkCheck bool, authNetwork string, next http.Handler) http.Ha } var isAuthorized = false - var macaddress = "" + var nodeID = "" username, networks, isadmin, errN := logic.VerifyUserToken(authToken) isnetadmin := isadmin if errN == nil && isadmin { - macaddress = "mastermac" + nodeID = "mastermac" isAuthorized = true r.Header.Set("ismasterkey", "yes") } @@ -191,7 +191,7 @@ func authorize(networkCheck bool, authNetwork string, next http.Handler) http.Ha } } //The mastermac (login with masterkey from config) can do everything!! May be dangerous. - if macaddress == "mastermac" { + if nodeID == "mastermac" { isAuthorized = true r.Header.Set("ismasterkey", "yes") //for everyone else, there's poor man's RBAC. The "cases" are defined in the routes in the handlers @@ -201,12 +201,12 @@ func authorize(networkCheck bool, authNetwork string, next http.Handler) http.Ha case "all": isAuthorized = true case "nodes": - isAuthorized = (macaddress != "") || isnetadmin + isAuthorized = (nodeID != "") || isnetadmin case "network": if isnetadmin { isAuthorized = true } else { - node, err := logic.GetNodeByMacAddress(params["network"], macaddress) + node, err := logic.GetNodeByID(nodeID) if err != nil { errorResponse = models.ErrorResponse{ Code: http.StatusUnauthorized, Message: "W1R3: Missing Auth Token.", @@ -220,7 +220,7 @@ func authorize(networkCheck bool, authNetwork string, next http.Handler) http.Ha if isnetadmin { isAuthorized = true } else { - isAuthorized = (macaddress == params["macaddress"]) + isAuthorized = (nodeID == params["netid"]) } case "user": isAuthorized = true @@ -315,12 +315,12 @@ func getNode(w http.ResponseWriter, r *http.Request) { var params = mux.Vars(r) - node, err := logic.GetNode(params["macaddress"], params["network"]) + node, err := logic.GetNodeByID(params["nodeid"]) if err != nil { returnErrorResponse(w, r, formatError(err, "internal")) return } - logger.Log(2, r.Header.Get("user"), "fetched node", params["macaddress"]) + logger.Log(2, r.Header.Get("user"), "fetched node", params["nodeid"]) w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(node) } @@ -414,7 +414,7 @@ func createNode(w http.ResponseWriter, r *http.Request) { func uncordonNode(w http.ResponseWriter, r *http.Request) { var params = mux.Vars(r) w.Header().Set("Content-Type", "application/json") - node, err := logic.UncordonNode(params["network"], params["macaddress"]) + node, err := logic.UncordonNode(params["nodeid"]) if err != nil { returnErrorResponse(w, r, formatError(err, "internal")) return @@ -434,7 +434,7 @@ func createEgressGateway(w http.ResponseWriter, r *http.Request) { return } gateway.NetID = params["network"] - gateway.NodeID = params["macaddress"] + gateway.NodeID = params["nodeid"] node, err := logic.CreateEgressGateway(gateway) if err != nil { returnErrorResponse(w, r, formatError(err, "internal")) @@ -448,14 +448,14 @@ func createEgressGateway(w http.ResponseWriter, r *http.Request) { func deleteEgressGateway(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") var params = mux.Vars(r) - nodeMac := params["macaddress"] + nodeid := params["nodeid"] netid := params["network"] - node, err := logic.DeleteEgressGateway(netid, nodeMac) + node, err := logic.DeleteEgressGateway(netid, nodeid) if err != nil { returnErrorResponse(w, r, formatError(err, "internal")) return } - logger.Log(1, r.Header.Get("user"), "deleted egress gateway", nodeMac, "on network", netid) + logger.Log(1, r.Header.Get("user"), "deleted egress gateway", nodeid, "on network", netid) w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(node) } @@ -465,14 +465,14 @@ func deleteEgressGateway(w http.ResponseWriter, r *http.Request) { func createIngressGateway(w http.ResponseWriter, r *http.Request) { var params = mux.Vars(r) w.Header().Set("Content-Type", "application/json") - nodeMac := params["macaddress"] + nodeid := params["nodeid"] netid := params["network"] - node, err := logic.CreateIngressGateway(netid, nodeMac) + node, err := logic.CreateIngressGateway(netid, nodeid) if err != nil { returnErrorResponse(w, r, formatError(err, "internal")) return } - logger.Log(1, r.Header.Get("user"), "created ingress gateway on node", nodeMac, "on network", netid) + logger.Log(1, r.Header.Get("user"), "created ingress gateway on node", nodeid, "on network", netid) w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(node) } @@ -480,13 +480,13 @@ func createIngressGateway(w http.ResponseWriter, r *http.Request) { func deleteIngressGateway(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") var params = mux.Vars(r) - nodeMac := params["macaddress"] - node, err := logic.DeleteIngressGateway(params["network"], nodeMac) + nodeid := params["nodeid"] + node, err := logic.DeleteIngressGateway(params["network"], nodeid) if err != nil { returnErrorResponse(w, r, formatError(err, "internal")) return } - logger.Log(1, r.Header.Get("user"), "deleted ingress gateway", nodeMac) + logger.Log(1, r.Header.Get("user"), "deleted ingress gateway", nodeid) w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(node) } @@ -498,7 +498,7 @@ func updateNode(w http.ResponseWriter, r *http.Request) { var node models.Node //start here - node, err := logic.GetNodeByMacAddress(params["network"], params["macaddress"]) + node, err := logic.GetNodeByID(params["nodeid"]) if err != nil { returnErrorResponse(w, r, formatError(err, "internal")) return @@ -560,17 +560,18 @@ func deleteNode(w http.ResponseWriter, r *http.Request) { // get params var params = mux.Vars(r) - var node, err = logic.GetNode(params["macaddress"], params["network"]) + var nodeid = params["nodeid"] + var node, err = logic.GetNodeByID(nodeid) if err != nil { returnErrorResponse(w, r, formatError(err, "badrequest")) return } - err = logic.DeleteNode(&node, false) + err = logic.DeleteNodeByMacAddress(&node, false) if err != nil { returnErrorResponse(w, r, formatError(err, "internal")) return } - logger.Log(1, r.Header.Get("user"), "Deleted node", params["macaddress"], "from network", params["network"]) - returnSuccessResponse(w, r, params["macaddress"]+" deleted.") + logger.Log(1, r.Header.Get("user"), "Deleted node", nodeid, "from network", params["network"]) + returnSuccessResponse(w, r, nodeid+" deleted.") } diff --git a/controllers/node_grpc.go b/controllers/node_grpc.go index 633cb369..e0dddae4 100644 --- a/controllers/node_grpc.go +++ b/controllers/node_grpc.go @@ -21,15 +21,21 @@ type NodeServiceServer struct { // NodeServiceServer.ReadNode - reads node and responds with gRPC func (s *NodeServiceServer) ReadNode(ctx context.Context, req *nodepb.Object) (*nodepb.Object, error) { // convert string id (from proto) to mongoDB ObjectId - macAndNetwork := strings.Split(req.Data, "###") - - if len(macAndNetwork) != 2 { - return nil, errors.New("could not read node, invalid node id given") + var err error + var node models.Node + var macAndNetwork = make([]string, 2) + if strings.Contains(req.Data, "###") { + macAndNetwork = strings.Split(req.Data, "###") + if len(macAndNetwork) != 2 { + return nil, errors.New("could not read node, invalid node id given") + } } - node, err := logic.GetNode(macAndNetwork[0], macAndNetwork[1]) + + node, err = logic.GetNodeByIDorMacAddress(req.Data, macAndNetwork[0], macAndNetwork[1]) if err != nil { return nil, err } + node.NetworkSettings, err = logic.GetNetworkSettings(node.Network) if err != nil { return nil, err @@ -101,10 +107,8 @@ func (s *NodeServiceServer) UpdateNode(ctx context.Context, req *nodepb.Object) if err := json.Unmarshal([]byte(req.GetData()), &newnode); err != nil { return nil, err } - macaddress := newnode.MacAddress - networkName := newnode.Network - node, err := logic.GetNodeByMacAddress(networkName, macaddress) + node, err := logic.GetNodeByIDorMacAddress(newnode.ID, newnode.MacAddress, newnode.Network) if err != nil { return nil, err } @@ -140,7 +144,7 @@ func (s *NodeServiceServer) DeleteNode(ctx context.Context, req *nodepb.Object) return nil, errors.New("node not found") } var node, err = logic.GetNode(nodeInfo[0], nodeInfo[1]) - err = logic.DeleteNode(&node, true) + err = logic.DeleteNodeByMacAddress(&node, true) if err != nil { return nil, err } diff --git a/controllers/node_test.go b/controllers/node_test.go index d1e6ae92..965d56da 100644 --- a/controllers/node_test.go +++ b/controllers/node_test.go @@ -105,18 +105,13 @@ func TestUncordonNode(t *testing.T) { deleteAllNetworks() createNet() node := createTestNode() - t.Run("BadNet", func(t *testing.T) { - resp, err := logic.UncordonNode("badnet", node.MacAddress) - assert.Equal(t, models.Node{}, resp) - assert.EqualError(t, err, "no result found") - }) - t.Run("BadMac", func(t *testing.T) { - resp, err := logic.UncordonNode("skynet", "01:02:03") + t.Run("BadID", func(t *testing.T) { + resp, err := logic.UncordonNode("blahblah") assert.Equal(t, models.Node{}, resp) assert.EqualError(t, err, "no result found") }) t.Run("Success", func(t *testing.T) { - resp, err := logic.UncordonNode("skynet", node.MacAddress) + resp, err := logic.UncordonNode(node.ID) assert.Nil(t, err) assert.Equal(t, "no", resp.IsPending) }) @@ -147,7 +142,7 @@ func TestValidateEgressGateway(t *testing.T) { func deleteAllNodes() { nodes, _ := logic.GetAllNodes() for _, node := range nodes { - logic.DeleteNode(&node, true) + logic.DeleteNodeByMacAddress(&node, true) } } diff --git a/controllers/relay.go b/controllers/relay.go index 3023a5b0..00cb236a 100644 --- a/controllers/relay.go +++ b/controllers/relay.go @@ -20,7 +20,7 @@ func createRelay(w http.ResponseWriter, r *http.Request) { return } relay.NetID = params["network"] - relay.NodeID = params["macaddress"] + relay.NodeID = params["nodeid"] node, err := logic.CreateRelay(relay) if err != nil { returnErrorResponse(w, r, formatError(err, "internal")) @@ -34,14 +34,14 @@ func createRelay(w http.ResponseWriter, r *http.Request) { func deleteRelay(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") var params = mux.Vars(r) - nodeMac := params["macaddress"] + nodeid := params["nodeid"] netid := params["network"] - node, err := logic.DeleteRelay(netid, nodeMac) + node, err := logic.DeleteRelay(netid, nodeid) if err != nil { returnErrorResponse(w, r, formatError(err, "internal")) return } - logger.Log(1, r.Header.Get("user"), "deleted egress gateway", nodeMac, "on network", netid) + logger.Log(1, r.Header.Get("user"), "deleted egress gateway", nodeid, "on network", netid) w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(node) } diff --git a/logic/gateway.go b/logic/gateway.go index 1b050c7e..7a1710c9 100644 --- a/logic/gateway.go +++ b/logic/gateway.go @@ -13,7 +13,7 @@ import ( // CreateEgressGateway - creates an egress gateway func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.Node, error) { - node, err := GetNodeByMacAddress(gateway.NetID, gateway.NodeID) + node, err := GetNodeByID(gateway.NodeID) if node.OS == "windows" || node.OS == "macos" { // add in darwin later return models.Node{}, errors.New(node.OS + " is unsupported for egress gateways") } @@ -80,9 +80,9 @@ func ValidateEgressGateway(gateway models.EgressGatewayRequest) error { } // DeleteEgressGateway - deletes egress from node -func DeleteEgressGateway(network, macaddress string) (models.Node, error) { +func DeleteEgressGateway(network, nodeid string) (models.Node, error) { - node, err := GetNodeByMacAddress(network, macaddress) + node, err := GetNodeByID(nodeid) if err != nil { return models.Node{}, err } @@ -115,10 +115,10 @@ func DeleteEgressGateway(network, macaddress string) (models.Node, error) { } // CreateIngressGateway - creates an ingress gateway -func CreateIngressGateway(netid string, macaddress string) (models.Node, error) { +func CreateIngressGateway(netid string, nodeid string) (models.Node, error) { - node, err := GetNodeByMacAddress(netid, macaddress) - if node.OS == "windows" || node.OS == "macos" { // add in darwin later + node, err := GetNodeByID(nodeid) + if node.OS == "windows" || node.OS == "darwin" { // add in darwin later return models.Node{}, errors.New(node.OS + " is unsupported for ingress gateways") } diff --git a/logic/jwts.go b/logic/jwts.go index 06771780..bb3fea06 100644 --- a/logic/jwts.go +++ b/logic/jwts.go @@ -12,11 +12,12 @@ import ( var jwtSecretKey = []byte("(BytesOverTheWire)") // CreateJWT func will used to create the JWT while signing in and signing out -func CreateJWT(macaddress string, network string) (response string, err error) { +func CreateJWT(uuid string, macAddress string, network string) (response string, err error) { expirationTime := time.Now().Add(5 * time.Minute) claims := &models.Claims{ - MacAddress: macaddress, + ID: uuid, Network: network, + MacAddress: macAddress, StandardClaims: jwt.StandardClaims{ ExpiresAt: expirationTime.Unix(), }, @@ -73,13 +74,13 @@ func VerifyUserToken(tokenString string) (username string, networks []string, is } // VerifyToken - gRPC [nodes] Only -func VerifyToken(tokenString string) (macaddress string, network string, err error) { +func VerifyToken(tokenString string) (nodeID string, mac string, network string, err error) { claims := &models.Claims{} //this may be a stupid way of serving up a master key //TODO: look into a different method. Encryption? if tokenString == servercfg.GetMasterKey() { - return "mastermac", "", nil + return "mastermac", "", "", nil } token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) { @@ -87,7 +88,7 @@ func VerifyToken(tokenString string) (macaddress string, network string, err err }) if token != nil { - return claims.MacAddress, claims.Network, nil + return claims.ID, claims.MacAddress, claims.Network, nil } - return "", "", err + return "", "", "", err } diff --git a/logic/nodes.go b/logic/nodes.go index 61dea4cd..d7a34ee6 100644 --- a/logic/nodes.go +++ b/logic/nodes.go @@ -64,8 +64,8 @@ func GetSortedNetworkServerNodes(network string) ([]models.Node, error) { } // UncordonNode - approves a node to join a network -func UncordonNode(network, macaddress string) (models.Node, error) { - node, err := GetNodeByMacAddress(network, macaddress) +func UncordonNode(nodeid string) (models.Node, error) { + node, err := GetNodeByID(nodeid) if err != nil { return models.Node{}, err } @@ -296,6 +296,7 @@ func SetNodeDefaults(node *models.Node) { } // GetRecordKey - get record key +// depricated func GetRecordKey(id string, network string) (string, error) { if id == "" || network == "" { return "", errors.New("unable to get record key") @@ -379,6 +380,28 @@ func GetNodeRelay(network string, relayedNodeAddr string) (models.Node, error) { return relay, errors.New("could not find relay for node " + relayedNodeAddr) } +// GetNodeByIDorMacAddress - gets the node, if a mac address exists, but not id, then it should delete it and recreate in DB with new ID +func GetNodeByIDorMacAddress(uuid string, macaddress string, network string) (models.Node, error) { + var node models.Node + var err error + node, err = GetNodeByID(uuid) + if err != nil && macaddress != "" && network != "" { + node, err = GetNodeByMacAddress(network, macaddress) + if err != nil { + return models.Node{}, err + } + err = DeleteNodeByMacAddress(&node, true) // remove node + if err != nil { + return models.Node{}, err + } + err = CreateNode(&node) + if err != nil { + return models.Node{}, err + } + } + return node, err +} + // GetNodeByID - get node by uuid, should have been set by create func GetNodeByID(uuid string) (models.Node, error) { var record, err = database.FetchRecord(database.NODES_TABLE_NAME, uuid) @@ -391,3 +414,22 @@ func GetNodeByID(uuid string) (models.Node, error) { } return node, nil } + +// GetDeletedNodeByID - get a deleted node +func GetDeletedNodeByID(uuid string) (models.Node, error) { + + var node models.Node + + record, err := database.FetchRecord(database.DELETED_NODES_TABLE_NAME, uuid) + if err != nil { + return models.Node{}, err + } + + if err = json.Unmarshal([]byte(record), &node); err != nil { + return models.Node{}, err + } + + SetNodeDefaults(&node) + + return node, nil +} diff --git a/logic/relay.go b/logic/relay.go index 06b8fc67..ea1e7cf4 100644 --- a/logic/relay.go +++ b/logic/relay.go @@ -12,7 +12,7 @@ import ( // CreateRelay - creates a relay func CreateRelay(relay models.RelayRequest) (models.Node, error) { - node, err := GetNodeByMacAddress(relay.NetID, relay.NodeID) + node, err := GetNodeByID(relay.NodeID) if node.OS == "macos" { // add in darwin later return models.Node{}, errors.New(node.OS + " is unsupported for relay") } @@ -106,9 +106,9 @@ func UpdateRelay(network string, oldAddrs []string, newAddrs []string) { } // DeleteRelay - deletes a relay -func DeleteRelay(network, macaddress string) (models.Node, error) { +func DeleteRelay(network, nodeid string) (models.Node, error) { - node, err := GetNodeByMacAddress(network, macaddress) + node, err := GetNodeByID(nodeid) if err != nil { return models.Node{}, err } @@ -121,15 +121,12 @@ func DeleteRelay(network, macaddress string) (models.Node, error) { node.RelayAddrs = []string{} node.SetLastModified() node.PullChanges = "yes" - key, err := GetRecordKey(node.MacAddress, node.Network) - if err != nil { - return models.Node{}, err - } + data, err := json.Marshal(&node) if err != nil { return models.Node{}, err } - if err = database.Insert(key, string(data), database.NODES_TABLE_NAME); err != nil { + if err = database.Insert(nodeid, string(data), database.NODES_TABLE_NAME); err != nil { return models.Node{}, err } if err = NetworkNodesUpdatePullChanges(network); err != nil { diff --git a/logic/server.go b/logic/server.go index 4319c5b1..d34c222c 100644 --- a/logic/server.go +++ b/logic/server.go @@ -214,7 +214,7 @@ func ServerLeave(mac string, network string) error { if err != nil { return err } - return DeleteNode(&serverNode, true) + return DeleteNodeByMacAddress(&serverNode, true) } /** diff --git a/logic/util.go b/logic/util.go index 7b63fdfe..4ddc985e 100644 --- a/logic/util.go +++ b/logic/util.go @@ -42,8 +42,8 @@ func SetNetworkServerPeers(node *models.Node) { } } -// DeleteNode - deletes a node from database or moves into delete nodes table -func DeleteNode(node *models.Node, exterminate bool) error { +// DeleteNodeByMacAddress - deletes a node from database or moves into delete nodes table +func DeleteNodeByMacAddress(node *models.Node, exterminate bool) error { var err error var key = node.ID if !exterminate { @@ -104,8 +104,10 @@ func CreateNode(node *models.Node) error { if err != nil { return err } + node.ID = uuid.NewString() + //Create a JWT for the node - tokenString, _ := CreateJWT(node.MacAddress, node.Network) + tokenString, _ := CreateJWT(node.ID, node.MacAddress, node.Network) if tokenString == "" { //returnErrorResponse(w, r, errorResponse) return err @@ -115,8 +117,6 @@ func CreateNode(node *models.Node) error { return err } - node.ID = uuid.NewString() - nodebytes, err := json.Marshal(&node) if err != nil { return err @@ -180,6 +180,34 @@ func GetNode(macaddress string, network string) (models.Node, error) { return node, err } +// DeleteNodeByID - deletes a node from database or moves into delete nodes table +func DeleteNodeByID(node *models.Node, exterminate bool) error { + var err error + var key = node.ID + if !exterminate { + node.Action = models.NODE_DELETE + nodedata, err := json.Marshal(&node) + if err != nil { + return err + } + err = database.Insert(key, string(nodedata), database.DELETED_NODES_TABLE_NAME) + if err != nil { + return err + } + } else { + if err := database.DeleteRecord(database.DELETED_NODES_TABLE_NAME, key); err != nil { + logger.Log(2, err.Error()) + } + } + if err = database.DeleteRecord(database.NODES_TABLE_NAME, key); err != nil { + return err + } + if servercfg.IsDNSMode() { + SetDNS() + } + return removeLocalServer(node) +} + // GetNodePeers - fetches peers for a given node func GetNodePeers(networkName string, excludeRelayed bool) ([]models.Node, error) { var peers []models.Node diff --git a/models/structs.go b/models/structs.go index 0742c516..a0a0ea2d 100644 --- a/models/structs.go +++ b/models/structs.go @@ -8,6 +8,7 @@ const PLACEHOLDER_TOKEN_TEXT = "ACCESS_TOKEN" // AuthParams - struct for auth params type AuthParams struct { MacAddress string `json:"macaddress"` + ID string `json:"id"` Password string `json:"password"` } @@ -49,8 +50,9 @@ type SuccessfulUserLoginResponse struct { // Claims is a struct that will be encoded to a JWT. // jwt.StandardClaims is an embedded type to provide expiry time type Claims struct { - Network string + ID string MacAddress string + Network string jwt.StandardClaims } @@ -70,7 +72,8 @@ type ErrorResponse struct { type NodeAuth struct { Network string Password string - MacAddress string + MacAddress string // Depricated + ID string } // SuccessResponse is struct for sending error message with code. From f08ba6f5a1ee6482565e80bdf1068b210e63e426 Mon Sep 17 00:00:00 2001 From: 0xdcarns Date: Mon, 10 Jan 2022 17:56:37 -0500 Subject: [PATCH 020/116] missave --- logic/networks.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/logic/networks.go b/logic/networks.go index d5798d5f..410968d9 100644 --- a/logic/networks.go +++ b/logic/networks.go @@ -47,7 +47,7 @@ func DeleteNetwork(network string) error { servers, err := GetSortedNetworkServerNodes(network) if err == nil { for _, s := range servers { - if err = DeleteNode(&s, true); err != nil { + if err = DeleteNodeByMacAddress(&s, true); err != nil { logger.Log(2, "could not removed server", s.Name, "before deleting network", network) } else { logger.Log(2, "removed server", s.Name, "before deleting network", network) From 75a20b70cf376475df6eea96f7404e4a7ebd31c5 Mon Sep 17 00:00:00 2001 From: 0xdcarns Date: Mon, 10 Jan 2022 18:32:49 -0500 Subject: [PATCH 021/116] refactored more --- controllers/node.go | 2 +- controllers/node_grpc.go | 85 ++++++++++++++++++++++++---------------- controllers/node_test.go | 2 +- logic/extpeers.go | 4 +- logic/networks.go | 2 +- logic/nodes.go | 1 + logic/server.go | 19 ++++----- logic/util.go | 5 ++- models/node.go | 7 ++-- serverctl/serverctl.go | 4 +- 10 files changed, 78 insertions(+), 53 deletions(-) diff --git a/controllers/node.go b/controllers/node.go index e6156382..100b8efd 100644 --- a/controllers/node.go +++ b/controllers/node.go @@ -566,7 +566,7 @@ func deleteNode(w http.ResponseWriter, r *http.Request) { returnErrorResponse(w, r, formatError(err, "badrequest")) return } - err = logic.DeleteNodeByMacAddress(&node, false) + err = logic.DeleteNodeByID(&node, false) if err != nil { returnErrorResponse(w, r, formatError(err, "internal")) return diff --git a/controllers/node_grpc.go b/controllers/node_grpc.go index e0dddae4..1343ae0e 100644 --- a/controllers/node_grpc.go +++ b/controllers/node_grpc.go @@ -139,12 +139,16 @@ func (s *NodeServiceServer) UpdateNode(ctx context.Context, req *nodepb.Object) // NodeServiceServer.DeleteNode - deletes a node and responds over gRPC func (s *NodeServiceServer) DeleteNode(ctx context.Context, req *nodepb.Object) (*nodepb.Object, error) { nodeID := req.GetData() - var nodeInfo = strings.Split(nodeID, "###") - if len(nodeInfo) != 2 { - return nil, errors.New("node not found") + var nodeInfo = make([]string, 2) + if strings.Contains(nodeID, "###") { + nodeInfo = strings.Split(nodeID, "###") + if len(nodeInfo) != 2 { + return nil, errors.New("node not found") + } } - var node, err = logic.GetNode(nodeInfo[0], nodeInfo[1]) - err = logic.DeleteNodeByMacAddress(&node, true) + + var node, err = logic.GetNodeByIDorMacAddress(nodeID, nodeInfo[0], nodeInfo[1]) + err = logic.DeleteNodeByID(&node, true) if err != nil { return nil, err } @@ -157,37 +161,38 @@ func (s *NodeServiceServer) DeleteNode(ctx context.Context, req *nodepb.Object) // NodeServiceServer.GetPeers - fetches peers over gRPC func (s *NodeServiceServer) GetPeers(ctx context.Context, req *nodepb.Object) (*nodepb.Object, error) { - macAndNetwork := strings.Split(req.Data, "###") - if len(macAndNetwork) == 2 { - // TODO: Make constant and new variable for isServer - node, err := logic.GetNode(macAndNetwork[0], macAndNetwork[1]) - if err != nil { - return nil, err + nodeID := req.GetData() + var nodeInfo = make([]string, 2) + if strings.Contains(nodeID, "###") { + nodeInfo = strings.Split(nodeID, "###") + if len(nodeInfo) != 2 { + return nil, errors.New("could not fetch peers, invalid node id") } - if node.IsServer == "yes" && logic.IsLeader(&node) { - logic.SetNetworkServerPeers(&node) - } - excludeIsRelayed := node.IsRelay != "yes" - var relayedNode string - if node.IsRelayed == "yes" { - relayedNode = node.Address - } - peers, err := logic.GetPeersList(macAndNetwork[1], excludeIsRelayed, relayedNode) - if err != nil { - return nil, err - } - - peersData, err := json.Marshal(&peers) - logger.Log(3, node.Address, "checked in successfully") - return &nodepb.Object{ - Data: string(peersData), - Type: nodepb.NODE_TYPE, - }, err } + + node, err := logic.GetNodeByIDorMacAddress(nodeID, nodeInfo[0], nodeInfo[1]) + if err != nil { + return nil, err + } + if node.IsServer == "yes" && logic.IsLeader(&node) { + logic.SetNetworkServerPeers(&node) + } + excludeIsRelayed := node.IsRelay != "yes" + var relayedNode string + if node.IsRelayed == "yes" { + relayedNode = node.Address + } + peers, err := logic.GetPeersList(node.Network, excludeIsRelayed, relayedNode) + if err != nil { + return nil, err + } + + peersData, err := json.Marshal(&peers) + logger.Log(3, node.Address, "checked in successfully") return &nodepb.Object{ - Data: "", + Data: string(peersData), Type: nodepb.NODE_TYPE, - }, errors.New("could not fetch peers, invalid node id") + }, err } // NodeServiceServer.GetExtPeers - returns ext peers for a gateway node @@ -199,7 +204,21 @@ func (s *NodeServiceServer) GetExtPeers(ctx context.Context, req *nodepb.Object) if len(macAndNetwork) != 2 { return nil, errors.New("did not receive valid node id when fetching ext peers") } - peers, err := logic.GetExtPeersList(macAndNetwork[0], macAndNetwork[1]) + nodeID := req.GetData() + var nodeInfo = make([]string, 2) + if strings.Contains(nodeID, "###") { + nodeInfo = strings.Split(nodeID, "###") + if len(nodeInfo) != 2 { + return nil, errors.New("could not fetch peers, invalid node id") + } + } + + node, err := logic.GetNodeByIDorMacAddress(nodeID, nodeInfo[0], nodeInfo[1]) + if err != nil { + return nil, err + } + + peers, err := logic.GetExtPeersList(&node) if err != nil { return nil, err } diff --git a/controllers/node_test.go b/controllers/node_test.go index 965d56da..bf4312bc 100644 --- a/controllers/node_test.go +++ b/controllers/node_test.go @@ -142,7 +142,7 @@ func TestValidateEgressGateway(t *testing.T) { func deleteAllNodes() { nodes, _ := logic.GetAllNodes() for _, node := range nodes { - logic.DeleteNodeByMacAddress(&node, true) + logic.DeleteNodeByID(&node, true) } } diff --git a/logic/extpeers.go b/logic/extpeers.go index 2fba619d..c40b54f2 100644 --- a/logic/extpeers.go +++ b/logic/extpeers.go @@ -11,7 +11,7 @@ import ( ) // GetExtPeersList - gets the ext peers lists -func GetExtPeersList(macaddress string, networkName string) ([]models.ExtPeersResponse, error) { +func GetExtPeersList(node *models.Node) ([]models.ExtPeersResponse, error) { var peers []models.ExtPeersResponse records, err := database.FetchRecords(database.EXT_CLIENT_TABLE_NAME) @@ -33,7 +33,7 @@ func GetExtPeersList(macaddress string, networkName string) ([]models.ExtPeersRe logger.Log(2, "failed to unmarshal ext client") continue } - if extClient.Network == networkName && extClient.IngressGatewayID == macaddress { + if extClient.Network == node.Network && extClient.IngressGatewayID == node.ID { peers = append(peers, peer) } } diff --git a/logic/networks.go b/logic/networks.go index 410968d9..79e4bdd9 100644 --- a/logic/networks.go +++ b/logic/networks.go @@ -47,7 +47,7 @@ func DeleteNetwork(network string) error { servers, err := GetSortedNetworkServerNodes(network) if err == nil { for _, s := range servers { - if err = DeleteNodeByMacAddress(&s, true); err != nil { + if err = DeleteNodeByID(&s, true); err != nil { logger.Log(2, "could not removed server", s.Name, "before deleting network", network) } else { logger.Log(2, "removed server", s.Name, "before deleting network", network) diff --git a/logic/nodes.go b/logic/nodes.go index d7a34ee6..69c95328 100644 --- a/logic/nodes.go +++ b/logic/nodes.go @@ -395,6 +395,7 @@ func GetNodeByIDorMacAddress(uuid string, macaddress string, network string) (mo return models.Node{}, err } err = CreateNode(&node) + logger.Log(2, "rewriting legacy node data; node now has id,", node.ID) if err != nil { return models.Node{}, err } diff --git a/logic/server.go b/logic/server.go index d34c222c..26512d0f 100644 --- a/logic/server.go +++ b/logic/server.go @@ -39,6 +39,7 @@ func ServerJoin(networkSettings *models.Network, serverID string) error { IsStatic: "yes", Name: models.NODE_SERVER_NAME, MacAddress: serverID, + ID: serverID, UDPHolePunch: "no", IsLocal: networkSettings.IsLocal, LocalRange: networkSettings.LocalRange, @@ -135,9 +136,9 @@ func ServerJoin(networkSettings *models.Network, serverID string) error { } // ServerCheckin - runs pulls and pushes for server -func ServerCheckin(mac string, network string) error { +func ServerCheckin(serverID string, mac string, network string) error { var serverNode = &models.Node{} - var currentNode, err = GetNode(mac, network) + var currentNode, err = GetNodeByIDorMacAddress(serverID, mac, network) if err != nil { return err } @@ -145,7 +146,7 @@ func ServerCheckin(mac string, network string) error { err = ServerPull(serverNode, false) if isDeleteError(err) { - return ServerLeave(mac, network) + return ServerLeave(currentNode.ID) } else if err != nil { return err } @@ -208,13 +209,13 @@ func ServerPush(serverNode *models.Node) error { } // ServerLeave - removes a server node -func ServerLeave(mac string, network string) error { +func ServerLeave(serverID string) error { - var serverNode, err = GetNode(mac, network) + var serverNode, err = GetNodeByID(serverID) if err != nil { return err } - return DeleteNodeByMacAddress(&serverNode, true) + return DeleteNodeByID(&serverNode, true) } /** @@ -229,7 +230,7 @@ func GetServerPeers(serverNode *models.Node) ([]wgtypes.PeerConfig, bool, []stri var peers []wgtypes.PeerConfig var nodes []models.Node // fill above fields from server or client - var nodecfg, err = GetNode(serverNode.MacAddress, serverNode.Network) + var nodecfg, err = GetNodeByIDorMacAddress(serverNode.ID, serverNode.MacAddress, serverNode.Network) if err != nil { return nil, hasGateway, gateways, err } @@ -348,7 +349,7 @@ func GetServerExtPeers(serverNode *models.Node) ([]wgtypes.PeerConfig, error) { var err error var tempPeers []models.ExtPeersResponse - tempPeers, err = GetExtPeersList(serverNode.MacAddress, serverNode.Network) + tempPeers, err = GetExtPeersList(serverNode) if err != nil { return nil, err } @@ -419,7 +420,7 @@ func checkNodeActions(node *models.Node) string { } } if node.Action == models.NODE_DELETE { - err := ServerLeave(node.MacAddress, node.Network) + err := ServerLeave(node.ID) if err != nil { logger.Log(1, "error deleting locally:", err.Error()) } diff --git a/logic/util.go b/logic/util.go index 4ddc985e..b9eddf38 100644 --- a/logic/util.go +++ b/logic/util.go @@ -104,7 +104,10 @@ func CreateNode(node *models.Node) error { if err != nil { return err } - node.ID = uuid.NewString() + + if node.IsServer != "yes" || (node.IsServer == "yes" && servercfg.GetNodeID() == "") { + node.ID = uuid.NewString() + } //Create a JWT for the node tokenString, _ := CreateJWT(node.ID, node.MacAddress, node.Network) diff --git a/models/node.go b/models/node.go index 4ed0ee63..32808b5f 100644 --- a/models/node.go +++ b/models/node.go @@ -23,9 +23,9 @@ const NODE_NOOP = "noop" var seededRand *rand.Rand = rand.New( rand.NewSource(time.Now().UnixNano())) -// node struct +// Node - struct for node model type Node struct { - ID string `json:"id,omitempty" bson:"id,omitempty"` + ID string `json:"id,omitempty" bson:"id,omitempty" yaml:"id,omitempty" validate:"required,min=5"` Address string `json:"address" bson:"address" yaml:"address" validate:"omitempty,ipv4"` Address6 string `json:"address6" bson:"address6" yaml:"address6" validate:"omitempty,ipv6"` LocalAddress string `json:"localaddress" bson:"localaddress" yaml:"localaddress" validate:"omitempty,ip"` @@ -46,7 +46,7 @@ type Node struct { ExpirationDateTime int64 `json:"expdatetime" bson:"expdatetime" yaml:"expdatetime"` LastPeerUpdate int64 `json:"lastpeerupdate" bson:"lastpeerupdate" yaml:"lastpeerupdate"` LastCheckIn int64 `json:"lastcheckin" bson:"lastcheckin" yaml:"lastcheckin"` - MacAddress string `json:"macaddress" bson:"macaddress" yaml:"macaddress" validate:"required,min=5,macaddress_unique"` + MacAddress string `json:"macaddress" bson:"macaddress" yaml:"macaddress"` // checkin interval is depreciated at the network level. Set on server with CHECKIN_INTERVAL CheckInInterval int32 `json:"checkininterval" bson:"checkininterval" yaml:"checkininterval"` Password string `json:"password" bson:"password" yaml:"password" validate:"required,min=6"` @@ -72,6 +72,7 @@ type Node struct { IPForwarding string `json:"ipforwarding" bson:"ipforwarding" yaml:"ipforwarding" validate:"checkyesorno"` OS string `json:"os" bson:"os" yaml:"os"` MTU int32 `json:"mtu" bson:"mtu" yaml:"mtu"` + Version string `json:"version" bson:"version" yaml:"version"` } // NodesArray - used for node sorting diff --git a/serverctl/serverctl.go b/serverctl/serverctl.go index 1e874daa..837536c2 100644 --- a/serverctl/serverctl.go +++ b/serverctl/serverctl.go @@ -42,7 +42,7 @@ func FileExists(f string) bool { // RemoveNetwork - removes a network locally on server func RemoveNetwork(network string) (bool, error) { - err := logic.ServerLeave(servercfg.GetNodeID(), network) + err := logic.ServerLeave(servercfg.GetNodeID()) return true, err } @@ -70,7 +70,7 @@ func HandleContainedClient() error { return err } for _, serverNet := range servernets { - err = logic.ServerCheckin(servercfg.GetNodeID(), serverNet.NetID) + err = logic.ServerCheckin(servercfg.GetNodeID(), servercfg.GetNodeID(), serverNet.NetID) if err != nil { logger.Log(1, "error occurred during server checkin:", err.Error()) } else { From 0569358cbd8acb068c4cb5ac19015d7f2db497c8 Mon Sep 17 00:00:00 2001 From: 0xdcarns Date: Mon, 10 Jan 2022 19:36:13 -0500 Subject: [PATCH 022/116] refactored all grpc to be uniform --- controllers/node_grpc.go | 61 +++++++++++++--------------------- netclient/auth/auth.go | 2 +- netclient/functions/checkin.go | 10 ++++-- netclient/functions/common.go | 28 +++++++++------- netclient/functions/list.go | 9 +++-- netclient/server/grpc.go | 20 ++++++++--- 6 files changed, 72 insertions(+), 58 deletions(-) diff --git a/controllers/node_grpc.go b/controllers/node_grpc.go index 1343ae0e..c5ce418a 100644 --- a/controllers/node_grpc.go +++ b/controllers/node_grpc.go @@ -4,7 +4,6 @@ import ( "context" "encoding/json" "errors" - "strings" nodepb "github.com/gravitl/netmaker/grpc" "github.com/gravitl/netmaker/logger" @@ -22,16 +21,14 @@ type NodeServiceServer struct { func (s *NodeServiceServer) ReadNode(ctx context.Context, req *nodepb.Object) (*nodepb.Object, error) { // convert string id (from proto) to mongoDB ObjectId var err error - var node models.Node - var macAndNetwork = make([]string, 2) - if strings.Contains(req.Data, "###") { - macAndNetwork = strings.Split(req.Data, "###") - if len(macAndNetwork) != 2 { - return nil, errors.New("could not read node, invalid node id given") - } + var reqNode models.Node + err = json.Unmarshal([]byte(req.Data), &reqNode) + if err != nil { + return nil, err } - node, err = logic.GetNodeByIDorMacAddress(req.Data, macAndNetwork[0], macAndNetwork[1]) + var node models.Node + node, err = logic.GetNodeByIDorMacAddress(reqNode.ID, reqNode.MacAddress, reqNode.Network) if err != nil { return nil, err } @@ -138,16 +135,17 @@ func (s *NodeServiceServer) UpdateNode(ctx context.Context, req *nodepb.Object) // NodeServiceServer.DeleteNode - deletes a node and responds over gRPC func (s *NodeServiceServer) DeleteNode(ctx context.Context, req *nodepb.Object) (*nodepb.Object, error) { - nodeID := req.GetData() - var nodeInfo = make([]string, 2) - if strings.Contains(nodeID, "###") { - nodeInfo = strings.Split(nodeID, "###") - if len(nodeInfo) != 2 { - return nil, errors.New("node not found") - } + + var reqNode models.Node + if err := json.Unmarshal([]byte(req.GetData()), &reqNode); err != nil { + return nil, err + } + + node, err := logic.GetNodeByIDorMacAddress(reqNode.ID, reqNode.MacAddress, reqNode.Network) + if err != nil { + return nil, err } - var node, err = logic.GetNodeByIDorMacAddress(nodeID, nodeInfo[0], nodeInfo[1]) err = logic.DeleteNodeByID(&node, true) if err != nil { return nil, err @@ -161,16 +159,13 @@ func (s *NodeServiceServer) DeleteNode(ctx context.Context, req *nodepb.Object) // NodeServiceServer.GetPeers - fetches peers over gRPC func (s *NodeServiceServer) GetPeers(ctx context.Context, req *nodepb.Object) (*nodepb.Object, error) { - nodeID := req.GetData() - var nodeInfo = make([]string, 2) - if strings.Contains(nodeID, "###") { - nodeInfo = strings.Split(nodeID, "###") - if len(nodeInfo) != 2 { - return nil, errors.New("could not fetch peers, invalid node id") - } + + var reqNode models.Node + if err := json.Unmarshal([]byte(req.GetData()), &reqNode); err != nil { + return nil, err } - node, err := logic.GetNodeByIDorMacAddress(nodeID, nodeInfo[0], nodeInfo[1]) + node, err := logic.GetNodeByIDorMacAddress(reqNode.ID, reqNode.MacAddress, reqNode.Network) if err != nil { return nil, err } @@ -200,20 +195,12 @@ func (s *NodeServiceServer) GetExtPeers(ctx context.Context, req *nodepb.Object) // Initiate a NodeItem type to write decoded data to //data := &models.PeersResponse{} // collection.Find returns a cursor for our (empty) query - macAndNetwork := strings.Split(req.Data, "###") - if len(macAndNetwork) != 2 { - return nil, errors.New("did not receive valid node id when fetching ext peers") - } - nodeID := req.GetData() - var nodeInfo = make([]string, 2) - if strings.Contains(nodeID, "###") { - nodeInfo = strings.Split(nodeID, "###") - if len(nodeInfo) != 2 { - return nil, errors.New("could not fetch peers, invalid node id") - } + var reqNode models.Node + if err := json.Unmarshal([]byte(req.GetData()), &reqNode); err != nil { + return nil, err } - node, err := logic.GetNodeByIDorMacAddress(nodeID, nodeInfo[0], nodeInfo[1]) + node, err := logic.GetNodeByIDorMacAddress(reqNode.ID, reqNode.MacAddress, reqNode.Network) if err != nil { return nil, err } diff --git a/netclient/auth/auth.go b/netclient/auth/auth.go index fdfedb78..f74cc903 100644 --- a/netclient/auth/auth.go +++ b/netclient/auth/auth.go @@ -71,7 +71,7 @@ func AutoLogin(client nodepb.NodeServiceClient, network string) error { return err } tokenstring := []byte(res.Data) - err = os.WriteFile(home+"nettoken-"+network, tokenstring, 0644) + err = os.WriteFile(home+"nettoken-"+network, tokenstring, 0644) // TODO: Proper permissions? if err != nil { return err } diff --git a/netclient/functions/checkin.go b/netclient/functions/checkin.go index 185be82e..1b6e481e 100644 --- a/netclient/functions/checkin.go +++ b/netclient/functions/checkin.go @@ -186,9 +186,15 @@ func Pull(network string, manual bool) (*models.Node, error) { return nil, err } + data, err := json.Marshal(&node) + if err != nil { + ncutils.PrintLog("Failed to parse node config: "+err.Error(), 1) + return nil, err + } + req := &nodepb.Object{ - Data: node.MacAddress + "###" + node.Network, - Type: nodepb.STRING_TYPE, + Data: string(data), + Type: nodepb.NODE_TYPE, } readres, err := wcclient.ReadNode(ctx, req, grpc.Header(&header)) diff --git a/netclient/functions/common.go b/netclient/functions/common.go index 34798a45..baa02f67 100644 --- a/netclient/functions/common.go +++ b/netclient/functions/common.go @@ -1,6 +1,7 @@ package functions import ( + "encoding/json" "errors" "fmt" "log" @@ -164,18 +165,21 @@ func LeaveNetwork(network string) error { log.Printf("Failed to authenticate: %v", err) } else { // handle client side var header metadata.MD - _, err = wcclient.DeleteNode( - ctx, - &nodepb.Object{ - Data: node.ID, - Type: nodepb.STRING_TYPE, - }, - grpc.Header(&header), - ) - if err != nil { - ncutils.PrintLog("encountered error deleting node: "+err.Error(), 1) - } else { - ncutils.PrintLog("removed machine from "+node.Network+" network on remote server", 1) + nodeData, err := json.Marshal(&node) + if err == nil { + _, err = wcclient.DeleteNode( + ctx, + &nodepb.Object{ + Data: string(nodeData), + Type: nodepb.NODE_TYPE, + }, + grpc.Header(&header), + ) + if err != nil { + ncutils.PrintLog("encountered error deleting node: "+err.Error(), 1) + } else { + ncutils.PrintLog("removed machine from "+node.Network+" network on remote server", 1) + } } } } diff --git a/netclient/functions/list.go b/netclient/functions/list.go index f5a0d92b..5cc836ba 100644 --- a/netclient/functions/list.go +++ b/netclient/functions/list.go @@ -98,9 +98,14 @@ func getPeers(network string) ([]Peer, error) { // Instantiate the BlogServiceClient with our client connection to the server wcclient = nodepb.NewNodeServiceClient(conn) + nodeData, err := json.Marshal(&nodecfg) + if err != nil { + return []Peer{}, fmt.Errorf("could not parse config node on network %s : %w", network, err) + } + req := &nodepb.Object{ - Data: nodecfg.MacAddress + "###" + nodecfg.Network, - Type: nodepb.STRING_TYPE, + Data: string(nodeData), + Type: nodepb.NODE_TYPE, } ctx, err := auth.SetJWT(wcclient, network) diff --git a/netclient/server/grpc.go b/netclient/server/grpc.go index 5bb1c213..96a7da92 100644 --- a/netclient/server/grpc.go +++ b/netclient/server/grpc.go @@ -101,9 +101,15 @@ func GetPeers(macaddress string, network string, server string, dualstack bool, // Instantiate the BlogServiceClient with our client connection to the server wcclient = nodepb.NewNodeServiceClient(conn) + nodeData, err := json.Marshal(&nodecfg) + if err != nil { + ncutils.PrintLog("could not parse node data from config during peer fetch for network "+network, 1) + return peers, hasGateway, gateways, err + } + req := &nodepb.Object{ - Data: macaddress + "###" + network, - Type: nodepb.STRING_TYPE, + Data: string(nodeData), + Type: nodepb.NODE_TYPE, } ctx, err := auth.SetJWT(wcclient, network) @@ -274,9 +280,15 @@ func GetExtPeers(macaddress string, network string, server string, dualstack boo // Instantiate the BlogServiceClient with our client connection to the server wcclient = nodepb.NewNodeServiceClient(conn) + nodeData, err := json.Marshal(&nodecfg) + if err != nil { + ncutils.PrintLog("could not parse node data from config during peer fetch for network "+network, 1) + return peers, err + } + req := &nodepb.Object{ - Data: macaddress + "###" + network, - Type: nodepb.STRING_TYPE, + Data: string(nodeData), + Type: nodepb.NODE_TYPE, } ctx, err := auth.SetJWT(wcclient, network) From eda5779a99de664e4bdf9a440b397a5dfdd363ec Mon Sep 17 00:00:00 2001 From: 0xdcarns Date: Mon, 10 Jan 2022 19:43:20 -0500 Subject: [PATCH 023/116] test logic update --- controllers/config/dnsconfig/netmaker.hosts | 1 - controllers/node_test.go | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/controllers/config/dnsconfig/netmaker.hosts b/controllers/config/dnsconfig/netmaker.hosts index 4cd3667a..e69de29b 100644 --- a/controllers/config/dnsconfig/netmaker.hosts +++ b/controllers/config/dnsconfig/netmaker.hosts @@ -1 +0,0 @@ -10.0.0.1 node-4bukt.skynet diff --git a/controllers/node_test.go b/controllers/node_test.go index bf4312bc..4da57179 100644 --- a/controllers/node_test.go +++ b/controllers/node_test.go @@ -19,12 +19,12 @@ func TestCreateEgressGateway(t *testing.T) { t.Run("NoNodes", func(t *testing.T) { node, err := logic.CreateEgressGateway(gateway) assert.Equal(t, models.Node{}, node) - assert.EqualError(t, err, "unable to get record key") + assert.EqualError(t, err, "could not find any records") }) t.Run("Success", func(t *testing.T) { testnode := createTestNode() gateway.NetID = "skynet" - gateway.NodeID = testnode.MacAddress + gateway.NodeID = testnode.ID node, err := logic.CreateEgressGateway(gateway) assert.Nil(t, err) @@ -43,7 +43,7 @@ func TestDeleteEgressGateway(t *testing.T) { gateway.Interface = "eth0" gateway.Ranges = []string{"10.100.100.0/24"} gateway.NetID = "skynet" - gateway.NodeID = testnode.MacAddress + gateway.NodeID = testnode.ID t.Run("Success", func(t *testing.T) { node, err := logic.CreateEgressGateway(gateway) assert.Nil(t, err) From 3c66c34ecb3112e11faf0a2f65072916c8a4b5e4 Mon Sep 17 00:00:00 2001 From: 0xdcarns Date: Mon, 10 Jan 2022 19:51:58 -0500 Subject: [PATCH 024/116] testing continued --- logic/nodes.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/logic/nodes.go b/logic/nodes.go index 69c95328..ac74ae7a 100644 --- a/logic/nodes.go +++ b/logic/nodes.go @@ -16,7 +16,7 @@ import ( // GetNetworkNodes - gets the nodes of a network func GetNetworkNodes(network string) ([]models.Node, error) { - var nodes []models.Node + var nodes = []models.Node{} collection, err := database.FetchRecords(database.NODES_TABLE_NAME) if err != nil { if database.IsEmptyRecord(err) { From 787e584389130709bc45d5bb8eac469035441a93 Mon Sep 17 00:00:00 2001 From: 0xdcarns Date: Mon, 10 Jan 2022 19:56:52 -0500 Subject: [PATCH 025/116] continued. --- controllers/node_test.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/controllers/node_test.go b/controllers/node_test.go index 4da57179..acc4924c 100644 --- a/controllers/node_test.go +++ b/controllers/node_test.go @@ -69,12 +69,6 @@ func TestDeleteEgressGateway(t *testing.T) { assert.EqualError(t, err, "no result found") assert.Equal(t, models.Node{}, node) }) - t.Run("BadNet", func(t *testing.T) { - node, err := logic.DeleteEgressGateway("badnet", gateway.NodeID) - assert.EqualError(t, err, "no result found") - assert.Equal(t, models.Node{}, node) - }) - } func TestGetNetworkNodes(t *testing.T) { From cf34b1b4ed91d9b3778cc38478981a45d47e25e4 Mon Sep 17 00:00:00 2001 From: 0xdcarns Date: Mon, 10 Jan 2022 20:40:43 -0500 Subject: [PATCH 026/116] continued. --- controllers/node_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/controllers/node_test.go b/controllers/node_test.go index acc4924c..8d7d6985 100644 --- a/controllers/node_test.go +++ b/controllers/node_test.go @@ -74,6 +74,7 @@ func TestDeleteEgressGateway(t *testing.T) { func TestGetNetworkNodes(t *testing.T) { database.InitializeDatabase() deleteAllNetworks() + deleteAllNodes() createNet() t.Run("BadNet", func(t *testing.T) { node, err := logic.GetNetworkNodes("badnet") From 82bc0bbd2eaebea68b9c346a274446693601d035 Mon Sep 17 00:00:00 2001 From: 0xdcarns Date: Mon, 10 Jan 2022 20:50:18 -0500 Subject: [PATCH 027/116] continued. --- controllers/node_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controllers/node_test.go b/controllers/node_test.go index 8d7d6985..0c2d79c7 100644 --- a/controllers/node_test.go +++ b/controllers/node_test.go @@ -68,13 +68,13 @@ func TestDeleteEgressGateway(t *testing.T) { node, err := logic.DeleteEgressGateway(gateway.NetID, "01:02:03") assert.EqualError(t, err, "no result found") assert.Equal(t, models.Node{}, node) + deleteAllNodes() }) } func TestGetNetworkNodes(t *testing.T) { database.InitializeDatabase() deleteAllNetworks() - deleteAllNodes() createNet() t.Run("BadNet", func(t *testing.T) { node, err := logic.GetNetworkNodes("badnet") From 02f08fea1395858d051f7bec1fbf1e09ed62ccdf Mon Sep 17 00:00:00 2001 From: 0xdcarns Date: Tue, 11 Jan 2022 08:40:51 -0500 Subject: [PATCH 028/116] test adjust --- controllers/node_test.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/controllers/node_test.go b/controllers/node_test.go index 0c2d79c7..38a84e60 100644 --- a/controllers/node_test.go +++ b/controllers/node_test.go @@ -135,10 +135,7 @@ func TestValidateEgressGateway(t *testing.T) { } func deleteAllNodes() { - nodes, _ := logic.GetAllNodes() - for _, node := range nodes { - logic.DeleteNodeByID(&node, true) - } + database.DeleteAllRecords(database.NODES_TABLE_NAME) } func createTestNode() *models.Node { From ef20aaa5df732847c8b39ceaea2c8c9f5eca3ab9 Mon Sep 17 00:00:00 2001 From: 0xdcarns Date: Tue, 11 Jan 2022 10:24:29 -0500 Subject: [PATCH 029/116] added hotfixes --- logic/nodes.go | 3 ++- logic/util.go | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/logic/nodes.go b/logic/nodes.go index ac74ae7a..18bd3a1d 100644 --- a/logic/nodes.go +++ b/logic/nodes.go @@ -395,10 +395,11 @@ func GetNodeByIDorMacAddress(uuid string, macaddress string, network string) (mo return models.Node{}, err } err = CreateNode(&node) - logger.Log(2, "rewriting legacy node data; node now has id,", node.ID) if err != nil { return models.Node{}, err } + logger.Log(2, "rewriting legacy node data; node now has id,", node.ID) + node.PullChanges = "yes" } return node, err } diff --git a/logic/util.go b/logic/util.go index b9eddf38..f202f68d 100644 --- a/logic/util.go +++ b/logic/util.go @@ -108,6 +108,7 @@ func CreateNode(node *models.Node) error { if node.IsServer != "yes" || (node.IsServer == "yes" && servercfg.GetNodeID() == "") { node.ID = uuid.NewString() } + logger.Log(0, "server ID: ", node.ID) //Create a JWT for the node tokenString, _ := CreateJWT(node.ID, node.MacAddress, node.Network) From 5c48532dc7fc32441cd891594beb024edfe03252 Mon Sep 17 00:00:00 2001 From: 0xdcarns Date: Tue, 11 Jan 2022 10:44:49 -0500 Subject: [PATCH 030/116] adjusting client join --- controllers/auth_grpc.go | 3 +++ netclient/functions/join.go | 10 ++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/controllers/auth_grpc.go b/controllers/auth_grpc.go index 6f890803..c1c10716 100644 --- a/controllers/auth_grpc.go +++ b/controllers/auth_grpc.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "errors" + "log" "github.com/gravitl/netmaker/database" "github.com/gravitl/netmaker/functions" @@ -118,6 +119,8 @@ func (s *NodeServiceServer) Login(ctx context.Context, req *nodepb.Object) (*nod password := reqNode.Password macaddress := reqNode.MacAddress + log.Printf("authing node: %v \n", reqNode) + var result models.NodeAuth var err error // err := errors.New("generic server error") diff --git a/netclient/functions/join.go b/netclient/functions/join.go index f8a8ba8f..c68331dd 100644 --- a/netclient/functions/join.go +++ b/netclient/functions/join.go @@ -8,6 +8,7 @@ import ( "log" "os/exec" + "github.com/google/uuid" nodepb "github.com/gravitl/netmaker/grpc" "github.com/gravitl/netmaker/models" "github.com/gravitl/netmaker/netclient/auth" @@ -76,12 +77,15 @@ func JoinNetwork(cfg config.ClientConfig, privateKey string) error { macs, err := ncutils.GetMacAddr() if err != nil { return err - } else if len(macs) == 0 { - log.Fatal("could not retrieve mac address") } else { cfg.Node.MacAddress = macs[0] } } + + if cfg.Node.ID == "" { + cfg.Node.ID = uuid.NewString() + } + if ncutils.IsLinux() { _, err := exec.LookPath("resolvconf") if err != nil { @@ -100,6 +104,7 @@ func JoinNetwork(cfg config.ClientConfig, privateKey string) error { var node models.Node // fill this node with appropriate calls postnode := &models.Node{ Password: cfg.Node.Password, + ID: cfg.Node.ID, MacAddress: cfg.Node.MacAddress, AccessKey: cfg.Server.AccessKey, IsStatic: cfg.Node.IsStatic, @@ -122,6 +127,7 @@ func JoinNetwork(cfg config.ClientConfig, privateKey string) error { if cfg.Node.IsServer != "yes" { ncutils.Log("joining " + cfg.Network + " at " + cfg.Server.GRPCAddress) var wcclient nodepb.NodeServiceClient + log.Printf("used: %v\n", postnode) conn, err := grpc.Dial(cfg.Server.GRPCAddress, ncutils.GRPCRequestOpts(cfg.Server.GRPCSSL)) From 395fe85518f79381ec51e909133ec3a8047ea694 Mon Sep 17 00:00:00 2001 From: 0xdcarns Date: Tue, 11 Jan 2022 10:58:20 -0500 Subject: [PATCH 031/116] fixed egress to use id --- logic/gateway.go | 8 +++----- netclient/auth/auth.go | 2 ++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/logic/gateway.go b/logic/gateway.go index 7a1710c9..61076f24 100644 --- a/logic/gateway.go +++ b/logic/gateway.go @@ -44,10 +44,7 @@ func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.Node, erro postDownCmd = node.PostDown + "; " + postDownCmd } } - key, err := GetRecordKey(gateway.NodeID, gateway.NetID) - if err != nil { - return node, err - } + node.PostUp = postUpCmd node.PostDown = postDownCmd node.SetLastModified() @@ -56,7 +53,7 @@ func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.Node, erro if err != nil { return node, err } - if err = database.Insert(key, string(nodeData), database.NODES_TABLE_NAME); err != nil { + if err = database.Insert(node.ID, string(nodeData), database.NODES_TABLE_NAME); err != nil { return models.Node{}, err } if err = NetworkNodesUpdatePullChanges(node.Network); err != nil { @@ -65,6 +62,7 @@ func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.Node, erro return node, nil } +// ValidateEgressGateway - validates the egress gateway model func ValidateEgressGateway(gateway models.EgressGatewayRequest) error { var err error diff --git a/netclient/auth/auth.go b/netclient/auth/auth.go index f74cc903..d17b82e6 100644 --- a/netclient/auth/auth.go +++ b/netclient/auth/auth.go @@ -55,6 +55,7 @@ func AutoLogin(client nodepb.NodeServiceClient, network string) error { node := models.Node{ Password: pass, MacAddress: cfg.Node.MacAddress, + ID: cfg.Node.ID, Network: network, } data, err := json.Marshal(&node) @@ -64,6 +65,7 @@ func AutoLogin(client nodepb.NodeServiceClient, network string) error { login := &nodepb.Object{ Data: string(data), + Type: nodepb.NODE_TYPE, } // RPC call res, err := client.Login(context.TODO(), login) From 9888a84e8aa9c0a0b25b1c5c10761b1441b6f584 Mon Sep 17 00:00:00 2001 From: 0xdcarns Date: Tue, 11 Jan 2022 11:59:26 -0500 Subject: [PATCH 032/116] updated routes to use uuid --- logic/gateway.go | 20 +++++--------------- logic/nodes.go | 6 +----- logic/relay.go | 13 +++++-------- logic/util.go | 2 +- 4 files changed, 12 insertions(+), 29 deletions(-) diff --git a/logic/gateway.go b/logic/gateway.go index 61076f24..e1b0a49e 100644 --- a/logic/gateway.go +++ b/logic/gateway.go @@ -95,15 +95,12 @@ func DeleteEgressGateway(network, nodeid string) (models.Node, error) { } node.SetLastModified() node.PullChanges = "yes" - key, err := GetRecordKey(node.MacAddress, node.Network) - if err != nil { - return models.Node{}, err - } + data, err := json.Marshal(&node) if err != nil { return models.Node{}, err } - if err = database.Insert(key, string(data), database.NODES_TABLE_NAME); err != nil { + if err = database.Insert(node.ID, string(data), database.NODES_TABLE_NAME); err != nil { return models.Node{}, err } if err = NetworkNodesUpdatePullChanges(network); err != nil { @@ -147,15 +144,12 @@ func CreateIngressGateway(netid string, nodeid string) (models.Node, error) { node.PostDown = postDownCmd node.PullChanges = "yes" node.UDPHolePunch = "no" - key, err := GetRecordKey(node.MacAddress, node.Network) - if err != nil { - return models.Node{}, err - } + data, err := json.Marshal(&node) if err != nil { return models.Node{}, err } - err = database.Insert(key, string(data), database.NODES_TABLE_NAME) + err = database.Insert(node.ID, string(data), database.NODES_TABLE_NAME) if err != nil { return models.Node{}, err } @@ -185,15 +179,11 @@ func DeleteIngressGateway(networkName string, macaddress string) (models.Node, e node.IngressGatewayRange = "" node.PullChanges = "yes" - key, err := GetRecordKey(node.MacAddress, node.Network) - if err != nil { - return models.Node{}, err - } data, err := json.Marshal(&node) if err != nil { return models.Node{}, err } - err = database.Insert(key, string(data), database.NODES_TABLE_NAME) + err = database.Insert(node.ID, string(data), database.NODES_TABLE_NAME) if err != nil { return models.Node{}, err } diff --git a/logic/nodes.go b/logic/nodes.go index 18bd3a1d..75e63036 100644 --- a/logic/nodes.go +++ b/logic/nodes.go @@ -76,12 +76,8 @@ func UncordonNode(nodeid string) (models.Node, error) { if err != nil { return node, err } - key, err := GetRecordKey(node.MacAddress, node.Network) - if err != nil { - return node, err - } - err = database.Insert(key, string(data), database.NODES_TABLE_NAME) + err = database.Insert(node.ID, string(data), database.NODES_TABLE_NAME) return node, err } diff --git a/logic/relay.go b/logic/relay.go index ea1e7cf4..30ea1ee9 100644 --- a/logic/relay.go +++ b/logic/relay.go @@ -13,12 +13,13 @@ import ( // CreateRelay - creates a relay func CreateRelay(relay models.RelayRequest) (models.Node, error) { node, err := GetNodeByID(relay.NodeID) - if node.OS == "macos" { // add in darwin later - return models.Node{}, errors.New(node.OS + " is unsupported for relay") - } if err != nil { return models.Node{}, err } + if node.OS == "macos" { // add in darwin later + return models.Node{}, errors.New(node.OS + " is unsupported for relay") + } + err = ValidateRelay(relay) if err != nil { return models.Node{}, err @@ -26,17 +27,13 @@ func CreateRelay(relay models.RelayRequest) (models.Node, error) { node.IsRelay = "yes" node.RelayAddrs = relay.RelayAddrs - key, err := GetRecordKey(relay.NodeID, relay.NetID) - if err != nil { - return node, err - } node.SetLastModified() node.PullChanges = "yes" nodeData, err := json.Marshal(&node) if err != nil { return node, err } - if err = database.Insert(key, string(nodeData), database.NODES_TABLE_NAME); err != nil { + if err = database.Insert(node.ID, string(nodeData), database.NODES_TABLE_NAME); err != nil { return models.Node{}, err } err = SetRelayedNodes("yes", node.Network, node.RelayAddrs) diff --git a/logic/util.go b/logic/util.go index f202f68d..e06e80fa 100644 --- a/logic/util.go +++ b/logic/util.go @@ -105,7 +105,7 @@ func CreateNode(node *models.Node) error { return err } - if node.IsServer != "yes" || (node.IsServer == "yes" && servercfg.GetNodeID() == "") { + if (node.IsServer != "yes" && (node.ID == "" || strings.Contains(node.ID, "###"))) || (node.IsServer == "yes" && servercfg.GetNodeID() == "") { node.ID = uuid.NewString() } logger.Log(0, "server ID: ", node.ID) From c70041ddd0c77bc78f2e7ad2d11304656b7c5884 Mon Sep 17 00:00:00 2001 From: 0xdcarns Date: Tue, 11 Jan 2022 12:00:14 -0500 Subject: [PATCH 033/116] updated routes to use uuid --- logic/util.go | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/logic/util.go b/logic/util.go index e06e80fa..c4f6b6a5 100644 --- a/logic/util.go +++ b/logic/util.go @@ -48,7 +48,7 @@ func DeleteNodeByMacAddress(node *models.Node, exterminate bool) error { var key = node.ID if !exterminate { args := strings.Split(key, "###") - node, err := GetNode(args[0], args[1]) + node, err := GetNodeByMacAddress(args[0], args[1]) if err != nil { return err } @@ -160,29 +160,29 @@ func SetNetworkNodesLastModified(networkName string) error { return nil } -// GetNode - fetches a node from database -func GetNode(macaddress string, network string) (models.Node, error) { - var node models.Node +// // GetNode - fetches a node from database +// func GetNode(macaddress string, network string) (models.Node, error) { +// var node models.Node - key, err := GetRecordKey(macaddress, network) - if err != nil { - return node, err - } - data, err := database.FetchRecord(database.NODES_TABLE_NAME, key) - if err != nil { - if data == "" { - data, _ = database.FetchRecord(database.DELETED_NODES_TABLE_NAME, key) - err = json.Unmarshal([]byte(data), &node) - } - return node, err - } - if err = json.Unmarshal([]byte(data), &node); err != nil { - return node, err - } - SetNodeDefaults(&node) +// key, err := GetRecordKey(macaddress, network) +// if err != nil { +// return node, err +// } +// data, err := database.FetchRecord(database.NODES_TABLE_NAME, key) +// if err != nil { +// if data == "" { +// data, _ = database.FetchRecord(database.DELETED_NODES_TABLE_NAME, key) +// err = json.Unmarshal([]byte(data), &node) +// } +// return node, err +// } +// if err = json.Unmarshal([]byte(data), &node); err != nil { +// return node, err +// } +// SetNodeDefaults(&node) - return node, err -} +// return node, err +// } // DeleteNodeByID - deletes a node from database or moves into delete nodes table func DeleteNodeByID(node *models.Node, exterminate bool) error { From 95306e87f8d2abb27af2588d216201eb33b0cc15 Mon Sep 17 00:00:00 2001 From: 0xdcarns Date: Tue, 11 Jan 2022 13:05:22 -0500 Subject: [PATCH 034/116] adapted node routes further to new id --- controllers/node.go | 2 +- logic/gateway.go | 6 +++--- logic/util.go | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/controllers/node.go b/controllers/node.go index 100b8efd..98259ef1 100644 --- a/controllers/node.go +++ b/controllers/node.go @@ -29,7 +29,7 @@ func nodeHandlers(r *mux.Router) { r.HandleFunc("/api/nodes/{network}/{nodeid}/createingress", securityCheck(false, http.HandlerFunc(createIngressGateway))).Methods("POST") r.HandleFunc("/api/nodes/{network}/{nodeid}/deleteingress", securityCheck(false, http.HandlerFunc(deleteIngressGateway))).Methods("DELETE") r.HandleFunc("/api/nodes/{network}/{nodeid}/approve", authorize(true, "user", http.HandlerFunc(uncordonNode))).Methods("POST") - // r.HandleFunc("/api/nodes/{network}", createNode).Methods("POST") + r.HandleFunc("/api/nodes/{network}", createNode).Methods("POST") r.HandleFunc("/api/nodes/adm/{network}/lastmodified", authorize(true, "network", http.HandlerFunc(getLastModified))).Methods("GET") r.HandleFunc("/api/nodes/adm/{network}/authenticate", authenticate).Methods("POST") diff --git a/logic/gateway.go b/logic/gateway.go index e1b0a49e..582fc0d5 100644 --- a/logic/gateway.go +++ b/logic/gateway.go @@ -158,9 +158,9 @@ func CreateIngressGateway(netid string, nodeid string) (models.Node, error) { } // DeleteIngressGateway - deletes an ingress gateway -func DeleteIngressGateway(networkName string, macaddress string) (models.Node, error) { +func DeleteIngressGateway(networkName string, nodeid string) (models.Node, error) { - node, err := GetNodeByMacAddress(networkName, macaddress) + node, err := GetNodeByID(nodeid) if err != nil { return models.Node{}, err } @@ -169,7 +169,7 @@ func DeleteIngressGateway(networkName string, macaddress string) (models.Node, e return models.Node{}, err } // delete ext clients belonging to ingress gateway - if err = DeleteGatewayExtClients(macaddress, networkName); err != nil { + if err = DeleteGatewayExtClients(node.ID, networkName); err != nil { return models.Node{}, err } diff --git a/logic/util.go b/logic/util.go index c4f6b6a5..173f1c89 100644 --- a/logic/util.go +++ b/logic/util.go @@ -105,10 +105,10 @@ func CreateNode(node *models.Node) error { return err } + // TODO: This covers legacy nodes, eventually want to remove legacy check if (node.IsServer != "yes" && (node.ID == "" || strings.Contains(node.ID, "###"))) || (node.IsServer == "yes" && servercfg.GetNodeID() == "") { node.ID = uuid.NewString() } - logger.Log(0, "server ID: ", node.ID) //Create a JWT for the node tokenString, _ := CreateJWT(node.ID, node.MacAddress, node.Network) From fe77f65b4105b0e96a2560c72f4605d07ac89813 Mon Sep 17 00:00:00 2001 From: 0xdcarns Date: Tue, 11 Jan 2022 13:13:45 -0500 Subject: [PATCH 035/116] version updates --- netclient/main.go | 2 +- servercfg/serverconf.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/netclient/main.go b/netclient/main.go index 1c6c1ff9..0f364ccd 100644 --- a/netclient/main.go +++ b/netclient/main.go @@ -18,7 +18,7 @@ func main() { 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." - app.Version = "v0.9.3" + app.Version = "v0.9.4" cliFlags := cli_options.GetFlags(ncutils.GetHostname()) app.Commands = cli_options.GetCommands(cliFlags[:]) diff --git a/servercfg/serverconf.go b/servercfg/serverconf.go index d15af77a..8c4daaf3 100644 --- a/servercfg/serverconf.go +++ b/servercfg/serverconf.go @@ -113,7 +113,7 @@ func GetAPIConnString() string { // GetVersion - version of netmaker func GetVersion() string { - version := "0.9.3" + version := "0.9.4" if config.Config.Server.Version != "" { version = config.Config.Server.Version } From 2e470f2f6df80eef1424baf7ebc22dea9a3c7988 Mon Sep 17 00:00:00 2001 From: 0xdcarns Date: Tue, 11 Jan 2022 19:01:20 -0500 Subject: [PATCH 036/116] added legacy check to maintain compatibility --- controllers/auth_grpc.go | 12 ++----- controllers/node_grpc.go | 62 ++++++++++++++++++------------------- netclient/functions/join.go | 1 - 3 files changed, 34 insertions(+), 41 deletions(-) diff --git a/controllers/auth_grpc.go b/controllers/auth_grpc.go index c1c10716..82a4119b 100644 --- a/controllers/auth_grpc.go +++ b/controllers/auth_grpc.go @@ -4,7 +4,6 @@ import ( "context" "encoding/json" "errors" - "log" "github.com/gravitl/netmaker/database" "github.com/gravitl/netmaker/functions" @@ -108,9 +107,8 @@ func grpcAuthorize(ctx context.Context) error { // Login - node authenticates using its password and retrieves a JWT for authorization. func (s *NodeServiceServer) Login(ctx context.Context, req *nodepb.Object) (*nodepb.Object, error) { - //out := new(LoginResponse) - var reqNode models.Node - if err := json.Unmarshal([]byte(req.Data), &reqNode); err != nil { + var reqNode, err = getNewOrLegacyNode(req.Data) + if err != nil { return nil, err } @@ -119,11 +117,7 @@ func (s *NodeServiceServer) Login(ctx context.Context, req *nodepb.Object) (*nod password := reqNode.Password macaddress := reqNode.MacAddress - log.Printf("authing node: %v \n", reqNode) - var result models.NodeAuth - var err error - // err := errors.New("generic server error") if nodeID == "" { //TODO: Set Error response @@ -133,7 +127,7 @@ func (s *NodeServiceServer) Login(ctx context.Context, req *nodepb.Object) (*nod err = errors.New("missing password") return nil, err } else { - //Search DB for node with Mac Address. Ignore pending nodes (they should not be able to authenticate with API until approved). + //Search DB for node with ID. Ignore pending nodes (they should not be able to authenticate with API until approved). collection, err := database.FetchRecords(database.NODES_TABLE_NAME) if err != nil { return nil, err diff --git a/controllers/node_grpc.go b/controllers/node_grpc.go index c5ce418a..02646798 100644 --- a/controllers/node_grpc.go +++ b/controllers/node_grpc.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "errors" + "strings" nodepb "github.com/gravitl/netmaker/grpc" "github.com/gravitl/netmaker/logger" @@ -19,16 +20,7 @@ type NodeServiceServer struct { // NodeServiceServer.ReadNode - reads node and responds with gRPC func (s *NodeServiceServer) ReadNode(ctx context.Context, req *nodepb.Object) (*nodepb.Object, error) { - // convert string id (from proto) to mongoDB ObjectId - var err error - var reqNode models.Node - err = json.Unmarshal([]byte(req.Data), &reqNode) - if err != nil { - return nil, err - } - - var node models.Node - node, err = logic.GetNodeByIDorMacAddress(reqNode.ID, reqNode.MacAddress, reqNode.Network) + var node, err = getNewOrLegacyNode(req.Data) if err != nil { return nil, err } @@ -99,7 +91,7 @@ func (s *NodeServiceServer) CreateNode(ctx context.Context, req *nodepb.Object) // NodeServiceServer.UpdateNode updates a node and responds over gRPC func (s *NodeServiceServer) UpdateNode(ctx context.Context, req *nodepb.Object) (*nodepb.Object, error) { - // Get the node data from the request + var newnode models.Node if err := json.Unmarshal([]byte(req.GetData()), &newnode); err != nil { return nil, err @@ -136,12 +128,7 @@ func (s *NodeServiceServer) UpdateNode(ctx context.Context, req *nodepb.Object) // NodeServiceServer.DeleteNode - deletes a node and responds over gRPC func (s *NodeServiceServer) DeleteNode(ctx context.Context, req *nodepb.Object) (*nodepb.Object, error) { - var reqNode models.Node - if err := json.Unmarshal([]byte(req.GetData()), &reqNode); err != nil { - return nil, err - } - - node, err := logic.GetNodeByIDorMacAddress(reqNode.ID, reqNode.MacAddress, reqNode.Network) + var node, err = getNewOrLegacyNode(req.Data) if err != nil { return nil, err } @@ -160,15 +147,11 @@ func (s *NodeServiceServer) DeleteNode(ctx context.Context, req *nodepb.Object) // NodeServiceServer.GetPeers - fetches peers over gRPC func (s *NodeServiceServer) GetPeers(ctx context.Context, req *nodepb.Object) (*nodepb.Object, error) { - var reqNode models.Node - if err := json.Unmarshal([]byte(req.GetData()), &reqNode); err != nil { - return nil, err - } - - node, err := logic.GetNodeByIDorMacAddress(reqNode.ID, reqNode.MacAddress, reqNode.Network) + var node, err = getNewOrLegacyNode(req.Data) if err != nil { return nil, err } + if node.IsServer == "yes" && logic.IsLeader(&node) { logic.SetNetworkServerPeers(&node) } @@ -192,15 +175,8 @@ func (s *NodeServiceServer) GetPeers(ctx context.Context, req *nodepb.Object) (* // NodeServiceServer.GetExtPeers - returns ext peers for a gateway node func (s *NodeServiceServer) GetExtPeers(ctx context.Context, req *nodepb.Object) (*nodepb.Object, error) { - // Initiate a NodeItem type to write decoded data to - //data := &models.PeersResponse{} - // collection.Find returns a cursor for our (empty) query - var reqNode models.Node - if err := json.Unmarshal([]byte(req.GetData()), &reqNode); err != nil { - return nil, err - } - node, err := logic.GetNodeByIDorMacAddress(reqNode.ID, reqNode.MacAddress, reqNode.Network) + var node, err = getNewOrLegacyNode(req.Data) if err != nil { return nil, err } @@ -232,3 +208,27 @@ func (s *NodeServiceServer) GetExtPeers(ctx context.Context, req *nodepb.Object) Type: nodepb.EXT_PEER, }, nil } + +// == private methods == + +func getNewOrLegacyNode(data string) (models.Node, error) { + var reqNode, node models.Node + var err error + + if err = json.Unmarshal([]byte(data), &reqNode); err != nil { + oldID := strings.Split(data, "###") // handle legacy client IDs + if len(oldID) == 2 { + if node, err = logic.GetNodeByIDorMacAddress(reqNode.ID, reqNode.MacAddress, reqNode.Network); err != nil { + return models.Node{}, err + } + } else { + return models.Node{}, err + } + } else { + node, err = logic.GetNodeByIDorMacAddress(reqNode.ID, reqNode.MacAddress, reqNode.Network) + if err != nil { + return models.Node{}, err + } + } + return node, nil +} diff --git a/netclient/functions/join.go b/netclient/functions/join.go index c68331dd..f5c38c85 100644 --- a/netclient/functions/join.go +++ b/netclient/functions/join.go @@ -127,7 +127,6 @@ func JoinNetwork(cfg config.ClientConfig, privateKey string) error { if cfg.Node.IsServer != "yes" { ncutils.Log("joining " + cfg.Network + " at " + cfg.Server.GRPCAddress) var wcclient nodepb.NodeServiceClient - log.Printf("used: %v\n", postnode) conn, err := grpc.Dial(cfg.Server.GRPCAddress, ncutils.GRPCRequestOpts(cfg.Server.GRPCSSL)) From 3572c33e0b078fa2160e25ed941ef3a93c2c56ad Mon Sep 17 00:00:00 2001 From: 0xdcarns Date: Tue, 11 Jan 2022 19:02:51 -0500 Subject: [PATCH 037/116] misplaced variable --- controllers/node_grpc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controllers/node_grpc.go b/controllers/node_grpc.go index 02646798..f606a187 100644 --- a/controllers/node_grpc.go +++ b/controllers/node_grpc.go @@ -218,7 +218,7 @@ func getNewOrLegacyNode(data string) (models.Node, error) { if err = json.Unmarshal([]byte(data), &reqNode); err != nil { oldID := strings.Split(data, "###") // handle legacy client IDs if len(oldID) == 2 { - if node, err = logic.GetNodeByIDorMacAddress(reqNode.ID, reqNode.MacAddress, reqNode.Network); err != nil { + if node, err = logic.GetNodeByIDorMacAddress(reqNode.ID, oldID[0], oldID[1]); err != nil { return models.Node{}, err } } else { From 3416a61e77a0b8e110ec447d6b9cc5db4449dc9c Mon Sep 17 00:00:00 2001 From: 0xdcarns Date: Wed, 12 Jan 2022 12:51:51 -0500 Subject: [PATCH 038/116] server fix --- logic/nodes.go | 2 ++ logic/server.go | 2 ++ 2 files changed, 4 insertions(+) diff --git a/logic/nodes.go b/logic/nodes.go index 75e63036..0bed8b9d 100644 --- a/logic/nodes.go +++ b/logic/nodes.go @@ -4,6 +4,7 @@ import ( "encoding/json" "errors" "fmt" + "log" "sort" "time" @@ -397,6 +398,7 @@ func GetNodeByIDorMacAddress(uuid string, macaddress string, network string) (mo logger.Log(2, "rewriting legacy node data; node now has id,", node.ID) node.PullChanges = "yes" } + log.Printf("Node is %v, Error is %v \n", node, err) return node, err } diff --git a/logic/server.go b/logic/server.go index 26512d0f..a7aa277e 100644 --- a/logic/server.go +++ b/logic/server.go @@ -87,6 +87,8 @@ func ServerJoin(networkSettings *models.Network, serverID string) error { node.Network = networkSettings.NetID + cleanupServerIfLegacy(node.MacAddress, network) + logger.Log(2, "adding a server instance on network", node.Network) err = CreateNode(node) if err != nil { From 02d60e0c2323c33de24213d474e61c01cc091128 Mon Sep 17 00:00:00 2001 From: 0xdcarns Date: Wed, 12 Jan 2022 13:43:59 -0500 Subject: [PATCH 039/116] cleaned up logs --- logic/nodes.go | 2 -- logic/server.go | 3 +-- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/logic/nodes.go b/logic/nodes.go index 0bed8b9d..75e63036 100644 --- a/logic/nodes.go +++ b/logic/nodes.go @@ -4,7 +4,6 @@ import ( "encoding/json" "errors" "fmt" - "log" "sort" "time" @@ -398,7 +397,6 @@ func GetNodeByIDorMacAddress(uuid string, macaddress string, network string) (mo logger.Log(2, "rewriting legacy node data; node now has id,", node.ID) node.PullChanges = "yes" } - log.Printf("Node is %v, Error is %v \n", node, err) return node, err } diff --git a/logic/server.go b/logic/server.go index a7aa277e..ee038550 100644 --- a/logic/server.go +++ b/logic/server.go @@ -87,8 +87,6 @@ func ServerJoin(networkSettings *models.Network, serverID string) error { node.Network = networkSettings.NetID - cleanupServerIfLegacy(node.MacAddress, network) - logger.Log(2, "adding a server instance on network", node.Network) err = CreateNode(node) if err != nil { @@ -139,6 +137,7 @@ func ServerJoin(networkSettings *models.Network, serverID string) error { // ServerCheckin - runs pulls and pushes for server func ServerCheckin(serverID string, mac string, network string) error { + cleanupLegacyServers(network) var serverNode = &models.Node{} var currentNode, err = GetNodeByIDorMacAddress(serverID, mac, network) if err != nil { From 374c9517a911ce38df8c2f9152c9737b4bf7373e Mon Sep 17 00:00:00 2001 From: 0xdcarns Date: Wed, 12 Jan 2022 14:08:59 -0500 Subject: [PATCH 040/116] removed cleanup function, kind of pointless --- logic/server.go | 1 - 1 file changed, 1 deletion(-) diff --git a/logic/server.go b/logic/server.go index ee038550..26512d0f 100644 --- a/logic/server.go +++ b/logic/server.go @@ -137,7 +137,6 @@ func ServerJoin(networkSettings *models.Network, serverID string) error { // ServerCheckin - runs pulls and pushes for server func ServerCheckin(serverID string, mac string, network string) error { - cleanupLegacyServers(network) var serverNode = &models.Node{} var currentNode, err = GetNodeByIDorMacAddress(serverID, mac, network) if err != nil { From 62d06736ee5fa13a5890e90508f9dcf14525a2ac Mon Sep 17 00:00:00 2001 From: 0xdcarns Date: Wed, 12 Jan 2022 14:21:15 -0500 Subject: [PATCH 041/116] Cover a legacy case, allow server to run with uuids --- logic/nodes.go | 27 +++++++++++++++++++++++++++ logic/server.go | 8 +++++--- logic/util.go | 4 +++- models/node.go | 5 ++--- serverctl/serverctl.go | 9 +++++++-- 5 files changed, 44 insertions(+), 9 deletions(-) diff --git a/logic/nodes.go b/logic/nodes.go index 75e63036..6b35c4bc 100644 --- a/logic/nodes.go +++ b/logic/nodes.go @@ -5,12 +5,14 @@ import ( "errors" "fmt" "sort" + "strings" "time" "github.com/go-playground/validator/v10" "github.com/gravitl/netmaker/database" "github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/models" + "github.com/gravitl/netmaker/servercfg" "github.com/gravitl/netmaker/validation" ) @@ -431,3 +433,28 @@ func GetDeletedNodeByID(uuid string) (models.Node, error) { return node, nil } + +// GetNetworkServerNodeID - get network server node ID if exists +func GetNetworkServerNodeID(network string) (string, error) { + var nodes, err = GetNetworkNodes(network) + if err != nil { + return "", err + } + for _, node := range nodes { + if node.IsServer == "yes" { + if servercfg.GetNodeID() != "" { + if servercfg.GetNodeID() == node.MacAddress { + if strings.Contains(node.ID, "###") { + DeleteNodeByMacAddress(&node, true) + logger.Log(1, "deleted legacy server node on network "+node.Network) + return "", errors.New("deleted legacy server node on network " + node.Network) + } + return node.ID, nil + } + continue + } + return node.ID, nil + } + } + return "", errors.New("could not find server node") +} diff --git a/logic/server.go b/logic/server.go index 26512d0f..4dbe777e 100644 --- a/logic/server.go +++ b/logic/server.go @@ -31,19 +31,21 @@ func ServerJoin(networkSettings *models.Network, serverID string) error { if networkSettings == nil || networkSettings.NetID == "" { return errors.New("no network provided") } - + var privateKey = "" var err error + var node = &models.Node{ IsServer: "yes", DNSOn: "no", IsStatic: "yes", Name: models.NODE_SERVER_NAME, - MacAddress: serverID, - ID: serverID, + MacAddress: servercfg.GetNodeID(), + ID: "", // will be set to new uuid UDPHolePunch: "no", IsLocal: networkSettings.IsLocal, LocalRange: networkSettings.LocalRange, } + SetNodeDefaults(node) if servercfg.GetPlatform() == "Kubernetes" { diff --git a/logic/util.go b/logic/util.go index 173f1c89..fc383060 100644 --- a/logic/util.go +++ b/logic/util.go @@ -106,7 +106,9 @@ func CreateNode(node *models.Node) error { } // TODO: This covers legacy nodes, eventually want to remove legacy check - if (node.IsServer != "yes" && (node.ID == "" || strings.Contains(node.ID, "###"))) || (node.IsServer == "yes" && servercfg.GetNodeID() == "") { + if node.IsServer == "yes" { + node.ID = uuid.NewString() + } else if node.IsServer != "yes" || (node.ID == "" || strings.Contains(node.ID, "###")) { node.ID = uuid.NewString() } diff --git a/models/node.go b/models/node.go index 32808b5f..64a30de2 100644 --- a/models/node.go +++ b/models/node.go @@ -210,9 +210,8 @@ func (node *Node) SetDefaultName() { } func (newNode *Node) Fill(currentNode *Node) { - if newNode.ID == "" { - newNode.ID = currentNode.ID - } + newNode.ID = currentNode.ID + if newNode.Address == "" && newNode.IsStatic != "yes" { newNode.Address = currentNode.Address } diff --git a/serverctl/serverctl.go b/serverctl/serverctl.go index 837536c2..9db9a3e9 100644 --- a/serverctl/serverctl.go +++ b/serverctl/serverctl.go @@ -42,7 +42,7 @@ func FileExists(f string) bool { // RemoveNetwork - removes a network locally on server func RemoveNetwork(network string) (bool, error) { - err := logic.ServerLeave(servercfg.GetNodeID()) + err := logic.ServerLeave(network) return true, err } @@ -70,7 +70,12 @@ func HandleContainedClient() error { return err } for _, serverNet := range servernets { - err = logic.ServerCheckin(servercfg.GetNodeID(), servercfg.GetNodeID(), serverNet.NetID) + var serverID, err = logic.GetNetworkServerNodeID(serverNet.NetID) + if err != nil { + logger.Log(1, "error occurred during server checkin:", err.Error()) + continue + } + err = logic.ServerCheckin(serverID, servercfg.GetNodeID(), serverNet.NetID) if err != nil { logger.Log(1, "error occurred during server checkin:", err.Error()) } else { From a9cbd10ef5661e0460db5080791913c7bff3528f Mon Sep 17 00:00:00 2001 From: 0xdcarns Date: Thu, 13 Jan 2022 10:05:12 -0500 Subject: [PATCH 042/116] version update --- netclient/main.go | 2 +- servercfg/serverconf.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/netclient/main.go b/netclient/main.go index 0f364ccd..5ef2a95e 100644 --- a/netclient/main.go +++ b/netclient/main.go @@ -18,7 +18,7 @@ func main() { 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." - app.Version = "v0.9.4" + app.Version = "v0.10.0" cliFlags := cli_options.GetFlags(ncutils.GetHostname()) app.Commands = cli_options.GetCommands(cliFlags[:]) diff --git a/servercfg/serverconf.go b/servercfg/serverconf.go index 8c4daaf3..e203ddd4 100644 --- a/servercfg/serverconf.go +++ b/servercfg/serverconf.go @@ -113,7 +113,7 @@ func GetAPIConnString() string { // GetVersion - version of netmaker func GetVersion() string { - version := "0.9.4" + version := "0.10.0" if config.Config.Server.Version != "" { version = config.Config.Server.Version } From cec49627d03b314b12cb346226f2b460fe920a59 Mon Sep 17 00:00:00 2001 From: 0xdcarns Date: Fri, 14 Jan 2022 09:21:41 -0500 Subject: [PATCH 043/116] rebased --- logic/server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/logic/server.go b/logic/server.go index 4dbe777e..94eb016e 100644 --- a/logic/server.go +++ b/logic/server.go @@ -31,7 +31,7 @@ func ServerJoin(networkSettings *models.Network, serverID string) error { if networkSettings == nil || networkSettings.NetID == "" { return errors.New("no network provided") } - var privateKey = "" + var err error var node = &models.Node{ From 815cfb9ec9156582e2735321986c66deffdb36d2 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Fri, 14 Jan 2022 14:30:26 -0500 Subject: [PATCH 044/116] WIP commit to enable rebasing to uuid feature --- main.go | 30 +++--- models/mqtt.go | 7 +- mq/mq.go | 120 ++++++++++++------------ netclient/functions/daemon.go | 35 ++++++- netclient/functions/peers.go | 167 ++++++++++++++++++++++++++++++++++ 5 files changed, 276 insertions(+), 83 deletions(-) create mode 100644 netclient/functions/peers.go diff --git a/main.go b/main.go index 52243051..3d527a0b 100644 --- a/main.go +++ b/main.go @@ -9,7 +9,7 @@ import ( "runtime/debug" "strconv" "sync" - "time" + "syscall" mqtt "github.com/eclipse/paho.mqtt.golang" "github.com/gravitl/netmaker/auth" @@ -118,16 +118,16 @@ func startControllers() { logger.Log(0, "No Server Mode selected, so nothing is being served! Set Agent mode (AGENT_BACKEND) or Rest mode (REST_BACKEND) or MessageQueue (MESSAGEQUEUE_BACKEND) to 'true'.") } - if servercfg.IsClientMode() == "on" { - var checkintime = time.Duration(servercfg.GetServerCheckinInterval()) * time.Second - for { // best effort currently - var serverGroup sync.WaitGroup - serverGroup.Add(1) - go runClient(&serverGroup) - serverGroup.Wait() - time.Sleep(checkintime) - } - } + //if servercfg.IsClientMode() == "on" { + // var checkintime = time.Duration(servercfg.GetServerCheckinInterval()) * time.Second + // for { // best effort currently + // var serverGroup sync.WaitGroup + // serverGroup.Add(1) + // go runClient(&serverGroup) + // serverGroup.Wait() + // time.Sleep(checkintime) + // } + //} waitnetwork.Wait() } @@ -204,7 +204,7 @@ func runMessageQueue(wg *sync.WaitGroup) { logger.Log(0, "could not subscribe to message queue ...") return } - if token := client.Subscribe("ping/#", 0, mq.Ping); token.Wait() && token.Error() != nil { + if token := client.Subscribe("ping/#", 2, mq.Ping); token.Wait() && token.Error() != nil { client.Disconnect(240) logger.Log(0, "ping sub failed") } @@ -224,8 +224,10 @@ func runMessageQueue(wg *sync.WaitGroup) { client.Disconnect(240) logger.Log(0, "metrics sub failed") } - for { - } + quit := make(chan os.Signal, 1) + signal.Notify(quit, syscall.SIGTERM, os.Interrupt) + <-quit + logger.Log(0, "Message Queue shutting down") } func authServerUnaryInterceptor() grpc.ServerOption { diff --git a/models/mqtt.go b/models/mqtt.go index da7265f3..07bb2157 100644 --- a/models/mqtt.go +++ b/models/mqtt.go @@ -1,10 +1,9 @@ package models -import "golang.zx2c4.com/wireguard/wgctrl/wgtypes" - type PeerUpdate struct { - Network string - Peers []wgtypes.Peer + Network string + Nodes []Node + ExtPeers []ExtPeersResponse } type KeyUpdate struct { diff --git a/mq/mq.go b/mq/mq.go index 3620b215..fd9657a7 100644 --- a/mq/mq.go +++ b/mq/mq.go @@ -1,19 +1,15 @@ package mq import ( - "encoding/json" "errors" - "log" - "net" + "fmt" "strings" - "time" mqtt "github.com/eclipse/paho.mqtt.golang" "github.com/gravitl/netmaker/database" "github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/logic" "github.com/gravitl/netmaker/models" - "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) var DefaultHandler mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { @@ -22,20 +18,11 @@ var DefaultHandler mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Messa var Metrics mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { logger.Log(0, "Metrics Handler") + //TODOD -- handle metrics data ---- store to database? } var Ping mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { - logger.Log(0, "Ping Handler") - //test code --- create a node if it doesn't exit for testing only - createnode := models.Node{PublicKey: "DM5qhLAE20PG9BbfBCger+Ac9D2NDOwCtY1rbYDLf34=", Name: "testnode", - Endpoint: "10.0.0.1", MacAddress: "01:02:03:04:05:06", Password: "password", Network: "skynet"} - if _, err := logic.GetNode("01:02:03:04:05:06", "skynet"); err != nil { - err := logic.CreateNode(&createnode) - if err != nil { - log.Println(err) - } - } - //end of test code + logger.Log(0, "Ping Handler: "+msg.Topic()) go func() { mac, net, err := GetMacNetwork(msg.Topic()) if err != nil { @@ -56,6 +43,7 @@ var Ping mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { return } node.SetLastCheckIn() + logger.Log(0, "ping processed") // --TODO --set client version once feature is implemented. //node.SetClientVersion(msg.Payload()) }() @@ -76,7 +64,9 @@ var PublicKeyUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Mess } node.PublicKey = key node.SetLastCheckIn() - UpdatePeers(&node, client) + if err := UpdatePeers(client, node); err != nil { + logger.Log(0, "error updating peers "+err.Error()) + } }() } @@ -97,58 +87,63 @@ var IPUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { } node.Endpoint = ip node.SetLastCheckIn() - UpdatePeers(&node, client) + if err := UpdatePeers(client, node); err != nil { + logger.Log(0, "error updating peers "+err.Error()) + } }() } -func UpdatePeers(node *models.Node, client mqtt.Client) { - peersToUpdate, err := logic.GetPeers(node) - if err != nil { - logger.Log(0, "error retrieving peers") - return - } - for _, peerToUpdate := range peersToUpdate { - var peerUpdate models.PeerUpdate - peerUpdate.Network = node.Network +func UpdatePeers(client mqtt.Client, node models.Node) error { + var peerUpdate models.PeerUpdate + peerUpdate.Network = node.Network - myPeers, err := logic.GetPeers(&peerToUpdate) - if err != nil { - logger.Log(0, "uable to get peers "+err.Error()) + nodes, err := logic.GetNetworkNodes(node.Network) + if err != nil { + return fmt.Errorf("unable to get network nodes %v: ", err) + } + if token := client.Connect(); token.Wait() && token.Error() != nil { + return token.Error() + } + for _, peer := range nodes { + //don't need to update the initiatiing client + if peer.ID == node.ID { continue } - for i, myPeer := range myPeers { - var allowedIPs []net.IPNet - var allowedIP net.IPNet - endpoint, err := net.ResolveUDPAddr("udp", myPeer.Address+":"+string(myPeer.ListenPort)) - if err != nil { - logger.Log(0, "error setting endpoint for peer "+err.Error()) - } - for _, ipString := range myPeer.AllowedIPs { - _, ipNet, _ := net.ParseCIDR(ipString) - allowedIP = *ipNet - allowedIPs = append(allowedIPs, allowedIP) - } - key, err := wgtypes.ParseKey(myPeer.PublicKey) - if err != nil { - logger.Log(0, "err parsing publickey") - continue - } - peerUpdate.Peers[i].PublicKey = key - peerUpdate.Peers[i].Endpoint = endpoint - peerUpdate.Peers[i].PersistentKeepaliveInterval = time.Duration(myPeer.PersistentKeepalive) - peerUpdate.Peers[i].AllowedIPs = allowedIPs - peerUpdate.Peers[i].ProtocolVersion = 0 - } - //PublishPeerUpdate(my) - data, err := json.Marshal(peerUpdate) + peerUpdate.Nodes = append(peerUpdate.Nodes, peer) + peerUpdate.ExtPeers, err = logic.GetExtPeersList(node.MacAddress, node.Network) if err != nil { - logger.Log(0, "err marshalling data for peer update "+err.Error()) + logger.Log(0) } - if token := client.Publish("update/peers/"+peerToUpdate.ID, 0, false, data); token.Wait() && token.Error() != nil { - logger.Log(0, "error publishing peer update "+token.Error().Error()) + if token := client.Publish("update/peers/"+peer.ID, 0, false, nodes); token.Wait() && token.Error() != nil { + logger.Log(0, "error publishing peer update "+peer.ID+" "+token.Error().Error()) } - client.Disconnect(250) } + + return nil +} + +func UpdateLocalPeers(client mqtt.Client, node models.Node) error { + nodes, err := logic.GetNetworkNodes(node.Network) + if err != nil { + return fmt.Errorf("unable to get network nodes %v: ", err) + } + if token := client.Connect(); token.Wait() && token.Error() != nil { + return token.Error() + } + for _, peer := range nodes { + //don't need to update the initiatiing client + if peer.ID == node.ID { + continue + } + //if peer.Endpoint is on same lan as node.LocalAddress + //if TODO{ + //continue + //} + if token := client.Publish("update/peers/"+peer.ID, 0, false, nodes); token.Wait() && token.Error() != nil { + logger.Log(0, "error publishing peer update "+peer.ID+" "+token.Error().Error()) + } + } + return nil } var LocalAddressUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { @@ -167,6 +162,9 @@ var LocalAddressUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.M } node.LocalAddress = string(msg.Payload()) node.SetLastCheckIn() + if err := UpdateLocalPeers(client, node); err != nil { + logger.Log(0, "error updating peers "+err.Error()) + } }() } @@ -176,7 +174,7 @@ func GetMacNetwork(topic string) (string, string, error) { if count == 1 { return "", "", errors.New("invalid topic") } - macnet := strings.Split(parts[count-1], "---") + macnet := strings.Split(parts[count-1], "-") if len(macnet) != 2 { return "", "", errors.New("topic id not in mac---network format") } @@ -189,7 +187,7 @@ func GetID(topic string) (string, error) { if count == 1 { return "", errors.New("invalid topic") } - macnet := strings.Split(parts[count-1], "---") + macnet := strings.Split(parts[count-1], "-") if len(macnet) != 2 { return "", errors.New("topic id not in mac---network format") } diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index a5360319..6e212c77 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -154,9 +154,19 @@ var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) var cfg config.ClientConfig cfg.Network = peerUpdate.Network cfg.ReadConfig() - err = wireguard.UpdateWgPeers(cfg.Node.Interface, peerUpdate.Peers) + peers, err := CalculatePeers(cfg.Node, peerUpdate.Nodes, cfg.Node.IsDualStack, cfg.Node.IsEgressGateway, cfg.Node.IsServer) if err != nil { - ncutils.Log("error updating peers" + err.Error()) + ncutils.Log("error calculating Peers " + err.Error()) + return + } + extpeers, err := CalculateExtPeers(cfg.Node, peerUpdate.ExtPeers) + if err != nil { + ncutils.Log("error updated external wireguard peers " + err.Error()) + } + peers = append(peers, extpeers...) + err = wireguard.UpdateWgPeers(cfg.Node.Interface, peers) + if err != nil { + ncutils.Log("error updating wireguard peers" + err.Error()) return } // path hardcoded for now... should be updated @@ -187,7 +197,9 @@ func UpdateKeys(cfg *config.ClientConfig, client mqtt.Client) (*config.ClientCon client.Disconnect(250) return cfg, err } - client.Disconnect(250) + if err := config.ModConfig(&cfg.Node); err != nil { + ncutils.Log("error updating local config " + err.Error()) + } return cfg, nil } @@ -202,6 +214,11 @@ func Checkin(ctx context.Context, cfg config.ClientConfig, network string) { //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? case <-time.After(time.Second * 10): ncutils.Log("Checkin running") + //read latest config + cfg.ReadConfig() + //fix NodeID to remove ### so NodeID can be used as message topic + //remove with GRA-73 + cfg.Node.ID = strings.Replace(cfg.Node.ID, "###", "-", 1) if cfg.Node.Roaming == "yes" && cfg.Node.IsStatic != "yes" { extIP, err := ncutils.GetPublicIP() if err != nil { @@ -242,6 +259,10 @@ func UpdateEndpoint(cfg config.ClientConfig, network, ip string) { if token := client.Publish("update/ip/"+cfg.Node.ID, 0, false, ip); token.Wait() && token.Error() != nil { ncutils.Log("error publishing endpoint update " + token.Error().Error()) } + cfg.Node.Endpoint = ip + if err := config.Write(&cfg, cfg.Network); err != nil { + ncutils.Log("error updating local config " + err.Error()) + } client.Disconnect(250) } @@ -252,13 +273,19 @@ func UpdateLocalAddress(cfg config.ClientConfig, network, ip string) { if token := client.Publish("update/localaddress/"+cfg.Node.ID, 0, false, ip); token.Wait() && token.Error() != nil { ncutils.Log("error publishing local address update " + token.Error().Error()) } + cfg.Node.LocalAddress = ip + ncutils.Log("updating local address in local config to: " + cfg.Node.LocalAddress) + if err := config.Write(&cfg, cfg.Network); err != nil { + ncutils.Log("error updating local config " + err.Error()) + } client.Disconnect(250) } // Hello -- ping the broker to let server know node is alive and doing fine func Hello(cfg config.ClientConfig, network string) { client := SetupMQTT(cfg) - if token := client.Publish("ping/"+cfg.Node.ID, 0, false, "hello world!"); token.Wait() && token.Error() != nil { + ncutils.Log("sending ping " + cfg.Node.ID) + if token := client.Publish("ping/"+cfg.Node.ID, 2, false, "hello world!"); token.Wait() && token.Error() != nil { ncutils.Log("error publishing ping " + token.Error().Error()) } client.Disconnect(250) diff --git a/netclient/functions/peers.go b/netclient/functions/peers.go new file mode 100644 index 00000000..833ebc90 --- /dev/null +++ b/netclient/functions/peers.go @@ -0,0 +1,167 @@ +package functions + +import ( + "log" + "net" + "strconv" + "strings" + "time" + + "github.com/gravitl/netmaker/models" + "github.com/gravitl/netmaker/netclient/ncutils" + "golang.zx2c4.com/wireguard/wgctrl/wgtypes" +) + +func CalculatePeers(thisNode models.Node, peernodes []models.Node, dualstack, egressgateway, server string) ([]wgtypes.Peer, error) { + //hasGateway := false + var gateways []string + var peers []wgtypes.Peer + + keepalive := thisNode.PersistentKeepalive + keepalivedur, _ := time.ParseDuration(strconv.FormatInt(int64(keepalive), 10) + "s") + keepaliveserver, err := time.ParseDuration(strconv.FormatInt(int64(5), 10) + "s") + if err != nil { + log.Fatalf("Issue with format of keepalive value. Please update netconfig: %v", err) + } + for _, node := range peernodes { + pubkey, err := wgtypes.ParseKey(node.PublicKey) + if err != nil { + log.Println("error parsing key") + //return peers, hasGateway, gateways, err + } + + if thisNode.PublicKey == node.PublicKey { + continue + } + if thisNode.Endpoint == node.Endpoint { + if thisNode.LocalAddress != node.LocalAddress && node.LocalAddress != "" { + node.Endpoint = node.LocalAddress + } else { + continue + } + } + + var peer wgtypes.Peer + var peeraddr = net.IPNet{ + IP: net.ParseIP(node.Address), + Mask: net.CIDRMask(32, 32), + } + var allowedips []net.IPNet + allowedips = append(allowedips, peeraddr) + // handle manually set peers + for _, allowedIp := range node.AllowedIPs { + if _, ipnet, err := net.ParseCIDR(allowedIp); err == nil { + nodeEndpointArr := strings.Split(node.Endpoint, ":") + if !ipnet.Contains(net.IP(nodeEndpointArr[0])) && ipnet.IP.String() != node.Address { // don't need to add an allowed ip that already exists.. + allowedips = append(allowedips, *ipnet) + } + } else if appendip := net.ParseIP(allowedIp); appendip != nil && allowedIp != node.Address { + ipnet := net.IPNet{ + IP: net.ParseIP(allowedIp), + Mask: net.CIDRMask(32, 32), + } + allowedips = append(allowedips, ipnet) + } + } + // handle egress gateway peers + if node.IsEgressGateway == "yes" { + //hasGateway = true + ranges := node.EgressGatewayRanges + for _, iprange := range ranges { // go through each cidr for egress gateway + _, ipnet, err := net.ParseCIDR(iprange) // confirming it's valid cidr + if err != nil { + ncutils.PrintLog("could not parse gateway IP range. Not adding "+iprange, 1) + continue // if can't parse CIDR + } + nodeEndpointArr := strings.Split(node.Endpoint, ":") // getting the public ip of node + if ipnet.Contains(net.ParseIP(nodeEndpointArr[0])) { // ensuring egress gateway range does not contain public ip of node + ncutils.PrintLog("egress IP range of "+iprange+" overlaps with "+node.Endpoint+", omitting", 2) + continue // skip adding egress range if overlaps with node's ip + } + if ipnet.Contains(net.ParseIP(thisNode.LocalAddress)) { // ensuring egress gateway range does not contain public ip of node + ncutils.PrintLog("egress IP range of "+iprange+" overlaps with "+thisNode.LocalAddress+", omitting", 2) + continue // skip adding egress range if overlaps with node's local ip + } + gateways = append(gateways, iprange) + if err != nil { + log.Println("ERROR ENCOUNTERED SETTING GATEWAY") + } else { + allowedips = append(allowedips, *ipnet) + } + } + } + if node.Address6 != "" && dualstack == "yes" { + var addr6 = net.IPNet{ + IP: net.ParseIP(node.Address6), + Mask: net.CIDRMask(128, 128), + } + allowedips = append(allowedips, addr6) + } + if thisNode.IsServer == "yes" && !(node.IsServer == "yes") { + peer = wgtypes.Peer{ + PublicKey: pubkey, + PersistentKeepaliveInterval: keepaliveserver, + AllowedIPs: allowedips, + } + } else if keepalive != 0 { + peer = wgtypes.Peer{ + PublicKey: pubkey, + PersistentKeepaliveInterval: keepalivedur, + Endpoint: &net.UDPAddr{ + IP: net.ParseIP(node.Endpoint), + Port: int(node.ListenPort), + }, + AllowedIPs: allowedips, + } + } else { + peer = wgtypes.Peer{ + PublicKey: pubkey, + Endpoint: &net.UDPAddr{ + IP: net.ParseIP(node.Endpoint), + Port: int(node.ListenPort), + }, + AllowedIPs: allowedips, + } + } + peers = append(peers, peer) + } + return peers, nil +} + +func CalculateExtPeers(thisNode models.Node, extPeers []models.ExtPeersResponse) ([]wgtypes.Peer, error) { + var peers []wgtypes.Peer + var err error + for _, extPeer := range extPeers { + pubkey, err := wgtypes.ParseKey(extPeer.PublicKey) + if err != nil { + log.Println("error parsing key") + return peers, err + } + + if thisNode.PublicKey == extPeer.PublicKey { + continue + } + + var peer wgtypes.Peer + var peeraddr = net.IPNet{ + IP: net.ParseIP(extPeer.Address), + Mask: net.CIDRMask(32, 32), + } + var allowedips []net.IPNet + allowedips = append(allowedips, peeraddr) + + if extPeer.Address6 != "" && thisNode.IsDualStack == "yes" { + var addr6 = net.IPNet{ + IP: net.ParseIP(extPeer.Address6), + Mask: net.CIDRMask(128, 128), + } + allowedips = append(allowedips, addr6) + } + peer = wgtypes.Peer{ + PublicKey: pubkey, + AllowedIPs: allowedips, + } + peers = append(peers, peer) + } + return peers, err +} From c2440b3f2e9940a304743111840c461e50552500 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Sat, 1 Jan 2022 15:30:39 +0000 Subject: [PATCH 045/116] update compose file and scripts to use mosquitto broker. Includes insecure config file for mosquitto --- compose/docker-compose.contained.yml | 11 +++++++++++ docker/mosquitto.conf | 10 ++++++++++ scripts/install-netmaker.sh | 3 +++ scripts/nm-quick.sh | 4 ++++ 4 files changed, 28 insertions(+) create mode 100644 docker/mosquitto.conf diff --git a/compose/docker-compose.contained.yml b/compose/docker-compose.contained.yml index 5d36e2c4..28e5e2d1 100644 --- a/compose/docker-compose.contained.yml +++ b/compose/docker-compose.contained.yml @@ -68,9 +68,20 @@ services: # - $PWD/site:/srv # you could also serve a static site in site folder - caddy_data:/data - caddy_conf:/config + mosquitto: + image: eclipse-mosquitto:2.0.14 + container_name: broker + restart: unless-stopped + network_mode: host + volumes: + - /root/mosquitto.conf:/mosquitto/config/mosquitto.conf + - mosquitto_data:/var/lib/mosquitto + - mosquitto_logs:/var/log/mosquitto/mosquitto.log volumes: caddy_data: {} caddy_conf: {} sqldata: {} dnsconfig: {} + mosquitto_data: {} + mosquitto_logs: {} diff --git a/docker/mosquitto.conf b/docker/mosquitto.conf new file mode 100644 index 00000000..20ab6597 --- /dev/null +++ b/docker/mosquitto.conf @@ -0,0 +1,10 @@ +persitance true +persistance_location /var/lib/mosquitto/ + +log_dest_file /var/log/mosquitto/mosquitto.log + +per_listener_settings true +listener 1883 +allow_anonymous true +bind_interface SERVER_PUBLIC_IP + diff --git a/scripts/install-netmaker.sh b/scripts/install-netmaker.sh index 52232d9a..547dca88 100644 --- a/scripts/install-netmaker.sh +++ b/scripts/install-netmaker.sh @@ -136,6 +136,9 @@ echo "Setting Caddyfile..." sed -i "s/NETMAKER_BASE_DOMAIN/$NETMAKER_BASE_DOMAIN/g" /root/Caddyfile sed -i "s/YOUR_EMAIL/$EMAIL/g" /root/Caddyfile +echo "Setting Broker..." +sed -i "s/SERVER_PBLIC_IP/$SERVER_PUBLIC_IP/g" /root/mosquitto.conf + echo "Setting docker-compose..." sed -i "s/NETMAKER_BASE_DOMAIN/$NETMAKER_BASE_DOMAIN/g" /root/docker-compose.yml diff --git a/scripts/nm-quick.sh b/scripts/nm-quick.sh index 6e253a09..ebe78b65 100755 --- a/scripts/nm-quick.sh +++ b/scripts/nm-quick.sh @@ -135,6 +135,10 @@ wget -q -O /root/Caddyfile https://raw.githubusercontent.com/gravitl/netmaker/ma sed -i "s/NETMAKER_BASE_DOMAIN/$NETMAKER_BASE_DOMAIN/g" /root/Caddyfile sed -i "s/YOUR_EMAIL/$EMAIL/g" /root/Caddyfile +echo "setting mosquitto.conf..." + +wget -q -O /root/mosquitto.conf https://raw.githubusercontent.com/gravil/netmaker/master/docker/mosquitto.conf +sed -i "s/SERVER_PUBLIC_IP/$SERVER_PUBLIC_IP/g" /root/mosquitto.conf echo "setting docker-compose..." From ce94ac8c97510018cb19fa4dbcaa99a40a186464 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Sat, 1 Jan 2022 15:43:55 +0000 Subject: [PATCH 046/116] fix typo --- docker/mosquitto.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/mosquitto.conf b/docker/mosquitto.conf index 20ab6597..3594af29 100644 --- a/docker/mosquitto.conf +++ b/docker/mosquitto.conf @@ -1,4 +1,4 @@ -persitance true +persistance true persistance_location /var/lib/mosquitto/ log_dest_file /var/log/mosquitto/mosquitto.log From 247ae57dcb5479d3b65cd8bf6a5d38b916b1efde Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Sat, 1 Jan 2022 18:22:06 +0000 Subject: [PATCH 047/116] update mosquitto broker conf and volume info --- compose/docker-compose.contained.yml | 4 ++-- docker/mosquitto.conf | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/compose/docker-compose.contained.yml b/compose/docker-compose.contained.yml index 28e5e2d1..f1b0002e 100644 --- a/compose/docker-compose.contained.yml +++ b/compose/docker-compose.contained.yml @@ -75,8 +75,8 @@ services: network_mode: host volumes: - /root/mosquitto.conf:/mosquitto/config/mosquitto.conf - - mosquitto_data:/var/lib/mosquitto - - mosquitto_logs:/var/log/mosquitto/mosquitto.log + - mosquitto_data:/mosquitto/data + - mosquitto_logs:/mosquitto/log volumes: caddy_data: {} caddy_conf: {} diff --git a/docker/mosquitto.conf b/docker/mosquitto.conf index 3594af29..85914bad 100644 --- a/docker/mosquitto.conf +++ b/docker/mosquitto.conf @@ -1,10 +1,11 @@ -persistance true -persistance_location /var/lib/mosquitto/ +persistence true +persistence file mosquitto.db +persistance_location mosquitto/data -log_dest_file /var/log/mosquitto/mosquitto.log +log_dest_file mosquitto/log/mosquitto.log per_listener_settings true listener 1883 allow_anonymous true -bind_interface SERVER_PUBLIC_IP +#bind_interface SERVER_PUBLIC_IP From 15bc9aae7d45924be3037d42372ca304fffca520 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Sat, 1 Jan 2022 15:30:39 +0000 Subject: [PATCH 048/116] update compose file and scripts to use mosquitto broker. Includes insecure config file for mosquitto --- docker/mosquitto.conf | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docker/mosquitto.conf b/docker/mosquitto.conf index 85914bad..8d0d9b1c 100644 --- a/docker/mosquitto.conf +++ b/docker/mosquitto.conf @@ -2,10 +2,9 @@ persistence true persistence file mosquitto.db persistance_location mosquitto/data -log_dest_file mosquitto/log/mosquitto.log + per_listener_settings true listener 1883 allow_anonymous true -#bind_interface SERVER_PUBLIC_IP From e986dfc1696671901496aa1c50fe3251f9bf0f7b Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Sat, 1 Jan 2022 15:43:55 +0000 Subject: [PATCH 049/116] fix typo --- docker/mosquitto.conf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docker/mosquitto.conf b/docker/mosquitto.conf index 8d0d9b1c..e77c6f41 100644 --- a/docker/mosquitto.conf +++ b/docker/mosquitto.conf @@ -2,6 +2,8 @@ persistence true persistence file mosquitto.db persistance_location mosquitto/data +persistance true +persistance_location /var/lib/mosquitto/ per_listener_settings true From 13d15ae0f81460c220f3f2cba8d88fa2898a84f3 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Sat, 1 Jan 2022 18:22:06 +0000 Subject: [PATCH 050/116] update mosquitto broker conf and volume info --- docker/mosquitto.conf | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docker/mosquitto.conf b/docker/mosquitto.conf index e77c6f41..23c53bc1 100644 --- a/docker/mosquitto.conf +++ b/docker/mosquitto.conf @@ -2,9 +2,8 @@ persistence true persistence file mosquitto.db persistance_location mosquitto/data -persistance true -persistance_location /var/lib/mosquitto/ +log_dest_file mosquitto/log/mosquitto.log per_listener_settings true listener 1883 From a8ccf8a7f0f5c7814c198fb81b3eaf46046dd2c9 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Sun, 2 Jan 2022 16:02:59 +0000 Subject: [PATCH 051/116] work in progress for message queue --- go.mod | 3 + go.sum | 11 ++ netclient/cli_options/cmds.go | 9 ++ netclient/command/commands.go | 5 + netclient/functions/daemon.go | 214 ++++++++++++++++++++++++++++++++++ 5 files changed, 242 insertions(+) create mode 100644 netclient/functions/daemon.go diff --git a/go.mod b/go.mod index 70f37dc5..dcc6b758 100644 --- a/go.mod +++ b/go.mod @@ -32,7 +32,9 @@ require ( cloud.google.com/go v0.34.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/eclipse/paho.mqtt.golang v1.3.5 // indirect github.com/felixge/httpsnoop v1.0.1 // indirect + github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534 // indirect github.com/go-playground/locales v0.14.0 // indirect github.com/go-playground/universal-translator v0.18.0 // indirect github.com/google/go-cmp v0.5.5 // indirect @@ -44,5 +46,6 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/russross/blackfriday/v2 v2.0.1 // indirect github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect + golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect google.golang.org/appengine v1.4.0 // indirect ) diff --git a/go.sum b/go.sum index 1843eb9d..dce93b9d 100644 --- a/go.sum +++ b/go.sum @@ -24,6 +24,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/eclipse/paho.mqtt.golang v1.3.5 h1:sWtmgNxYM9P2sP+xEItMozsR3w0cqZFlqnNN1bdl41Y= +github.com/eclipse/paho.mqtt.golang v1.3.5/go.mod h1:eTzb4gxwwyWpqBUHGQZ4ABAV7+Jgm1PklsYT/eo8Hcc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -34,6 +36,8 @@ github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8S github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534 h1:dhy9OQKGBh4zVXbjwbxxHjRxMJtLXj3zfgpBYQaR4Q4= +github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk= github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= @@ -76,6 +80,8 @@ github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -180,6 +186,7 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -187,6 +194,7 @@ golang.org/x/net v0.0.0-20201216054612-986b41b23924/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210504132125-bbd867fde50d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985 h1:4CSI6oo7cOjJKajidEljs9h+uP0rRZBPPPhcCbj5mw8= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -197,6 +205,8 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -218,6 +228,7 @@ golang.org/x/sys v0.0.0-20210123111255-9b0068b26619/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210216163648-f7da38b97c65/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210309040221-94ec62e08169/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210503173754-0981d6026fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/netclient/cli_options/cmds.go b/netclient/cli_options/cmds.go index a43a88c3..5f90c1a8 100644 --- a/netclient/cli_options/cmds.go +++ b/netclient/cli_options/cmds.go @@ -118,5 +118,14 @@ func GetCommands(cliFlags []cli.Flag) []*cli.Command { return err }, }, + { + Name: "daemon", + Usage: "run netclient as daemon", + Flags: cliFlags, + Action: func(c *cli.Context) error { + err := command.Daemon() + return err + }, + }, } } diff --git a/netclient/command/commands.go b/netclient/command/commands.go index 49e075a2..1aecdb4b 100644 --- a/netclient/command/commands.go +++ b/netclient/command/commands.go @@ -210,3 +210,8 @@ func Uninstall() error { ncutils.PrintLog("uninstalled netclient", 0) return err } + +func Daemon() error { + err := functions.Daemon() + return err +} diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go new file mode 100644 index 00000000..72c7998c --- /dev/null +++ b/netclient/functions/daemon.go @@ -0,0 +1,214 @@ +package functions + +import ( + "encoding/json" + "fmt" + "log" + "time" + + mqtt "github.com/eclipse/paho.mqtt.golang" + "github.com/go-ping/ping" + "github.com/gravitl/netmaker/netclient/config" + "github.com/gravitl/netmaker/netclient/ncutils" + "golang.zx2c4.com/wireguard/wgctrl" +) + +func Daemon() error { + networks, err := ncutils.GetSystemNetworks() + if err != nil { + return err + } + for _, network := range networks { + go Netclient(network) + } + for { + } + return nil +} + +func Netclient(network string) { + var cfg config.ClientConfig + cfg.Network = network + cfg.ReadConfig() + ncutils.Log("daemon started for network:" + network) + //setup MQTT + opts := mqtt.NewClientOptions() + ncutils.Log("setting broker to " + cfg.Server.CoreDNSAddr + ":1883") + opts.AddBroker(cfg.Server.CoreDNSAddr + ":1883") + opts.SetDefaultPublishHandler(All) + opts.SetClientID("netclient-mqttt") + client := mqtt.NewClient(opts) + if token := client.Connect(); token.Wait() && token.Error() != nil { + log.Fatal(token.Error()) + } + if token := client.Subscribe("#", 0, nil); token.Wait() && token.Error() != nil { + log.Fatal(token.Error()) + } + client.AddRoute("update/"+network+"/"+cfg.Node.MacAddress, NodeUpdate) + client.AddRoute("update/"+network+"/peers", UpdatePeers) + client.AddRoute("update/"+network+"/keys", UpdateKeys) + client.AddRoute("update/"+network+"/keys/"+cfg.Node.MacAddress, UpdateKeys) + defer client.Disconnect(250) + go Checkin(client, network) + //go Metrics(client, network) + //go Connectivity(client, network) + for { + } +} + +var All mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { + ncutils.Log("Topic: " + string(msg.Topic())) + ncutils.Log("Message: " + string(msg.Payload())) +} + +var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { + ncutils.Log("received message to update node " + string(msg.Payload())) +} + +var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { + ncutils.Log("received message to update peers " + string(msg.Payload())) +} + +var UpdateKeys mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { + ncutils.Log("received message to update keys " + string(msg.Payload())) +} + +func Checkin(client mqtt.Client, network string) { + var cfg config.ClientConfig + cfg.Network = network + cfg.ReadConfig() + for { + time.Sleep(time.Duration(cfg.Node.NetworkSettings.DefaultCheckInInterval) * time.Second) + ncutils.Log("Checkin running") + if cfg.Node.Roaming == "yes" && cfg.Node.IsStatic != "yes" { + extIP, err := ncutils.GetPublicIP() + if err != nil { + ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) + } + if cfg.Node.Endpoint != extIP && extIP != "" { + ncutils.PrintLog("endpoint has changed from "+cfg.Node.Endpoint+" to "+extIP, 1) + UpdateEndpoint(client, network, extIP) + } + intIP, err := getPrivateAddr() + if err != nil { + ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) + } + if cfg.Node.LocalAddress != intIP && intIP != "" { + ncutils.PrintLog("local Address has changed from "+cfg.Node.LocalAddress+" to "+intIP, 1) + UpdateLocalAddress(client, network, intIP) + } + } else { + localIP, err := ncutils.GetLocalIP(cfg.Node.LocalRange) + if err != nil { + ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) + } + if cfg.Node.Endpoint != localIP && localIP != "" { + ncutils.PrintLog("endpoint has changed from "+cfg.Node.Endpoint+" to "+localIP, 1) + UpdateEndpoint(client, network, localIP) + } + } + Ping(client, network) + } +} + +func Ping(client mqtt.Client, network string) { + var cfg config.ClientConfig + cfg.Network = network + cfg.ReadConfig() + if token := client.Publish("ping/"+network+"/"+cfg.Node.ID, 0, false, []byte("ping")); token.Wait() && token.Error() != nil { + ncutils.Log("error publishing ping " + token.Error().Error()) + } +} + +func Metrics(client mqtt.Client, network string) { + if token := client.Connect(); token.Wait() && token.Error() != nil { + log.Fatal(token.Error()) + } + var cfg config.ClientConfig + cfg.Network = network + cfg.ReadConfig() + for { + time.Sleep(time.Second * 60) + ncutils.Log("Metrics running") + wg, err := wgctrl.New() + if err != nil { + ncutils.Log("error getting devices " + err.Error()) + break + } + device, err := wg.Device(cfg.Node.Interface) + if err != nil { + ncutils.Log("error readind wg device " + err.Error()) + break + } + bytes, err := json.Marshal(device.Peers) + if err != nil { + ncutils.Log("error marshaling peers " + err.Error()) + break + } + if token := client.Publish("metrics/"+network+"/"+cfg.Node.ID, 1, false, bytes); token.Wait() && token.Error() != nil { + ncutils.Log("error publishing metrics " + token.Error().Error()) + break + } + wg.Close() + } +} + +type PingStat struct { + Name string + Reachable bool +} + +func Connectivity(client mqtt.Client, network string) { + if token := client.Connect(); token.Wait() && token.Error() != nil { + log.Fatal(token.Error()) + } + var cfg config.ClientConfig + cfg.Network = network + cfg.ReadConfig() + for { + time.Sleep(time.Duration(cfg.NetworkSettings.DefaultCheckInInterval) * time.Second) + ncutils.Log("Connectivity running") + var pingStats []PingStat + peers, err := ncutils.GetPeers(cfg.Node.Interface) + if err != nil { + ncutils.Log("error retriving peers " + err.Error()) + break + } + for _, peer := range peers { + var pingStat PingStat + pingStat.Name = peer.PublicKey.String() + pingStat.Reachable = true + ip := peer.Endpoint.IP.String() + fmt.Println("----------", peer.Endpoint.IP, ip) + pinger, err := ping.NewPinger(ip) + if err != nil { + ncutils.Log("error creating pinger " + err.Error()) + break + } + pinger.Timeout = 2 * time.Second + pinger.Run() + stats := pinger.Statistics() + if stats.PacketLoss == 100 { + pingStat.Reachable = false + } + pingStats = append(pingStats, pingStat) + } + bytes, err := json.Marshal(pingStats) + if err != nil { + ncutils.Log("error marshaling stats" + err.Error()) + break + } + if token := client.Publish("connectivity/"+network+"/"+cfg.Node.ID, 1, false, bytes); token.Wait() && token.Error() != nil { + ncutils.Log("error publishing ping stats " + token.Error().Error()) + break + } + } +} + +func UpdateEndpoint(client mqtt.Client, network, ip string) { + ncutils.Log("Updating endpoint") +} + +func UpdateLocalAddress(client mqtt.Client, network, ip string) { + ncutils.Log("Updating local address") +} From 1402c350ae348cb235a6e0f1caf7d65d52ddaf2d Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Mon, 3 Jan 2022 15:22:26 -0500 Subject: [PATCH 052/116] Replaced ### with - in Node.ID (local copy) to fix mqtt publishing errors added context to all go routines removed connectivity function --- netclient/functions/daemon.go | 191 ++++++++++++++++------------------ 1 file changed, 87 insertions(+), 104 deletions(-) diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index 72c7998c..2e31d37a 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -1,18 +1,22 @@ package functions import ( + "context" "encoding/json" - "fmt" "log" + "os" + "os/signal" + "strings" + "syscall" "time" mqtt "github.com/eclipse/paho.mqtt.golang" - "github.com/go-ping/ping" "github.com/gravitl/netmaker/netclient/config" "github.com/gravitl/netmaker/netclient/ncutils" "golang.zx2c4.com/wireguard/wgctrl" ) +//Daemon runs netclient daemon from command line func Daemon() error { networks, err := ncutils.GetSystemNetworks() if err != nil { @@ -26,59 +30,75 @@ func Daemon() error { return nil } -func Netclient(network string) { - var cfg config.ClientConfig - cfg.Network = network - cfg.ReadConfig() - ncutils.Log("daemon started for network:" + network) - //setup MQTT +//SetupMQTT creates a connection to broker and return client +func SetupMQTT(cfg config.ClientConfig) mqtt.Client { opts := mqtt.NewClientOptions() ncutils.Log("setting broker to " + cfg.Server.CoreDNSAddr + ":1883") opts.AddBroker(cfg.Server.CoreDNSAddr + ":1883") opts.SetDefaultPublishHandler(All) - opts.SetClientID("netclient-mqttt") client := mqtt.NewClient(opts) if token := client.Connect(); token.Wait() && token.Error() != nil { log.Fatal(token.Error()) } + return client +} + +//Netclient sets up Message Queue and subsribes/publishes updates to/from server +func Netclient(network string) { + ctx, cancel := context.WithCancel(context.Background()) + var cfg config.ClientConfig + cfg.Network = network + cfg.ReadConfig() + //fix NodeID to remove ### so NodeID can be used as message topic + //remove with GRA-73 + cfg.Node.ID = strings.ReplaceAll(cfg.Node.ID, "###", "-") + ncutils.Log("daemon started for network:" + network) + client := SetupMQTT(cfg) if token := client.Subscribe("#", 0, nil); token.Wait() && token.Error() != nil { log.Fatal(token.Error()) } - client.AddRoute("update/"+network+"/"+cfg.Node.MacAddress, NodeUpdate) - client.AddRoute("update/"+network+"/peers", UpdatePeers) - client.AddRoute("update/"+network+"/keys", UpdateKeys) - client.AddRoute("update/"+network+"/keys/"+cfg.Node.MacAddress, UpdateKeys) + client.AddRoute("update/"+cfg.Node.ID, NodeUpdate) + client.AddRoute("update/peers/"+cfg.Node.ID, UpdatePeers) + client.AddRoute("update/keys/"+cfg.Node.ID, UpdateKeys) defer client.Disconnect(250) - go Checkin(client, network) - //go Metrics(client, network) - //go Connectivity(client, network) - for { - } + go Checkin(ctx, cfg, network) + go Metrics(ctx, cfg, network) + quit := make(chan os.Signal, 1) + signal.Notify(quit, syscall.SIGTERM, os.Interrupt) + <-quit + cancel() } +//All -- mqtt message hander for all ('#') topics var All mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("Topic: " + string(msg.Topic())) ncutils.Log("Message: " + string(msg.Payload())) } +//NodeUpdate -- mqtt message handler for /update/ topic var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update node " + string(msg.Payload())) } +//NodeUpdate -- mqtt message handler for /update/peers/ topic var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update peers " + string(msg.Payload())) } +//NodeUpdate -- mqtt message handler for /update/keys/ topic var UpdateKeys mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update keys " + string(msg.Payload())) } -func Checkin(client mqtt.Client, network string) { - var cfg config.ClientConfig - cfg.Network = network - cfg.ReadConfig() - for { - time.Sleep(time.Duration(cfg.Node.NetworkSettings.DefaultCheckInInterval) * time.Second) +//Checkin -- go routine that checks for public or local ip changes, publishes changes +// if there are no updates, simply "pings" the server as a checkin +func Checkin(ctx context.Context, cfg config.ClientConfig, network string) { + select { + case <-ctx.Done(): + ncutils.Log("Checkin cancelled") + return + //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? + case <-time.After(time.Second * 10): ncutils.Log("Checkin running") if cfg.Node.Roaming == "yes" && cfg.Node.IsStatic != "yes" { extIP, err := ncutils.GetPublicIP() @@ -87,7 +107,7 @@ func Checkin(client mqtt.Client, network string) { } if cfg.Node.Endpoint != extIP && extIP != "" { ncutils.PrintLog("endpoint has changed from "+cfg.Node.Endpoint+" to "+extIP, 1) - UpdateEndpoint(client, network, extIP) + UpdateEndpoint(cfg, network, extIP) } intIP, err := getPrivateAddr() if err != nil { @@ -95,7 +115,7 @@ func Checkin(client mqtt.Client, network string) { } if cfg.Node.LocalAddress != intIP && intIP != "" { ncutils.PrintLog("local Address has changed from "+cfg.Node.LocalAddress+" to "+intIP, 1) - UpdateLocalAddress(client, network, intIP) + UpdateLocalAddress(cfg, network, intIP) } } else { localIP, err := ncutils.GetLocalIP(cfg.Node.LocalRange) @@ -104,31 +124,52 @@ func Checkin(client mqtt.Client, network string) { } if cfg.Node.Endpoint != localIP && localIP != "" { ncutils.PrintLog("endpoint has changed from "+cfg.Node.Endpoint+" to "+localIP, 1) - UpdateEndpoint(client, network, localIP) + UpdateEndpoint(cfg, network, localIP) } } - Ping(client, network) + Hello(cfg, network) + ncutils.Log("Checkin complete") } } -func Ping(client mqtt.Client, network string) { - var cfg config.ClientConfig - cfg.Network = network - cfg.ReadConfig() - if token := client.Publish("ping/"+network+"/"+cfg.Node.ID, 0, false, []byte("ping")); token.Wait() && token.Error() != nil { +//UpdateEndpoint -- publishes an endpoint update to broker +func UpdateEndpoint(cfg config.ClientConfig, network, ip string) { + ncutils.Log("Updating endpoint") + client := SetupMQTT(cfg) + if token := client.Publish("update/ip/"+cfg.Node.ID, 0, false, ip); token.Wait() && token.Error() != nil { + ncutils.Log("error publishing endpoint update " + token.Error().Error()) + } + client.Disconnect(250) +} + +//UpdateLocalAddress -- publishes a local address update to broker +func UpdateLocalAddress(cfg config.ClientConfig, network, ip string) { + ncutils.Log("Updating local address") + client := SetupMQTT(cfg) + if token := client.Publish("update/localaddress/"+cfg.Node.ID, 0, false, ip); token.Wait() && token.Error() != nil { + ncutils.Log("error publishing local address update " + token.Error().Error()) + } + client.Disconnect(250) +} + +//Hello -- ping the broker to let server know node is alive and doing fine +func Hello(cfg config.ClientConfig, network string) { + client := SetupMQTT(cfg) + if token := client.Publish("ping/"+network+"/"+cfg.Node.ID, 0, false, "hello world!"); token.Wait() && token.Error() != nil { ncutils.Log("error publishing ping " + token.Error().Error()) } + client.Disconnect(250) } -func Metrics(client mqtt.Client, network string) { - if token := client.Connect(); token.Wait() && token.Error() != nil { - log.Fatal(token.Error()) - } - var cfg config.ClientConfig - cfg.Network = network - cfg.ReadConfig() - for { - time.Sleep(time.Second * 60) +//Metics -- go routine that collects wireguard metrics and publishes to broker +func Metrics(ctx context.Context, cfg config.ClientConfig, network string) { + select { + case <-ctx.Done(): + ncutils.Log("Metrics collection cancelled") + return + //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? + case <-time.After(time.Second * 60): + ncutils.Log("Metrics collection running") ncutils.Log("Metrics running") wg, err := wgctrl.New() if err != nil { @@ -145,70 +186,12 @@ func Metrics(client mqtt.Client, network string) { ncutils.Log("error marshaling peers " + err.Error()) break } - if token := client.Publish("metrics/"+network+"/"+cfg.Node.ID, 1, false, bytes); token.Wait() && token.Error() != nil { + client := SetupMQTT(cfg) + if token := client.Publish("metrics/"+cfg.Node.ID, 1, false, bytes); token.Wait() && token.Error() != nil { ncutils.Log("error publishing metrics " + token.Error().Error()) - break } wg.Close() + client.Disconnect(250) + ncutils.Log("metrics collection complete") } } - -type PingStat struct { - Name string - Reachable bool -} - -func Connectivity(client mqtt.Client, network string) { - if token := client.Connect(); token.Wait() && token.Error() != nil { - log.Fatal(token.Error()) - } - var cfg config.ClientConfig - cfg.Network = network - cfg.ReadConfig() - for { - time.Sleep(time.Duration(cfg.NetworkSettings.DefaultCheckInInterval) * time.Second) - ncutils.Log("Connectivity running") - var pingStats []PingStat - peers, err := ncutils.GetPeers(cfg.Node.Interface) - if err != nil { - ncutils.Log("error retriving peers " + err.Error()) - break - } - for _, peer := range peers { - var pingStat PingStat - pingStat.Name = peer.PublicKey.String() - pingStat.Reachable = true - ip := peer.Endpoint.IP.String() - fmt.Println("----------", peer.Endpoint.IP, ip) - pinger, err := ping.NewPinger(ip) - if err != nil { - ncutils.Log("error creating pinger " + err.Error()) - break - } - pinger.Timeout = 2 * time.Second - pinger.Run() - stats := pinger.Statistics() - if stats.PacketLoss == 100 { - pingStat.Reachable = false - } - pingStats = append(pingStats, pingStat) - } - bytes, err := json.Marshal(pingStats) - if err != nil { - ncutils.Log("error marshaling stats" + err.Error()) - break - } - if token := client.Publish("connectivity/"+network+"/"+cfg.Node.ID, 1, false, bytes); token.Wait() && token.Error() != nil { - ncutils.Log("error publishing ping stats " + token.Error().Error()) - break - } - } -} - -func UpdateEndpoint(client mqtt.Client, network, ip string) { - ncutils.Log("Updating endpoint") -} - -func UpdateLocalAddress(client mqtt.Client, network, ip string) { - ncutils.Log("Updating local address") -} From 368746cc20427cebbea2642a4b12f27d8b22e8ec Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Mon, 3 Jan 2022 16:26:40 -0500 Subject: [PATCH 053/116] move context up a level --- netclient/functions/daemon.go | 58 +++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index 2e31d37a..43dae42f 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -18,15 +18,18 @@ import ( //Daemon runs netclient daemon from command line func Daemon() error { + ctx, cancel := context.WithCancel(context.Background()) networks, err := ncutils.GetSystemNetworks() if err != nil { return err } for _, network := range networks { - go Netclient(network) - } - for { + go Netclient(ctx, network) } + quit := make(chan os.Signal, 1) + signal.Notify(quit, syscall.SIGTERM, os.Interrupt) + <-quit + cancel() return nil } @@ -44,29 +47,30 @@ func SetupMQTT(cfg config.ClientConfig) mqtt.Client { } //Netclient sets up Message Queue and subsribes/publishes updates to/from server -func Netclient(network string) { - ctx, cancel := context.WithCancel(context.Background()) - var cfg config.ClientConfig - cfg.Network = network - cfg.ReadConfig() - //fix NodeID to remove ### so NodeID can be used as message topic - //remove with GRA-73 - cfg.Node.ID = strings.ReplaceAll(cfg.Node.ID, "###", "-") - ncutils.Log("daemon started for network:" + network) - client := SetupMQTT(cfg) - if token := client.Subscribe("#", 0, nil); token.Wait() && token.Error() != nil { - log.Fatal(token.Error()) +func Netclient(ctx context.Context, network string) { + select { + case <-ctx.Done(): + ncutils.Log("shutting down daemon") + return + default: + var cfg config.ClientConfig + cfg.Network = network + cfg.ReadConfig() + //fix NodeID to remove ### so NodeID can be used as message topic + //remove with GRA-73 + cfg.Node.ID = strings.ReplaceAll(cfg.Node.ID, "###", "-") + ncutils.Log("daemon started for network:" + network) + client := SetupMQTT(cfg) + if token := client.Subscribe("#", 0, nil); token.Wait() && token.Error() != nil { + log.Fatal(token.Error()) + } + client.AddRoute("update/"+cfg.Node.ID, NodeUpdate) + client.AddRoute("update/peers/"+cfg.Node.ID, UpdatePeers) + client.AddRoute("update/keys/"+cfg.Node.ID, UpdateKeys) + defer client.Disconnect(250) + go Checkin(ctx, cfg, network) + go Metrics(ctx, cfg, network) } - client.AddRoute("update/"+cfg.Node.ID, NodeUpdate) - client.AddRoute("update/peers/"+cfg.Node.ID, UpdatePeers) - client.AddRoute("update/keys/"+cfg.Node.ID, UpdateKeys) - defer client.Disconnect(250) - go Checkin(ctx, cfg, network) - go Metrics(ctx, cfg, network) - quit := make(chan os.Signal, 1) - signal.Notify(quit, syscall.SIGTERM, os.Interrupt) - <-quit - cancel() } //All -- mqtt message hander for all ('#') topics @@ -80,12 +84,12 @@ var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) ncutils.Log("received message to update node " + string(msg.Payload())) } -//NodeUpdate -- mqtt message handler for /update/peers/ topic +//UpdatePeers -- mqtt message handler for /update/peers/ topic var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update peers " + string(msg.Payload())) } -//NodeUpdate -- mqtt message handler for /update/keys/ topic +//UpdateKeys -- mqtt message handler for /update/keys/ topic var UpdateKeys mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update keys " + string(msg.Payload())) } From fbb76657d9245bff8df581a5690e9f6abb6f4e22 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Mon, 3 Jan 2022 22:21:52 +0000 Subject: [PATCH 054/116] go routines now run forever like they are supposed to --- netclient/functions/daemon.go | 176 +++++++++++++++++----------------- 1 file changed, 90 insertions(+), 86 deletions(-) diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index 43dae42f..e48e8c19 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -30,6 +30,7 @@ func Daemon() error { signal.Notify(quit, syscall.SIGTERM, os.Interrupt) <-quit cancel() + ncutils.Log("all done") return nil } @@ -48,29 +49,28 @@ func SetupMQTT(cfg config.ClientConfig) mqtt.Client { //Netclient sets up Message Queue and subsribes/publishes updates to/from server func Netclient(ctx context.Context, network string) { - select { - case <-ctx.Done(): - ncutils.Log("shutting down daemon") - return - default: - var cfg config.ClientConfig - cfg.Network = network - cfg.ReadConfig() - //fix NodeID to remove ### so NodeID can be used as message topic - //remove with GRA-73 - cfg.Node.ID = strings.ReplaceAll(cfg.Node.ID, "###", "-") - ncutils.Log("daemon started for network:" + network) - client := SetupMQTT(cfg) - if token := client.Subscribe("#", 0, nil); token.Wait() && token.Error() != nil { - log.Fatal(token.Error()) - } - client.AddRoute("update/"+cfg.Node.ID, NodeUpdate) - client.AddRoute("update/peers/"+cfg.Node.ID, UpdatePeers) - client.AddRoute("update/keys/"+cfg.Node.ID, UpdateKeys) - defer client.Disconnect(250) - go Checkin(ctx, cfg, network) - go Metrics(ctx, cfg, network) + ncutils.Log("netclient go routine started for " + network) + var cfg config.ClientConfig + cfg.Network = network + cfg.ReadConfig() + //fix NodeID to remove ### so NodeID can be used as message topic + //remove with GRA-73 + cfg.Node.ID = strings.ReplaceAll(cfg.Node.ID, "###", "-") + ncutils.Log("daemon started for network:" + network) + client := SetupMQTT(cfg) + if token := client.Subscribe("#", 0, nil); token.Wait() && token.Error() != nil { + log.Fatal(token.Error()) } + client.AddRoute("update/"+cfg.Node.ID, NodeUpdate) + client.AddRoute("update/peers/"+cfg.Node.ID, UpdatePeers) + client.AddRoute("update/keys/"+cfg.Node.ID, UpdateKeys) + defer client.Disconnect(250) + go Checkin(ctx, cfg, network) + go Metrics(ctx, cfg, network) + <-ctx.Done() + ncutils.Log("shutting down daemon") + return + ncutils.Log("netclient go routine ended for " + network) } //All -- mqtt message hander for all ('#') topics @@ -97,42 +97,44 @@ var UpdateKeys mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) //Checkin -- go routine that checks for public or local ip changes, publishes changes // if there are no updates, simply "pings" the server as a checkin func Checkin(ctx context.Context, cfg config.ClientConfig, network string) { - select { - case <-ctx.Done(): - ncutils.Log("Checkin cancelled") - return - //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? - case <-time.After(time.Second * 10): - ncutils.Log("Checkin running") - if cfg.Node.Roaming == "yes" && cfg.Node.IsStatic != "yes" { - extIP, err := ncutils.GetPublicIP() - if err != nil { - ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) - } - if cfg.Node.Endpoint != extIP && extIP != "" { - ncutils.PrintLog("endpoint has changed from "+cfg.Node.Endpoint+" to "+extIP, 1) - UpdateEndpoint(cfg, network, extIP) - } - intIP, err := getPrivateAddr() - if err != nil { - ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) - } - if cfg.Node.LocalAddress != intIP && intIP != "" { - ncutils.PrintLog("local Address has changed from "+cfg.Node.LocalAddress+" to "+intIP, 1) - UpdateLocalAddress(cfg, network, intIP) - } - } else { - localIP, err := ncutils.GetLocalIP(cfg.Node.LocalRange) - if err != nil { - ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) - } - if cfg.Node.Endpoint != localIP && localIP != "" { - ncutils.PrintLog("endpoint has changed from "+cfg.Node.Endpoint+" to "+localIP, 1) - UpdateEndpoint(cfg, network, localIP) + for { + select { + case <-ctx.Done(): + ncutils.Log("Checkin cancelled") + return + //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? + case <-time.After(time.Second * 10): + ncutils.Log("Checkin running") + if cfg.Node.Roaming == "yes" && cfg.Node.IsStatic != "yes" { + extIP, err := ncutils.GetPublicIP() + if err != nil { + ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) + } + if cfg.Node.Endpoint != extIP && extIP != "" { + ncutils.PrintLog("endpoint has changed from "+cfg.Node.Endpoint+" to "+extIP, 1) + UpdateEndpoint(cfg, network, extIP) + } + intIP, err := getPrivateAddr() + if err != nil { + ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) + } + if cfg.Node.LocalAddress != intIP && intIP != "" { + ncutils.PrintLog("local Address has changed from "+cfg.Node.LocalAddress+" to "+intIP, 1) + UpdateLocalAddress(cfg, network, intIP) + } + } else { + localIP, err := ncutils.GetLocalIP(cfg.Node.LocalRange) + if err != nil { + ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) + } + if cfg.Node.Endpoint != localIP && localIP != "" { + ncutils.PrintLog("endpoint has changed from "+cfg.Node.Endpoint+" to "+localIP, 1) + UpdateEndpoint(cfg, network, localIP) + } } + Hello(cfg, network) + ncutils.Log("Checkin complete") } - Hello(cfg, network) - ncutils.Log("Checkin complete") } } @@ -159,7 +161,7 @@ func UpdateLocalAddress(cfg config.ClientConfig, network, ip string) { //Hello -- ping the broker to let server know node is alive and doing fine func Hello(cfg config.ClientConfig, network string) { client := SetupMQTT(cfg) - if token := client.Publish("ping/"+network+"/"+cfg.Node.ID, 0, false, "hello world!"); token.Wait() && token.Error() != nil { + if token := client.Publish("ping/"+cfg.Node.ID, 0, false, "hello world!"); token.Wait() && token.Error() != nil { ncutils.Log("error publishing ping " + token.Error().Error()) } client.Disconnect(250) @@ -167,35 +169,37 @@ func Hello(cfg config.ClientConfig, network string) { //Metics -- go routine that collects wireguard metrics and publishes to broker func Metrics(ctx context.Context, cfg config.ClientConfig, network string) { - select { - case <-ctx.Done(): - ncutils.Log("Metrics collection cancelled") - return - //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? - case <-time.After(time.Second * 60): - ncutils.Log("Metrics collection running") - ncutils.Log("Metrics running") - wg, err := wgctrl.New() - if err != nil { - ncutils.Log("error getting devices " + err.Error()) - break + for { + select { + case <-ctx.Done(): + ncutils.Log("Metrics collection cancelled") + return + //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? + case <-time.After(time.Second * 60): + ncutils.Log("Metrics collection running") + ncutils.Log("Metrics running") + wg, err := wgctrl.New() + if err != nil { + ncutils.Log("error getting devices " + err.Error()) + break + } + device, err := wg.Device(cfg.Node.Interface) + if err != nil { + ncutils.Log("error readind wg device " + err.Error()) + break + } + bytes, err := json.Marshal(device.Peers) + if err != nil { + ncutils.Log("error marshaling peers " + err.Error()) + break + } + client := SetupMQTT(cfg) + if token := client.Publish("metrics/"+cfg.Node.ID, 1, false, bytes); token.Wait() && token.Error() != nil { + ncutils.Log("error publishing metrics " + token.Error().Error()) + } + wg.Close() + client.Disconnect(250) + ncutils.Log("metrics collection complete") } - device, err := wg.Device(cfg.Node.Interface) - if err != nil { - ncutils.Log("error readind wg device " + err.Error()) - break - } - bytes, err := json.Marshal(device.Peers) - if err != nil { - ncutils.Log("error marshaling peers " + err.Error()) - break - } - client := SetupMQTT(cfg) - if token := client.Publish("metrics/"+cfg.Node.ID, 1, false, bytes); token.Wait() && token.Error() != nil { - ncutils.Log("error publishing metrics " + token.Error().Error()) - } - wg.Close() - client.Disconnect(250) - ncutils.Log("metrics collection complete") } } From 842c4671da2e27f4c2d010650c38b20fe1e891ca Mon Sep 17 00:00:00 2001 From: 0xdcarns Date: Mon, 3 Jan 2022 18:27:13 -0500 Subject: [PATCH 055/116] linting fixes --- netclient/functions/daemon.go | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index e48e8c19..45a49d9b 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -16,11 +16,12 @@ import ( "golang.zx2c4.com/wireguard/wgctrl" ) -//Daemon runs netclient daemon from command line +// Daemon runs netclient daemon from command line func Daemon() error { ctx, cancel := context.WithCancel(context.Background()) networks, err := ncutils.GetSystemNetworks() if err != nil { + cancel() return err } for _, network := range networks { @@ -34,7 +35,7 @@ func Daemon() error { return nil } -//SetupMQTT creates a connection to broker and return client +// SetupMQTT creates a connection to broker and return client func SetupMQTT(cfg config.ClientConfig) mqtt.Client { opts := mqtt.NewClientOptions() ncutils.Log("setting broker to " + cfg.Server.CoreDNSAddr + ":1883") @@ -47,7 +48,7 @@ func SetupMQTT(cfg config.ClientConfig) mqtt.Client { return client } -//Netclient sets up Message Queue and subsribes/publishes updates to/from server +// Netclient sets up Message Queue and subsribes/publishes updates to/from server func Netclient(ctx context.Context, network string) { ncutils.Log("netclient go routine started for " + network) var cfg config.ClientConfig @@ -55,7 +56,7 @@ func Netclient(ctx context.Context, network string) { cfg.ReadConfig() //fix NodeID to remove ### so NodeID can be used as message topic //remove with GRA-73 - cfg.Node.ID = strings.ReplaceAll(cfg.Node.ID, "###", "-") + cfg.Node.ID = strings.Replace(cfg.Node.ID, "###", "-", 1) ncutils.Log("daemon started for network:" + network) client := SetupMQTT(cfg) if token := client.Subscribe("#", 0, nil); token.Wait() && token.Error() != nil { @@ -69,32 +70,30 @@ func Netclient(ctx context.Context, network string) { go Metrics(ctx, cfg, network) <-ctx.Done() ncutils.Log("shutting down daemon") - return - ncutils.Log("netclient go routine ended for " + network) } -//All -- mqtt message hander for all ('#') topics +// All -- mqtt message hander for all ('#') topics var All mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("Topic: " + string(msg.Topic())) ncutils.Log("Message: " + string(msg.Payload())) } -//NodeUpdate -- mqtt message handler for /update/ topic +// NodeUpdate -- mqtt message handler for /update/ topic var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update node " + string(msg.Payload())) } -//UpdatePeers -- mqtt message handler for /update/peers/ topic +// UpdatePeers -- mqtt message handler for /update/peers/ topic var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update peers " + string(msg.Payload())) } -//UpdateKeys -- mqtt message handler for /update/keys/ topic +// UpdateKeys -- mqtt message handler for /update/keys/ topic var UpdateKeys mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update keys " + string(msg.Payload())) } -//Checkin -- go routine that checks for public or local ip changes, publishes changes +// Checkin -- go routine that checks for public or local ip changes, publishes changes // if there are no updates, simply "pings" the server as a checkin func Checkin(ctx context.Context, cfg config.ClientConfig, network string) { for { @@ -138,7 +137,7 @@ func Checkin(ctx context.Context, cfg config.ClientConfig, network string) { } } -//UpdateEndpoint -- publishes an endpoint update to broker +// UpdateEndpoint -- publishes an endpoint update to broker func UpdateEndpoint(cfg config.ClientConfig, network, ip string) { ncutils.Log("Updating endpoint") client := SetupMQTT(cfg) @@ -148,7 +147,7 @@ func UpdateEndpoint(cfg config.ClientConfig, network, ip string) { client.Disconnect(250) } -//UpdateLocalAddress -- publishes a local address update to broker +// UpdateLocalAddress -- publishes a local address update to broker func UpdateLocalAddress(cfg config.ClientConfig, network, ip string) { ncutils.Log("Updating local address") client := SetupMQTT(cfg) @@ -158,7 +157,7 @@ func UpdateLocalAddress(cfg config.ClientConfig, network, ip string) { client.Disconnect(250) } -//Hello -- ping the broker to let server know node is alive and doing fine +// Hello -- ping the broker to let server know node is alive and doing fine func Hello(cfg config.ClientConfig, network string) { client := SetupMQTT(cfg) if token := client.Publish("ping/"+cfg.Node.ID, 0, false, "hello world!"); token.Wait() && token.Error() != nil { @@ -167,7 +166,7 @@ func Hello(cfg config.ClientConfig, network string) { client.Disconnect(250) } -//Metics -- go routine that collects wireguard metrics and publishes to broker +// Metics -- go routine that collects wireguard metrics and publishes to broker func Metrics(ctx context.Context, cfg config.ClientConfig, network string) { for { select { From bfd09a1f7535f73ac133cb3ba0d5cf421113c030 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Wed, 5 Jan 2022 10:05:51 -0500 Subject: [PATCH 056/116] subscribed message handlers implemented --- go.mod | 1 + go.sum | 2 + models/mqtt.go | 14 ++++ netclient/functions/daemon.go | 75 +++++++++++++++++++++ netclient/wireguard/common.go | 123 ++++++++++++++++++++++++++++++++++ 5 files changed, 215 insertions(+) create mode 100644 models/mqtt.go diff --git a/go.mod b/go.mod index dcc6b758..b8b169d9 100644 --- a/go.mod +++ b/go.mod @@ -48,4 +48,5 @@ require ( github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect google.golang.org/appengine v1.4.0 // indirect + gopkg.in/ini.v1 v1.66.2 // indirect ) diff --git a/go.sum b/go.sum index dce93b9d..84dbc91f 100644 --- a/go.sum +++ b/go.sum @@ -292,6 +292,8 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/ini.v1 v1.66.2 h1:XfR1dOYubytKy4Shzc2LHrrGhU0lDCfDGG1yLPmpgsI= +gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/models/mqtt.go b/models/mqtt.go new file mode 100644 index 00000000..a7e87e1f --- /dev/null +++ b/models/mqtt.go @@ -0,0 +1,14 @@ +package models + +import "golang.zx2c4.com/wireguard/wgctrl/wgtypes" + +type PeerUpdate struct { + Network string + Interface string + Peers []wgtypes.Peer +} + +type KeyUpdate struct { + Network string + Interface string +} diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index 45a49d9b..fc926bda 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -11,9 +11,12 @@ import ( "time" mqtt "github.com/eclipse/paho.mqtt.golang" + "github.com/gravitl/netmaker/models" "github.com/gravitl/netmaker/netclient/config" "github.com/gravitl/netmaker/netclient/ncutils" + "github.com/gravitl/netmaker/netclient/wireguard" "golang.zx2c4.com/wireguard/wgctrl" + "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) // Daemon runs netclient daemon from command line @@ -81,16 +84,88 @@ var All mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { // NodeUpdate -- mqtt message handler for /update/ topic var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update node " + string(msg.Payload())) + //potentiall blocking i/o so do this in a go routine + go func() { + var data models.Node + err := json.Unmarshal(msg.Payload(), &data) + if err != nil { + ncutils.Log("error unmarshalling node update data" + err.Error()) + return + } + var cfg config.ClientConfig + cfg.Network = data.Network + cfg.ReadConfig() + nameserver := cfg.Server.CoreDNSAddr + privateKey, err := wireguard.RetrievePrivKey(data.Network) + if err := wireguard.UpdateWgInterface(cfg.Node.Interface, privateKey, nameserver, data); err != nil { + ncutils.Log("error updating wireguard config " + err.Error()) + return + } + // path hardcoded for now... should be updated + err = wireguard.ApplyWGQuickConf("/etc/netclient/config/" + cfg.Node.Interface + ".conf") + if err != nil { + ncutils.Log("error restarting wg after peer update " + err.Error()) + return + } + }() } // UpdatePeers -- mqtt message handler for /update/peers/ topic var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update peers " + string(msg.Payload())) + //potentiall blocking i/o so do this in a go routine + go func() { + var peerUpdate models.PeerUpdate + err := json.Unmarshal(msg.Payload(), &peerUpdate) + if err != nil { + ncutils.Log("error unmarshalling peer data") + return + } + var cfg config.ClientConfig + cfg.Network = peerUpdate.Network + cfg.ReadConfig() + err = wireguard.UpdateWgPeers(cfg.Node.Interface, peerUpdate.Peers) + if err != nil { + ncutils.Log("error updating peers" + err.Error()) + return + } + // path hardcoded for now... should be updated + err = wireguard.ApplyWGQuickConf("/etc/netclient/config/" + cfg.Node.Interface + ".conf") + if err != nil { + ncutils.Log("error restarting wg after peer update " + err.Error()) + return + } + }() } // UpdateKeys -- mqtt message handler for /update/keys/ topic var UpdateKeys mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update keys " + string(msg.Payload())) + //potentiall blocking i/o so do this in a go routine + go func() { + var data models.KeyUpdate + if err := json.Unmarshal(msg.Payload(), &data); err != nil { + ncutils.Log("error unmarshalling key update data" + err.Error()) + return + } + var cfg config.ClientConfig + cfg.Network = data.Network + cfg.ReadConfig() + key, err := wgtypes.GeneratePrivateKey() + if err != nil { + ncutils.Log("error generating privatekey " + err.Error()) + return + } + if err := wireguard.UpdatePrivateKey(data.Interface, key.String()); err != nil { + ncutils.Log("error updating wireguard key " + err.Error()) + return + } + publicKey := key.PublicKey() + if token := client.Publish("update/publickey/"+cfg.Node.ID, 0, false, publicKey.String()); token.Wait() && token.Error() != nil { + ncutils.Log("error publishing publickey update " + token.Error().Error()) + } + client.Disconnect(250) + }() } // Checkin -- go routine that checks for public or local ip changes, publishes changes diff --git a/netclient/wireguard/common.go b/netclient/wireguard/common.go index e264cab6..b954dee6 100644 --- a/netclient/wireguard/common.go +++ b/netclient/wireguard/common.go @@ -16,6 +16,7 @@ import ( "github.com/gravitl/netmaker/netclient/server" "golang.zx2c4.com/wireguard/wgctrl" "golang.zx2c4.com/wireguard/wgctrl/wgtypes" + "gopkg.in/ini.v1" ) // SetPeers - sets peers on a given WireGuard interface @@ -280,3 +281,125 @@ func ApplyConf(confPath string) error { } return err } + +// WriteWgConfig - creates a wireguard config file +func WriteWgConfig(cfg config.ClientConfig, privateKey string, peers []wgtypes.Peer) error { + options := ini.LoadOptions{ + AllowNonUniqueSections: true, + AllowShadows: true, + } + wireguard := ini.Empty(options) + wireguard.Section("Interface").Key("PrivateKey").SetValue(privateKey) + wireguard.Section("Interface").Key("ListenPort").SetValue(strconv.Itoa(int(cfg.Node.ListenPort))) + if cfg.Node.Address != "" { + wireguard.Section("Interface").Key("Address").SetValue(cfg.Node.Address) + } + if cfg.Node.Address6 != "" { + wireguard.Section("Interface").Key("Address").SetValue(cfg.Node.Address6) + } + if cfg.Node.DNSOn == "yes" { + wireguard.Section("Interface").Key("DNS").SetValue(cfg.Server.CoreDNSAddr) + } + if cfg.Node.PostUp != "" { + wireguard.Section("Interface").Key("PostUp").SetValue(cfg.Node.PostUp) + } + if cfg.Node.PostDown != "" { + wireguard.Section("Interface").Key("PostDown").SetValue(cfg.Node.PostDown) + } + for i, peer := range peers { + wireguard.SectionWithIndex("Peer", i).Key("PublicKey").SetValue(peer.PublicKey.String()) + if peer.PresharedKey.String() != "" { + wireguard.SectionWithIndex("Peer", i).Key("PreSharedKey").SetValue(peer.PresharedKey.String()) + } + if peer.AllowedIPs != nil { + var allowedIPs string + for _, ip := range peer.AllowedIPs { + allowedIPs = allowedIPs + ", " + ip.String() + } + wireguard.SectionWithIndex("Peer", i).Key("AllowedIps").SetValue(allowedIPs) + } + if peer.Endpoint != nil { + wireguard.SectionWithIndex("Peer", i).Key("Endpoint").SetValue(peer.Endpoint.String()) + } + } + if err := wireguard.SaveTo("/etc/netclient/config" + cfg.Node.Interface + ".conf"); err != nil { + return err + } + return nil +} + +// UpdateWgPeers - updates the peers of a network +func UpdateWgPeers(wgInterface string, peers []wgtypes.Peer) error { + //update to get path properly + file := "/etc/netclient/config/" + wgInterface + ".conf" + wireguard, err := ini.ShadowLoad(file) + if err != nil { + return err + } + for i, peer := range peers { + wireguard.SectionWithIndex("Peer", i).Key("PublicKey").SetValue(peer.PublicKey.String()) + if peer.PresharedKey.String() != "" { + wireguard.SectionWithIndex("Peer", i).Key("PreSharedKey").SetValue(peer.PresharedKey.String()) + } + if peer.AllowedIPs != nil { + var allowedIPs string + for _, ip := range peer.AllowedIPs { + allowedIPs = allowedIPs + ", " + ip.String() + } + wireguard.SectionWithIndex("Peer", i).Key("AllowedIps").SetValue(allowedIPs) + } + if peer.Endpoint != nil { + wireguard.SectionWithIndex("Peer", i).Key("Endpoint").SetValue(peer.Endpoint.String()) + } + } + if err := wireguard.SaveTo(file); err != nil { + return err + } + return nil +} + +// UpdateWgInterface - updates the interface section of a wireguard config file +func UpdateWgInterface(wgInterface, privateKey, nameserver string, node models.Node) error { + //update to get path properly + file := "/etc/netclient/config/" + wgInterface + ".conf" + wireguard, err := ini.ShadowLoad(file) + if err != nil { + return err + } + wireguard.Section("Interface").Key("PrivateKey").SetValue(privateKey) + wireguard.Section("Interface").Key("ListenPort").SetValue(strconv.Itoa(int(node.ListenPort))) + if node.Address != "" { + wireguard.Section("Interface").Key("Address").SetValue(node.Address) + } + if node.Address6 != "" { + wireguard.Section("Interface").Key("Address").SetValue(node.Address6) + } + if node.DNSOn == "yes" { + wireguard.Section("Interface").Key("DNS").SetValue(nameserver) + } + if node.PostUp != "" { + wireguard.Section("Interface").Key("PostUp").SetValue(node.PostUp) + } + if node.PostDown != "" { + wireguard.Section("Interface").Key("PostDown").SetValue(node.PostDown) + } + if err := wireguard.SaveTo(file); err != nil { + return err + } + return nil +} + +// UpdatePrivateKey - updates the private key of a wireguard config file +func UpdatePrivateKey(wgInterface, privateKey string) error { + //update to get path properly + file := "/etc/netclient/config/" + wgInterface + ".conf" + wireguard, err := ini.ShadowLoad(file) + if err != nil { + return err + } + wireguard.Section("Interface").Key("PrivateKey").SetValue(privateKey) + if err := wireguard.SaveTo(file); err != nil { + return err + } + return nil +} From e26d70e78806a4099328e907c21f3579d8889fe9 Mon Sep 17 00:00:00 2001 From: 0xdcarns Date: Wed, 5 Jan 2022 10:32:20 -0500 Subject: [PATCH 057/116] constants --- netclient/wireguard/common.go | 59 +++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/netclient/wireguard/common.go b/netclient/wireguard/common.go index b954dee6..5fd70fc1 100644 --- a/netclient/wireguard/common.go +++ b/netclient/wireguard/common.go @@ -19,6 +19,11 @@ import ( "gopkg.in/ini.v1" ) +const ( + section_interface = "Interface" + section_peers = "Peer" +) + // SetPeers - sets peers on a given WireGuard interface func SetPeers(iface string, keepalive int32, peers []wgtypes.PeerConfig) error { @@ -289,40 +294,40 @@ func WriteWgConfig(cfg config.ClientConfig, privateKey string, peers []wgtypes.P AllowShadows: true, } wireguard := ini.Empty(options) - wireguard.Section("Interface").Key("PrivateKey").SetValue(privateKey) - wireguard.Section("Interface").Key("ListenPort").SetValue(strconv.Itoa(int(cfg.Node.ListenPort))) + wireguard.Section(section_interface).Key("PrivateKey").SetValue(privateKey) + wireguard.Section(section_interface).Key("ListenPort").SetValue(strconv.Itoa(int(cfg.Node.ListenPort))) if cfg.Node.Address != "" { - wireguard.Section("Interface").Key("Address").SetValue(cfg.Node.Address) + wireguard.Section(section_interface).Key("Address").SetValue(cfg.Node.Address) } if cfg.Node.Address6 != "" { - wireguard.Section("Interface").Key("Address").SetValue(cfg.Node.Address6) + wireguard.Section(section_interface).Key("Address").SetValue(cfg.Node.Address6) } if cfg.Node.DNSOn == "yes" { - wireguard.Section("Interface").Key("DNS").SetValue(cfg.Server.CoreDNSAddr) + wireguard.Section(section_interface).Key("DNS").SetValue(cfg.Server.CoreDNSAddr) } if cfg.Node.PostUp != "" { - wireguard.Section("Interface").Key("PostUp").SetValue(cfg.Node.PostUp) + wireguard.Section(section_interface).Key("PostUp").SetValue(cfg.Node.PostUp) } if cfg.Node.PostDown != "" { - wireguard.Section("Interface").Key("PostDown").SetValue(cfg.Node.PostDown) + wireguard.Section(section_interface).Key("PostDown").SetValue(cfg.Node.PostDown) } for i, peer := range peers { - wireguard.SectionWithIndex("Peer", i).Key("PublicKey").SetValue(peer.PublicKey.String()) + wireguard.SectionWithIndex(section_peers, i).Key("PublicKey").SetValue(peer.PublicKey.String()) if peer.PresharedKey.String() != "" { - wireguard.SectionWithIndex("Peer", i).Key("PreSharedKey").SetValue(peer.PresharedKey.String()) + wireguard.SectionWithIndex(section_peers, i).Key("PreSharedKey").SetValue(peer.PresharedKey.String()) } if peer.AllowedIPs != nil { var allowedIPs string for _, ip := range peer.AllowedIPs { allowedIPs = allowedIPs + ", " + ip.String() } - wireguard.SectionWithIndex("Peer", i).Key("AllowedIps").SetValue(allowedIPs) + wireguard.SectionWithIndex(section_peers, i).Key("AllowedIps").SetValue(allowedIPs) } if peer.Endpoint != nil { - wireguard.SectionWithIndex("Peer", i).Key("Endpoint").SetValue(peer.Endpoint.String()) + wireguard.SectionWithIndex(section_peers, i).Key("Endpoint").SetValue(peer.Endpoint.String()) } } - if err := wireguard.SaveTo("/etc/netclient/config" + cfg.Node.Interface + ".conf"); err != nil { + if err := wireguard.SaveTo(ncutils.GetNetclientPathSpecific() + cfg.Node.Interface + ".conf"); err != nil { return err } return nil @@ -331,25 +336,25 @@ func WriteWgConfig(cfg config.ClientConfig, privateKey string, peers []wgtypes.P // UpdateWgPeers - updates the peers of a network func UpdateWgPeers(wgInterface string, peers []wgtypes.Peer) error { //update to get path properly - file := "/etc/netclient/config/" + wgInterface + ".conf" + file := ncutils.GetNetclientPathSpecific() + wgInterface + ".conf" wireguard, err := ini.ShadowLoad(file) if err != nil { return err } for i, peer := range peers { - wireguard.SectionWithIndex("Peer", i).Key("PublicKey").SetValue(peer.PublicKey.String()) + wireguard.SectionWithIndex(section_peers, i).Key("PublicKey").SetValue(peer.PublicKey.String()) if peer.PresharedKey.String() != "" { - wireguard.SectionWithIndex("Peer", i).Key("PreSharedKey").SetValue(peer.PresharedKey.String()) + wireguard.SectionWithIndex(section_peers, i).Key("PreSharedKey").SetValue(peer.PresharedKey.String()) } if peer.AllowedIPs != nil { var allowedIPs string for _, ip := range peer.AllowedIPs { allowedIPs = allowedIPs + ", " + ip.String() } - wireguard.SectionWithIndex("Peer", i).Key("AllowedIps").SetValue(allowedIPs) + wireguard.SectionWithIndex(section_peers, i).Key("AllowedIps").SetValue(allowedIPs) } if peer.Endpoint != nil { - wireguard.SectionWithIndex("Peer", i).Key("Endpoint").SetValue(peer.Endpoint.String()) + wireguard.SectionWithIndex(section_peers, i).Key("Endpoint").SetValue(peer.Endpoint.String()) } } if err := wireguard.SaveTo(file); err != nil { @@ -361,27 +366,27 @@ func UpdateWgPeers(wgInterface string, peers []wgtypes.Peer) error { // UpdateWgInterface - updates the interface section of a wireguard config file func UpdateWgInterface(wgInterface, privateKey, nameserver string, node models.Node) error { //update to get path properly - file := "/etc/netclient/config/" + wgInterface + ".conf" + file := ncutils.GetNetclientPathSpecific() + wgInterface + ".conf" wireguard, err := ini.ShadowLoad(file) if err != nil { return err } - wireguard.Section("Interface").Key("PrivateKey").SetValue(privateKey) - wireguard.Section("Interface").Key("ListenPort").SetValue(strconv.Itoa(int(node.ListenPort))) + wireguard.Section(section_interface).Key("PrivateKey").SetValue(privateKey) + wireguard.Section(section_interface).Key("ListenPort").SetValue(strconv.Itoa(int(node.ListenPort))) if node.Address != "" { - wireguard.Section("Interface").Key("Address").SetValue(node.Address) + wireguard.Section(section_interface).Key("Address").SetValue(node.Address) } if node.Address6 != "" { - wireguard.Section("Interface").Key("Address").SetValue(node.Address6) + wireguard.Section(section_interface).Key("Address").SetValue(node.Address6) } if node.DNSOn == "yes" { - wireguard.Section("Interface").Key("DNS").SetValue(nameserver) + wireguard.Section(section_interface).Key("DNS").SetValue(nameserver) } if node.PostUp != "" { - wireguard.Section("Interface").Key("PostUp").SetValue(node.PostUp) + wireguard.Section(section_interface).Key("PostUp").SetValue(node.PostUp) } if node.PostDown != "" { - wireguard.Section("Interface").Key("PostDown").SetValue(node.PostDown) + wireguard.Section(section_interface).Key("PostDown").SetValue(node.PostDown) } if err := wireguard.SaveTo(file); err != nil { return err @@ -392,12 +397,12 @@ func UpdateWgInterface(wgInterface, privateKey, nameserver string, node models.N // UpdatePrivateKey - updates the private key of a wireguard config file func UpdatePrivateKey(wgInterface, privateKey string) error { //update to get path properly - file := "/etc/netclient/config/" + wgInterface + ".conf" + file := ncutils.GetNetclientPathSpecific() + wgInterface + ".conf" wireguard, err := ini.ShadowLoad(file) if err != nil { return err } - wireguard.Section("Interface").Key("PrivateKey").SetValue(privateKey) + wireguard.Section(section_interface).Key("PrivateKey").SetValue(privateKey) if err := wireguard.SaveTo(file); err != nil { return err } From 710567064e822c1190247d017768b581a7b979a1 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Wed, 5 Jan 2022 11:07:09 -0500 Subject: [PATCH 058/116] add error handling on failed key generation --- netclient/functions/daemon.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index fc926bda..8baaa392 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -97,6 +97,10 @@ var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) cfg.ReadConfig() nameserver := cfg.Server.CoreDNSAddr privateKey, err := wireguard.RetrievePrivKey(data.Network) + if err != nil { + ncutils.Log("error generating PrivateKey " + err.Error()) + return + } if err := wireguard.UpdateWgInterface(cfg.Node.Interface, privateKey, nameserver, data); err != nil { ncutils.Log("error updating wireguard config " + err.Error()) return From 78363ede259782499d86bc48530cb30c13ae11a0 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Mon, 10 Jan 2022 14:35:53 -0500 Subject: [PATCH 059/116] refactor NodeUpdate message queue handler --- netclient/functions/daemon.go | 89 +++++++++++++++++++++-------------- 1 file changed, 54 insertions(+), 35 deletions(-) diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index 8baaa392..639436ae 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -6,6 +6,7 @@ import ( "log" "os" "os/signal" + "runtime" "strings" "syscall" "time" @@ -67,7 +68,8 @@ func Netclient(ctx context.Context, network string) { } client.AddRoute("update/"+cfg.Node.ID, NodeUpdate) client.AddRoute("update/peers/"+cfg.Node.ID, UpdatePeers) - client.AddRoute("update/keys/"+cfg.Node.ID, UpdateKeys) + //handle key updates in node update + //client.AddRoute("update/keys/"+cfg.Node.ID, UpdateKeys) defer client.Disconnect(250) go Checkin(ctx, cfg, network) go Metrics(ctx, cfg, network) @@ -86,19 +88,44 @@ var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) ncutils.Log("received message to update node " + string(msg.Payload())) //potentiall blocking i/o so do this in a go routine go func() { - var data models.Node - err := json.Unmarshal(msg.Payload(), &data) + var newNode models.Node + var cfg config.ClientConfig + cfg.Network = newNode.Network + cfg.ReadConfig() + err := json.Unmarshal(msg.Payload(), &newNode) if err != nil { ncutils.Log("error unmarshalling node update data" + err.Error()) return } - var cfg config.ClientConfig - cfg.Network = data.Network - cfg.ReadConfig() + //check if interface name has changed if so delete. + if cfg.Node.Interface != newNode.Interface { + if err = wireguard.RemoveConf(cfg.Node.Interface, true); err != nil { + ncutils.PrintLog("could not delete old interface "+cfg.Node.Interface+": ", err.Error(), 1) + } + } + newNode.PullChanges = "no" + //ensure that OS never changes + newNode.OS = runtime.GOOS + cfg.Node = newNode + switch newNode.Action { + case models.NODE_DELETE: + if err := RemoveLocalInstance(cfg, cfg.Network); err != nil { + ncutils.Printlog("error deleting local instance: "+err.Error(), 1) + return + } + case models.NODE_UPDATE_KEY: + UpdateKeys(cfg) + case models.NODE_NOOP: + default: + } + //Save new config + if err := config.Write(&cfg, cfg.Network); err != nil { + ncutils.PrintLog("error updating node configuration: "+err.Error(), 1) + } nameserver := cfg.Server.CoreDNSAddr privateKey, err := wireguard.RetrievePrivKey(data.Network) if err != nil { - ncutils.Log("error generating PrivateKey " + err.Error()) + ncutils.Log("error reading PrivateKey " + err.Error()) return } if err := wireguard.UpdateWgInterface(cfg.Node.Interface, privateKey, nameserver, data); err != nil { @@ -108,7 +135,7 @@ var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) // path hardcoded for now... should be updated err = wireguard.ApplyWGQuickConf("/etc/netclient/config/" + cfg.Node.Interface + ".conf") if err != nil { - ncutils.Log("error restarting wg after peer update " + err.Error()) + ncutils.Log("error restarting wg after node update " + err.Error()) return } }() @@ -117,7 +144,6 @@ var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) // UpdatePeers -- mqtt message handler for /update/peers/ topic var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update peers " + string(msg.Payload())) - //potentiall blocking i/o so do this in a go routine go func() { var peerUpdate models.PeerUpdate err := json.Unmarshal(msg.Payload(), &peerUpdate) @@ -142,34 +168,27 @@ var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) }() } -// UpdateKeys -- mqtt message handler for /update/keys/ topic -var UpdateKeys mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { - ncutils.Log("received message to update keys " + string(msg.Payload())) +// UpdateKeys -- updates private key and returns new publickey +func UpdateKeys(cfg *config.ClientConfig, client mqtt.Client) (*config.ClientConfig, error) { + ncutils.Log("received message to update keys") //potentiall blocking i/o so do this in a go routine - go func() { - var data models.KeyUpdate - if err := json.Unmarshal(msg.Payload(), &data); err != nil { - ncutils.Log("error unmarshalling key update data" + err.Error()) - return - } - var cfg config.ClientConfig - cfg.Network = data.Network - cfg.ReadConfig() - key, err := wgtypes.GeneratePrivateKey() - if err != nil { - ncutils.Log("error generating privatekey " + err.Error()) - return - } - if err := wireguard.UpdatePrivateKey(data.Interface, key.String()); err != nil { - ncutils.Log("error updating wireguard key " + err.Error()) - return - } - publicKey := key.PublicKey() - if token := client.Publish("update/publickey/"+cfg.Node.ID, 0, false, publicKey.String()); token.Wait() && token.Error() != nil { - ncutils.Log("error publishing publickey update " + token.Error().Error()) - } + key, err := wgtypes.GeneratePrivateKey() + if err != nil { + ncutils.Log("error generating privatekey " + err.Error()) + return cfg, err + } + if err := wireguard.UpdatePrivateKey(data.Interface, key.String()); err != nil { + ncutils.Log("error updating wireguard key " + err.Error()) + return cfg, err + } + publicKey := key.PublicKey() + if token := client.Publish("update/publickey/"+cfg.Node.ID, 0, false, publicKey.String()); token.Wait() && token.Error() != nil { + ncutils.Log("error publishing publickey update " + token.Error().Error()) client.Disconnect(250) - }() + return cfg, err + } + client.Disconnect(250) + return cfg, nil } // Checkin -- go routine that checks for public or local ip changes, publishes changes From ff22f84a479e437f144dd5e15a824012836b63d1 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Wed, 12 Jan 2022 16:23:34 -0500 Subject: [PATCH 060/116] WIP commit --- .gitignore | 1 + config/config.go | 2 + go.mod | 6 +- go.sum | 6 -- main.go | 57 +++++++++- models/mqtt.go | 5 +- mq/mq.go | 197 ++++++++++++++++++++++++++++++++++ netclient/functions/daemon.go | 14 +-- servercfg/serverconf.go | 27 +++++ 9 files changed, 293 insertions(+), 22 deletions(-) create mode 100644 mq/mq.go diff --git a/.gitignore b/.gitignore index 3f09bc2e..18da4b52 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ config/dnsconfig/ data/ .vscode/ .idea/ +.vscode/ diff --git a/config/config.go b/config/config.go index fc1bcbf2..649ef1b9 100644 --- a/config/config.go +++ b/config/config.go @@ -43,12 +43,14 @@ type ServerConfig struct { GRPCHost string `yaml:"grpchost"` GRPCPort string `yaml:"grpcport"` GRPCSecure string `yaml:"grpcsecure"` + MQHOST string `yaml:"mqhost"` MasterKey string `yaml:"masterkey"` DNSKey string `yaml:"dnskey"` AllowedOrigin string `yaml:"allowedorigin"` NodeID string `yaml:"nodeid"` RestBackend string `yaml:"restbackend"` AgentBackend string `yaml:"agentbackend"` + MessageQueueBackend string `yaml:"messagequeuebackend"` ClientMode string `yaml:"clientmode"` DNSMode string `yaml:"dnsmode"` SplitDNS string `yaml:"splitdns"` diff --git a/go.mod b/go.mod index b8b169d9..b4df5780 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/gravitl/netmaker go 1.17 require ( + github.com/eclipse/paho.mqtt.golang v1.3.5 github.com/go-playground/validator/v10 v10.10.0 github.com/golang-jwt/jwt/v4 v4.2.0 github.com/golang/protobuf v1.5.2 // indirect @@ -25,6 +26,7 @@ require ( google.golang.org/genproto v0.0.0-20210201151548-94839c025ad4 // indirect google.golang.org/grpc v1.43.0 google.golang.org/protobuf v1.27.1 + gopkg.in/ini.v1 v1.66.2 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b ) @@ -32,9 +34,7 @@ require ( cloud.google.com/go v0.34.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/eclipse/paho.mqtt.golang v1.3.5 // indirect github.com/felixge/httpsnoop v1.0.1 // indirect - github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534 // indirect github.com/go-playground/locales v0.14.0 // indirect github.com/go-playground/universal-translator v0.18.0 // indirect github.com/google/go-cmp v0.5.5 // indirect @@ -46,7 +46,5 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/russross/blackfriday/v2 v2.0.1 // indirect github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect - golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect google.golang.org/appengine v1.4.0 // indirect - gopkg.in/ini.v1 v1.66.2 // indirect ) diff --git a/go.sum b/go.sum index 84dbc91f..e36273a2 100644 --- a/go.sum +++ b/go.sum @@ -36,8 +36,6 @@ github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8S github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534 h1:dhy9OQKGBh4zVXbjwbxxHjRxMJtLXj3zfgpBYQaR4Q4= -github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk= github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= @@ -194,7 +192,6 @@ golang.org/x/net v0.0.0-20201216054612-986b41b23924/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210504132125-bbd867fde50d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985 h1:4CSI6oo7cOjJKajidEljs9h+uP0rRZBPPPhcCbj5mw8= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -205,8 +202,6 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -228,7 +223,6 @@ golang.org/x/sys v0.0.0-20210123111255-9b0068b26619/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210216163648-f7da38b97c65/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210309040221-94ec62e08169/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210503173754-0981d6026fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/main.go b/main.go index fd9aad97..52243051 100644 --- a/main.go +++ b/main.go @@ -11,6 +11,7 @@ import ( "sync" "time" + mqtt "github.com/eclipse/paho.mqtt.golang" "github.com/gravitl/netmaker/auth" controller "github.com/gravitl/netmaker/controllers" "github.com/gravitl/netmaker/database" @@ -19,6 +20,7 @@ import ( "github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/logic" "github.com/gravitl/netmaker/models" + "github.com/gravitl/netmaker/mq" "github.com/gravitl/netmaker/netclient/ncutils" "github.com/gravitl/netmaker/servercfg" "github.com/gravitl/netmaker/serverctl" @@ -106,8 +108,14 @@ func startControllers() { go controller.HandleRESTRequests(&waitnetwork) } - if !servercfg.IsAgentBackend() && !servercfg.IsRestBackend() { - logger.Log(0, "No Server Mode selected, so nothing is being served! Set either Agent mode (AGENT_BACKEND) or Rest mode (REST_BACKEND) to 'true'.") + //Run MessageQueue + if servercfg.IsMessageQueueBackend() { + waitnetwork.Add(1) + go runMessageQueue(&waitnetwork) + } + + if !servercfg.IsAgentBackend() && !servercfg.IsRestBackend() && !servercfg.IsMessageQueueBackend() { + logger.Log(0, "No Server Mode selected, so nothing is being served! Set Agent mode (AGENT_BACKEND) or Rest mode (REST_BACKEND) or MessageQueue (MESSAGEQUEUE_BACKEND) to 'true'.") } if servercfg.IsClientMode() == "on" { @@ -175,6 +183,51 @@ func runGRPC(wg *sync.WaitGroup) { logger.Log(0, "Closed DB connection.") } +// Should we be using a context vice a waitgroup???????????? +func runMessageQueue(wg *sync.WaitGroup) { + defer wg.Done() + //refactor netclient.functions.SetupMQTT so can be called from here + //setupMQTT + opts := mqtt.NewClientOptions() + opts.AddBroker(servercfg.GetMessageQueueEndpoint()) + logger.Log(0, "setting broker "+servercfg.GetMessageQueueEndpoint()) + opts.SetDefaultPublishHandler(mq.DefaultHandler) + client := mqtt.NewClient(opts) + if token := client.Connect(); token.Wait() && token.Error() != nil { + logger.Log(0, "unable to connect to message queue broker, closing down") + return + } + //Set up Subscriptions + if token := client.Subscribe("#", 0, nil); token.Wait() && token.Error() != nil { + //should make constant for disconnect wait period + client.Disconnect(250) + logger.Log(0, "could not subscribe to message queue ...") + return + } + if token := client.Subscribe("ping/#", 0, mq.Ping); token.Wait() && token.Error() != nil { + client.Disconnect(240) + logger.Log(0, "ping sub failed") + } + if token := client.Subscribe("metrics/#", 0, mq.Metrics); token.Wait() && token.Error() != nil { + client.Disconnect(240) + logger.Log(0, "metrics sub failed") + } + if token := client.Subscribe("update/localaddress/#", 0, mq.LocalAddressUpdate); token.Wait() && token.Error() != nil { + client.Disconnect(240) + logger.Log(0, "metrics sub failed") + } + if token := client.Subscribe("update/ip/#", 0, mq.IPUpdate); token.Wait() && token.Error() != nil { + client.Disconnect(240) + logger.Log(0, "metrics sub failed") + } + if token := client.Subscribe("update/publickey/#", 0, mq.PublicKeyUpdate); token.Wait() && token.Error() != nil { + client.Disconnect(240) + logger.Log(0, "metrics sub failed") + } + for { + } +} + func authServerUnaryInterceptor() grpc.ServerOption { return grpc.UnaryInterceptor(controller.AuthServerUnaryInterceptor) } diff --git a/models/mqtt.go b/models/mqtt.go index a7e87e1f..da7265f3 100644 --- a/models/mqtt.go +++ b/models/mqtt.go @@ -3,9 +3,8 @@ package models import "golang.zx2c4.com/wireguard/wgctrl/wgtypes" type PeerUpdate struct { - Network string - Interface string - Peers []wgtypes.Peer + Network string + Peers []wgtypes.Peer } type KeyUpdate struct { diff --git a/mq/mq.go b/mq/mq.go new file mode 100644 index 00000000..3620b215 --- /dev/null +++ b/mq/mq.go @@ -0,0 +1,197 @@ +package mq + +import ( + "encoding/json" + "errors" + "log" + "net" + "strings" + "time" + + mqtt "github.com/eclipse/paho.mqtt.golang" + "github.com/gravitl/netmaker/database" + "github.com/gravitl/netmaker/logger" + "github.com/gravitl/netmaker/logic" + "github.com/gravitl/netmaker/models" + "golang.zx2c4.com/wireguard/wgctrl/wgtypes" +) + +var DefaultHandler mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { + logger.Log(0, "MQTT Message: Topic: "+string(msg.Topic())+" Message: "+string(msg.Payload())) +} + +var Metrics mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { + logger.Log(0, "Metrics Handler") +} + +var Ping mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { + logger.Log(0, "Ping Handler") + //test code --- create a node if it doesn't exit for testing only + createnode := models.Node{PublicKey: "DM5qhLAE20PG9BbfBCger+Ac9D2NDOwCtY1rbYDLf34=", Name: "testnode", + Endpoint: "10.0.0.1", MacAddress: "01:02:03:04:05:06", Password: "password", Network: "skynet"} + if _, err := logic.GetNode("01:02:03:04:05:06", "skynet"); err != nil { + err := logic.CreateNode(&createnode) + if err != nil { + log.Println(err) + } + } + //end of test code + go func() { + mac, net, err := GetMacNetwork(msg.Topic()) + if err != nil { + logger.Log(0, "error getting node.ID sent on ping topic ") + return + } + logger.Log(0, "ping recieved from "+mac+" on net "+net) + node, err := logic.GetNodeByMacAddress(net, mac) + if err != nil { + logger.Log(0, "mq-ping error getting node: "+err.Error()) + record, err := database.FetchRecord(database.NODES_TABLE_NAME, mac+"###"+net) + if err != nil { + logger.Log(0, "error reading database ", err.Error()) + return + } + logger.Log(0, "record from database") + logger.Log(0, record) + return + } + node.SetLastCheckIn() + // --TODO --set client version once feature is implemented. + //node.SetClientVersion(msg.Payload()) + }() +} + +var PublicKeyUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { + logger.Log(0, "PublicKey Handler") + go func() { + logger.Log(0, "public key update "+msg.Topic()) + key := string(msg.Payload()) + mac, network, err := GetMacNetwork(msg.Topic()) + if err != nil { + logger.Log(0, "error getting node.ID sent on "+msg.Topic()+" "+err.Error()) + } + node, err := logic.GetNode(mac, network) + if err != nil { + logger.Log(0, "error retrieving node "+msg.Topic()+" "+err.Error()) + } + node.PublicKey = key + node.SetLastCheckIn() + UpdatePeers(&node, client) + }() +} + +var IPUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { + go func() { + ip := string(msg.Payload()) + logger.Log(0, "IPUpdate Handler") + mac, network, err := GetMacNetwork(msg.Topic()) + logger.Log(0, "ipUpdate recieved from "+mac+" on net "+network) + if err != nil { + logger.Log(0, "error getting node.ID sent on update/ip topic ") + return + } + node, err := logic.GetNode(mac, network) + if err != nil { + logger.Log(0, "invalid ID recieved on update/ip topic: "+err.Error()) + return + } + node.Endpoint = ip + node.SetLastCheckIn() + UpdatePeers(&node, client) + }() +} + +func UpdatePeers(node *models.Node, client mqtt.Client) { + peersToUpdate, err := logic.GetPeers(node) + if err != nil { + logger.Log(0, "error retrieving peers") + return + } + for _, peerToUpdate := range peersToUpdate { + var peerUpdate models.PeerUpdate + peerUpdate.Network = node.Network + + myPeers, err := logic.GetPeers(&peerToUpdate) + if err != nil { + logger.Log(0, "uable to get peers "+err.Error()) + continue + } + for i, myPeer := range myPeers { + var allowedIPs []net.IPNet + var allowedIP net.IPNet + endpoint, err := net.ResolveUDPAddr("udp", myPeer.Address+":"+string(myPeer.ListenPort)) + if err != nil { + logger.Log(0, "error setting endpoint for peer "+err.Error()) + } + for _, ipString := range myPeer.AllowedIPs { + _, ipNet, _ := net.ParseCIDR(ipString) + allowedIP = *ipNet + allowedIPs = append(allowedIPs, allowedIP) + } + key, err := wgtypes.ParseKey(myPeer.PublicKey) + if err != nil { + logger.Log(0, "err parsing publickey") + continue + } + peerUpdate.Peers[i].PublicKey = key + peerUpdate.Peers[i].Endpoint = endpoint + peerUpdate.Peers[i].PersistentKeepaliveInterval = time.Duration(myPeer.PersistentKeepalive) + peerUpdate.Peers[i].AllowedIPs = allowedIPs + peerUpdate.Peers[i].ProtocolVersion = 0 + } + //PublishPeerUpdate(my) + data, err := json.Marshal(peerUpdate) + if err != nil { + logger.Log(0, "err marshalling data for peer update "+err.Error()) + } + if token := client.Publish("update/peers/"+peerToUpdate.ID, 0, false, data); token.Wait() && token.Error() != nil { + logger.Log(0, "error publishing peer update "+token.Error().Error()) + } + client.Disconnect(250) + } +} + +var LocalAddressUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { + logger.Log(0, "LocalAddressUpdate Handler") + go func() { + logger.Log(0, "LocalAddressUpdate handler") + mac, net, err := GetMacNetwork(msg.Topic()) + if err != nil { + logger.Log(0, "error getting node.ID "+msg.Topic()) + return + } + node, err := logic.GetNode(mac, net) + if err != nil { + logger.Log(0, "error get node "+msg.Topic()) + return + } + node.LocalAddress = string(msg.Payload()) + node.SetLastCheckIn() + }() +} + +func GetMacNetwork(topic string) (string, string, error) { + parts := strings.Split(topic, "/") + count := len(parts) + if count == 1 { + return "", "", errors.New("invalid topic") + } + macnet := strings.Split(parts[count-1], "---") + if len(macnet) != 2 { + return "", "", errors.New("topic id not in mac---network format") + } + return macnet[0], macnet[1], nil +} + +func GetID(topic string) (string, error) { + parts := strings.Split(topic, "/") + count := len(parts) + if count == 1 { + return "", errors.New("invalid topic") + } + macnet := strings.Split(parts[count-1], "---") + if len(macnet) != 2 { + return "", errors.New("topic id not in mac---network format") + } + return macnet[0] + "###" + macnet[1], nil +} diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index 639436ae..a5360319 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -100,7 +100,7 @@ var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) //check if interface name has changed if so delete. if cfg.Node.Interface != newNode.Interface { if err = wireguard.RemoveConf(cfg.Node.Interface, true); err != nil { - ncutils.PrintLog("could not delete old interface "+cfg.Node.Interface+": ", err.Error(), 1) + ncutils.PrintLog("could not delete old interface "+cfg.Node.Interface+": "+err.Error(), 1) } } newNode.PullChanges = "no" @@ -109,12 +109,12 @@ var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) cfg.Node = newNode switch newNode.Action { case models.NODE_DELETE: - if err := RemoveLocalInstance(cfg, cfg.Network); err != nil { - ncutils.Printlog("error deleting local instance: "+err.Error(), 1) + if err := RemoveLocalInstance(&cfg, cfg.Network); err != nil { + ncutils.PrintLog("error deleting local instance: "+err.Error(), 1) return } case models.NODE_UPDATE_KEY: - UpdateKeys(cfg) + UpdateKeys(&cfg, client) case models.NODE_NOOP: default: } @@ -123,12 +123,12 @@ var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) ncutils.PrintLog("error updating node configuration: "+err.Error(), 1) } nameserver := cfg.Server.CoreDNSAddr - privateKey, err := wireguard.RetrievePrivKey(data.Network) + privateKey, err := wireguard.RetrievePrivKey(newNode.Network) if err != nil { ncutils.Log("error reading PrivateKey " + err.Error()) return } - if err := wireguard.UpdateWgInterface(cfg.Node.Interface, privateKey, nameserver, data); err != nil { + if err := wireguard.UpdateWgInterface(cfg.Node.Interface, privateKey, nameserver, newNode); err != nil { ncutils.Log("error updating wireguard config " + err.Error()) return } @@ -177,7 +177,7 @@ func UpdateKeys(cfg *config.ClientConfig, client mqtt.Client) (*config.ClientCon ncutils.Log("error generating privatekey " + err.Error()) return cfg, err } - if err := wireguard.UpdatePrivateKey(data.Interface, key.String()); err != nil { + if err := wireguard.UpdatePrivateKey(cfg.Node.Interface, key.String()); err != nil { ncutils.Log("error updating wireguard key " + err.Error()) return cfg, err } diff --git a/servercfg/serverconf.go b/servercfg/serverconf.go index e203ddd4..ed280aa1 100644 --- a/servercfg/serverconf.go +++ b/servercfg/serverconf.go @@ -244,6 +244,18 @@ func GetGRPCPort() string { return grpcport } +// GetMessageQueueEndpoint - gets the message queue endpoint +func GetMessageQueueEndpoint() string { + host, _ := GetPublicIP() + if os.Getenv("MQ_HOST") != "" { + host = os.Getenv("MQ_HOST") + } else if config.Config.Server.MQHOST != "" { + host = config.Config.Server.MQHOST + } + //Do we want MQ port configurable??? + return host + ":1883" +} + // GetMasterKey - gets the configured master key of server func GetMasterKey() string { key := "secretkey" @@ -307,6 +319,21 @@ func IsAgentBackend() bool { return isagent } +// IsMessageQueueBackend - checks if message queue is on or off +func IsMessageQueueBackend() bool { + ismessagequeue := true + if os.Getenv("MESSAGEQUEUE_BACKEND") != "" { + if os.Getenv("MESSAGEQUEUE_BACKEND") == "off" { + ismessagequeue = false + } + } else if config.Config.Server.MessageQueueBackend != "" { + if config.Config.Server.MessageQueueBackend == "off" { + ismessagequeue = false + } + } + return ismessagequeue +} + // IsClientMode - checks if it should run in client mode func IsClientMode() string { isclient := "on" From a1c56591794b017be3be065a5eaffa976c0b9823 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Fri, 14 Jan 2022 14:30:26 -0500 Subject: [PATCH 061/116] WIP commit to enable rebasing to uuid feature --- main.go | 30 +++--- models/mqtt.go | 7 +- mq/mq.go | 120 ++++++++++++------------ netclient/functions/daemon.go | 35 ++++++- netclient/functions/peers.go | 167 ++++++++++++++++++++++++++++++++++ 5 files changed, 276 insertions(+), 83 deletions(-) create mode 100644 netclient/functions/peers.go diff --git a/main.go b/main.go index 52243051..3d527a0b 100644 --- a/main.go +++ b/main.go @@ -9,7 +9,7 @@ import ( "runtime/debug" "strconv" "sync" - "time" + "syscall" mqtt "github.com/eclipse/paho.mqtt.golang" "github.com/gravitl/netmaker/auth" @@ -118,16 +118,16 @@ func startControllers() { logger.Log(0, "No Server Mode selected, so nothing is being served! Set Agent mode (AGENT_BACKEND) or Rest mode (REST_BACKEND) or MessageQueue (MESSAGEQUEUE_BACKEND) to 'true'.") } - if servercfg.IsClientMode() == "on" { - var checkintime = time.Duration(servercfg.GetServerCheckinInterval()) * time.Second - for { // best effort currently - var serverGroup sync.WaitGroup - serverGroup.Add(1) - go runClient(&serverGroup) - serverGroup.Wait() - time.Sleep(checkintime) - } - } + //if servercfg.IsClientMode() == "on" { + // var checkintime = time.Duration(servercfg.GetServerCheckinInterval()) * time.Second + // for { // best effort currently + // var serverGroup sync.WaitGroup + // serverGroup.Add(1) + // go runClient(&serverGroup) + // serverGroup.Wait() + // time.Sleep(checkintime) + // } + //} waitnetwork.Wait() } @@ -204,7 +204,7 @@ func runMessageQueue(wg *sync.WaitGroup) { logger.Log(0, "could not subscribe to message queue ...") return } - if token := client.Subscribe("ping/#", 0, mq.Ping); token.Wait() && token.Error() != nil { + if token := client.Subscribe("ping/#", 2, mq.Ping); token.Wait() && token.Error() != nil { client.Disconnect(240) logger.Log(0, "ping sub failed") } @@ -224,8 +224,10 @@ func runMessageQueue(wg *sync.WaitGroup) { client.Disconnect(240) logger.Log(0, "metrics sub failed") } - for { - } + quit := make(chan os.Signal, 1) + signal.Notify(quit, syscall.SIGTERM, os.Interrupt) + <-quit + logger.Log(0, "Message Queue shutting down") } func authServerUnaryInterceptor() grpc.ServerOption { diff --git a/models/mqtt.go b/models/mqtt.go index da7265f3..07bb2157 100644 --- a/models/mqtt.go +++ b/models/mqtt.go @@ -1,10 +1,9 @@ package models -import "golang.zx2c4.com/wireguard/wgctrl/wgtypes" - type PeerUpdate struct { - Network string - Peers []wgtypes.Peer + Network string + Nodes []Node + ExtPeers []ExtPeersResponse } type KeyUpdate struct { diff --git a/mq/mq.go b/mq/mq.go index 3620b215..fd9657a7 100644 --- a/mq/mq.go +++ b/mq/mq.go @@ -1,19 +1,15 @@ package mq import ( - "encoding/json" "errors" - "log" - "net" + "fmt" "strings" - "time" mqtt "github.com/eclipse/paho.mqtt.golang" "github.com/gravitl/netmaker/database" "github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/logic" "github.com/gravitl/netmaker/models" - "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) var DefaultHandler mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { @@ -22,20 +18,11 @@ var DefaultHandler mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Messa var Metrics mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { logger.Log(0, "Metrics Handler") + //TODOD -- handle metrics data ---- store to database? } var Ping mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { - logger.Log(0, "Ping Handler") - //test code --- create a node if it doesn't exit for testing only - createnode := models.Node{PublicKey: "DM5qhLAE20PG9BbfBCger+Ac9D2NDOwCtY1rbYDLf34=", Name: "testnode", - Endpoint: "10.0.0.1", MacAddress: "01:02:03:04:05:06", Password: "password", Network: "skynet"} - if _, err := logic.GetNode("01:02:03:04:05:06", "skynet"); err != nil { - err := logic.CreateNode(&createnode) - if err != nil { - log.Println(err) - } - } - //end of test code + logger.Log(0, "Ping Handler: "+msg.Topic()) go func() { mac, net, err := GetMacNetwork(msg.Topic()) if err != nil { @@ -56,6 +43,7 @@ var Ping mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { return } node.SetLastCheckIn() + logger.Log(0, "ping processed") // --TODO --set client version once feature is implemented. //node.SetClientVersion(msg.Payload()) }() @@ -76,7 +64,9 @@ var PublicKeyUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Mess } node.PublicKey = key node.SetLastCheckIn() - UpdatePeers(&node, client) + if err := UpdatePeers(client, node); err != nil { + logger.Log(0, "error updating peers "+err.Error()) + } }() } @@ -97,58 +87,63 @@ var IPUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { } node.Endpoint = ip node.SetLastCheckIn() - UpdatePeers(&node, client) + if err := UpdatePeers(client, node); err != nil { + logger.Log(0, "error updating peers "+err.Error()) + } }() } -func UpdatePeers(node *models.Node, client mqtt.Client) { - peersToUpdate, err := logic.GetPeers(node) - if err != nil { - logger.Log(0, "error retrieving peers") - return - } - for _, peerToUpdate := range peersToUpdate { - var peerUpdate models.PeerUpdate - peerUpdate.Network = node.Network +func UpdatePeers(client mqtt.Client, node models.Node) error { + var peerUpdate models.PeerUpdate + peerUpdate.Network = node.Network - myPeers, err := logic.GetPeers(&peerToUpdate) - if err != nil { - logger.Log(0, "uable to get peers "+err.Error()) + nodes, err := logic.GetNetworkNodes(node.Network) + if err != nil { + return fmt.Errorf("unable to get network nodes %v: ", err) + } + if token := client.Connect(); token.Wait() && token.Error() != nil { + return token.Error() + } + for _, peer := range nodes { + //don't need to update the initiatiing client + if peer.ID == node.ID { continue } - for i, myPeer := range myPeers { - var allowedIPs []net.IPNet - var allowedIP net.IPNet - endpoint, err := net.ResolveUDPAddr("udp", myPeer.Address+":"+string(myPeer.ListenPort)) - if err != nil { - logger.Log(0, "error setting endpoint for peer "+err.Error()) - } - for _, ipString := range myPeer.AllowedIPs { - _, ipNet, _ := net.ParseCIDR(ipString) - allowedIP = *ipNet - allowedIPs = append(allowedIPs, allowedIP) - } - key, err := wgtypes.ParseKey(myPeer.PublicKey) - if err != nil { - logger.Log(0, "err parsing publickey") - continue - } - peerUpdate.Peers[i].PublicKey = key - peerUpdate.Peers[i].Endpoint = endpoint - peerUpdate.Peers[i].PersistentKeepaliveInterval = time.Duration(myPeer.PersistentKeepalive) - peerUpdate.Peers[i].AllowedIPs = allowedIPs - peerUpdate.Peers[i].ProtocolVersion = 0 - } - //PublishPeerUpdate(my) - data, err := json.Marshal(peerUpdate) + peerUpdate.Nodes = append(peerUpdate.Nodes, peer) + peerUpdate.ExtPeers, err = logic.GetExtPeersList(node.MacAddress, node.Network) if err != nil { - logger.Log(0, "err marshalling data for peer update "+err.Error()) + logger.Log(0) } - if token := client.Publish("update/peers/"+peerToUpdate.ID, 0, false, data); token.Wait() && token.Error() != nil { - logger.Log(0, "error publishing peer update "+token.Error().Error()) + if token := client.Publish("update/peers/"+peer.ID, 0, false, nodes); token.Wait() && token.Error() != nil { + logger.Log(0, "error publishing peer update "+peer.ID+" "+token.Error().Error()) } - client.Disconnect(250) } + + return nil +} + +func UpdateLocalPeers(client mqtt.Client, node models.Node) error { + nodes, err := logic.GetNetworkNodes(node.Network) + if err != nil { + return fmt.Errorf("unable to get network nodes %v: ", err) + } + if token := client.Connect(); token.Wait() && token.Error() != nil { + return token.Error() + } + for _, peer := range nodes { + //don't need to update the initiatiing client + if peer.ID == node.ID { + continue + } + //if peer.Endpoint is on same lan as node.LocalAddress + //if TODO{ + //continue + //} + if token := client.Publish("update/peers/"+peer.ID, 0, false, nodes); token.Wait() && token.Error() != nil { + logger.Log(0, "error publishing peer update "+peer.ID+" "+token.Error().Error()) + } + } + return nil } var LocalAddressUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { @@ -167,6 +162,9 @@ var LocalAddressUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.M } node.LocalAddress = string(msg.Payload()) node.SetLastCheckIn() + if err := UpdateLocalPeers(client, node); err != nil { + logger.Log(0, "error updating peers "+err.Error()) + } }() } @@ -176,7 +174,7 @@ func GetMacNetwork(topic string) (string, string, error) { if count == 1 { return "", "", errors.New("invalid topic") } - macnet := strings.Split(parts[count-1], "---") + macnet := strings.Split(parts[count-1], "-") if len(macnet) != 2 { return "", "", errors.New("topic id not in mac---network format") } @@ -189,7 +187,7 @@ func GetID(topic string) (string, error) { if count == 1 { return "", errors.New("invalid topic") } - macnet := strings.Split(parts[count-1], "---") + macnet := strings.Split(parts[count-1], "-") if len(macnet) != 2 { return "", errors.New("topic id not in mac---network format") } diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index a5360319..6e212c77 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -154,9 +154,19 @@ var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) var cfg config.ClientConfig cfg.Network = peerUpdate.Network cfg.ReadConfig() - err = wireguard.UpdateWgPeers(cfg.Node.Interface, peerUpdate.Peers) + peers, err := CalculatePeers(cfg.Node, peerUpdate.Nodes, cfg.Node.IsDualStack, cfg.Node.IsEgressGateway, cfg.Node.IsServer) if err != nil { - ncutils.Log("error updating peers" + err.Error()) + ncutils.Log("error calculating Peers " + err.Error()) + return + } + extpeers, err := CalculateExtPeers(cfg.Node, peerUpdate.ExtPeers) + if err != nil { + ncutils.Log("error updated external wireguard peers " + err.Error()) + } + peers = append(peers, extpeers...) + err = wireguard.UpdateWgPeers(cfg.Node.Interface, peers) + if err != nil { + ncutils.Log("error updating wireguard peers" + err.Error()) return } // path hardcoded for now... should be updated @@ -187,7 +197,9 @@ func UpdateKeys(cfg *config.ClientConfig, client mqtt.Client) (*config.ClientCon client.Disconnect(250) return cfg, err } - client.Disconnect(250) + if err := config.ModConfig(&cfg.Node); err != nil { + ncutils.Log("error updating local config " + err.Error()) + } return cfg, nil } @@ -202,6 +214,11 @@ func Checkin(ctx context.Context, cfg config.ClientConfig, network string) { //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? case <-time.After(time.Second * 10): ncutils.Log("Checkin running") + //read latest config + cfg.ReadConfig() + //fix NodeID to remove ### so NodeID can be used as message topic + //remove with GRA-73 + cfg.Node.ID = strings.Replace(cfg.Node.ID, "###", "-", 1) if cfg.Node.Roaming == "yes" && cfg.Node.IsStatic != "yes" { extIP, err := ncutils.GetPublicIP() if err != nil { @@ -242,6 +259,10 @@ func UpdateEndpoint(cfg config.ClientConfig, network, ip string) { if token := client.Publish("update/ip/"+cfg.Node.ID, 0, false, ip); token.Wait() && token.Error() != nil { ncutils.Log("error publishing endpoint update " + token.Error().Error()) } + cfg.Node.Endpoint = ip + if err := config.Write(&cfg, cfg.Network); err != nil { + ncutils.Log("error updating local config " + err.Error()) + } client.Disconnect(250) } @@ -252,13 +273,19 @@ func UpdateLocalAddress(cfg config.ClientConfig, network, ip string) { if token := client.Publish("update/localaddress/"+cfg.Node.ID, 0, false, ip); token.Wait() && token.Error() != nil { ncutils.Log("error publishing local address update " + token.Error().Error()) } + cfg.Node.LocalAddress = ip + ncutils.Log("updating local address in local config to: " + cfg.Node.LocalAddress) + if err := config.Write(&cfg, cfg.Network); err != nil { + ncutils.Log("error updating local config " + err.Error()) + } client.Disconnect(250) } // Hello -- ping the broker to let server know node is alive and doing fine func Hello(cfg config.ClientConfig, network string) { client := SetupMQTT(cfg) - if token := client.Publish("ping/"+cfg.Node.ID, 0, false, "hello world!"); token.Wait() && token.Error() != nil { + ncutils.Log("sending ping " + cfg.Node.ID) + if token := client.Publish("ping/"+cfg.Node.ID, 2, false, "hello world!"); token.Wait() && token.Error() != nil { ncutils.Log("error publishing ping " + token.Error().Error()) } client.Disconnect(250) diff --git a/netclient/functions/peers.go b/netclient/functions/peers.go new file mode 100644 index 00000000..833ebc90 --- /dev/null +++ b/netclient/functions/peers.go @@ -0,0 +1,167 @@ +package functions + +import ( + "log" + "net" + "strconv" + "strings" + "time" + + "github.com/gravitl/netmaker/models" + "github.com/gravitl/netmaker/netclient/ncutils" + "golang.zx2c4.com/wireguard/wgctrl/wgtypes" +) + +func CalculatePeers(thisNode models.Node, peernodes []models.Node, dualstack, egressgateway, server string) ([]wgtypes.Peer, error) { + //hasGateway := false + var gateways []string + var peers []wgtypes.Peer + + keepalive := thisNode.PersistentKeepalive + keepalivedur, _ := time.ParseDuration(strconv.FormatInt(int64(keepalive), 10) + "s") + keepaliveserver, err := time.ParseDuration(strconv.FormatInt(int64(5), 10) + "s") + if err != nil { + log.Fatalf("Issue with format of keepalive value. Please update netconfig: %v", err) + } + for _, node := range peernodes { + pubkey, err := wgtypes.ParseKey(node.PublicKey) + if err != nil { + log.Println("error parsing key") + //return peers, hasGateway, gateways, err + } + + if thisNode.PublicKey == node.PublicKey { + continue + } + if thisNode.Endpoint == node.Endpoint { + if thisNode.LocalAddress != node.LocalAddress && node.LocalAddress != "" { + node.Endpoint = node.LocalAddress + } else { + continue + } + } + + var peer wgtypes.Peer + var peeraddr = net.IPNet{ + IP: net.ParseIP(node.Address), + Mask: net.CIDRMask(32, 32), + } + var allowedips []net.IPNet + allowedips = append(allowedips, peeraddr) + // handle manually set peers + for _, allowedIp := range node.AllowedIPs { + if _, ipnet, err := net.ParseCIDR(allowedIp); err == nil { + nodeEndpointArr := strings.Split(node.Endpoint, ":") + if !ipnet.Contains(net.IP(nodeEndpointArr[0])) && ipnet.IP.String() != node.Address { // don't need to add an allowed ip that already exists.. + allowedips = append(allowedips, *ipnet) + } + } else if appendip := net.ParseIP(allowedIp); appendip != nil && allowedIp != node.Address { + ipnet := net.IPNet{ + IP: net.ParseIP(allowedIp), + Mask: net.CIDRMask(32, 32), + } + allowedips = append(allowedips, ipnet) + } + } + // handle egress gateway peers + if node.IsEgressGateway == "yes" { + //hasGateway = true + ranges := node.EgressGatewayRanges + for _, iprange := range ranges { // go through each cidr for egress gateway + _, ipnet, err := net.ParseCIDR(iprange) // confirming it's valid cidr + if err != nil { + ncutils.PrintLog("could not parse gateway IP range. Not adding "+iprange, 1) + continue // if can't parse CIDR + } + nodeEndpointArr := strings.Split(node.Endpoint, ":") // getting the public ip of node + if ipnet.Contains(net.ParseIP(nodeEndpointArr[0])) { // ensuring egress gateway range does not contain public ip of node + ncutils.PrintLog("egress IP range of "+iprange+" overlaps with "+node.Endpoint+", omitting", 2) + continue // skip adding egress range if overlaps with node's ip + } + if ipnet.Contains(net.ParseIP(thisNode.LocalAddress)) { // ensuring egress gateway range does not contain public ip of node + ncutils.PrintLog("egress IP range of "+iprange+" overlaps with "+thisNode.LocalAddress+", omitting", 2) + continue // skip adding egress range if overlaps with node's local ip + } + gateways = append(gateways, iprange) + if err != nil { + log.Println("ERROR ENCOUNTERED SETTING GATEWAY") + } else { + allowedips = append(allowedips, *ipnet) + } + } + } + if node.Address6 != "" && dualstack == "yes" { + var addr6 = net.IPNet{ + IP: net.ParseIP(node.Address6), + Mask: net.CIDRMask(128, 128), + } + allowedips = append(allowedips, addr6) + } + if thisNode.IsServer == "yes" && !(node.IsServer == "yes") { + peer = wgtypes.Peer{ + PublicKey: pubkey, + PersistentKeepaliveInterval: keepaliveserver, + AllowedIPs: allowedips, + } + } else if keepalive != 0 { + peer = wgtypes.Peer{ + PublicKey: pubkey, + PersistentKeepaliveInterval: keepalivedur, + Endpoint: &net.UDPAddr{ + IP: net.ParseIP(node.Endpoint), + Port: int(node.ListenPort), + }, + AllowedIPs: allowedips, + } + } else { + peer = wgtypes.Peer{ + PublicKey: pubkey, + Endpoint: &net.UDPAddr{ + IP: net.ParseIP(node.Endpoint), + Port: int(node.ListenPort), + }, + AllowedIPs: allowedips, + } + } + peers = append(peers, peer) + } + return peers, nil +} + +func CalculateExtPeers(thisNode models.Node, extPeers []models.ExtPeersResponse) ([]wgtypes.Peer, error) { + var peers []wgtypes.Peer + var err error + for _, extPeer := range extPeers { + pubkey, err := wgtypes.ParseKey(extPeer.PublicKey) + if err != nil { + log.Println("error parsing key") + return peers, err + } + + if thisNode.PublicKey == extPeer.PublicKey { + continue + } + + var peer wgtypes.Peer + var peeraddr = net.IPNet{ + IP: net.ParseIP(extPeer.Address), + Mask: net.CIDRMask(32, 32), + } + var allowedips []net.IPNet + allowedips = append(allowedips, peeraddr) + + if extPeer.Address6 != "" && thisNode.IsDualStack == "yes" { + var addr6 = net.IPNet{ + IP: net.ParseIP(extPeer.Address6), + Mask: net.CIDRMask(128, 128), + } + allowedips = append(allowedips, addr6) + } + peer = wgtypes.Peer{ + PublicKey: pubkey, + AllowedIPs: allowedips, + } + peers = append(peers, peer) + } + return peers, err +} From c06784e19f5e8fcfe07e4759c703529b29b88d50 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Fri, 14 Jan 2022 15:35:15 -0500 Subject: [PATCH 062/116] use uuid in message queue functions --- go.mod | 3 ++- mq/mq.go | 44 +++++++++++------------------------ netclient/functions/daemon.go | 13 ++--------- 3 files changed, 18 insertions(+), 42 deletions(-) diff --git a/go.mod b/go.mod index b4df5780..b3729fdb 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/go-playground/validator/v10 v10.10.0 github.com/golang-jwt/jwt/v4 v4.2.0 github.com/golang/protobuf v1.5.2 // indirect + github.com/google/uuid v1.3.0 github.com/gorilla/handlers v1.5.1 github.com/gorilla/mux v1.8.0 github.com/lib/pq v1.10.4 @@ -38,7 +39,7 @@ require ( github.com/go-playground/locales v0.14.0 // indirect github.com/go-playground/universal-translator v0.18.0 // indirect github.com/google/go-cmp v0.5.5 // indirect - github.com/google/uuid v1.3.0 // indirect + github.com/gorilla/websocket v1.4.2 // indirect github.com/josharian/native v0.0.0-20200817173448-b6b71def0850 // indirect github.com/leodido/go-urn v1.2.1 // indirect github.com/mdlayher/genetlink v1.0.0 // indirect diff --git a/mq/mq.go b/mq/mq.go index fd9657a7..9b5197b2 100644 --- a/mq/mq.go +++ b/mq/mq.go @@ -24,16 +24,15 @@ var Metrics mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { var Ping mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { logger.Log(0, "Ping Handler: "+msg.Topic()) go func() { - mac, net, err := GetMacNetwork(msg.Topic()) + id, err := GetID(msg.Topic()) if err != nil { logger.Log(0, "error getting node.ID sent on ping topic ") return } - logger.Log(0, "ping recieved from "+mac+" on net "+net) - node, err := logic.GetNodeByMacAddress(net, mac) + node, err := logic.GetNodeByID(id) if err != nil { logger.Log(0, "mq-ping error getting node: "+err.Error()) - record, err := database.FetchRecord(database.NODES_TABLE_NAME, mac+"###"+net) + record, err := database.FetchRecord(database.NODES_TABLE_NAME, id) if err != nil { logger.Log(0, "error reading database ", err.Error()) return @@ -54,11 +53,11 @@ var PublicKeyUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Mess go func() { logger.Log(0, "public key update "+msg.Topic()) key := string(msg.Payload()) - mac, network, err := GetMacNetwork(msg.Topic()) + id, err := GetID(msg.Topic()) if err != nil { logger.Log(0, "error getting node.ID sent on "+msg.Topic()+" "+err.Error()) } - node, err := logic.GetNode(mac, network) + node, err := logic.GetNodeByID(id) if err != nil { logger.Log(0, "error retrieving node "+msg.Topic()+" "+err.Error()) } @@ -74,13 +73,13 @@ var IPUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { go func() { ip := string(msg.Payload()) logger.Log(0, "IPUpdate Handler") - mac, network, err := GetMacNetwork(msg.Topic()) - logger.Log(0, "ipUpdate recieved from "+mac+" on net "+network) + id, err := GetID(msg.Topic()) + logger.Log(0, "ipUpdate recieved from "+id) if err != nil { logger.Log(0, "error getting node.ID sent on update/ip topic ") return } - node, err := logic.GetNode(mac, network) + node, err := logic.GetNodeByID(id) if err != nil { logger.Log(0, "invalid ID recieved on update/ip topic: "+err.Error()) return @@ -110,7 +109,8 @@ func UpdatePeers(client mqtt.Client, node models.Node) error { continue } peerUpdate.Nodes = append(peerUpdate.Nodes, peer) - peerUpdate.ExtPeers, err = logic.GetExtPeersList(node.MacAddress, node.Network) + peerUpdate.ExtPeers, err = logic.GetExtPeersList(&node) + if err != nil { logger.Log(0) } @@ -150,12 +150,12 @@ var LocalAddressUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.M logger.Log(0, "LocalAddressUpdate Handler") go func() { logger.Log(0, "LocalAddressUpdate handler") - mac, net, err := GetMacNetwork(msg.Topic()) + id, err := GetID(msg.Topic()) if err != nil { logger.Log(0, "error getting node.ID "+msg.Topic()) return } - node, err := logic.GetNode(mac, net) + node, err := logic.GetNodeByID(id) if err != nil { logger.Log(0, "error get node "+msg.Topic()) return @@ -168,28 +168,12 @@ var LocalAddressUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.M }() } -func GetMacNetwork(topic string) (string, string, error) { - parts := strings.Split(topic, "/") - count := len(parts) - if count == 1 { - return "", "", errors.New("invalid topic") - } - macnet := strings.Split(parts[count-1], "-") - if len(macnet) != 2 { - return "", "", errors.New("topic id not in mac---network format") - } - return macnet[0], macnet[1], nil -} - func GetID(topic string) (string, error) { parts := strings.Split(topic, "/") count := len(parts) if count == 1 { return "", errors.New("invalid topic") } - macnet := strings.Split(parts[count-1], "-") - if len(macnet) != 2 { - return "", errors.New("topic id not in mac---network format") - } - return macnet[0] + "###" + macnet[1], nil + //the last part of the topic will be the node.ID + return parts[count], nil } diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index 6e212c77..bd27ee4d 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -7,7 +7,6 @@ import ( "os" "os/signal" "runtime" - "strings" "syscall" "time" @@ -58,9 +57,6 @@ func Netclient(ctx context.Context, network string) { var cfg config.ClientConfig cfg.Network = network cfg.ReadConfig() - //fix NodeID to remove ### so NodeID can be used as message topic - //remove with GRA-73 - cfg.Node.ID = strings.Replace(cfg.Node.ID, "###", "-", 1) ncutils.Log("daemon started for network:" + network) client := SetupMQTT(cfg) if token := client.Subscribe("#", 0, nil); token.Wait() && token.Error() != nil { @@ -216,9 +212,6 @@ func Checkin(ctx context.Context, cfg config.ClientConfig, network string) { ncutils.Log("Checkin running") //read latest config cfg.ReadConfig() - //fix NodeID to remove ### so NodeID can be used as message topic - //remove with GRA-73 - cfg.Node.ID = strings.Replace(cfg.Node.ID, "###", "-", 1) if cfg.Node.Roaming == "yes" && cfg.Node.IsStatic != "yes" { extIP, err := ncutils.GetPublicIP() if err != nil { @@ -301,15 +294,15 @@ func Metrics(ctx context.Context, cfg config.ClientConfig, network string) { //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? case <-time.After(time.Second * 60): ncutils.Log("Metrics collection running") - ncutils.Log("Metrics running") wg, err := wgctrl.New() + defer wg.Close() if err != nil { ncutils.Log("error getting devices " + err.Error()) break } device, err := wg.Device(cfg.Node.Interface) if err != nil { - ncutils.Log("error readind wg device " + err.Error()) + ncutils.Log("error reading wg device " + err.Error()) break } bytes, err := json.Marshal(device.Peers) @@ -321,8 +314,6 @@ func Metrics(ctx context.Context, cfg config.ClientConfig, network string) { if token := client.Publish("metrics/"+cfg.Node.ID, 1, false, bytes); token.Wait() && token.Error() != nil { ncutils.Log("error publishing metrics " + token.Error().Error()) } - wg.Close() - client.Disconnect(250) ncutils.Log("metrics collection complete") } } From fd981f3d3a04c607d689282f328ff3e12d060eb6 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Fri, 14 Jan 2022 22:22:11 +0000 Subject: [PATCH 063/116] fix off by one error in GetID --- mq/mq.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mq/mq.go b/mq/mq.go index 9b5197b2..3521a165 100644 --- a/mq/mq.go +++ b/mq/mq.go @@ -175,5 +175,5 @@ func GetID(topic string) (string, error) { return "", errors.New("invalid topic") } //the last part of the topic will be the node.ID - return parts[count], nil + return parts[count-1], nil } From cec92773b5d06392bac33d8c5baf67add6aca4c3 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Sat, 15 Jan 2022 18:16:44 -0500 Subject: [PATCH 064/116] moved peer determination to server --- models/mqtt.go | 7 +- mq/mq.go | 67 +++++--------- netclient/functions/daemon.go | 19 +--- netclient/functions/peers.go | 167 ---------------------------------- netclient/wireguard/common.go | 2 +- 5 files changed, 32 insertions(+), 230 deletions(-) delete mode 100644 netclient/functions/peers.go diff --git a/models/mqtt.go b/models/mqtt.go index 07bb2157..3ccab619 100644 --- a/models/mqtt.go +++ b/models/mqtt.go @@ -1,9 +1,10 @@ package models +import "golang.zx2c4.com/wireguard/wgctrl/wgtypes" + type PeerUpdate struct { - Network string - Nodes []Node - ExtPeers []ExtPeersResponse + Network string + Peers []wgtypes.PeerConfig } type KeyUpdate struct { diff --git a/mq/mq.go b/mq/mq.go index 3521a165..cb32b430 100644 --- a/mq/mq.go +++ b/mq/mq.go @@ -1,8 +1,8 @@ package mq import ( + "encoding/json" "errors" - "fmt" "strings" mqtt "github.com/eclipse/paho.mqtt.golang" @@ -86,61 +86,38 @@ var IPUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { } node.Endpoint = ip node.SetLastCheckIn() - if err := UpdatePeers(client, node); err != nil { + if err != UpdatePeers(client, node) { logger.Log(0, "error updating peers "+err.Error()) } }() } func UpdatePeers(client mqtt.Client, node models.Node) error { - var peerUpdate models.PeerUpdate - peerUpdate.Network = node.Network - - nodes, err := logic.GetNetworkNodes(node.Network) + peersToUpdate, err := logic.GetNetworkNodes(node.Network) if err != nil { - return fmt.Errorf("unable to get network nodes %v: ", err) + logger.Log(0, "error retrieving peers to be updated "+err.Error()) + return err } - if token := client.Connect(); token.Wait() && token.Error() != nil { - return token.Error() - } - for _, peer := range nodes { - //don't need to update the initiatiing client - if peer.ID == node.ID { - continue - } - peerUpdate.Nodes = append(peerUpdate.Nodes, peer) - peerUpdate.ExtPeers, err = logic.GetExtPeersList(&node) - + for _, peerToUpdate := range peersToUpdate { + peers, _, _, err := logic.GetServerPeers(&peerToUpdate) if err != nil { - logger.Log(0) + logger.Log(0, "error retrieving peers "+err.Error()) + return err } - if token := client.Publish("update/peers/"+peer.ID, 0, false, nodes); token.Wait() && token.Error() != nil { - logger.Log(0, "error publishing peer update "+peer.ID+" "+token.Error().Error()) - } - } - - return nil -} - -func UpdateLocalPeers(client mqtt.Client, node models.Node) error { - nodes, err := logic.GetNetworkNodes(node.Network) - if err != nil { - return fmt.Errorf("unable to get network nodes %v: ", err) - } - if token := client.Connect(); token.Wait() && token.Error() != nil { - return token.Error() - } - for _, peer := range nodes { - //don't need to update the initiatiing client - if peer.ID == node.ID { + if peerToUpdate.ID == node.ID { continue } - //if peer.Endpoint is on same lan as node.LocalAddress - //if TODO{ - //continue - //} - if token := client.Publish("update/peers/"+peer.ID, 0, false, nodes); token.Wait() && token.Error() != nil { - logger.Log(0, "error publishing peer update "+peer.ID+" "+token.Error().Error()) + var peerUpdate models.PeerUpdate + peerUpdate.Network = node.Network + peerUpdate.Peers = peers + data, err := json.Marshal(peerUpdate) + if err != nil { + logger.Log(0, "error marshaling peer update "+err.Error()) + return err + } + if token := client.Publish("/update/peers/"+peerToUpdate.ID, 0, false, data); token.Wait() && token.Error() != nil { + logger.Log(0, "error sending peer updatte to no") + return err } } return nil @@ -162,7 +139,7 @@ var LocalAddressUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.M } node.LocalAddress = string(msg.Payload()) node.SetLastCheckIn() - if err := UpdateLocalPeers(client, node); err != nil { + if err := UpdatePeers(client, node); err != nil { logger.Log(0, "error updating peers "+err.Error()) } }() diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index bd27ee4d..ec569e7c 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -28,7 +28,7 @@ func Daemon() error { return err } for _, network := range networks { - go Netclient(ctx, network) + go MessageQueue(ctx, network) } quit := make(chan os.Signal, 1) signal.Notify(quit, syscall.SIGTERM, os.Interrupt) @@ -51,8 +51,8 @@ func SetupMQTT(cfg config.ClientConfig) mqtt.Client { return client } -// Netclient sets up Message Queue and subsribes/publishes updates to/from server -func Netclient(ctx context.Context, network string) { +// MessageQueue sets up Message Queue and subsribes/publishes updates to/from server +func MessageQueue(ctx context.Context, network string) { ncutils.Log("netclient go routine started for " + network) var cfg config.ClientConfig cfg.Network = network @@ -150,17 +150,7 @@ var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) var cfg config.ClientConfig cfg.Network = peerUpdate.Network cfg.ReadConfig() - peers, err := CalculatePeers(cfg.Node, peerUpdate.Nodes, cfg.Node.IsDualStack, cfg.Node.IsEgressGateway, cfg.Node.IsServer) - if err != nil { - ncutils.Log("error calculating Peers " + err.Error()) - return - } - extpeers, err := CalculateExtPeers(cfg.Node, peerUpdate.ExtPeers) - if err != nil { - ncutils.Log("error updated external wireguard peers " + err.Error()) - } - peers = append(peers, extpeers...) - err = wireguard.UpdateWgPeers(cfg.Node.Interface, peers) + err = wireguard.UpdateWgPeers(cfg.Node.Interface, peerUpdate.Peers) if err != nil { ncutils.Log("error updating wireguard peers" + err.Error()) return @@ -315,6 +305,7 @@ func Metrics(ctx context.Context, cfg config.ClientConfig, network string) { ncutils.Log("error publishing metrics " + token.Error().Error()) } ncutils.Log("metrics collection complete") + client.Disconnect(250) } } } diff --git a/netclient/functions/peers.go b/netclient/functions/peers.go deleted file mode 100644 index 833ebc90..00000000 --- a/netclient/functions/peers.go +++ /dev/null @@ -1,167 +0,0 @@ -package functions - -import ( - "log" - "net" - "strconv" - "strings" - "time" - - "github.com/gravitl/netmaker/models" - "github.com/gravitl/netmaker/netclient/ncutils" - "golang.zx2c4.com/wireguard/wgctrl/wgtypes" -) - -func CalculatePeers(thisNode models.Node, peernodes []models.Node, dualstack, egressgateway, server string) ([]wgtypes.Peer, error) { - //hasGateway := false - var gateways []string - var peers []wgtypes.Peer - - keepalive := thisNode.PersistentKeepalive - keepalivedur, _ := time.ParseDuration(strconv.FormatInt(int64(keepalive), 10) + "s") - keepaliveserver, err := time.ParseDuration(strconv.FormatInt(int64(5), 10) + "s") - if err != nil { - log.Fatalf("Issue with format of keepalive value. Please update netconfig: %v", err) - } - for _, node := range peernodes { - pubkey, err := wgtypes.ParseKey(node.PublicKey) - if err != nil { - log.Println("error parsing key") - //return peers, hasGateway, gateways, err - } - - if thisNode.PublicKey == node.PublicKey { - continue - } - if thisNode.Endpoint == node.Endpoint { - if thisNode.LocalAddress != node.LocalAddress && node.LocalAddress != "" { - node.Endpoint = node.LocalAddress - } else { - continue - } - } - - var peer wgtypes.Peer - var peeraddr = net.IPNet{ - IP: net.ParseIP(node.Address), - Mask: net.CIDRMask(32, 32), - } - var allowedips []net.IPNet - allowedips = append(allowedips, peeraddr) - // handle manually set peers - for _, allowedIp := range node.AllowedIPs { - if _, ipnet, err := net.ParseCIDR(allowedIp); err == nil { - nodeEndpointArr := strings.Split(node.Endpoint, ":") - if !ipnet.Contains(net.IP(nodeEndpointArr[0])) && ipnet.IP.String() != node.Address { // don't need to add an allowed ip that already exists.. - allowedips = append(allowedips, *ipnet) - } - } else if appendip := net.ParseIP(allowedIp); appendip != nil && allowedIp != node.Address { - ipnet := net.IPNet{ - IP: net.ParseIP(allowedIp), - Mask: net.CIDRMask(32, 32), - } - allowedips = append(allowedips, ipnet) - } - } - // handle egress gateway peers - if node.IsEgressGateway == "yes" { - //hasGateway = true - ranges := node.EgressGatewayRanges - for _, iprange := range ranges { // go through each cidr for egress gateway - _, ipnet, err := net.ParseCIDR(iprange) // confirming it's valid cidr - if err != nil { - ncutils.PrintLog("could not parse gateway IP range. Not adding "+iprange, 1) - continue // if can't parse CIDR - } - nodeEndpointArr := strings.Split(node.Endpoint, ":") // getting the public ip of node - if ipnet.Contains(net.ParseIP(nodeEndpointArr[0])) { // ensuring egress gateway range does not contain public ip of node - ncutils.PrintLog("egress IP range of "+iprange+" overlaps with "+node.Endpoint+", omitting", 2) - continue // skip adding egress range if overlaps with node's ip - } - if ipnet.Contains(net.ParseIP(thisNode.LocalAddress)) { // ensuring egress gateway range does not contain public ip of node - ncutils.PrintLog("egress IP range of "+iprange+" overlaps with "+thisNode.LocalAddress+", omitting", 2) - continue // skip adding egress range if overlaps with node's local ip - } - gateways = append(gateways, iprange) - if err != nil { - log.Println("ERROR ENCOUNTERED SETTING GATEWAY") - } else { - allowedips = append(allowedips, *ipnet) - } - } - } - if node.Address6 != "" && dualstack == "yes" { - var addr6 = net.IPNet{ - IP: net.ParseIP(node.Address6), - Mask: net.CIDRMask(128, 128), - } - allowedips = append(allowedips, addr6) - } - if thisNode.IsServer == "yes" && !(node.IsServer == "yes") { - peer = wgtypes.Peer{ - PublicKey: pubkey, - PersistentKeepaliveInterval: keepaliveserver, - AllowedIPs: allowedips, - } - } else if keepalive != 0 { - peer = wgtypes.Peer{ - PublicKey: pubkey, - PersistentKeepaliveInterval: keepalivedur, - Endpoint: &net.UDPAddr{ - IP: net.ParseIP(node.Endpoint), - Port: int(node.ListenPort), - }, - AllowedIPs: allowedips, - } - } else { - peer = wgtypes.Peer{ - PublicKey: pubkey, - Endpoint: &net.UDPAddr{ - IP: net.ParseIP(node.Endpoint), - Port: int(node.ListenPort), - }, - AllowedIPs: allowedips, - } - } - peers = append(peers, peer) - } - return peers, nil -} - -func CalculateExtPeers(thisNode models.Node, extPeers []models.ExtPeersResponse) ([]wgtypes.Peer, error) { - var peers []wgtypes.Peer - var err error - for _, extPeer := range extPeers { - pubkey, err := wgtypes.ParseKey(extPeer.PublicKey) - if err != nil { - log.Println("error parsing key") - return peers, err - } - - if thisNode.PublicKey == extPeer.PublicKey { - continue - } - - var peer wgtypes.Peer - var peeraddr = net.IPNet{ - IP: net.ParseIP(extPeer.Address), - Mask: net.CIDRMask(32, 32), - } - var allowedips []net.IPNet - allowedips = append(allowedips, peeraddr) - - if extPeer.Address6 != "" && thisNode.IsDualStack == "yes" { - var addr6 = net.IPNet{ - IP: net.ParseIP(extPeer.Address6), - Mask: net.CIDRMask(128, 128), - } - allowedips = append(allowedips, addr6) - } - peer = wgtypes.Peer{ - PublicKey: pubkey, - AllowedIPs: allowedips, - } - peers = append(peers, peer) - } - return peers, err -} diff --git a/netclient/wireguard/common.go b/netclient/wireguard/common.go index 5fd70fc1..cf3e7017 100644 --- a/netclient/wireguard/common.go +++ b/netclient/wireguard/common.go @@ -334,7 +334,7 @@ func WriteWgConfig(cfg config.ClientConfig, privateKey string, peers []wgtypes.P } // UpdateWgPeers - updates the peers of a network -func UpdateWgPeers(wgInterface string, peers []wgtypes.Peer) error { +func UpdateWgPeers(wgInterface string, peers []wgtypes.PeerConfig) error { //update to get path properly file := ncutils.GetNetclientPathSpecific() + wgInterface + ".conf" wireguard, err := ini.ShadowLoad(file) From a926709c1020b76c4ab5b6f66fd84d78d6c174f4 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Tue, 18 Jan 2022 22:32:12 +0000 Subject: [PATCH 065/116] fix publish peers --- controllers/node_grpc.go | 5 +++ logic/nodes.go | 54 +++++++++++++++++++++--- main.go | 4 -- mq/mq.go | 90 +++++++++++++++++++++++++++++++--------- 4 files changed, 124 insertions(+), 29 deletions(-) diff --git a/controllers/node_grpc.go b/controllers/node_grpc.go index f606a187..06591ca9 100644 --- a/controllers/node_grpc.go +++ b/controllers/node_grpc.go @@ -10,6 +10,7 @@ import ( "github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/logic" "github.com/gravitl/netmaker/models" + "github.com/gravitl/netmaker/mq" "github.com/gravitl/netmaker/servercfg" ) @@ -85,6 +86,10 @@ func (s *NodeServiceServer) CreateNode(ctx context.Context, req *nodepb.Object) if err != nil { return nil, err } + // notify other nodes on network of new peer + if err := mq.NewPeer(node); err != nil { + logger.Log(0, "failed to inform peers of new node "+err.Error()) + } return response, nil } diff --git a/logic/nodes.go b/logic/nodes.go index 6b35c4bc..0c8c6b81 100644 --- a/logic/nodes.go +++ b/logic/nodes.go @@ -4,7 +4,9 @@ import ( "encoding/json" "errors" "fmt" + "net" "sort" + "strconv" "strings" "time" @@ -14,6 +16,7 @@ import ( "github.com/gravitl/netmaker/models" "github.com/gravitl/netmaker/servercfg" "github.com/gravitl/netmaker/validation" + "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) // GetNetworkNodes - gets the nodes of a network @@ -74,7 +77,7 @@ func UncordonNode(nodeid string) (models.Node, error) { node.SetLastModified() node.IsPending = "no" node.PullChanges = "yes" - data, err := json.Marshal(&node) + data, err := json.Marshal(&node) if err != nil { return node, err } @@ -83,11 +86,52 @@ func UncordonNode(nodeid string) (models.Node, error) { return node, err } -// GetPeers - gets the peers of a given node -func GetPeers(node *models.Node) ([]models.Node, error) { - if IsLeader(node) { - SetNetworkServerPeers(node) +// GetWGNodePeers - gets the wg peers of a given node +func GetWGNodePeers(node *models.Node) ([]wgtypes.PeerConfig, error){ + var peers []wgtypes.PeerConfig + var peerData wgtypes.PeerConfig + nodes, err := GetPeers(node) + if err != nil { + return peers, err } + logger.Log(0, "the peers of " + node.Name + " are:") + for _, peer := range nodes { + logger.Log(0, "peer: " + peer.Name) + } + for _, peer := range nodes { + //this should not happen but it does + if peer.Name == node.Name { + logger.Log(0, "GetPeers returned me " + node.Name) + continue + } + pubkey, err :=wgtypes.ParseKey(peer.PublicKey) + if err != nil { + logger.Log(0, "ParseKey failed " +err.Error()) + continue + } + endpoint := peer.Endpoint + ":" + strconv.Itoa(int(peer.ListenPort)) + address, err := net.ResolveUDPAddr("udp", endpoint) + if err != nil { + logger.Log(0, "could not resolve endpoint " + err.Error()) + continue + } + ///Persitent Keepalive + //Allowed IPs + peerData = wgtypes.PeerConfig{ + PublicKey: pubkey, + Endpoint: address, + } + peers = append (peers, peerData) + } + return peers, nil +} + +// GetPeers - gets a list of nodes that are peers of a given node +func GetPeers(node *models.Node) ([]models.Node, error) { + //if IsLeader(node) { + // logger.Log(0, node.Name + " is a leader") + // SetNetworkServerPeers(node) + //} excludeIsRelayed := node.IsRelay != "yes" var relayedNode string if node.IsRelayed == "yes" { diff --git a/main.go b/main.go index 3d527a0b..b48ed5f7 100644 --- a/main.go +++ b/main.go @@ -208,10 +208,6 @@ func runMessageQueue(wg *sync.WaitGroup) { client.Disconnect(240) logger.Log(0, "ping sub failed") } - if token := client.Subscribe("metrics/#", 0, mq.Metrics); token.Wait() && token.Error() != nil { - client.Disconnect(240) - logger.Log(0, "metrics sub failed") - } if token := client.Subscribe("update/localaddress/#", 0, mq.LocalAddressUpdate); token.Wait() && token.Error() != nil { client.Disconnect(240) logger.Log(0, "metrics sub failed") diff --git a/mq/mq.go b/mq/mq.go index cb32b430..6cd80dcc 100644 --- a/mq/mq.go +++ b/mq/mq.go @@ -3,24 +3,24 @@ package mq import ( "encoding/json" "errors" + "net" + "strconv" "strings" + "time" mqtt "github.com/eclipse/paho.mqtt.golang" "github.com/gravitl/netmaker/database" "github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/logic" "github.com/gravitl/netmaker/models" + "github.com/gravitl/netmaker/servercfg" + "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) var DefaultHandler mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { logger.Log(0, "MQTT Message: Topic: "+string(msg.Topic())+" Message: "+string(msg.Payload())) } -var Metrics mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { - logger.Log(0, "Metrics Handler") - //TODOD -- handle metrics data ---- store to database? -} - var Ping mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { logger.Log(0, "Ping Handler: "+msg.Topic()) go func() { @@ -42,6 +42,9 @@ var Ping mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { return } node.SetLastCheckIn() + if err := logic.UpdateNode(&node, &node) ; err != nil { + logger.Log(0, "error updating node "+ err.Error()) + } logger.Log(0, "ping processed") // --TODO --set client version once feature is implemented. //node.SetClientVersion(msg.Payload()) @@ -63,6 +66,9 @@ var PublicKeyUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Mess } node.PublicKey = key node.SetLastCheckIn() + if err := logic.UpdateNode(&node, &node) ; err != nil { + logger.Log(0, "error updating node "+ err.Error()) + } if err := UpdatePeers(client, node); err != nil { logger.Log(0, "error updating peers "+err.Error()) } @@ -86,36 +92,64 @@ var IPUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { } node.Endpoint = ip node.SetLastCheckIn() + if err := logic.UpdateNode(&node, &node) ; err != nil { + logger.Log(0, "error updating node "+ err.Error()) + } if err != UpdatePeers(client, node) { logger.Log(0, "error updating peers "+err.Error()) } }() } -func UpdatePeers(client mqtt.Client, node models.Node) error { - peersToUpdate, err := logic.GetNetworkNodes(node.Network) +func UpdatePeers(client mqtt.Client, newnode models.Node) error { + networkNodes, err := logic.GetNetworkNodes(newnode.Network) if err != nil { - logger.Log(0, "error retrieving peers to be updated "+err.Error()) return err } - for _, peerToUpdate := range peersToUpdate { - peers, _, _, err := logic.GetServerPeers(&peerToUpdate) - if err != nil { - logger.Log(0, "error retrieving peers "+err.Error()) - return err - } - if peerToUpdate.ID == node.ID { - continue - } + keepalive, _ := time.ParseDuration(string(newnode.PersistentKeepalive)+"s") + for _, node := range networkNodes { + var peers []wgtypes.PeerConfig var peerUpdate models.PeerUpdate + for _, peer := range networkNodes{ + if peer.ID == node.ID { + //skip + continue + } + pubkey, err := wgtypes.ParseKey(peer.PublicKey) + if err != nil { + return err + } + if node.Endpoint == peer.Endpoint { + if node.LocalAddress != peer.LocalAddress && peer.LocalAddress != "" { + peer.Endpoint = peer.LocalAddress + }else { + continue + } + } + endpoint := peer.Endpoint + ":" + strconv.Itoa(int(peer.ListenPort)) + //fmt.Println("endpoint: ", endpoint, peer.Endpoint, peer.ListenPort) + address, err := net.ResolveUDPAddr("udp", endpoint) + if err != nil { + return err + } + //calculate Allowed IPs. + var peerData wgtypes.PeerConfig + peerData = wgtypes.PeerConfig{ + PublicKey: pubkey, + Endpoint: address, + PersistentKeepaliveInterval: &keepalive, + //AllowedIPs: allowedIPs + } + peers = append (peers, peerData) + } peerUpdate.Network = node.Network - peerUpdate.Peers = peers - data, err := json.Marshal(peerUpdate) + peerUpdate.Peers = peers + data, err := json.Marshal(&peerUpdate) if err != nil { logger.Log(0, "error marshaling peer update "+err.Error()) return err } - if token := client.Publish("/update/peers/"+peerToUpdate.ID, 0, false, data); token.Wait() && token.Error() != nil { + if token := client.Publish("/update/peers/"+node.ID, 0, false, data); token.Wait() && token.Error() != nil { logger.Log(0, "error sending peer updatte to no") return err } @@ -154,3 +188,19 @@ func GetID(topic string) (string, error) { //the last part of the topic will be the node.ID return parts[count-1], nil } + +func NewPeer(node models.Node) error { + opts := mqtt.NewClientOptions() + broker := servercfg.GetMessageQueueEndpoint() + logger.Log(0, "broker: "+broker) + opts.AddBroker(broker) + client := mqtt.NewClient(opts) + if token := client.Connect(); token.Wait() && token.Error() != nil { + return token.Error() + } + + if err := UpdatePeers(client, node); err != nil { + return err + } + return nil +} From 4213a4a3fd055eee471d080595eec00fc3040fe5 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Tue, 18 Jan 2022 17:36:10 -0500 Subject: [PATCH 066/116] remove metrics from client --- netclient/functions/daemon.go | 40 +---------------------------------- 1 file changed, 1 insertion(+), 39 deletions(-) diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index ec569e7c..dcb16e1a 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -15,7 +15,6 @@ import ( "github.com/gravitl/netmaker/netclient/config" "github.com/gravitl/netmaker/netclient/ncutils" "github.com/gravitl/netmaker/netclient/wireguard" - "golang.zx2c4.com/wireguard/wgctrl" "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) @@ -68,7 +67,6 @@ func MessageQueue(ctx context.Context, network string) { //client.AddRoute("update/keys/"+cfg.Node.ID, UpdateKeys) defer client.Disconnect(250) go Checkin(ctx, cfg, network) - go Metrics(ctx, cfg, network) <-ctx.Done() ncutils.Log("shutting down daemon") } @@ -198,7 +196,7 @@ func Checkin(ctx context.Context, cfg config.ClientConfig, network string) { ncutils.Log("Checkin cancelled") return //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? - case <-time.After(time.Second * 10): + case <-time.After(time.Second * 60): ncutils.Log("Checkin running") //read latest config cfg.ReadConfig() @@ -273,39 +271,3 @@ func Hello(cfg config.ClientConfig, network string) { } client.Disconnect(250) } - -// Metics -- go routine that collects wireguard metrics and publishes to broker -func Metrics(ctx context.Context, cfg config.ClientConfig, network string) { - for { - select { - case <-ctx.Done(): - ncutils.Log("Metrics collection cancelled") - return - //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? - case <-time.After(time.Second * 60): - ncutils.Log("Metrics collection running") - wg, err := wgctrl.New() - defer wg.Close() - if err != nil { - ncutils.Log("error getting devices " + err.Error()) - break - } - device, err := wg.Device(cfg.Node.Interface) - if err != nil { - ncutils.Log("error reading wg device " + err.Error()) - break - } - bytes, err := json.Marshal(device.Peers) - if err != nil { - ncutils.Log("error marshaling peers " + err.Error()) - break - } - client := SetupMQTT(cfg) - if token := client.Publish("metrics/"+cfg.Node.ID, 1, false, bytes); token.Wait() && token.Error() != nil { - ncutils.Log("error publishing metrics " + token.Error().Error()) - } - ncutils.Log("metrics collection complete") - client.Disconnect(250) - } - } -} From 81e65b0fd0d19237a412019e40cc9b996a014252 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Wed, 19 Jan 2022 09:44:35 -0500 Subject: [PATCH 067/116] calculate allowed ips --- mq/mq.go | 177 ++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 135 insertions(+), 42 deletions(-) diff --git a/mq/mq.go b/mq/mq.go index 6cd80dcc..f1f5553d 100644 --- a/mq/mq.go +++ b/mq/mq.go @@ -3,6 +3,7 @@ package mq import ( "encoding/json" "errors" + "log" "net" "strconv" "strings" @@ -13,6 +14,7 @@ import ( "github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/logic" "github.com/gravitl/netmaker/models" + "github.com/gravitl/netmaker/netclient/ncutils" "github.com/gravitl/netmaker/servercfg" "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) @@ -42,8 +44,8 @@ var Ping mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { return } node.SetLastCheckIn() - if err := logic.UpdateNode(&node, &node) ; err != nil { - logger.Log(0, "error updating node "+ err.Error()) + if err := logic.UpdateNode(&node, &node); err != nil { + logger.Log(0, "error updating node "+err.Error()) } logger.Log(0, "ping processed") // --TODO --set client version once feature is implemented. @@ -66,8 +68,8 @@ var PublicKeyUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Mess } node.PublicKey = key node.SetLastCheckIn() - if err := logic.UpdateNode(&node, &node) ; err != nil { - logger.Log(0, "error updating node "+ err.Error()) + if err := logic.UpdateNode(&node, &node); err != nil { + logger.Log(0, "error updating node "+err.Error()) } if err := UpdatePeers(client, node); err != nil { logger.Log(0, "error updating peers "+err.Error()) @@ -92,8 +94,8 @@ var IPUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { } node.Endpoint = ip node.SetLastCheckIn() - if err := logic.UpdateNode(&node, &node) ; err != nil { - logger.Log(0, "error updating node "+ err.Error()) + if err := logic.UpdateNode(&node, &node); err != nil { + logger.Log(0, "error updating node "+err.Error()) } if err != UpdatePeers(client, node) { logger.Log(0, "error updating peers "+err.Error()) @@ -106,50 +108,141 @@ func UpdatePeers(client mqtt.Client, newnode models.Node) error { if err != nil { return err } - keepalive, _ := time.ParseDuration(string(newnode.PersistentKeepalive)+"s") - for _, node := range networkNodes { - var peers []wgtypes.PeerConfig + dualstack := false + keepalive, _ := time.ParseDuration(string(newnode.PersistentKeepalive) + "s") + defaultkeepalive, _ := time.ParseDuration("25s") + for _, node := range networkNodes { + var peers []wgtypes.PeerConfig var peerUpdate models.PeerUpdate - for _, peer := range networkNodes{ - if peer.ID == node.ID { - //skip - continue - } - pubkey, err := wgtypes.ParseKey(peer.PublicKey) - if err != nil { + var gateways []string + + for _, peer := range networkNodes { + if peer.ID == node.ID { + //skip + continue + } + var allowedips []net.IPNet + var peeraddr = net.IPNet{ + IP: net.ParseIP(peer.Address), + Mask: net.CIDRMask(32, 32), + } + //hasGateway := false + pubkey, err := wgtypes.ParseKey(peer.PublicKey) + if err != nil { return err - } - if node.Endpoint == peer.Endpoint { - if node.LocalAddress != peer.LocalAddress && peer.LocalAddress != "" { - peer.Endpoint = peer.LocalAddress - }else { - continue - } - } - endpoint := peer.Endpoint + ":" + strconv.Itoa(int(peer.ListenPort)) - //fmt.Println("endpoint: ", endpoint, peer.Endpoint, peer.ListenPort) - address, err := net.ResolveUDPAddr("udp", endpoint) - if err != nil { + } + if node.Endpoint == peer.Endpoint { + if node.LocalAddress != peer.LocalAddress && peer.LocalAddress != "" { + peer.Endpoint = peer.LocalAddress + } else { + continue + } + } + endpoint := peer.Endpoint + ":" + strconv.Itoa(int(peer.ListenPort)) + //fmt.Println("endpoint: ", endpoint, peer.Endpoint, peer.ListenPort) + address, err := net.ResolveUDPAddr("udp", endpoint) + if err != nil { return err - } - //calculate Allowed IPs. - var peerData wgtypes.PeerConfig - peerData = wgtypes.PeerConfig{ - PublicKey: pubkey, - Endpoint: address, - PersistentKeepaliveInterval: &keepalive, - //AllowedIPs: allowedIPs - } - peers = append (peers, peerData) - } + } + //calculate Allowed IPs. + allowedips = append(allowedips, peeraddr) + // handle manually set peers + for _, allowedIp := range node.AllowedIPs { + if _, ipnet, err := net.ParseCIDR(allowedIp); err == nil { + nodeEndpointArr := strings.Split(node.Endpoint, ":") + if !ipnet.Contains(net.IP(nodeEndpointArr[0])) && ipnet.IP.String() != node.Address { // don't need to add an allowed ip that already exists.. + allowedips = append(allowedips, *ipnet) + } + } else if appendip := net.ParseIP(allowedIp); appendip != nil && allowedIp != node.Address { + ipnet := net.IPNet{ + IP: net.ParseIP(allowedIp), + Mask: net.CIDRMask(32, 32), + } + allowedips = append(allowedips, ipnet) + } + } + // handle egress gateway peers + if node.IsEgressGateway == "yes" { + //hasGateway = true + ranges := node.EgressGatewayRanges + for _, iprange := range ranges { // go through each cidr for egress gateway + _, ipnet, err := net.ParseCIDR(iprange) // confirming it's valid cidr + if err != nil { + ncutils.PrintLog("could not parse gateway IP range. Not adding "+iprange, 1) + continue // if can't parse CIDR + } + nodeEndpointArr := strings.Split(node.Endpoint, ":") // getting the public ip of node + if ipnet.Contains(net.ParseIP(nodeEndpointArr[0])) { // ensuring egress gateway range does not contain public ip of node + ncutils.PrintLog("egress IP range of "+iprange+" overlaps with "+node.Endpoint+", omitting", 2) + continue // skip adding egress range if overlaps with node's ip + } + if ipnet.Contains(net.ParseIP(node.LocalAddress)) { // ensuring egress gateway range does not contain public ip of node + ncutils.PrintLog("egress IP range of "+iprange+" overlaps with "+node.LocalAddress+", omitting", 2) + continue // skip adding egress range if overlaps with node's local ip + } + gateways = append(gateways, iprange) + if err != nil { + log.Println("ERROR ENCOUNTERED SETTING GATEWAY") + } else { + allowedips = append(allowedips, *ipnet) + } + } + } + var peerData wgtypes.PeerConfig + if node.Address6 != "" && dualstack { + var addr6 = net.IPNet{ + IP: net.ParseIP(node.Address6), + Mask: net.CIDRMask(128, 128), + } + allowedips = append(allowedips, addr6) + } + if node.IsServer == "yes" && !(node.IsServer == "yes") { + peerData = wgtypes.PeerConfig{ + PublicKey: pubkey, + PersistentKeepaliveInterval: &defaultkeepalive, + ReplaceAllowedIPs: true, + AllowedIPs: allowedips, + } + } else if keepalive != 0 { + peerData = wgtypes.PeerConfig{ + PublicKey: pubkey, + PersistentKeepaliveInterval: &defaultkeepalive, + //Endpoint: &net.UDPAddr{ + // IP: net.ParseIP(node.Endpoint), + // Port: int(node.ListenPort), + //}, + Endpoint: address, + ReplaceAllowedIPs: true, + AllowedIPs: allowedips, + } + } else { + peerData = wgtypes.PeerConfig{ + PublicKey: pubkey, + //Endpoint: &net.UDPAddr{ + // IP: net.ParseIP(node.Endpoint), + // Port: int(node.ListenPort), + //}, + Endpoint: address, + ReplaceAllowedIPs: true, + AllowedIPs: allowedips, + } + } + //peerData = wgtypes.PeerConfig{ + // PublicKey: pubkey, + // Endpoint: address, + // PersistentKeepaliveInterval: &keepalive, + //AllowedIPs: allowedIPs + //} + peers = append(peers, peerData) + } peerUpdate.Network = node.Network - peerUpdate.Peers = peers + peerUpdate.Peers = peers data, err := json.Marshal(&peerUpdate) if err != nil { logger.Log(0, "error marshaling peer update "+err.Error()) return err } - if token := client.Publish("/update/peers/"+node.ID, 0, false, data); token.Wait() && token.Error() != nil { + if token := client.Publish("/update/peers/"+node.ID, 0, false, data); token.Wait() && token.Error() != nil { logger.Log(0, "error sending peer updatte to no") return err } @@ -198,7 +291,7 @@ func NewPeer(node models.Node) error { if token := client.Connect(); token.Wait() && token.Error() != nil { return token.Error() } - + if err := UpdatePeers(client, node); err != nil { return err } From e215f2a9d011fa261294b8aebfd62acb0a1ae852 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Wed, 19 Jan 2022 15:00:03 -0500 Subject: [PATCH 068/116] fix UpdateWgPeers --- netclient/functions/daemon.go | 29 +++++++++++++++++++++++------ netclient/wireguard/common.go | 26 ++++++++++++++++++-------- netclient/wireguard/unix.go | 15 +++++++++++++-- 3 files changed, 54 insertions(+), 16 deletions(-) diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index dcb16e1a..b339e1b4 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -61,8 +61,16 @@ func MessageQueue(ctx context.Context, network string) { if token := client.Subscribe("#", 0, nil); token.Wait() && token.Error() != nil { log.Fatal(token.Error()) } - client.AddRoute("update/"+cfg.Node.ID, NodeUpdate) - client.AddRoute("update/peers/"+cfg.Node.ID, UpdatePeers) + if token := client.Subscribe("update/"+cfg.Node.ID, 0, NodeUpdate); token.Wait() && token.Error() != nil { + log.Fatal(token.Error()) + } + if token := client.Subscribe("/update/peers/"+cfg.Node.ID, 0, UpdatePeers); token.Wait() && token.Error() != nil { + log.Fatal(token.Error()) + } + + //addroute doesn't seem to work consistently + //client.AddRoute("update/"+cfg.Node.ID, NodeUpdate) + //client.AddRoute("update/peers/"+cfg.Node.ID, UpdatePeers) //handle key updates in node update //client.AddRoute("update/keys/"+cfg.Node.ID, UpdateKeys) defer client.Disconnect(250) @@ -73,8 +81,9 @@ func MessageQueue(ctx context.Context, network string) { // All -- mqtt message hander for all ('#') topics var All mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { + ncutils.Log("default message handler -- received message but not handling") ncutils.Log("Topic: " + string(msg.Topic())) - ncutils.Log("Message: " + string(msg.Payload())) + //ncutils.Log("Message: " + string(msg.Payload())) } // NodeUpdate -- mqtt message handler for /update/ topic @@ -137,7 +146,6 @@ var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) // UpdatePeers -- mqtt message handler for /update/peers/ topic var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { - ncutils.Log("received message to update peers " + string(msg.Payload())) go func() { var peerUpdate models.PeerUpdate err := json.Unmarshal(msg.Payload(), &peerUpdate) @@ -145,6 +153,14 @@ var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) ncutils.Log("error unmarshalling peer data") return } + ncutils.Log("update peer handler") + ncutils.Log("recieved " + string(len(peerUpdate.Peers)) + "peers to update") + ncutils.Log(string(msg.Payload())) + ncutils.Log(peerUpdate.Network) + for _, peer := range peerUpdate.Peers { + key := peer.PublicKey.String() + ncutils.Log(key) + } var cfg config.ClientConfig cfg.Network = peerUpdate.Network cfg.ReadConfig() @@ -153,8 +169,9 @@ var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) ncutils.Log("error updating wireguard peers" + err.Error()) return } - // path hardcoded for now... should be updated - err = wireguard.ApplyWGQuickConf("/etc/netclient/config/" + cfg.Node.Interface + ".conf") + file := ncutils.GetNetclientPathSpecific() + cfg.Node.Interface + ".conf" + ncutils.Log("applyWGQuickConf to " + file) + err = wireguard.ApplyWGQuickConf(file) if err != nil { ncutils.Log("error restarting wg after peer update " + err.Error()) return diff --git a/netclient/wireguard/common.go b/netclient/wireguard/common.go index cf3e7017..94742eb9 100644 --- a/netclient/wireguard/common.go +++ b/netclient/wireguard/common.go @@ -318,8 +318,12 @@ func WriteWgConfig(cfg config.ClientConfig, privateKey string, peers []wgtypes.P } if peer.AllowedIPs != nil { var allowedIPs string - for _, ip := range peer.AllowedIPs { - allowedIPs = allowedIPs + ", " + ip.String() + for i, ip := range peer.AllowedIPs { + if i == 0 { + allowedIPs = ip.String() + } else { + allowedIPs = allowedIPs + ", " + ip.String() + } } wireguard.SectionWithIndex(section_peers, i).Key("AllowedIps").SetValue(allowedIPs) } @@ -335,21 +339,27 @@ func WriteWgConfig(cfg config.ClientConfig, privateKey string, peers []wgtypes.P // UpdateWgPeers - updates the peers of a network func UpdateWgPeers(wgInterface string, peers []wgtypes.PeerConfig) error { - //update to get path properly file := ncutils.GetNetclientPathSpecific() + wgInterface + ".conf" + ncutils.Log("updating " + file) wireguard, err := ini.ShadowLoad(file) if err != nil { return err } + //delete the peers sections as they are going to be replaced + wireguard.DeleteSection(section_peers) for i, peer := range peers { wireguard.SectionWithIndex(section_peers, i).Key("PublicKey").SetValue(peer.PublicKey.String()) - if peer.PresharedKey.String() != "" { - wireguard.SectionWithIndex(section_peers, i).Key("PreSharedKey").SetValue(peer.PresharedKey.String()) - } + //if peer.PresharedKey.String() != "" { + //wireguard.SectionWithIndex(section_peers, i).Key("PreSharedKey").SetValue(peer.PresharedKey.String()) + //} if peer.AllowedIPs != nil { var allowedIPs string - for _, ip := range peer.AllowedIPs { - allowedIPs = allowedIPs + ", " + ip.String() + for i, ip := range peer.AllowedIPs { + if i == 0 { + allowedIPs = ip.String() + } else { + allowedIPs = allowedIPs + ", " + ip.String() + } } wireguard.SectionWithIndex(section_peers, i).Key("AllowedIps").SetValue(allowedIPs) } diff --git a/netclient/wireguard/unix.go b/netclient/wireguard/unix.go index 254f6482..7d6eb6ff 100644 --- a/netclient/wireguard/unix.go +++ b/netclient/wireguard/unix.go @@ -53,8 +53,19 @@ func SetWGKeyConfig(network string, serveraddr string) error { // ApplyWGQuickConf - applies wg-quick commands if os supports func ApplyWGQuickConf(confPath string) error { - _, _ = ncutils.RunCmd("wg-quick down "+confPath, false) - _, err := ncutils.RunCmd("wg-quick up "+confPath, false) + _, err := os.Stat(confPath) + if err != nil { + ncutils.Log(confPath + " does not exist " + err.Error()) + return err + } + _, err = ncutils.RunCmd("wg-quick down "+confPath, false) + if err != nil { + ncutils.Log("err runing wg-quick down " + confPath + err.Error()) + } + _, err = ncutils.RunCmd("wg-quick up "+confPath, false) + if err != nil { + ncutils.Log("err runing wg-quick up " + confPath + err.Error()) + } return err } From efbb166e5125317d63970d4672063a681fce3412 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Wed, 19 Jan 2022 15:12:09 -0500 Subject: [PATCH 069/116] fix UpdateWgPeers to enable multiple peer sections --- netclient/wireguard/common.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/netclient/wireguard/common.go b/netclient/wireguard/common.go index 94742eb9..9e3c6dc7 100644 --- a/netclient/wireguard/common.go +++ b/netclient/wireguard/common.go @@ -339,15 +339,20 @@ func WriteWgConfig(cfg config.ClientConfig, privateKey string, peers []wgtypes.P // UpdateWgPeers - updates the peers of a network func UpdateWgPeers(wgInterface string, peers []wgtypes.PeerConfig) error { + options := ini.LoadOptions{ + AllowNonUniqueSections: true, + AllowShadows: true, + } file := ncutils.GetNetclientPathSpecific() + wgInterface + ".conf" ncutils.Log("updating " + file) - wireguard, err := ini.ShadowLoad(file) + wireguard, err := ini.LoadSources(options, file) if err != nil { return err } //delete the peers sections as they are going to be replaced wireguard.DeleteSection(section_peers) for i, peer := range peers { + ncutils.Log("adding peer section for peer #: " + string(i) + peer.PublicKey.String()) wireguard.SectionWithIndex(section_peers, i).Key("PublicKey").SetValue(peer.PublicKey.String()) //if peer.PresharedKey.String() != "" { //wireguard.SectionWithIndex(section_peers, i).Key("PreSharedKey").SetValue(peer.PresharedKey.String()) From ac0dba5e81b2c4d9c32ac0564bc3e3971caf9de0 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Wed, 19 Jan 2022 15:25:39 -0500 Subject: [PATCH 070/116] fixed tests and removed some debugging logs --- netclient/functions/daemon.go | 7 ------- netclient/wireguard/common.go | 1 - 2 files changed, 8 deletions(-) diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index b339e1b4..d38ebf30 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -154,13 +154,6 @@ var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) return } ncutils.Log("update peer handler") - ncutils.Log("recieved " + string(len(peerUpdate.Peers)) + "peers to update") - ncutils.Log(string(msg.Payload())) - ncutils.Log(peerUpdate.Network) - for _, peer := range peerUpdate.Peers { - key := peer.PublicKey.String() - ncutils.Log(key) - } var cfg config.ClientConfig cfg.Network = peerUpdate.Network cfg.ReadConfig() diff --git a/netclient/wireguard/common.go b/netclient/wireguard/common.go index 9e3c6dc7..7fddc84f 100644 --- a/netclient/wireguard/common.go +++ b/netclient/wireguard/common.go @@ -352,7 +352,6 @@ func UpdateWgPeers(wgInterface string, peers []wgtypes.PeerConfig) error { //delete the peers sections as they are going to be replaced wireguard.DeleteSection(section_peers) for i, peer := range peers { - ncutils.Log("adding peer section for peer #: " + string(i) + peer.PublicKey.String()) wireguard.SectionWithIndex(section_peers, i).Key("PublicKey").SetValue(peer.PublicKey.String()) //if peer.PresharedKey.String() != "" { //wireguard.SectionWithIndex(section_peers, i).Key("PreSharedKey").SetValue(peer.PresharedKey.String()) From 746d90d1094df2393c5465f29b2a803dfc7d97aa Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Wed, 19 Jan 2022 15:33:29 -0500 Subject: [PATCH 071/116] add logic to grpc leave handler to publish peer update message --- controllers/node_grpc.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/controllers/node_grpc.go b/controllers/node_grpc.go index 06591ca9..774ce61d 100644 --- a/controllers/node_grpc.go +++ b/controllers/node_grpc.go @@ -142,6 +142,10 @@ func (s *NodeServiceServer) DeleteNode(ctx context.Context, req *nodepb.Object) if err != nil { return nil, err } + // notify other nodes on network of deleted peer + if err := mq.NewPeer(node); err != nil { + logger.Log(0, "failed to inform peers of deleted node "+err.Error()) + } return &nodepb.Object{ Data: "success", From 6a30bca315fdc9b56cf9e22d7d1b169dcdd0747a Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Wed, 19 Jan 2022 16:16:12 -0500 Subject: [PATCH 072/116] updated service files for linux and darwin to start netclient daemon vice netclient checkin --- netclient/daemon/macos.go | 11 ++++---- netclient/daemon/systemd.go | 51 ++++++++----------------------------- 2 files changed, 16 insertions(+), 46 deletions(-) diff --git a/netclient/daemon/macos.go b/netclient/daemon/macos.go index 4fe21ff1..cf1cfddb 100644 --- a/netclient/daemon/macos.go +++ b/netclient/daemon/macos.go @@ -19,8 +19,8 @@ func SetupMacDaemon(interval string) error { } binarypath := dir + "/netclient" - if !ncutils.FileExists("/etc/netclient/netclient") { - err = ncutils.Copy(binarypath, "/etc/netclient/netclient") + if !ncutils.FileExists("/sbin/netclient") { + err = ncutils.Copy(binarypath, "/sbin/netclient") if err != nil { log.Println(err) return err @@ -49,6 +49,7 @@ func CleanupMac() { } os.RemoveAll(ncutils.GetNetclientPath()) + os.Remove("/sbin/netclient") } func CreateMacService(servicename string, interval string) error { @@ -76,10 +77,8 @@ func MacDaemonString(interval string) string { Labelcom.gravitl.netclient ProgramArguments - /etc/netclient/netclient - checkin - -n - all + /sbin/netclient + daemon StandardOutPath/etc/netclient/com.gravitl.netclient.log StandardErrorPath/etc/netclient/com.gravitl.netclient.log diff --git a/netclient/daemon/systemd.go b/netclient/daemon/systemd.go index 015f4626..6b1ecc4a 100644 --- a/netclient/daemon/systemd.go +++ b/netclient/daemon/systemd.go @@ -29,12 +29,10 @@ func SetupSystemDDaemon(interval string) error { log.Println("couldnt find or create /etc/netclient") return err } - - if !ncutils.FileExists("/usr/local/bin/netclient") { - os.Symlink("/etc/netclient/netclient", "/usr/local/bin/netclient") - } - if !ncutils.FileExists("/etc/netclient/netclient") { - err = ncutils.Copy(binarypath, "/etc/netclient/netclient") + //install binary + //should check if the existing binary is the corect version -- for now only copy if file doesn't exist + if !ncutils.FileExists("/usr/sbin/netclient") { + err = ncutils.Copy(binarypath, "/usr/sbin/netclient") if err != nil { log.Println(err) return err @@ -42,36 +40,17 @@ func SetupSystemDDaemon(interval string) error { } systemservice := `[Unit] -Description=Network Check -Wants=netclient.timer +Description=Netclient message queue [Service] Type=simple -ExecStart=/etc/netclient/netclient checkin -n all +ExecStart=/usr/sbin/netclient daemon [Install] WantedBy=multi-user.target -` - - systemtimer := `[Unit] -Description=Calls the Netmaker Mesh Client Service -Requires=netclient.service - -[Timer] -Unit=netclient.service - -` - systemtimer = systemtimer + "OnCalendar=*:*:0/" + interval - - systemtimer = systemtimer + - ` - -[Install] -WantedBy=timers.target ` servicebytes := []byte(systemservice) - timerbytes := []byte(systemtimer) if !ncutils.FileExists("/etc/systemd/system/netclient.service") { err = os.WriteFile("/etc/systemd/system/netclient.service", servicebytes, 0644) @@ -80,25 +59,17 @@ WantedBy=timers.target return err } } - - if !ncutils.FileExists("/etc/systemd/system/netclient.timer") { - err = os.WriteFile("/etc/systemd/system/netclient.timer", timerbytes, 0644) - if err != nil { - log.Println(err) - return err - } - } - _, _ = ncutils.RunCmd("systemctl enable netclient.service", true) _, _ = ncutils.RunCmd("systemctl daemon-reload", true) - _, _ = ncutils.RunCmd("systemctl enable netclient.timer", true) - _, _ = ncutils.RunCmd("systemctl start netclient.timer", true) + _, _ = ncutils.RunCmd("systemctl start netclient.server", true) return nil } func CleanupLinux() { - err := os.RemoveAll(ncutils.GetNetclientPath()) - if err != nil { + if err := os.RemoveAll(ncutils.GetNetclientPath()); err != nil { + ncutils.PrintLog("Removing netclient configs: "+err.Error(), 1) + } + if err := os.Remove("/usr/sbin/netclient"); err != nil { ncutils.PrintLog("Removing netclient binary: "+err.Error(), 1) } } From 78c169052c585c016a6258bd8a90a9084742889c Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Wed, 19 Jan 2022 16:27:19 -0500 Subject: [PATCH 073/116] write node to database when localAddress update received. --- mq/mq.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mq/mq.go b/mq/mq.go index f1f5553d..32a8a031 100644 --- a/mq/mq.go +++ b/mq/mq.go @@ -266,6 +266,9 @@ var LocalAddressUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.M } node.LocalAddress = string(msg.Payload()) node.SetLastCheckIn() + if err := logic.UpdateNode(&node, &node); err != nil { + logger.Log(0, "error updating node "+err.Error()) + } if err := UpdatePeers(client, node); err != nil { logger.Log(0, "error updating peers "+err.Error()) } From f956a90f76f914525408f9e826729cb893020865 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Thu, 20 Jan 2022 09:34:07 -0500 Subject: [PATCH 074/116] added extclient peers and persitent keepalive --- mq/mq.go | 43 +++++++++++++------------------------------ 1 file changed, 13 insertions(+), 30 deletions(-) diff --git a/mq/mq.go b/mq/mq.go index 32a8a031..573fae39 100644 --- a/mq/mq.go +++ b/mq/mq.go @@ -109,8 +109,11 @@ func UpdatePeers(client mqtt.Client, newnode models.Node) error { return err } dualstack := false - keepalive, _ := time.ParseDuration(string(newnode.PersistentKeepalive) + "s") - defaultkeepalive, _ := time.ParseDuration("25s") + var keepalive time.Duration + //keepalive = time.Duration{} + if newnode.PersistentKeepalive != 0 { + keepalive, _ = time.ParseDuration(strconv.FormatInt(int64(newnode.PersistentKeepalive), 10) + "s") + } for _, node := range networkNodes { var peers []wgtypes.PeerConfig var peerUpdate models.PeerUpdate @@ -144,6 +147,7 @@ func UpdatePeers(client mqtt.Client, newnode models.Node) error { if err != nil { return err } + //calculate Allowed IPs. allowedips = append(allowedips, peeraddr) // handle manually set peers @@ -196,43 +200,22 @@ func UpdatePeers(client mqtt.Client, newnode models.Node) error { } allowedips = append(allowedips, addr6) } - if node.IsServer == "yes" && !(node.IsServer == "yes") { + if &keepalive == nil { peerData = wgtypes.PeerConfig{ - PublicKey: pubkey, - PersistentKeepaliveInterval: &defaultkeepalive, - ReplaceAllowedIPs: true, - AllowedIPs: allowedips, - } - } else if keepalive != 0 { - peerData = wgtypes.PeerConfig{ - PublicKey: pubkey, - PersistentKeepaliveInterval: &defaultkeepalive, - //Endpoint: &net.UDPAddr{ - // IP: net.ParseIP(node.Endpoint), - // Port: int(node.ListenPort), - //}, + PublicKey: pubkey, Endpoint: address, ReplaceAllowedIPs: true, AllowedIPs: allowedips, } } else { peerData = wgtypes.PeerConfig{ - PublicKey: pubkey, - //Endpoint: &net.UDPAddr{ - // IP: net.ParseIP(node.Endpoint), - // Port: int(node.ListenPort), - //}, - Endpoint: address, - ReplaceAllowedIPs: true, - AllowedIPs: allowedips, + PublicKey: pubkey, + PersistentKeepaliveInterval: &keepalive, + Endpoint: address, + ReplaceAllowedIPs: true, + AllowedIPs: allowedips, } } - //peerData = wgtypes.PeerConfig{ - // PublicKey: pubkey, - // Endpoint: address, - // PersistentKeepaliveInterval: &keepalive, - //AllowedIPs: allowedIPs - //} peers = append(peers, peerData) } peerUpdate.Network = node.Network From 4a6bad922b8f5bb0aecc8b78d36ae34ab1a2b341 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Sat, 1 Jan 2022 15:30:39 +0000 Subject: [PATCH 075/116] update compose file and scripts to use mosquitto broker. Includes insecure config file for mosquitto --- compose/docker-compose.contained.yml | 11 +++++++++++ docker/mosquitto.conf | 10 ++++++++++ scripts/install-netmaker.sh | 3 +++ scripts/nm-quick.sh | 4 ++++ 4 files changed, 28 insertions(+) create mode 100644 docker/mosquitto.conf diff --git a/compose/docker-compose.contained.yml b/compose/docker-compose.contained.yml index e8124158..2254b1c9 100644 --- a/compose/docker-compose.contained.yml +++ b/compose/docker-compose.contained.yml @@ -68,9 +68,20 @@ services: # - $PWD/site:/srv # you could also serve a static site in site folder - caddy_data:/data - caddy_conf:/config + mosquitto: + image: eclipse-mosquitto:2.0.14 + container_name: broker + restart: unless-stopped + network_mode: host + volumes: + - /root/mosquitto.conf:/mosquitto/config/mosquitto.conf + - mosquitto_data:/var/lib/mosquitto + - mosquitto_logs:/var/log/mosquitto/mosquitto.log volumes: caddy_data: {} caddy_conf: {} sqldata: {} dnsconfig: {} + mosquitto_data: {} + mosquitto_logs: {} diff --git a/docker/mosquitto.conf b/docker/mosquitto.conf new file mode 100644 index 00000000..20ab6597 --- /dev/null +++ b/docker/mosquitto.conf @@ -0,0 +1,10 @@ +persitance true +persistance_location /var/lib/mosquitto/ + +log_dest_file /var/log/mosquitto/mosquitto.log + +per_listener_settings true +listener 1883 +allow_anonymous true +bind_interface SERVER_PUBLIC_IP + diff --git a/scripts/install-netmaker.sh b/scripts/install-netmaker.sh index 52232d9a..547dca88 100644 --- a/scripts/install-netmaker.sh +++ b/scripts/install-netmaker.sh @@ -136,6 +136,9 @@ echo "Setting Caddyfile..." sed -i "s/NETMAKER_BASE_DOMAIN/$NETMAKER_BASE_DOMAIN/g" /root/Caddyfile sed -i "s/YOUR_EMAIL/$EMAIL/g" /root/Caddyfile +echo "Setting Broker..." +sed -i "s/SERVER_PBLIC_IP/$SERVER_PUBLIC_IP/g" /root/mosquitto.conf + echo "Setting docker-compose..." sed -i "s/NETMAKER_BASE_DOMAIN/$NETMAKER_BASE_DOMAIN/g" /root/docker-compose.yml diff --git a/scripts/nm-quick.sh b/scripts/nm-quick.sh index 6e253a09..ebe78b65 100755 --- a/scripts/nm-quick.sh +++ b/scripts/nm-quick.sh @@ -135,6 +135,10 @@ wget -q -O /root/Caddyfile https://raw.githubusercontent.com/gravitl/netmaker/ma sed -i "s/NETMAKER_BASE_DOMAIN/$NETMAKER_BASE_DOMAIN/g" /root/Caddyfile sed -i "s/YOUR_EMAIL/$EMAIL/g" /root/Caddyfile +echo "setting mosquitto.conf..." + +wget -q -O /root/mosquitto.conf https://raw.githubusercontent.com/gravil/netmaker/master/docker/mosquitto.conf +sed -i "s/SERVER_PUBLIC_IP/$SERVER_PUBLIC_IP/g" /root/mosquitto.conf echo "setting docker-compose..." From a46aac9f24e0003d2ab5a210696971681cec8339 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Sat, 1 Jan 2022 15:43:55 +0000 Subject: [PATCH 076/116] fix typo --- docker/mosquitto.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/mosquitto.conf b/docker/mosquitto.conf index 20ab6597..3594af29 100644 --- a/docker/mosquitto.conf +++ b/docker/mosquitto.conf @@ -1,4 +1,4 @@ -persitance true +persistance true persistance_location /var/lib/mosquitto/ log_dest_file /var/log/mosquitto/mosquitto.log From b6f26869e01e9108945e0fa3640bdc67fab6a4e9 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Sat, 1 Jan 2022 18:22:06 +0000 Subject: [PATCH 077/116] update mosquitto broker conf and volume info --- compose/docker-compose.contained.yml | 4 ++-- docker/mosquitto.conf | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/compose/docker-compose.contained.yml b/compose/docker-compose.contained.yml index 2254b1c9..fb3373cb 100644 --- a/compose/docker-compose.contained.yml +++ b/compose/docker-compose.contained.yml @@ -75,8 +75,8 @@ services: network_mode: host volumes: - /root/mosquitto.conf:/mosquitto/config/mosquitto.conf - - mosquitto_data:/var/lib/mosquitto - - mosquitto_logs:/var/log/mosquitto/mosquitto.log + - mosquitto_data:/mosquitto/data + - mosquitto_logs:/mosquitto/log volumes: caddy_data: {} caddy_conf: {} diff --git a/docker/mosquitto.conf b/docker/mosquitto.conf index 3594af29..85914bad 100644 --- a/docker/mosquitto.conf +++ b/docker/mosquitto.conf @@ -1,10 +1,11 @@ -persistance true -persistance_location /var/lib/mosquitto/ +persistence true +persistence file mosquitto.db +persistance_location mosquitto/data -log_dest_file /var/log/mosquitto/mosquitto.log +log_dest_file mosquitto/log/mosquitto.log per_listener_settings true listener 1883 allow_anonymous true -bind_interface SERVER_PUBLIC_IP +#bind_interface SERVER_PUBLIC_IP From 33f34f7b295b926bc5bcd0a96991d1fe3957e4d2 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Sat, 1 Jan 2022 15:30:39 +0000 Subject: [PATCH 078/116] update compose file and scripts to use mosquitto broker. Includes insecure config file for mosquitto --- docker/mosquitto.conf | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docker/mosquitto.conf b/docker/mosquitto.conf index 85914bad..8d0d9b1c 100644 --- a/docker/mosquitto.conf +++ b/docker/mosquitto.conf @@ -2,10 +2,9 @@ persistence true persistence file mosquitto.db persistance_location mosquitto/data -log_dest_file mosquitto/log/mosquitto.log + per_listener_settings true listener 1883 allow_anonymous true -#bind_interface SERVER_PUBLIC_IP From 756d0a69b137d08440886a6fbc5ca1481186fde7 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Sat, 1 Jan 2022 15:43:55 +0000 Subject: [PATCH 079/116] fix typo --- docker/mosquitto.conf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docker/mosquitto.conf b/docker/mosquitto.conf index 8d0d9b1c..e77c6f41 100644 --- a/docker/mosquitto.conf +++ b/docker/mosquitto.conf @@ -2,6 +2,8 @@ persistence true persistence file mosquitto.db persistance_location mosquitto/data +persistance true +persistance_location /var/lib/mosquitto/ per_listener_settings true From 29a078c27c371d6dc873383567159a4dec7cee58 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Sat, 1 Jan 2022 18:22:06 +0000 Subject: [PATCH 080/116] update mosquitto broker conf and volume info --- docker/mosquitto.conf | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docker/mosquitto.conf b/docker/mosquitto.conf index e77c6f41..23c53bc1 100644 --- a/docker/mosquitto.conf +++ b/docker/mosquitto.conf @@ -2,9 +2,8 @@ persistence true persistence file mosquitto.db persistance_location mosquitto/data -persistance true -persistance_location /var/lib/mosquitto/ +log_dest_file mosquitto/log/mosquitto.log per_listener_settings true listener 1883 From 120207f662bf92987d8e015c1c716774761797d4 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Sun, 2 Jan 2022 16:02:59 +0000 Subject: [PATCH 081/116] work in progress for message queue --- go.mod | 3 + go.sum | 11 ++ netclient/cli_options/cmds.go | 9 ++ netclient/command/commands.go | 5 + netclient/functions/daemon.go | 214 ++++++++++++++++++++++++++++++++++ 5 files changed, 242 insertions(+) create mode 100644 netclient/functions/daemon.go diff --git a/go.mod b/go.mod index 70f37dc5..dcc6b758 100644 --- a/go.mod +++ b/go.mod @@ -32,7 +32,9 @@ require ( cloud.google.com/go v0.34.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/eclipse/paho.mqtt.golang v1.3.5 // indirect github.com/felixge/httpsnoop v1.0.1 // indirect + github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534 // indirect github.com/go-playground/locales v0.14.0 // indirect github.com/go-playground/universal-translator v0.18.0 // indirect github.com/google/go-cmp v0.5.5 // indirect @@ -44,5 +46,6 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/russross/blackfriday/v2 v2.0.1 // indirect github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect + golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect google.golang.org/appengine v1.4.0 // indirect ) diff --git a/go.sum b/go.sum index 1843eb9d..dce93b9d 100644 --- a/go.sum +++ b/go.sum @@ -24,6 +24,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/eclipse/paho.mqtt.golang v1.3.5 h1:sWtmgNxYM9P2sP+xEItMozsR3w0cqZFlqnNN1bdl41Y= +github.com/eclipse/paho.mqtt.golang v1.3.5/go.mod h1:eTzb4gxwwyWpqBUHGQZ4ABAV7+Jgm1PklsYT/eo8Hcc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -34,6 +36,8 @@ github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8S github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534 h1:dhy9OQKGBh4zVXbjwbxxHjRxMJtLXj3zfgpBYQaR4Q4= +github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk= github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= @@ -76,6 +80,8 @@ github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -180,6 +186,7 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -187,6 +194,7 @@ golang.org/x/net v0.0.0-20201216054612-986b41b23924/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210504132125-bbd867fde50d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985 h1:4CSI6oo7cOjJKajidEljs9h+uP0rRZBPPPhcCbj5mw8= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -197,6 +205,8 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -218,6 +228,7 @@ golang.org/x/sys v0.0.0-20210123111255-9b0068b26619/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210216163648-f7da38b97c65/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210309040221-94ec62e08169/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210503173754-0981d6026fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/netclient/cli_options/cmds.go b/netclient/cli_options/cmds.go index a43a88c3..5f90c1a8 100644 --- a/netclient/cli_options/cmds.go +++ b/netclient/cli_options/cmds.go @@ -118,5 +118,14 @@ func GetCommands(cliFlags []cli.Flag) []*cli.Command { return err }, }, + { + Name: "daemon", + Usage: "run netclient as daemon", + Flags: cliFlags, + Action: func(c *cli.Context) error { + err := command.Daemon() + return err + }, + }, } } diff --git a/netclient/command/commands.go b/netclient/command/commands.go index 49e075a2..1aecdb4b 100644 --- a/netclient/command/commands.go +++ b/netclient/command/commands.go @@ -210,3 +210,8 @@ func Uninstall() error { ncutils.PrintLog("uninstalled netclient", 0) return err } + +func Daemon() error { + err := functions.Daemon() + return err +} diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go new file mode 100644 index 00000000..72c7998c --- /dev/null +++ b/netclient/functions/daemon.go @@ -0,0 +1,214 @@ +package functions + +import ( + "encoding/json" + "fmt" + "log" + "time" + + mqtt "github.com/eclipse/paho.mqtt.golang" + "github.com/go-ping/ping" + "github.com/gravitl/netmaker/netclient/config" + "github.com/gravitl/netmaker/netclient/ncutils" + "golang.zx2c4.com/wireguard/wgctrl" +) + +func Daemon() error { + networks, err := ncutils.GetSystemNetworks() + if err != nil { + return err + } + for _, network := range networks { + go Netclient(network) + } + for { + } + return nil +} + +func Netclient(network string) { + var cfg config.ClientConfig + cfg.Network = network + cfg.ReadConfig() + ncutils.Log("daemon started for network:" + network) + //setup MQTT + opts := mqtt.NewClientOptions() + ncutils.Log("setting broker to " + cfg.Server.CoreDNSAddr + ":1883") + opts.AddBroker(cfg.Server.CoreDNSAddr + ":1883") + opts.SetDefaultPublishHandler(All) + opts.SetClientID("netclient-mqttt") + client := mqtt.NewClient(opts) + if token := client.Connect(); token.Wait() && token.Error() != nil { + log.Fatal(token.Error()) + } + if token := client.Subscribe("#", 0, nil); token.Wait() && token.Error() != nil { + log.Fatal(token.Error()) + } + client.AddRoute("update/"+network+"/"+cfg.Node.MacAddress, NodeUpdate) + client.AddRoute("update/"+network+"/peers", UpdatePeers) + client.AddRoute("update/"+network+"/keys", UpdateKeys) + client.AddRoute("update/"+network+"/keys/"+cfg.Node.MacAddress, UpdateKeys) + defer client.Disconnect(250) + go Checkin(client, network) + //go Metrics(client, network) + //go Connectivity(client, network) + for { + } +} + +var All mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { + ncutils.Log("Topic: " + string(msg.Topic())) + ncutils.Log("Message: " + string(msg.Payload())) +} + +var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { + ncutils.Log("received message to update node " + string(msg.Payload())) +} + +var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { + ncutils.Log("received message to update peers " + string(msg.Payload())) +} + +var UpdateKeys mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { + ncutils.Log("received message to update keys " + string(msg.Payload())) +} + +func Checkin(client mqtt.Client, network string) { + var cfg config.ClientConfig + cfg.Network = network + cfg.ReadConfig() + for { + time.Sleep(time.Duration(cfg.Node.NetworkSettings.DefaultCheckInInterval) * time.Second) + ncutils.Log("Checkin running") + if cfg.Node.Roaming == "yes" && cfg.Node.IsStatic != "yes" { + extIP, err := ncutils.GetPublicIP() + if err != nil { + ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) + } + if cfg.Node.Endpoint != extIP && extIP != "" { + ncutils.PrintLog("endpoint has changed from "+cfg.Node.Endpoint+" to "+extIP, 1) + UpdateEndpoint(client, network, extIP) + } + intIP, err := getPrivateAddr() + if err != nil { + ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) + } + if cfg.Node.LocalAddress != intIP && intIP != "" { + ncutils.PrintLog("local Address has changed from "+cfg.Node.LocalAddress+" to "+intIP, 1) + UpdateLocalAddress(client, network, intIP) + } + } else { + localIP, err := ncutils.GetLocalIP(cfg.Node.LocalRange) + if err != nil { + ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) + } + if cfg.Node.Endpoint != localIP && localIP != "" { + ncutils.PrintLog("endpoint has changed from "+cfg.Node.Endpoint+" to "+localIP, 1) + UpdateEndpoint(client, network, localIP) + } + } + Ping(client, network) + } +} + +func Ping(client mqtt.Client, network string) { + var cfg config.ClientConfig + cfg.Network = network + cfg.ReadConfig() + if token := client.Publish("ping/"+network+"/"+cfg.Node.ID, 0, false, []byte("ping")); token.Wait() && token.Error() != nil { + ncutils.Log("error publishing ping " + token.Error().Error()) + } +} + +func Metrics(client mqtt.Client, network string) { + if token := client.Connect(); token.Wait() && token.Error() != nil { + log.Fatal(token.Error()) + } + var cfg config.ClientConfig + cfg.Network = network + cfg.ReadConfig() + for { + time.Sleep(time.Second * 60) + ncutils.Log("Metrics running") + wg, err := wgctrl.New() + if err != nil { + ncutils.Log("error getting devices " + err.Error()) + break + } + device, err := wg.Device(cfg.Node.Interface) + if err != nil { + ncutils.Log("error readind wg device " + err.Error()) + break + } + bytes, err := json.Marshal(device.Peers) + if err != nil { + ncutils.Log("error marshaling peers " + err.Error()) + break + } + if token := client.Publish("metrics/"+network+"/"+cfg.Node.ID, 1, false, bytes); token.Wait() && token.Error() != nil { + ncutils.Log("error publishing metrics " + token.Error().Error()) + break + } + wg.Close() + } +} + +type PingStat struct { + Name string + Reachable bool +} + +func Connectivity(client mqtt.Client, network string) { + if token := client.Connect(); token.Wait() && token.Error() != nil { + log.Fatal(token.Error()) + } + var cfg config.ClientConfig + cfg.Network = network + cfg.ReadConfig() + for { + time.Sleep(time.Duration(cfg.NetworkSettings.DefaultCheckInInterval) * time.Second) + ncutils.Log("Connectivity running") + var pingStats []PingStat + peers, err := ncutils.GetPeers(cfg.Node.Interface) + if err != nil { + ncutils.Log("error retriving peers " + err.Error()) + break + } + for _, peer := range peers { + var pingStat PingStat + pingStat.Name = peer.PublicKey.String() + pingStat.Reachable = true + ip := peer.Endpoint.IP.String() + fmt.Println("----------", peer.Endpoint.IP, ip) + pinger, err := ping.NewPinger(ip) + if err != nil { + ncutils.Log("error creating pinger " + err.Error()) + break + } + pinger.Timeout = 2 * time.Second + pinger.Run() + stats := pinger.Statistics() + if stats.PacketLoss == 100 { + pingStat.Reachable = false + } + pingStats = append(pingStats, pingStat) + } + bytes, err := json.Marshal(pingStats) + if err != nil { + ncutils.Log("error marshaling stats" + err.Error()) + break + } + if token := client.Publish("connectivity/"+network+"/"+cfg.Node.ID, 1, false, bytes); token.Wait() && token.Error() != nil { + ncutils.Log("error publishing ping stats " + token.Error().Error()) + break + } + } +} + +func UpdateEndpoint(client mqtt.Client, network, ip string) { + ncutils.Log("Updating endpoint") +} + +func UpdateLocalAddress(client mqtt.Client, network, ip string) { + ncutils.Log("Updating local address") +} From fc5388302eca5fd46963042b639145a3b4966ec0 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Mon, 3 Jan 2022 15:22:26 -0500 Subject: [PATCH 082/116] Replaced ### with - in Node.ID (local copy) to fix mqtt publishing errors added context to all go routines removed connectivity function --- netclient/functions/daemon.go | 191 ++++++++++++++++------------------ 1 file changed, 87 insertions(+), 104 deletions(-) diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index 72c7998c..2e31d37a 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -1,18 +1,22 @@ package functions import ( + "context" "encoding/json" - "fmt" "log" + "os" + "os/signal" + "strings" + "syscall" "time" mqtt "github.com/eclipse/paho.mqtt.golang" - "github.com/go-ping/ping" "github.com/gravitl/netmaker/netclient/config" "github.com/gravitl/netmaker/netclient/ncutils" "golang.zx2c4.com/wireguard/wgctrl" ) +//Daemon runs netclient daemon from command line func Daemon() error { networks, err := ncutils.GetSystemNetworks() if err != nil { @@ -26,59 +30,75 @@ func Daemon() error { return nil } -func Netclient(network string) { - var cfg config.ClientConfig - cfg.Network = network - cfg.ReadConfig() - ncutils.Log("daemon started for network:" + network) - //setup MQTT +//SetupMQTT creates a connection to broker and return client +func SetupMQTT(cfg config.ClientConfig) mqtt.Client { opts := mqtt.NewClientOptions() ncutils.Log("setting broker to " + cfg.Server.CoreDNSAddr + ":1883") opts.AddBroker(cfg.Server.CoreDNSAddr + ":1883") opts.SetDefaultPublishHandler(All) - opts.SetClientID("netclient-mqttt") client := mqtt.NewClient(opts) if token := client.Connect(); token.Wait() && token.Error() != nil { log.Fatal(token.Error()) } + return client +} + +//Netclient sets up Message Queue and subsribes/publishes updates to/from server +func Netclient(network string) { + ctx, cancel := context.WithCancel(context.Background()) + var cfg config.ClientConfig + cfg.Network = network + cfg.ReadConfig() + //fix NodeID to remove ### so NodeID can be used as message topic + //remove with GRA-73 + cfg.Node.ID = strings.ReplaceAll(cfg.Node.ID, "###", "-") + ncutils.Log("daemon started for network:" + network) + client := SetupMQTT(cfg) if token := client.Subscribe("#", 0, nil); token.Wait() && token.Error() != nil { log.Fatal(token.Error()) } - client.AddRoute("update/"+network+"/"+cfg.Node.MacAddress, NodeUpdate) - client.AddRoute("update/"+network+"/peers", UpdatePeers) - client.AddRoute("update/"+network+"/keys", UpdateKeys) - client.AddRoute("update/"+network+"/keys/"+cfg.Node.MacAddress, UpdateKeys) + client.AddRoute("update/"+cfg.Node.ID, NodeUpdate) + client.AddRoute("update/peers/"+cfg.Node.ID, UpdatePeers) + client.AddRoute("update/keys/"+cfg.Node.ID, UpdateKeys) defer client.Disconnect(250) - go Checkin(client, network) - //go Metrics(client, network) - //go Connectivity(client, network) - for { - } + go Checkin(ctx, cfg, network) + go Metrics(ctx, cfg, network) + quit := make(chan os.Signal, 1) + signal.Notify(quit, syscall.SIGTERM, os.Interrupt) + <-quit + cancel() } +//All -- mqtt message hander for all ('#') topics var All mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("Topic: " + string(msg.Topic())) ncutils.Log("Message: " + string(msg.Payload())) } +//NodeUpdate -- mqtt message handler for /update/ topic var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update node " + string(msg.Payload())) } +//NodeUpdate -- mqtt message handler for /update/peers/ topic var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update peers " + string(msg.Payload())) } +//NodeUpdate -- mqtt message handler for /update/keys/ topic var UpdateKeys mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update keys " + string(msg.Payload())) } -func Checkin(client mqtt.Client, network string) { - var cfg config.ClientConfig - cfg.Network = network - cfg.ReadConfig() - for { - time.Sleep(time.Duration(cfg.Node.NetworkSettings.DefaultCheckInInterval) * time.Second) +//Checkin -- go routine that checks for public or local ip changes, publishes changes +// if there are no updates, simply "pings" the server as a checkin +func Checkin(ctx context.Context, cfg config.ClientConfig, network string) { + select { + case <-ctx.Done(): + ncutils.Log("Checkin cancelled") + return + //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? + case <-time.After(time.Second * 10): ncutils.Log("Checkin running") if cfg.Node.Roaming == "yes" && cfg.Node.IsStatic != "yes" { extIP, err := ncutils.GetPublicIP() @@ -87,7 +107,7 @@ func Checkin(client mqtt.Client, network string) { } if cfg.Node.Endpoint != extIP && extIP != "" { ncutils.PrintLog("endpoint has changed from "+cfg.Node.Endpoint+" to "+extIP, 1) - UpdateEndpoint(client, network, extIP) + UpdateEndpoint(cfg, network, extIP) } intIP, err := getPrivateAddr() if err != nil { @@ -95,7 +115,7 @@ func Checkin(client mqtt.Client, network string) { } if cfg.Node.LocalAddress != intIP && intIP != "" { ncutils.PrintLog("local Address has changed from "+cfg.Node.LocalAddress+" to "+intIP, 1) - UpdateLocalAddress(client, network, intIP) + UpdateLocalAddress(cfg, network, intIP) } } else { localIP, err := ncutils.GetLocalIP(cfg.Node.LocalRange) @@ -104,31 +124,52 @@ func Checkin(client mqtt.Client, network string) { } if cfg.Node.Endpoint != localIP && localIP != "" { ncutils.PrintLog("endpoint has changed from "+cfg.Node.Endpoint+" to "+localIP, 1) - UpdateEndpoint(client, network, localIP) + UpdateEndpoint(cfg, network, localIP) } } - Ping(client, network) + Hello(cfg, network) + ncutils.Log("Checkin complete") } } -func Ping(client mqtt.Client, network string) { - var cfg config.ClientConfig - cfg.Network = network - cfg.ReadConfig() - if token := client.Publish("ping/"+network+"/"+cfg.Node.ID, 0, false, []byte("ping")); token.Wait() && token.Error() != nil { +//UpdateEndpoint -- publishes an endpoint update to broker +func UpdateEndpoint(cfg config.ClientConfig, network, ip string) { + ncutils.Log("Updating endpoint") + client := SetupMQTT(cfg) + if token := client.Publish("update/ip/"+cfg.Node.ID, 0, false, ip); token.Wait() && token.Error() != nil { + ncutils.Log("error publishing endpoint update " + token.Error().Error()) + } + client.Disconnect(250) +} + +//UpdateLocalAddress -- publishes a local address update to broker +func UpdateLocalAddress(cfg config.ClientConfig, network, ip string) { + ncutils.Log("Updating local address") + client := SetupMQTT(cfg) + if token := client.Publish("update/localaddress/"+cfg.Node.ID, 0, false, ip); token.Wait() && token.Error() != nil { + ncutils.Log("error publishing local address update " + token.Error().Error()) + } + client.Disconnect(250) +} + +//Hello -- ping the broker to let server know node is alive and doing fine +func Hello(cfg config.ClientConfig, network string) { + client := SetupMQTT(cfg) + if token := client.Publish("ping/"+network+"/"+cfg.Node.ID, 0, false, "hello world!"); token.Wait() && token.Error() != nil { ncutils.Log("error publishing ping " + token.Error().Error()) } + client.Disconnect(250) } -func Metrics(client mqtt.Client, network string) { - if token := client.Connect(); token.Wait() && token.Error() != nil { - log.Fatal(token.Error()) - } - var cfg config.ClientConfig - cfg.Network = network - cfg.ReadConfig() - for { - time.Sleep(time.Second * 60) +//Metics -- go routine that collects wireguard metrics and publishes to broker +func Metrics(ctx context.Context, cfg config.ClientConfig, network string) { + select { + case <-ctx.Done(): + ncutils.Log("Metrics collection cancelled") + return + //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? + case <-time.After(time.Second * 60): + ncutils.Log("Metrics collection running") ncutils.Log("Metrics running") wg, err := wgctrl.New() if err != nil { @@ -145,70 +186,12 @@ func Metrics(client mqtt.Client, network string) { ncutils.Log("error marshaling peers " + err.Error()) break } - if token := client.Publish("metrics/"+network+"/"+cfg.Node.ID, 1, false, bytes); token.Wait() && token.Error() != nil { + client := SetupMQTT(cfg) + if token := client.Publish("metrics/"+cfg.Node.ID, 1, false, bytes); token.Wait() && token.Error() != nil { ncutils.Log("error publishing metrics " + token.Error().Error()) - break } wg.Close() + client.Disconnect(250) + ncutils.Log("metrics collection complete") } } - -type PingStat struct { - Name string - Reachable bool -} - -func Connectivity(client mqtt.Client, network string) { - if token := client.Connect(); token.Wait() && token.Error() != nil { - log.Fatal(token.Error()) - } - var cfg config.ClientConfig - cfg.Network = network - cfg.ReadConfig() - for { - time.Sleep(time.Duration(cfg.NetworkSettings.DefaultCheckInInterval) * time.Second) - ncutils.Log("Connectivity running") - var pingStats []PingStat - peers, err := ncutils.GetPeers(cfg.Node.Interface) - if err != nil { - ncutils.Log("error retriving peers " + err.Error()) - break - } - for _, peer := range peers { - var pingStat PingStat - pingStat.Name = peer.PublicKey.String() - pingStat.Reachable = true - ip := peer.Endpoint.IP.String() - fmt.Println("----------", peer.Endpoint.IP, ip) - pinger, err := ping.NewPinger(ip) - if err != nil { - ncutils.Log("error creating pinger " + err.Error()) - break - } - pinger.Timeout = 2 * time.Second - pinger.Run() - stats := pinger.Statistics() - if stats.PacketLoss == 100 { - pingStat.Reachable = false - } - pingStats = append(pingStats, pingStat) - } - bytes, err := json.Marshal(pingStats) - if err != nil { - ncutils.Log("error marshaling stats" + err.Error()) - break - } - if token := client.Publish("connectivity/"+network+"/"+cfg.Node.ID, 1, false, bytes); token.Wait() && token.Error() != nil { - ncutils.Log("error publishing ping stats " + token.Error().Error()) - break - } - } -} - -func UpdateEndpoint(client mqtt.Client, network, ip string) { - ncutils.Log("Updating endpoint") -} - -func UpdateLocalAddress(client mqtt.Client, network, ip string) { - ncutils.Log("Updating local address") -} From b28c2113d9044e8a1d80f1f0217aab4dfbd4493a Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Mon, 3 Jan 2022 16:26:40 -0500 Subject: [PATCH 083/116] move context up a level --- netclient/functions/daemon.go | 58 +++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index 2e31d37a..43dae42f 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -18,15 +18,18 @@ import ( //Daemon runs netclient daemon from command line func Daemon() error { + ctx, cancel := context.WithCancel(context.Background()) networks, err := ncutils.GetSystemNetworks() if err != nil { return err } for _, network := range networks { - go Netclient(network) - } - for { + go Netclient(ctx, network) } + quit := make(chan os.Signal, 1) + signal.Notify(quit, syscall.SIGTERM, os.Interrupt) + <-quit + cancel() return nil } @@ -44,29 +47,30 @@ func SetupMQTT(cfg config.ClientConfig) mqtt.Client { } //Netclient sets up Message Queue and subsribes/publishes updates to/from server -func Netclient(network string) { - ctx, cancel := context.WithCancel(context.Background()) - var cfg config.ClientConfig - cfg.Network = network - cfg.ReadConfig() - //fix NodeID to remove ### so NodeID can be used as message topic - //remove with GRA-73 - cfg.Node.ID = strings.ReplaceAll(cfg.Node.ID, "###", "-") - ncutils.Log("daemon started for network:" + network) - client := SetupMQTT(cfg) - if token := client.Subscribe("#", 0, nil); token.Wait() && token.Error() != nil { - log.Fatal(token.Error()) +func Netclient(ctx context.Context, network string) { + select { + case <-ctx.Done(): + ncutils.Log("shutting down daemon") + return + default: + var cfg config.ClientConfig + cfg.Network = network + cfg.ReadConfig() + //fix NodeID to remove ### so NodeID can be used as message topic + //remove with GRA-73 + cfg.Node.ID = strings.ReplaceAll(cfg.Node.ID, "###", "-") + ncutils.Log("daemon started for network:" + network) + client := SetupMQTT(cfg) + if token := client.Subscribe("#", 0, nil); token.Wait() && token.Error() != nil { + log.Fatal(token.Error()) + } + client.AddRoute("update/"+cfg.Node.ID, NodeUpdate) + client.AddRoute("update/peers/"+cfg.Node.ID, UpdatePeers) + client.AddRoute("update/keys/"+cfg.Node.ID, UpdateKeys) + defer client.Disconnect(250) + go Checkin(ctx, cfg, network) + go Metrics(ctx, cfg, network) } - client.AddRoute("update/"+cfg.Node.ID, NodeUpdate) - client.AddRoute("update/peers/"+cfg.Node.ID, UpdatePeers) - client.AddRoute("update/keys/"+cfg.Node.ID, UpdateKeys) - defer client.Disconnect(250) - go Checkin(ctx, cfg, network) - go Metrics(ctx, cfg, network) - quit := make(chan os.Signal, 1) - signal.Notify(quit, syscall.SIGTERM, os.Interrupt) - <-quit - cancel() } //All -- mqtt message hander for all ('#') topics @@ -80,12 +84,12 @@ var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) ncutils.Log("received message to update node " + string(msg.Payload())) } -//NodeUpdate -- mqtt message handler for /update/peers/ topic +//UpdatePeers -- mqtt message handler for /update/peers/ topic var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update peers " + string(msg.Payload())) } -//NodeUpdate -- mqtt message handler for /update/keys/ topic +//UpdateKeys -- mqtt message handler for /update/keys/ topic var UpdateKeys mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update keys " + string(msg.Payload())) } From 40302b3a17af491d0f0014bce7b226aff6ef3ae7 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Mon, 3 Jan 2022 22:21:52 +0000 Subject: [PATCH 084/116] go routines now run forever like they are supposed to --- netclient/functions/daemon.go | 176 +++++++++++++++++----------------- 1 file changed, 90 insertions(+), 86 deletions(-) diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index 43dae42f..e48e8c19 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -30,6 +30,7 @@ func Daemon() error { signal.Notify(quit, syscall.SIGTERM, os.Interrupt) <-quit cancel() + ncutils.Log("all done") return nil } @@ -48,29 +49,28 @@ func SetupMQTT(cfg config.ClientConfig) mqtt.Client { //Netclient sets up Message Queue and subsribes/publishes updates to/from server func Netclient(ctx context.Context, network string) { - select { - case <-ctx.Done(): - ncutils.Log("shutting down daemon") - return - default: - var cfg config.ClientConfig - cfg.Network = network - cfg.ReadConfig() - //fix NodeID to remove ### so NodeID can be used as message topic - //remove with GRA-73 - cfg.Node.ID = strings.ReplaceAll(cfg.Node.ID, "###", "-") - ncutils.Log("daemon started for network:" + network) - client := SetupMQTT(cfg) - if token := client.Subscribe("#", 0, nil); token.Wait() && token.Error() != nil { - log.Fatal(token.Error()) - } - client.AddRoute("update/"+cfg.Node.ID, NodeUpdate) - client.AddRoute("update/peers/"+cfg.Node.ID, UpdatePeers) - client.AddRoute("update/keys/"+cfg.Node.ID, UpdateKeys) - defer client.Disconnect(250) - go Checkin(ctx, cfg, network) - go Metrics(ctx, cfg, network) + ncutils.Log("netclient go routine started for " + network) + var cfg config.ClientConfig + cfg.Network = network + cfg.ReadConfig() + //fix NodeID to remove ### so NodeID can be used as message topic + //remove with GRA-73 + cfg.Node.ID = strings.ReplaceAll(cfg.Node.ID, "###", "-") + ncutils.Log("daemon started for network:" + network) + client := SetupMQTT(cfg) + if token := client.Subscribe("#", 0, nil); token.Wait() && token.Error() != nil { + log.Fatal(token.Error()) } + client.AddRoute("update/"+cfg.Node.ID, NodeUpdate) + client.AddRoute("update/peers/"+cfg.Node.ID, UpdatePeers) + client.AddRoute("update/keys/"+cfg.Node.ID, UpdateKeys) + defer client.Disconnect(250) + go Checkin(ctx, cfg, network) + go Metrics(ctx, cfg, network) + <-ctx.Done() + ncutils.Log("shutting down daemon") + return + ncutils.Log("netclient go routine ended for " + network) } //All -- mqtt message hander for all ('#') topics @@ -97,42 +97,44 @@ var UpdateKeys mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) //Checkin -- go routine that checks for public or local ip changes, publishes changes // if there are no updates, simply "pings" the server as a checkin func Checkin(ctx context.Context, cfg config.ClientConfig, network string) { - select { - case <-ctx.Done(): - ncutils.Log("Checkin cancelled") - return - //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? - case <-time.After(time.Second * 10): - ncutils.Log("Checkin running") - if cfg.Node.Roaming == "yes" && cfg.Node.IsStatic != "yes" { - extIP, err := ncutils.GetPublicIP() - if err != nil { - ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) - } - if cfg.Node.Endpoint != extIP && extIP != "" { - ncutils.PrintLog("endpoint has changed from "+cfg.Node.Endpoint+" to "+extIP, 1) - UpdateEndpoint(cfg, network, extIP) - } - intIP, err := getPrivateAddr() - if err != nil { - ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) - } - if cfg.Node.LocalAddress != intIP && intIP != "" { - ncutils.PrintLog("local Address has changed from "+cfg.Node.LocalAddress+" to "+intIP, 1) - UpdateLocalAddress(cfg, network, intIP) - } - } else { - localIP, err := ncutils.GetLocalIP(cfg.Node.LocalRange) - if err != nil { - ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) - } - if cfg.Node.Endpoint != localIP && localIP != "" { - ncutils.PrintLog("endpoint has changed from "+cfg.Node.Endpoint+" to "+localIP, 1) - UpdateEndpoint(cfg, network, localIP) + for { + select { + case <-ctx.Done(): + ncutils.Log("Checkin cancelled") + return + //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? + case <-time.After(time.Second * 10): + ncutils.Log("Checkin running") + if cfg.Node.Roaming == "yes" && cfg.Node.IsStatic != "yes" { + extIP, err := ncutils.GetPublicIP() + if err != nil { + ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) + } + if cfg.Node.Endpoint != extIP && extIP != "" { + ncutils.PrintLog("endpoint has changed from "+cfg.Node.Endpoint+" to "+extIP, 1) + UpdateEndpoint(cfg, network, extIP) + } + intIP, err := getPrivateAddr() + if err != nil { + ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) + } + if cfg.Node.LocalAddress != intIP && intIP != "" { + ncutils.PrintLog("local Address has changed from "+cfg.Node.LocalAddress+" to "+intIP, 1) + UpdateLocalAddress(cfg, network, intIP) + } + } else { + localIP, err := ncutils.GetLocalIP(cfg.Node.LocalRange) + if err != nil { + ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) + } + if cfg.Node.Endpoint != localIP && localIP != "" { + ncutils.PrintLog("endpoint has changed from "+cfg.Node.Endpoint+" to "+localIP, 1) + UpdateEndpoint(cfg, network, localIP) + } } + Hello(cfg, network) + ncutils.Log("Checkin complete") } - Hello(cfg, network) - ncutils.Log("Checkin complete") } } @@ -159,7 +161,7 @@ func UpdateLocalAddress(cfg config.ClientConfig, network, ip string) { //Hello -- ping the broker to let server know node is alive and doing fine func Hello(cfg config.ClientConfig, network string) { client := SetupMQTT(cfg) - if token := client.Publish("ping/"+network+"/"+cfg.Node.ID, 0, false, "hello world!"); token.Wait() && token.Error() != nil { + if token := client.Publish("ping/"+cfg.Node.ID, 0, false, "hello world!"); token.Wait() && token.Error() != nil { ncutils.Log("error publishing ping " + token.Error().Error()) } client.Disconnect(250) @@ -167,35 +169,37 @@ func Hello(cfg config.ClientConfig, network string) { //Metics -- go routine that collects wireguard metrics and publishes to broker func Metrics(ctx context.Context, cfg config.ClientConfig, network string) { - select { - case <-ctx.Done(): - ncutils.Log("Metrics collection cancelled") - return - //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? - case <-time.After(time.Second * 60): - ncutils.Log("Metrics collection running") - ncutils.Log("Metrics running") - wg, err := wgctrl.New() - if err != nil { - ncutils.Log("error getting devices " + err.Error()) - break + for { + select { + case <-ctx.Done(): + ncutils.Log("Metrics collection cancelled") + return + //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? + case <-time.After(time.Second * 60): + ncutils.Log("Metrics collection running") + ncutils.Log("Metrics running") + wg, err := wgctrl.New() + if err != nil { + ncutils.Log("error getting devices " + err.Error()) + break + } + device, err := wg.Device(cfg.Node.Interface) + if err != nil { + ncutils.Log("error readind wg device " + err.Error()) + break + } + bytes, err := json.Marshal(device.Peers) + if err != nil { + ncutils.Log("error marshaling peers " + err.Error()) + break + } + client := SetupMQTT(cfg) + if token := client.Publish("metrics/"+cfg.Node.ID, 1, false, bytes); token.Wait() && token.Error() != nil { + ncutils.Log("error publishing metrics " + token.Error().Error()) + } + wg.Close() + client.Disconnect(250) + ncutils.Log("metrics collection complete") } - device, err := wg.Device(cfg.Node.Interface) - if err != nil { - ncutils.Log("error readind wg device " + err.Error()) - break - } - bytes, err := json.Marshal(device.Peers) - if err != nil { - ncutils.Log("error marshaling peers " + err.Error()) - break - } - client := SetupMQTT(cfg) - if token := client.Publish("metrics/"+cfg.Node.ID, 1, false, bytes); token.Wait() && token.Error() != nil { - ncutils.Log("error publishing metrics " + token.Error().Error()) - } - wg.Close() - client.Disconnect(250) - ncutils.Log("metrics collection complete") } } From 2fcd874738f320a407f5167ab0ec785140b4bac9 Mon Sep 17 00:00:00 2001 From: 0xdcarns Date: Mon, 3 Jan 2022 18:27:13 -0500 Subject: [PATCH 085/116] linting fixes --- netclient/functions/daemon.go | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index e48e8c19..45a49d9b 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -16,11 +16,12 @@ import ( "golang.zx2c4.com/wireguard/wgctrl" ) -//Daemon runs netclient daemon from command line +// Daemon runs netclient daemon from command line func Daemon() error { ctx, cancel := context.WithCancel(context.Background()) networks, err := ncutils.GetSystemNetworks() if err != nil { + cancel() return err } for _, network := range networks { @@ -34,7 +35,7 @@ func Daemon() error { return nil } -//SetupMQTT creates a connection to broker and return client +// SetupMQTT creates a connection to broker and return client func SetupMQTT(cfg config.ClientConfig) mqtt.Client { opts := mqtt.NewClientOptions() ncutils.Log("setting broker to " + cfg.Server.CoreDNSAddr + ":1883") @@ -47,7 +48,7 @@ func SetupMQTT(cfg config.ClientConfig) mqtt.Client { return client } -//Netclient sets up Message Queue and subsribes/publishes updates to/from server +// Netclient sets up Message Queue and subsribes/publishes updates to/from server func Netclient(ctx context.Context, network string) { ncutils.Log("netclient go routine started for " + network) var cfg config.ClientConfig @@ -55,7 +56,7 @@ func Netclient(ctx context.Context, network string) { cfg.ReadConfig() //fix NodeID to remove ### so NodeID can be used as message topic //remove with GRA-73 - cfg.Node.ID = strings.ReplaceAll(cfg.Node.ID, "###", "-") + cfg.Node.ID = strings.Replace(cfg.Node.ID, "###", "-", 1) ncutils.Log("daemon started for network:" + network) client := SetupMQTT(cfg) if token := client.Subscribe("#", 0, nil); token.Wait() && token.Error() != nil { @@ -69,32 +70,30 @@ func Netclient(ctx context.Context, network string) { go Metrics(ctx, cfg, network) <-ctx.Done() ncutils.Log("shutting down daemon") - return - ncutils.Log("netclient go routine ended for " + network) } -//All -- mqtt message hander for all ('#') topics +// All -- mqtt message hander for all ('#') topics var All mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("Topic: " + string(msg.Topic())) ncutils.Log("Message: " + string(msg.Payload())) } -//NodeUpdate -- mqtt message handler for /update/ topic +// NodeUpdate -- mqtt message handler for /update/ topic var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update node " + string(msg.Payload())) } -//UpdatePeers -- mqtt message handler for /update/peers/ topic +// UpdatePeers -- mqtt message handler for /update/peers/ topic var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update peers " + string(msg.Payload())) } -//UpdateKeys -- mqtt message handler for /update/keys/ topic +// UpdateKeys -- mqtt message handler for /update/keys/ topic var UpdateKeys mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update keys " + string(msg.Payload())) } -//Checkin -- go routine that checks for public or local ip changes, publishes changes +// Checkin -- go routine that checks for public or local ip changes, publishes changes // if there are no updates, simply "pings" the server as a checkin func Checkin(ctx context.Context, cfg config.ClientConfig, network string) { for { @@ -138,7 +137,7 @@ func Checkin(ctx context.Context, cfg config.ClientConfig, network string) { } } -//UpdateEndpoint -- publishes an endpoint update to broker +// UpdateEndpoint -- publishes an endpoint update to broker func UpdateEndpoint(cfg config.ClientConfig, network, ip string) { ncutils.Log("Updating endpoint") client := SetupMQTT(cfg) @@ -148,7 +147,7 @@ func UpdateEndpoint(cfg config.ClientConfig, network, ip string) { client.Disconnect(250) } -//UpdateLocalAddress -- publishes a local address update to broker +// UpdateLocalAddress -- publishes a local address update to broker func UpdateLocalAddress(cfg config.ClientConfig, network, ip string) { ncutils.Log("Updating local address") client := SetupMQTT(cfg) @@ -158,7 +157,7 @@ func UpdateLocalAddress(cfg config.ClientConfig, network, ip string) { client.Disconnect(250) } -//Hello -- ping the broker to let server know node is alive and doing fine +// Hello -- ping the broker to let server know node is alive and doing fine func Hello(cfg config.ClientConfig, network string) { client := SetupMQTT(cfg) if token := client.Publish("ping/"+cfg.Node.ID, 0, false, "hello world!"); token.Wait() && token.Error() != nil { @@ -167,7 +166,7 @@ func Hello(cfg config.ClientConfig, network string) { client.Disconnect(250) } -//Metics -- go routine that collects wireguard metrics and publishes to broker +// Metics -- go routine that collects wireguard metrics and publishes to broker func Metrics(ctx context.Context, cfg config.ClientConfig, network string) { for { select { From 87d16ad76686f8e2c8ce7c9c5bb9e629356f280d Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Wed, 5 Jan 2022 10:05:51 -0500 Subject: [PATCH 086/116] subscribed message handlers implemented --- go.mod | 1 + go.sum | 2 + models/mqtt.go | 14 ++++ netclient/functions/daemon.go | 75 +++++++++++++++++++++ netclient/wireguard/common.go | 123 ++++++++++++++++++++++++++++++++++ 5 files changed, 215 insertions(+) create mode 100644 models/mqtt.go diff --git a/go.mod b/go.mod index dcc6b758..b8b169d9 100644 --- a/go.mod +++ b/go.mod @@ -48,4 +48,5 @@ require ( github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect google.golang.org/appengine v1.4.0 // indirect + gopkg.in/ini.v1 v1.66.2 // indirect ) diff --git a/go.sum b/go.sum index dce93b9d..84dbc91f 100644 --- a/go.sum +++ b/go.sum @@ -292,6 +292,8 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/ini.v1 v1.66.2 h1:XfR1dOYubytKy4Shzc2LHrrGhU0lDCfDGG1yLPmpgsI= +gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/models/mqtt.go b/models/mqtt.go new file mode 100644 index 00000000..a7e87e1f --- /dev/null +++ b/models/mqtt.go @@ -0,0 +1,14 @@ +package models + +import "golang.zx2c4.com/wireguard/wgctrl/wgtypes" + +type PeerUpdate struct { + Network string + Interface string + Peers []wgtypes.Peer +} + +type KeyUpdate struct { + Network string + Interface string +} diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index 45a49d9b..fc926bda 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -11,9 +11,12 @@ import ( "time" mqtt "github.com/eclipse/paho.mqtt.golang" + "github.com/gravitl/netmaker/models" "github.com/gravitl/netmaker/netclient/config" "github.com/gravitl/netmaker/netclient/ncutils" + "github.com/gravitl/netmaker/netclient/wireguard" "golang.zx2c4.com/wireguard/wgctrl" + "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) // Daemon runs netclient daemon from command line @@ -81,16 +84,88 @@ var All mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { // NodeUpdate -- mqtt message handler for /update/ topic var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update node " + string(msg.Payload())) + //potentiall blocking i/o so do this in a go routine + go func() { + var data models.Node + err := json.Unmarshal(msg.Payload(), &data) + if err != nil { + ncutils.Log("error unmarshalling node update data" + err.Error()) + return + } + var cfg config.ClientConfig + cfg.Network = data.Network + cfg.ReadConfig() + nameserver := cfg.Server.CoreDNSAddr + privateKey, err := wireguard.RetrievePrivKey(data.Network) + if err := wireguard.UpdateWgInterface(cfg.Node.Interface, privateKey, nameserver, data); err != nil { + ncutils.Log("error updating wireguard config " + err.Error()) + return + } + // path hardcoded for now... should be updated + err = wireguard.ApplyWGQuickConf("/etc/netclient/config/" + cfg.Node.Interface + ".conf") + if err != nil { + ncutils.Log("error restarting wg after peer update " + err.Error()) + return + } + }() } // UpdatePeers -- mqtt message handler for /update/peers/ topic var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update peers " + string(msg.Payload())) + //potentiall blocking i/o so do this in a go routine + go func() { + var peerUpdate models.PeerUpdate + err := json.Unmarshal(msg.Payload(), &peerUpdate) + if err != nil { + ncutils.Log("error unmarshalling peer data") + return + } + var cfg config.ClientConfig + cfg.Network = peerUpdate.Network + cfg.ReadConfig() + err = wireguard.UpdateWgPeers(cfg.Node.Interface, peerUpdate.Peers) + if err != nil { + ncutils.Log("error updating peers" + err.Error()) + return + } + // path hardcoded for now... should be updated + err = wireguard.ApplyWGQuickConf("/etc/netclient/config/" + cfg.Node.Interface + ".conf") + if err != nil { + ncutils.Log("error restarting wg after peer update " + err.Error()) + return + } + }() } // UpdateKeys -- mqtt message handler for /update/keys/ topic var UpdateKeys mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update keys " + string(msg.Payload())) + //potentiall blocking i/o so do this in a go routine + go func() { + var data models.KeyUpdate + if err := json.Unmarshal(msg.Payload(), &data); err != nil { + ncutils.Log("error unmarshalling key update data" + err.Error()) + return + } + var cfg config.ClientConfig + cfg.Network = data.Network + cfg.ReadConfig() + key, err := wgtypes.GeneratePrivateKey() + if err != nil { + ncutils.Log("error generating privatekey " + err.Error()) + return + } + if err := wireguard.UpdatePrivateKey(data.Interface, key.String()); err != nil { + ncutils.Log("error updating wireguard key " + err.Error()) + return + } + publicKey := key.PublicKey() + if token := client.Publish("update/publickey/"+cfg.Node.ID, 0, false, publicKey.String()); token.Wait() && token.Error() != nil { + ncutils.Log("error publishing publickey update " + token.Error().Error()) + } + client.Disconnect(250) + }() } // Checkin -- go routine that checks for public or local ip changes, publishes changes diff --git a/netclient/wireguard/common.go b/netclient/wireguard/common.go index 27a29292..8b9762c7 100644 --- a/netclient/wireguard/common.go +++ b/netclient/wireguard/common.go @@ -16,6 +16,7 @@ import ( "github.com/gravitl/netmaker/netclient/server" "golang.zx2c4.com/wireguard/wgctrl" "golang.zx2c4.com/wireguard/wgctrl/wgtypes" + "gopkg.in/ini.v1" ) // SetPeers - sets peers on a given WireGuard interface @@ -289,3 +290,125 @@ func ApplyConf(node models.Node, ifacename string, confPath string) error { } return err } + +// WriteWgConfig - creates a wireguard config file +func WriteWgConfig(cfg config.ClientConfig, privateKey string, peers []wgtypes.Peer) error { + options := ini.LoadOptions{ + AllowNonUniqueSections: true, + AllowShadows: true, + } + wireguard := ini.Empty(options) + wireguard.Section("Interface").Key("PrivateKey").SetValue(privateKey) + wireguard.Section("Interface").Key("ListenPort").SetValue(strconv.Itoa(int(cfg.Node.ListenPort))) + if cfg.Node.Address != "" { + wireguard.Section("Interface").Key("Address").SetValue(cfg.Node.Address) + } + if cfg.Node.Address6 != "" { + wireguard.Section("Interface").Key("Address").SetValue(cfg.Node.Address6) + } + if cfg.Node.DNSOn == "yes" { + wireguard.Section("Interface").Key("DNS").SetValue(cfg.Server.CoreDNSAddr) + } + if cfg.Node.PostUp != "" { + wireguard.Section("Interface").Key("PostUp").SetValue(cfg.Node.PostUp) + } + if cfg.Node.PostDown != "" { + wireguard.Section("Interface").Key("PostDown").SetValue(cfg.Node.PostDown) + } + for i, peer := range peers { + wireguard.SectionWithIndex("Peer", i).Key("PublicKey").SetValue(peer.PublicKey.String()) + if peer.PresharedKey.String() != "" { + wireguard.SectionWithIndex("Peer", i).Key("PreSharedKey").SetValue(peer.PresharedKey.String()) + } + if peer.AllowedIPs != nil { + var allowedIPs string + for _, ip := range peer.AllowedIPs { + allowedIPs = allowedIPs + ", " + ip.String() + } + wireguard.SectionWithIndex("Peer", i).Key("AllowedIps").SetValue(allowedIPs) + } + if peer.Endpoint != nil { + wireguard.SectionWithIndex("Peer", i).Key("Endpoint").SetValue(peer.Endpoint.String()) + } + } + if err := wireguard.SaveTo("/etc/netclient/config" + cfg.Node.Interface + ".conf"); err != nil { + return err + } + return nil +} + +// UpdateWgPeers - updates the peers of a network +func UpdateWgPeers(wgInterface string, peers []wgtypes.Peer) error { + //update to get path properly + file := "/etc/netclient/config/" + wgInterface + ".conf" + wireguard, err := ini.ShadowLoad(file) + if err != nil { + return err + } + for i, peer := range peers { + wireguard.SectionWithIndex("Peer", i).Key("PublicKey").SetValue(peer.PublicKey.String()) + if peer.PresharedKey.String() != "" { + wireguard.SectionWithIndex("Peer", i).Key("PreSharedKey").SetValue(peer.PresharedKey.String()) + } + if peer.AllowedIPs != nil { + var allowedIPs string + for _, ip := range peer.AllowedIPs { + allowedIPs = allowedIPs + ", " + ip.String() + } + wireguard.SectionWithIndex("Peer", i).Key("AllowedIps").SetValue(allowedIPs) + } + if peer.Endpoint != nil { + wireguard.SectionWithIndex("Peer", i).Key("Endpoint").SetValue(peer.Endpoint.String()) + } + } + if err := wireguard.SaveTo(file); err != nil { + return err + } + return nil +} + +// UpdateWgInterface - updates the interface section of a wireguard config file +func UpdateWgInterface(wgInterface, privateKey, nameserver string, node models.Node) error { + //update to get path properly + file := "/etc/netclient/config/" + wgInterface + ".conf" + wireguard, err := ini.ShadowLoad(file) + if err != nil { + return err + } + wireguard.Section("Interface").Key("PrivateKey").SetValue(privateKey) + wireguard.Section("Interface").Key("ListenPort").SetValue(strconv.Itoa(int(node.ListenPort))) + if node.Address != "" { + wireguard.Section("Interface").Key("Address").SetValue(node.Address) + } + if node.Address6 != "" { + wireguard.Section("Interface").Key("Address").SetValue(node.Address6) + } + if node.DNSOn == "yes" { + wireguard.Section("Interface").Key("DNS").SetValue(nameserver) + } + if node.PostUp != "" { + wireguard.Section("Interface").Key("PostUp").SetValue(node.PostUp) + } + if node.PostDown != "" { + wireguard.Section("Interface").Key("PostDown").SetValue(node.PostDown) + } + if err := wireguard.SaveTo(file); err != nil { + return err + } + return nil +} + +// UpdatePrivateKey - updates the private key of a wireguard config file +func UpdatePrivateKey(wgInterface, privateKey string) error { + //update to get path properly + file := "/etc/netclient/config/" + wgInterface + ".conf" + wireguard, err := ini.ShadowLoad(file) + if err != nil { + return err + } + wireguard.Section("Interface").Key("PrivateKey").SetValue(privateKey) + if err := wireguard.SaveTo(file); err != nil { + return err + } + return nil +} From 3148d1cd182628e53898fbc8d17ede24efa55807 Mon Sep 17 00:00:00 2001 From: 0xdcarns Date: Wed, 5 Jan 2022 10:32:20 -0500 Subject: [PATCH 087/116] constants --- netclient/wireguard/common.go | 59 +++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/netclient/wireguard/common.go b/netclient/wireguard/common.go index 8b9762c7..34acb962 100644 --- a/netclient/wireguard/common.go +++ b/netclient/wireguard/common.go @@ -19,6 +19,11 @@ import ( "gopkg.in/ini.v1" ) +const ( + section_interface = "Interface" + section_peers = "Peer" +) + // SetPeers - sets peers on a given WireGuard interface func SetPeers(iface string, keepalive int32, peers []wgtypes.PeerConfig) error { @@ -298,40 +303,40 @@ func WriteWgConfig(cfg config.ClientConfig, privateKey string, peers []wgtypes.P AllowShadows: true, } wireguard := ini.Empty(options) - wireguard.Section("Interface").Key("PrivateKey").SetValue(privateKey) - wireguard.Section("Interface").Key("ListenPort").SetValue(strconv.Itoa(int(cfg.Node.ListenPort))) + wireguard.Section(section_interface).Key("PrivateKey").SetValue(privateKey) + wireguard.Section(section_interface).Key("ListenPort").SetValue(strconv.Itoa(int(cfg.Node.ListenPort))) if cfg.Node.Address != "" { - wireguard.Section("Interface").Key("Address").SetValue(cfg.Node.Address) + wireguard.Section(section_interface).Key("Address").SetValue(cfg.Node.Address) } if cfg.Node.Address6 != "" { - wireguard.Section("Interface").Key("Address").SetValue(cfg.Node.Address6) + wireguard.Section(section_interface).Key("Address").SetValue(cfg.Node.Address6) } if cfg.Node.DNSOn == "yes" { - wireguard.Section("Interface").Key("DNS").SetValue(cfg.Server.CoreDNSAddr) + wireguard.Section(section_interface).Key("DNS").SetValue(cfg.Server.CoreDNSAddr) } if cfg.Node.PostUp != "" { - wireguard.Section("Interface").Key("PostUp").SetValue(cfg.Node.PostUp) + wireguard.Section(section_interface).Key("PostUp").SetValue(cfg.Node.PostUp) } if cfg.Node.PostDown != "" { - wireguard.Section("Interface").Key("PostDown").SetValue(cfg.Node.PostDown) + wireguard.Section(section_interface).Key("PostDown").SetValue(cfg.Node.PostDown) } for i, peer := range peers { - wireguard.SectionWithIndex("Peer", i).Key("PublicKey").SetValue(peer.PublicKey.String()) + wireguard.SectionWithIndex(section_peers, i).Key("PublicKey").SetValue(peer.PublicKey.String()) if peer.PresharedKey.String() != "" { - wireguard.SectionWithIndex("Peer", i).Key("PreSharedKey").SetValue(peer.PresharedKey.String()) + wireguard.SectionWithIndex(section_peers, i).Key("PreSharedKey").SetValue(peer.PresharedKey.String()) } if peer.AllowedIPs != nil { var allowedIPs string for _, ip := range peer.AllowedIPs { allowedIPs = allowedIPs + ", " + ip.String() } - wireguard.SectionWithIndex("Peer", i).Key("AllowedIps").SetValue(allowedIPs) + wireguard.SectionWithIndex(section_peers, i).Key("AllowedIps").SetValue(allowedIPs) } if peer.Endpoint != nil { - wireguard.SectionWithIndex("Peer", i).Key("Endpoint").SetValue(peer.Endpoint.String()) + wireguard.SectionWithIndex(section_peers, i).Key("Endpoint").SetValue(peer.Endpoint.String()) } } - if err := wireguard.SaveTo("/etc/netclient/config" + cfg.Node.Interface + ".conf"); err != nil { + if err := wireguard.SaveTo(ncutils.GetNetclientPathSpecific() + cfg.Node.Interface + ".conf"); err != nil { return err } return nil @@ -340,25 +345,25 @@ func WriteWgConfig(cfg config.ClientConfig, privateKey string, peers []wgtypes.P // UpdateWgPeers - updates the peers of a network func UpdateWgPeers(wgInterface string, peers []wgtypes.Peer) error { //update to get path properly - file := "/etc/netclient/config/" + wgInterface + ".conf" + file := ncutils.GetNetclientPathSpecific() + wgInterface + ".conf" wireguard, err := ini.ShadowLoad(file) if err != nil { return err } for i, peer := range peers { - wireguard.SectionWithIndex("Peer", i).Key("PublicKey").SetValue(peer.PublicKey.String()) + wireguard.SectionWithIndex(section_peers, i).Key("PublicKey").SetValue(peer.PublicKey.String()) if peer.PresharedKey.String() != "" { - wireguard.SectionWithIndex("Peer", i).Key("PreSharedKey").SetValue(peer.PresharedKey.String()) + wireguard.SectionWithIndex(section_peers, i).Key("PreSharedKey").SetValue(peer.PresharedKey.String()) } if peer.AllowedIPs != nil { var allowedIPs string for _, ip := range peer.AllowedIPs { allowedIPs = allowedIPs + ", " + ip.String() } - wireguard.SectionWithIndex("Peer", i).Key("AllowedIps").SetValue(allowedIPs) + wireguard.SectionWithIndex(section_peers, i).Key("AllowedIps").SetValue(allowedIPs) } if peer.Endpoint != nil { - wireguard.SectionWithIndex("Peer", i).Key("Endpoint").SetValue(peer.Endpoint.String()) + wireguard.SectionWithIndex(section_peers, i).Key("Endpoint").SetValue(peer.Endpoint.String()) } } if err := wireguard.SaveTo(file); err != nil { @@ -370,27 +375,27 @@ func UpdateWgPeers(wgInterface string, peers []wgtypes.Peer) error { // UpdateWgInterface - updates the interface section of a wireguard config file func UpdateWgInterface(wgInterface, privateKey, nameserver string, node models.Node) error { //update to get path properly - file := "/etc/netclient/config/" + wgInterface + ".conf" + file := ncutils.GetNetclientPathSpecific() + wgInterface + ".conf" wireguard, err := ini.ShadowLoad(file) if err != nil { return err } - wireguard.Section("Interface").Key("PrivateKey").SetValue(privateKey) - wireguard.Section("Interface").Key("ListenPort").SetValue(strconv.Itoa(int(node.ListenPort))) + wireguard.Section(section_interface).Key("PrivateKey").SetValue(privateKey) + wireguard.Section(section_interface).Key("ListenPort").SetValue(strconv.Itoa(int(node.ListenPort))) if node.Address != "" { - wireguard.Section("Interface").Key("Address").SetValue(node.Address) + wireguard.Section(section_interface).Key("Address").SetValue(node.Address) } if node.Address6 != "" { - wireguard.Section("Interface").Key("Address").SetValue(node.Address6) + wireguard.Section(section_interface).Key("Address").SetValue(node.Address6) } if node.DNSOn == "yes" { - wireguard.Section("Interface").Key("DNS").SetValue(nameserver) + wireguard.Section(section_interface).Key("DNS").SetValue(nameserver) } if node.PostUp != "" { - wireguard.Section("Interface").Key("PostUp").SetValue(node.PostUp) + wireguard.Section(section_interface).Key("PostUp").SetValue(node.PostUp) } if node.PostDown != "" { - wireguard.Section("Interface").Key("PostDown").SetValue(node.PostDown) + wireguard.Section(section_interface).Key("PostDown").SetValue(node.PostDown) } if err := wireguard.SaveTo(file); err != nil { return err @@ -401,12 +406,12 @@ func UpdateWgInterface(wgInterface, privateKey, nameserver string, node models.N // UpdatePrivateKey - updates the private key of a wireguard config file func UpdatePrivateKey(wgInterface, privateKey string) error { //update to get path properly - file := "/etc/netclient/config/" + wgInterface + ".conf" + file := ncutils.GetNetclientPathSpecific() + wgInterface + ".conf" wireguard, err := ini.ShadowLoad(file) if err != nil { return err } - wireguard.Section("Interface").Key("PrivateKey").SetValue(privateKey) + wireguard.Section(section_interface).Key("PrivateKey").SetValue(privateKey) if err := wireguard.SaveTo(file); err != nil { return err } From 5f26798a217f3a29b83eca5029e5f210744fddf9 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Wed, 5 Jan 2022 11:07:09 -0500 Subject: [PATCH 088/116] add error handling on failed key generation --- netclient/functions/daemon.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index fc926bda..8baaa392 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -97,6 +97,10 @@ var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) cfg.ReadConfig() nameserver := cfg.Server.CoreDNSAddr privateKey, err := wireguard.RetrievePrivKey(data.Network) + if err != nil { + ncutils.Log("error generating PrivateKey " + err.Error()) + return + } if err := wireguard.UpdateWgInterface(cfg.Node.Interface, privateKey, nameserver, data); err != nil { ncutils.Log("error updating wireguard config " + err.Error()) return From 2f47c351d855aae6ba5d42c69b3fb5514ab48e48 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Mon, 10 Jan 2022 14:35:53 -0500 Subject: [PATCH 089/116] refactor NodeUpdate message queue handler --- netclient/functions/daemon.go | 89 +++++++++++++++++++++-------------- 1 file changed, 54 insertions(+), 35 deletions(-) diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index 8baaa392..639436ae 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -6,6 +6,7 @@ import ( "log" "os" "os/signal" + "runtime" "strings" "syscall" "time" @@ -67,7 +68,8 @@ func Netclient(ctx context.Context, network string) { } client.AddRoute("update/"+cfg.Node.ID, NodeUpdate) client.AddRoute("update/peers/"+cfg.Node.ID, UpdatePeers) - client.AddRoute("update/keys/"+cfg.Node.ID, UpdateKeys) + //handle key updates in node update + //client.AddRoute("update/keys/"+cfg.Node.ID, UpdateKeys) defer client.Disconnect(250) go Checkin(ctx, cfg, network) go Metrics(ctx, cfg, network) @@ -86,19 +88,44 @@ var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) ncutils.Log("received message to update node " + string(msg.Payload())) //potentiall blocking i/o so do this in a go routine go func() { - var data models.Node - err := json.Unmarshal(msg.Payload(), &data) + var newNode models.Node + var cfg config.ClientConfig + cfg.Network = newNode.Network + cfg.ReadConfig() + err := json.Unmarshal(msg.Payload(), &newNode) if err != nil { ncutils.Log("error unmarshalling node update data" + err.Error()) return } - var cfg config.ClientConfig - cfg.Network = data.Network - cfg.ReadConfig() + //check if interface name has changed if so delete. + if cfg.Node.Interface != newNode.Interface { + if err = wireguard.RemoveConf(cfg.Node.Interface, true); err != nil { + ncutils.PrintLog("could not delete old interface "+cfg.Node.Interface+": ", err.Error(), 1) + } + } + newNode.PullChanges = "no" + //ensure that OS never changes + newNode.OS = runtime.GOOS + cfg.Node = newNode + switch newNode.Action { + case models.NODE_DELETE: + if err := RemoveLocalInstance(cfg, cfg.Network); err != nil { + ncutils.Printlog("error deleting local instance: "+err.Error(), 1) + return + } + case models.NODE_UPDATE_KEY: + UpdateKeys(cfg) + case models.NODE_NOOP: + default: + } + //Save new config + if err := config.Write(&cfg, cfg.Network); err != nil { + ncutils.PrintLog("error updating node configuration: "+err.Error(), 1) + } nameserver := cfg.Server.CoreDNSAddr privateKey, err := wireguard.RetrievePrivKey(data.Network) if err != nil { - ncutils.Log("error generating PrivateKey " + err.Error()) + ncutils.Log("error reading PrivateKey " + err.Error()) return } if err := wireguard.UpdateWgInterface(cfg.Node.Interface, privateKey, nameserver, data); err != nil { @@ -108,7 +135,7 @@ var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) // path hardcoded for now... should be updated err = wireguard.ApplyWGQuickConf("/etc/netclient/config/" + cfg.Node.Interface + ".conf") if err != nil { - ncutils.Log("error restarting wg after peer update " + err.Error()) + ncutils.Log("error restarting wg after node update " + err.Error()) return } }() @@ -117,7 +144,6 @@ var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) // UpdatePeers -- mqtt message handler for /update/peers/ topic var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update peers " + string(msg.Payload())) - //potentiall blocking i/o so do this in a go routine go func() { var peerUpdate models.PeerUpdate err := json.Unmarshal(msg.Payload(), &peerUpdate) @@ -142,34 +168,27 @@ var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) }() } -// UpdateKeys -- mqtt message handler for /update/keys/ topic -var UpdateKeys mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { - ncutils.Log("received message to update keys " + string(msg.Payload())) +// UpdateKeys -- updates private key and returns new publickey +func UpdateKeys(cfg *config.ClientConfig, client mqtt.Client) (*config.ClientConfig, error) { + ncutils.Log("received message to update keys") //potentiall blocking i/o so do this in a go routine - go func() { - var data models.KeyUpdate - if err := json.Unmarshal(msg.Payload(), &data); err != nil { - ncutils.Log("error unmarshalling key update data" + err.Error()) - return - } - var cfg config.ClientConfig - cfg.Network = data.Network - cfg.ReadConfig() - key, err := wgtypes.GeneratePrivateKey() - if err != nil { - ncutils.Log("error generating privatekey " + err.Error()) - return - } - if err := wireguard.UpdatePrivateKey(data.Interface, key.String()); err != nil { - ncutils.Log("error updating wireguard key " + err.Error()) - return - } - publicKey := key.PublicKey() - if token := client.Publish("update/publickey/"+cfg.Node.ID, 0, false, publicKey.String()); token.Wait() && token.Error() != nil { - ncutils.Log("error publishing publickey update " + token.Error().Error()) - } + key, err := wgtypes.GeneratePrivateKey() + if err != nil { + ncutils.Log("error generating privatekey " + err.Error()) + return cfg, err + } + if err := wireguard.UpdatePrivateKey(data.Interface, key.String()); err != nil { + ncutils.Log("error updating wireguard key " + err.Error()) + return cfg, err + } + publicKey := key.PublicKey() + if token := client.Publish("update/publickey/"+cfg.Node.ID, 0, false, publicKey.String()); token.Wait() && token.Error() != nil { + ncutils.Log("error publishing publickey update " + token.Error().Error()) client.Disconnect(250) - }() + return cfg, err + } + client.Disconnect(250) + return cfg, nil } // Checkin -- go routine that checks for public or local ip changes, publishes changes From 9be97b3bc810ccd4c38b313392773e7d4c036637 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Wed, 12 Jan 2022 16:23:34 -0500 Subject: [PATCH 090/116] WIP commit --- .gitignore | 1 + config/config.go | 2 + go.mod | 6 +- go.sum | 6 -- main.go | 57 +++++++++- models/mqtt.go | 5 +- mq/mq.go | 197 ++++++++++++++++++++++++++++++++++ netclient/functions/daemon.go | 14 +-- servercfg/serverconf.go | 27 +++++ 9 files changed, 293 insertions(+), 22 deletions(-) create mode 100644 mq/mq.go diff --git a/.gitignore b/.gitignore index 3f09bc2e..18da4b52 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ config/dnsconfig/ data/ .vscode/ .idea/ +.vscode/ diff --git a/config/config.go b/config/config.go index fc1bcbf2..649ef1b9 100644 --- a/config/config.go +++ b/config/config.go @@ -43,12 +43,14 @@ type ServerConfig struct { GRPCHost string `yaml:"grpchost"` GRPCPort string `yaml:"grpcport"` GRPCSecure string `yaml:"grpcsecure"` + MQHOST string `yaml:"mqhost"` MasterKey string `yaml:"masterkey"` DNSKey string `yaml:"dnskey"` AllowedOrigin string `yaml:"allowedorigin"` NodeID string `yaml:"nodeid"` RestBackend string `yaml:"restbackend"` AgentBackend string `yaml:"agentbackend"` + MessageQueueBackend string `yaml:"messagequeuebackend"` ClientMode string `yaml:"clientmode"` DNSMode string `yaml:"dnsmode"` SplitDNS string `yaml:"splitdns"` diff --git a/go.mod b/go.mod index b8b169d9..b4df5780 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/gravitl/netmaker go 1.17 require ( + github.com/eclipse/paho.mqtt.golang v1.3.5 github.com/go-playground/validator/v10 v10.10.0 github.com/golang-jwt/jwt/v4 v4.2.0 github.com/golang/protobuf v1.5.2 // indirect @@ -25,6 +26,7 @@ require ( google.golang.org/genproto v0.0.0-20210201151548-94839c025ad4 // indirect google.golang.org/grpc v1.43.0 google.golang.org/protobuf v1.27.1 + gopkg.in/ini.v1 v1.66.2 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b ) @@ -32,9 +34,7 @@ require ( cloud.google.com/go v0.34.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/eclipse/paho.mqtt.golang v1.3.5 // indirect github.com/felixge/httpsnoop v1.0.1 // indirect - github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534 // indirect github.com/go-playground/locales v0.14.0 // indirect github.com/go-playground/universal-translator v0.18.0 // indirect github.com/google/go-cmp v0.5.5 // indirect @@ -46,7 +46,5 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/russross/blackfriday/v2 v2.0.1 // indirect github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect - golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect google.golang.org/appengine v1.4.0 // indirect - gopkg.in/ini.v1 v1.66.2 // indirect ) diff --git a/go.sum b/go.sum index 84dbc91f..e36273a2 100644 --- a/go.sum +++ b/go.sum @@ -36,8 +36,6 @@ github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8S github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534 h1:dhy9OQKGBh4zVXbjwbxxHjRxMJtLXj3zfgpBYQaR4Q4= -github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk= github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= @@ -194,7 +192,6 @@ golang.org/x/net v0.0.0-20201216054612-986b41b23924/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210504132125-bbd867fde50d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985 h1:4CSI6oo7cOjJKajidEljs9h+uP0rRZBPPPhcCbj5mw8= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -205,8 +202,6 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -228,7 +223,6 @@ golang.org/x/sys v0.0.0-20210123111255-9b0068b26619/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210216163648-f7da38b97c65/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210309040221-94ec62e08169/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210503173754-0981d6026fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/main.go b/main.go index fd9aad97..52243051 100644 --- a/main.go +++ b/main.go @@ -11,6 +11,7 @@ import ( "sync" "time" + mqtt "github.com/eclipse/paho.mqtt.golang" "github.com/gravitl/netmaker/auth" controller "github.com/gravitl/netmaker/controllers" "github.com/gravitl/netmaker/database" @@ -19,6 +20,7 @@ import ( "github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/logic" "github.com/gravitl/netmaker/models" + "github.com/gravitl/netmaker/mq" "github.com/gravitl/netmaker/netclient/ncutils" "github.com/gravitl/netmaker/servercfg" "github.com/gravitl/netmaker/serverctl" @@ -106,8 +108,14 @@ func startControllers() { go controller.HandleRESTRequests(&waitnetwork) } - if !servercfg.IsAgentBackend() && !servercfg.IsRestBackend() { - logger.Log(0, "No Server Mode selected, so nothing is being served! Set either Agent mode (AGENT_BACKEND) or Rest mode (REST_BACKEND) to 'true'.") + //Run MessageQueue + if servercfg.IsMessageQueueBackend() { + waitnetwork.Add(1) + go runMessageQueue(&waitnetwork) + } + + if !servercfg.IsAgentBackend() && !servercfg.IsRestBackend() && !servercfg.IsMessageQueueBackend() { + logger.Log(0, "No Server Mode selected, so nothing is being served! Set Agent mode (AGENT_BACKEND) or Rest mode (REST_BACKEND) or MessageQueue (MESSAGEQUEUE_BACKEND) to 'true'.") } if servercfg.IsClientMode() == "on" { @@ -175,6 +183,51 @@ func runGRPC(wg *sync.WaitGroup) { logger.Log(0, "Closed DB connection.") } +// Should we be using a context vice a waitgroup???????????? +func runMessageQueue(wg *sync.WaitGroup) { + defer wg.Done() + //refactor netclient.functions.SetupMQTT so can be called from here + //setupMQTT + opts := mqtt.NewClientOptions() + opts.AddBroker(servercfg.GetMessageQueueEndpoint()) + logger.Log(0, "setting broker "+servercfg.GetMessageQueueEndpoint()) + opts.SetDefaultPublishHandler(mq.DefaultHandler) + client := mqtt.NewClient(opts) + if token := client.Connect(); token.Wait() && token.Error() != nil { + logger.Log(0, "unable to connect to message queue broker, closing down") + return + } + //Set up Subscriptions + if token := client.Subscribe("#", 0, nil); token.Wait() && token.Error() != nil { + //should make constant for disconnect wait period + client.Disconnect(250) + logger.Log(0, "could not subscribe to message queue ...") + return + } + if token := client.Subscribe("ping/#", 0, mq.Ping); token.Wait() && token.Error() != nil { + client.Disconnect(240) + logger.Log(0, "ping sub failed") + } + if token := client.Subscribe("metrics/#", 0, mq.Metrics); token.Wait() && token.Error() != nil { + client.Disconnect(240) + logger.Log(0, "metrics sub failed") + } + if token := client.Subscribe("update/localaddress/#", 0, mq.LocalAddressUpdate); token.Wait() && token.Error() != nil { + client.Disconnect(240) + logger.Log(0, "metrics sub failed") + } + if token := client.Subscribe("update/ip/#", 0, mq.IPUpdate); token.Wait() && token.Error() != nil { + client.Disconnect(240) + logger.Log(0, "metrics sub failed") + } + if token := client.Subscribe("update/publickey/#", 0, mq.PublicKeyUpdate); token.Wait() && token.Error() != nil { + client.Disconnect(240) + logger.Log(0, "metrics sub failed") + } + for { + } +} + func authServerUnaryInterceptor() grpc.ServerOption { return grpc.UnaryInterceptor(controller.AuthServerUnaryInterceptor) } diff --git a/models/mqtt.go b/models/mqtt.go index a7e87e1f..da7265f3 100644 --- a/models/mqtt.go +++ b/models/mqtt.go @@ -3,9 +3,8 @@ package models import "golang.zx2c4.com/wireguard/wgctrl/wgtypes" type PeerUpdate struct { - Network string - Interface string - Peers []wgtypes.Peer + Network string + Peers []wgtypes.Peer } type KeyUpdate struct { diff --git a/mq/mq.go b/mq/mq.go new file mode 100644 index 00000000..3620b215 --- /dev/null +++ b/mq/mq.go @@ -0,0 +1,197 @@ +package mq + +import ( + "encoding/json" + "errors" + "log" + "net" + "strings" + "time" + + mqtt "github.com/eclipse/paho.mqtt.golang" + "github.com/gravitl/netmaker/database" + "github.com/gravitl/netmaker/logger" + "github.com/gravitl/netmaker/logic" + "github.com/gravitl/netmaker/models" + "golang.zx2c4.com/wireguard/wgctrl/wgtypes" +) + +var DefaultHandler mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { + logger.Log(0, "MQTT Message: Topic: "+string(msg.Topic())+" Message: "+string(msg.Payload())) +} + +var Metrics mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { + logger.Log(0, "Metrics Handler") +} + +var Ping mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { + logger.Log(0, "Ping Handler") + //test code --- create a node if it doesn't exit for testing only + createnode := models.Node{PublicKey: "DM5qhLAE20PG9BbfBCger+Ac9D2NDOwCtY1rbYDLf34=", Name: "testnode", + Endpoint: "10.0.0.1", MacAddress: "01:02:03:04:05:06", Password: "password", Network: "skynet"} + if _, err := logic.GetNode("01:02:03:04:05:06", "skynet"); err != nil { + err := logic.CreateNode(&createnode) + if err != nil { + log.Println(err) + } + } + //end of test code + go func() { + mac, net, err := GetMacNetwork(msg.Topic()) + if err != nil { + logger.Log(0, "error getting node.ID sent on ping topic ") + return + } + logger.Log(0, "ping recieved from "+mac+" on net "+net) + node, err := logic.GetNodeByMacAddress(net, mac) + if err != nil { + logger.Log(0, "mq-ping error getting node: "+err.Error()) + record, err := database.FetchRecord(database.NODES_TABLE_NAME, mac+"###"+net) + if err != nil { + logger.Log(0, "error reading database ", err.Error()) + return + } + logger.Log(0, "record from database") + logger.Log(0, record) + return + } + node.SetLastCheckIn() + // --TODO --set client version once feature is implemented. + //node.SetClientVersion(msg.Payload()) + }() +} + +var PublicKeyUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { + logger.Log(0, "PublicKey Handler") + go func() { + logger.Log(0, "public key update "+msg.Topic()) + key := string(msg.Payload()) + mac, network, err := GetMacNetwork(msg.Topic()) + if err != nil { + logger.Log(0, "error getting node.ID sent on "+msg.Topic()+" "+err.Error()) + } + node, err := logic.GetNode(mac, network) + if err != nil { + logger.Log(0, "error retrieving node "+msg.Topic()+" "+err.Error()) + } + node.PublicKey = key + node.SetLastCheckIn() + UpdatePeers(&node, client) + }() +} + +var IPUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { + go func() { + ip := string(msg.Payload()) + logger.Log(0, "IPUpdate Handler") + mac, network, err := GetMacNetwork(msg.Topic()) + logger.Log(0, "ipUpdate recieved from "+mac+" on net "+network) + if err != nil { + logger.Log(0, "error getting node.ID sent on update/ip topic ") + return + } + node, err := logic.GetNode(mac, network) + if err != nil { + logger.Log(0, "invalid ID recieved on update/ip topic: "+err.Error()) + return + } + node.Endpoint = ip + node.SetLastCheckIn() + UpdatePeers(&node, client) + }() +} + +func UpdatePeers(node *models.Node, client mqtt.Client) { + peersToUpdate, err := logic.GetPeers(node) + if err != nil { + logger.Log(0, "error retrieving peers") + return + } + for _, peerToUpdate := range peersToUpdate { + var peerUpdate models.PeerUpdate + peerUpdate.Network = node.Network + + myPeers, err := logic.GetPeers(&peerToUpdate) + if err != nil { + logger.Log(0, "uable to get peers "+err.Error()) + continue + } + for i, myPeer := range myPeers { + var allowedIPs []net.IPNet + var allowedIP net.IPNet + endpoint, err := net.ResolveUDPAddr("udp", myPeer.Address+":"+string(myPeer.ListenPort)) + if err != nil { + logger.Log(0, "error setting endpoint for peer "+err.Error()) + } + for _, ipString := range myPeer.AllowedIPs { + _, ipNet, _ := net.ParseCIDR(ipString) + allowedIP = *ipNet + allowedIPs = append(allowedIPs, allowedIP) + } + key, err := wgtypes.ParseKey(myPeer.PublicKey) + if err != nil { + logger.Log(0, "err parsing publickey") + continue + } + peerUpdate.Peers[i].PublicKey = key + peerUpdate.Peers[i].Endpoint = endpoint + peerUpdate.Peers[i].PersistentKeepaliveInterval = time.Duration(myPeer.PersistentKeepalive) + peerUpdate.Peers[i].AllowedIPs = allowedIPs + peerUpdate.Peers[i].ProtocolVersion = 0 + } + //PublishPeerUpdate(my) + data, err := json.Marshal(peerUpdate) + if err != nil { + logger.Log(0, "err marshalling data for peer update "+err.Error()) + } + if token := client.Publish("update/peers/"+peerToUpdate.ID, 0, false, data); token.Wait() && token.Error() != nil { + logger.Log(0, "error publishing peer update "+token.Error().Error()) + } + client.Disconnect(250) + } +} + +var LocalAddressUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { + logger.Log(0, "LocalAddressUpdate Handler") + go func() { + logger.Log(0, "LocalAddressUpdate handler") + mac, net, err := GetMacNetwork(msg.Topic()) + if err != nil { + logger.Log(0, "error getting node.ID "+msg.Topic()) + return + } + node, err := logic.GetNode(mac, net) + if err != nil { + logger.Log(0, "error get node "+msg.Topic()) + return + } + node.LocalAddress = string(msg.Payload()) + node.SetLastCheckIn() + }() +} + +func GetMacNetwork(topic string) (string, string, error) { + parts := strings.Split(topic, "/") + count := len(parts) + if count == 1 { + return "", "", errors.New("invalid topic") + } + macnet := strings.Split(parts[count-1], "---") + if len(macnet) != 2 { + return "", "", errors.New("topic id not in mac---network format") + } + return macnet[0], macnet[1], nil +} + +func GetID(topic string) (string, error) { + parts := strings.Split(topic, "/") + count := len(parts) + if count == 1 { + return "", errors.New("invalid topic") + } + macnet := strings.Split(parts[count-1], "---") + if len(macnet) != 2 { + return "", errors.New("topic id not in mac---network format") + } + return macnet[0] + "###" + macnet[1], nil +} diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index 639436ae..a5360319 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -100,7 +100,7 @@ var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) //check if interface name has changed if so delete. if cfg.Node.Interface != newNode.Interface { if err = wireguard.RemoveConf(cfg.Node.Interface, true); err != nil { - ncutils.PrintLog("could not delete old interface "+cfg.Node.Interface+": ", err.Error(), 1) + ncutils.PrintLog("could not delete old interface "+cfg.Node.Interface+": "+err.Error(), 1) } } newNode.PullChanges = "no" @@ -109,12 +109,12 @@ var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) cfg.Node = newNode switch newNode.Action { case models.NODE_DELETE: - if err := RemoveLocalInstance(cfg, cfg.Network); err != nil { - ncutils.Printlog("error deleting local instance: "+err.Error(), 1) + if err := RemoveLocalInstance(&cfg, cfg.Network); err != nil { + ncutils.PrintLog("error deleting local instance: "+err.Error(), 1) return } case models.NODE_UPDATE_KEY: - UpdateKeys(cfg) + UpdateKeys(&cfg, client) case models.NODE_NOOP: default: } @@ -123,12 +123,12 @@ var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) ncutils.PrintLog("error updating node configuration: "+err.Error(), 1) } nameserver := cfg.Server.CoreDNSAddr - privateKey, err := wireguard.RetrievePrivKey(data.Network) + privateKey, err := wireguard.RetrievePrivKey(newNode.Network) if err != nil { ncutils.Log("error reading PrivateKey " + err.Error()) return } - if err := wireguard.UpdateWgInterface(cfg.Node.Interface, privateKey, nameserver, data); err != nil { + if err := wireguard.UpdateWgInterface(cfg.Node.Interface, privateKey, nameserver, newNode); err != nil { ncutils.Log("error updating wireguard config " + err.Error()) return } @@ -177,7 +177,7 @@ func UpdateKeys(cfg *config.ClientConfig, client mqtt.Client) (*config.ClientCon ncutils.Log("error generating privatekey " + err.Error()) return cfg, err } - if err := wireguard.UpdatePrivateKey(data.Interface, key.String()); err != nil { + if err := wireguard.UpdatePrivateKey(cfg.Node.Interface, key.String()); err != nil { ncutils.Log("error updating wireguard key " + err.Error()) return cfg, err } diff --git a/servercfg/serverconf.go b/servercfg/serverconf.go index e203ddd4..ed280aa1 100644 --- a/servercfg/serverconf.go +++ b/servercfg/serverconf.go @@ -244,6 +244,18 @@ func GetGRPCPort() string { return grpcport } +// GetMessageQueueEndpoint - gets the message queue endpoint +func GetMessageQueueEndpoint() string { + host, _ := GetPublicIP() + if os.Getenv("MQ_HOST") != "" { + host = os.Getenv("MQ_HOST") + } else if config.Config.Server.MQHOST != "" { + host = config.Config.Server.MQHOST + } + //Do we want MQ port configurable??? + return host + ":1883" +} + // GetMasterKey - gets the configured master key of server func GetMasterKey() string { key := "secretkey" @@ -307,6 +319,21 @@ func IsAgentBackend() bool { return isagent } +// IsMessageQueueBackend - checks if message queue is on or off +func IsMessageQueueBackend() bool { + ismessagequeue := true + if os.Getenv("MESSAGEQUEUE_BACKEND") != "" { + if os.Getenv("MESSAGEQUEUE_BACKEND") == "off" { + ismessagequeue = false + } + } else if config.Config.Server.MessageQueueBackend != "" { + if config.Config.Server.MessageQueueBackend == "off" { + ismessagequeue = false + } + } + return ismessagequeue +} + // IsClientMode - checks if it should run in client mode func IsClientMode() string { isclient := "on" From c63e8565b023163ed9ad05326ef5b99be054143f Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Fri, 14 Jan 2022 14:30:26 -0500 Subject: [PATCH 091/116] WIP commit to enable rebasing to uuid feature --- main.go | 30 +++--- models/mqtt.go | 7 +- mq/mq.go | 120 ++++++++++++------------ netclient/functions/daemon.go | 35 ++++++- netclient/functions/peers.go | 167 ++++++++++++++++++++++++++++++++++ 5 files changed, 276 insertions(+), 83 deletions(-) create mode 100644 netclient/functions/peers.go diff --git a/main.go b/main.go index 52243051..3d527a0b 100644 --- a/main.go +++ b/main.go @@ -9,7 +9,7 @@ import ( "runtime/debug" "strconv" "sync" - "time" + "syscall" mqtt "github.com/eclipse/paho.mqtt.golang" "github.com/gravitl/netmaker/auth" @@ -118,16 +118,16 @@ func startControllers() { logger.Log(0, "No Server Mode selected, so nothing is being served! Set Agent mode (AGENT_BACKEND) or Rest mode (REST_BACKEND) or MessageQueue (MESSAGEQUEUE_BACKEND) to 'true'.") } - if servercfg.IsClientMode() == "on" { - var checkintime = time.Duration(servercfg.GetServerCheckinInterval()) * time.Second - for { // best effort currently - var serverGroup sync.WaitGroup - serverGroup.Add(1) - go runClient(&serverGroup) - serverGroup.Wait() - time.Sleep(checkintime) - } - } + //if servercfg.IsClientMode() == "on" { + // var checkintime = time.Duration(servercfg.GetServerCheckinInterval()) * time.Second + // for { // best effort currently + // var serverGroup sync.WaitGroup + // serverGroup.Add(1) + // go runClient(&serverGroup) + // serverGroup.Wait() + // time.Sleep(checkintime) + // } + //} waitnetwork.Wait() } @@ -204,7 +204,7 @@ func runMessageQueue(wg *sync.WaitGroup) { logger.Log(0, "could not subscribe to message queue ...") return } - if token := client.Subscribe("ping/#", 0, mq.Ping); token.Wait() && token.Error() != nil { + if token := client.Subscribe("ping/#", 2, mq.Ping); token.Wait() && token.Error() != nil { client.Disconnect(240) logger.Log(0, "ping sub failed") } @@ -224,8 +224,10 @@ func runMessageQueue(wg *sync.WaitGroup) { client.Disconnect(240) logger.Log(0, "metrics sub failed") } - for { - } + quit := make(chan os.Signal, 1) + signal.Notify(quit, syscall.SIGTERM, os.Interrupt) + <-quit + logger.Log(0, "Message Queue shutting down") } func authServerUnaryInterceptor() grpc.ServerOption { diff --git a/models/mqtt.go b/models/mqtt.go index da7265f3..07bb2157 100644 --- a/models/mqtt.go +++ b/models/mqtt.go @@ -1,10 +1,9 @@ package models -import "golang.zx2c4.com/wireguard/wgctrl/wgtypes" - type PeerUpdate struct { - Network string - Peers []wgtypes.Peer + Network string + Nodes []Node + ExtPeers []ExtPeersResponse } type KeyUpdate struct { diff --git a/mq/mq.go b/mq/mq.go index 3620b215..fd9657a7 100644 --- a/mq/mq.go +++ b/mq/mq.go @@ -1,19 +1,15 @@ package mq import ( - "encoding/json" "errors" - "log" - "net" + "fmt" "strings" - "time" mqtt "github.com/eclipse/paho.mqtt.golang" "github.com/gravitl/netmaker/database" "github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/logic" "github.com/gravitl/netmaker/models" - "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) var DefaultHandler mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { @@ -22,20 +18,11 @@ var DefaultHandler mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Messa var Metrics mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { logger.Log(0, "Metrics Handler") + //TODOD -- handle metrics data ---- store to database? } var Ping mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { - logger.Log(0, "Ping Handler") - //test code --- create a node if it doesn't exit for testing only - createnode := models.Node{PublicKey: "DM5qhLAE20PG9BbfBCger+Ac9D2NDOwCtY1rbYDLf34=", Name: "testnode", - Endpoint: "10.0.0.1", MacAddress: "01:02:03:04:05:06", Password: "password", Network: "skynet"} - if _, err := logic.GetNode("01:02:03:04:05:06", "skynet"); err != nil { - err := logic.CreateNode(&createnode) - if err != nil { - log.Println(err) - } - } - //end of test code + logger.Log(0, "Ping Handler: "+msg.Topic()) go func() { mac, net, err := GetMacNetwork(msg.Topic()) if err != nil { @@ -56,6 +43,7 @@ var Ping mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { return } node.SetLastCheckIn() + logger.Log(0, "ping processed") // --TODO --set client version once feature is implemented. //node.SetClientVersion(msg.Payload()) }() @@ -76,7 +64,9 @@ var PublicKeyUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Mess } node.PublicKey = key node.SetLastCheckIn() - UpdatePeers(&node, client) + if err := UpdatePeers(client, node); err != nil { + logger.Log(0, "error updating peers "+err.Error()) + } }() } @@ -97,58 +87,63 @@ var IPUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { } node.Endpoint = ip node.SetLastCheckIn() - UpdatePeers(&node, client) + if err := UpdatePeers(client, node); err != nil { + logger.Log(0, "error updating peers "+err.Error()) + } }() } -func UpdatePeers(node *models.Node, client mqtt.Client) { - peersToUpdate, err := logic.GetPeers(node) - if err != nil { - logger.Log(0, "error retrieving peers") - return - } - for _, peerToUpdate := range peersToUpdate { - var peerUpdate models.PeerUpdate - peerUpdate.Network = node.Network +func UpdatePeers(client mqtt.Client, node models.Node) error { + var peerUpdate models.PeerUpdate + peerUpdate.Network = node.Network - myPeers, err := logic.GetPeers(&peerToUpdate) - if err != nil { - logger.Log(0, "uable to get peers "+err.Error()) + nodes, err := logic.GetNetworkNodes(node.Network) + if err != nil { + return fmt.Errorf("unable to get network nodes %v: ", err) + } + if token := client.Connect(); token.Wait() && token.Error() != nil { + return token.Error() + } + for _, peer := range nodes { + //don't need to update the initiatiing client + if peer.ID == node.ID { continue } - for i, myPeer := range myPeers { - var allowedIPs []net.IPNet - var allowedIP net.IPNet - endpoint, err := net.ResolveUDPAddr("udp", myPeer.Address+":"+string(myPeer.ListenPort)) - if err != nil { - logger.Log(0, "error setting endpoint for peer "+err.Error()) - } - for _, ipString := range myPeer.AllowedIPs { - _, ipNet, _ := net.ParseCIDR(ipString) - allowedIP = *ipNet - allowedIPs = append(allowedIPs, allowedIP) - } - key, err := wgtypes.ParseKey(myPeer.PublicKey) - if err != nil { - logger.Log(0, "err parsing publickey") - continue - } - peerUpdate.Peers[i].PublicKey = key - peerUpdate.Peers[i].Endpoint = endpoint - peerUpdate.Peers[i].PersistentKeepaliveInterval = time.Duration(myPeer.PersistentKeepalive) - peerUpdate.Peers[i].AllowedIPs = allowedIPs - peerUpdate.Peers[i].ProtocolVersion = 0 - } - //PublishPeerUpdate(my) - data, err := json.Marshal(peerUpdate) + peerUpdate.Nodes = append(peerUpdate.Nodes, peer) + peerUpdate.ExtPeers, err = logic.GetExtPeersList(node.MacAddress, node.Network) if err != nil { - logger.Log(0, "err marshalling data for peer update "+err.Error()) + logger.Log(0) } - if token := client.Publish("update/peers/"+peerToUpdate.ID, 0, false, data); token.Wait() && token.Error() != nil { - logger.Log(0, "error publishing peer update "+token.Error().Error()) + if token := client.Publish("update/peers/"+peer.ID, 0, false, nodes); token.Wait() && token.Error() != nil { + logger.Log(0, "error publishing peer update "+peer.ID+" "+token.Error().Error()) } - client.Disconnect(250) } + + return nil +} + +func UpdateLocalPeers(client mqtt.Client, node models.Node) error { + nodes, err := logic.GetNetworkNodes(node.Network) + if err != nil { + return fmt.Errorf("unable to get network nodes %v: ", err) + } + if token := client.Connect(); token.Wait() && token.Error() != nil { + return token.Error() + } + for _, peer := range nodes { + //don't need to update the initiatiing client + if peer.ID == node.ID { + continue + } + //if peer.Endpoint is on same lan as node.LocalAddress + //if TODO{ + //continue + //} + if token := client.Publish("update/peers/"+peer.ID, 0, false, nodes); token.Wait() && token.Error() != nil { + logger.Log(0, "error publishing peer update "+peer.ID+" "+token.Error().Error()) + } + } + return nil } var LocalAddressUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { @@ -167,6 +162,9 @@ var LocalAddressUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.M } node.LocalAddress = string(msg.Payload()) node.SetLastCheckIn() + if err := UpdateLocalPeers(client, node); err != nil { + logger.Log(0, "error updating peers "+err.Error()) + } }() } @@ -176,7 +174,7 @@ func GetMacNetwork(topic string) (string, string, error) { if count == 1 { return "", "", errors.New("invalid topic") } - macnet := strings.Split(parts[count-1], "---") + macnet := strings.Split(parts[count-1], "-") if len(macnet) != 2 { return "", "", errors.New("topic id not in mac---network format") } @@ -189,7 +187,7 @@ func GetID(topic string) (string, error) { if count == 1 { return "", errors.New("invalid topic") } - macnet := strings.Split(parts[count-1], "---") + macnet := strings.Split(parts[count-1], "-") if len(macnet) != 2 { return "", errors.New("topic id not in mac---network format") } diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index a5360319..6e212c77 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -154,9 +154,19 @@ var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) var cfg config.ClientConfig cfg.Network = peerUpdate.Network cfg.ReadConfig() - err = wireguard.UpdateWgPeers(cfg.Node.Interface, peerUpdate.Peers) + peers, err := CalculatePeers(cfg.Node, peerUpdate.Nodes, cfg.Node.IsDualStack, cfg.Node.IsEgressGateway, cfg.Node.IsServer) if err != nil { - ncutils.Log("error updating peers" + err.Error()) + ncutils.Log("error calculating Peers " + err.Error()) + return + } + extpeers, err := CalculateExtPeers(cfg.Node, peerUpdate.ExtPeers) + if err != nil { + ncutils.Log("error updated external wireguard peers " + err.Error()) + } + peers = append(peers, extpeers...) + err = wireguard.UpdateWgPeers(cfg.Node.Interface, peers) + if err != nil { + ncutils.Log("error updating wireguard peers" + err.Error()) return } // path hardcoded for now... should be updated @@ -187,7 +197,9 @@ func UpdateKeys(cfg *config.ClientConfig, client mqtt.Client) (*config.ClientCon client.Disconnect(250) return cfg, err } - client.Disconnect(250) + if err := config.ModConfig(&cfg.Node); err != nil { + ncutils.Log("error updating local config " + err.Error()) + } return cfg, nil } @@ -202,6 +214,11 @@ func Checkin(ctx context.Context, cfg config.ClientConfig, network string) { //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? case <-time.After(time.Second * 10): ncutils.Log("Checkin running") + //read latest config + cfg.ReadConfig() + //fix NodeID to remove ### so NodeID can be used as message topic + //remove with GRA-73 + cfg.Node.ID = strings.Replace(cfg.Node.ID, "###", "-", 1) if cfg.Node.Roaming == "yes" && cfg.Node.IsStatic != "yes" { extIP, err := ncutils.GetPublicIP() if err != nil { @@ -242,6 +259,10 @@ func UpdateEndpoint(cfg config.ClientConfig, network, ip string) { if token := client.Publish("update/ip/"+cfg.Node.ID, 0, false, ip); token.Wait() && token.Error() != nil { ncutils.Log("error publishing endpoint update " + token.Error().Error()) } + cfg.Node.Endpoint = ip + if err := config.Write(&cfg, cfg.Network); err != nil { + ncutils.Log("error updating local config " + err.Error()) + } client.Disconnect(250) } @@ -252,13 +273,19 @@ func UpdateLocalAddress(cfg config.ClientConfig, network, ip string) { if token := client.Publish("update/localaddress/"+cfg.Node.ID, 0, false, ip); token.Wait() && token.Error() != nil { ncutils.Log("error publishing local address update " + token.Error().Error()) } + cfg.Node.LocalAddress = ip + ncutils.Log("updating local address in local config to: " + cfg.Node.LocalAddress) + if err := config.Write(&cfg, cfg.Network); err != nil { + ncutils.Log("error updating local config " + err.Error()) + } client.Disconnect(250) } // Hello -- ping the broker to let server know node is alive and doing fine func Hello(cfg config.ClientConfig, network string) { client := SetupMQTT(cfg) - if token := client.Publish("ping/"+cfg.Node.ID, 0, false, "hello world!"); token.Wait() && token.Error() != nil { + ncutils.Log("sending ping " + cfg.Node.ID) + if token := client.Publish("ping/"+cfg.Node.ID, 2, false, "hello world!"); token.Wait() && token.Error() != nil { ncutils.Log("error publishing ping " + token.Error().Error()) } client.Disconnect(250) diff --git a/netclient/functions/peers.go b/netclient/functions/peers.go new file mode 100644 index 00000000..833ebc90 --- /dev/null +++ b/netclient/functions/peers.go @@ -0,0 +1,167 @@ +package functions + +import ( + "log" + "net" + "strconv" + "strings" + "time" + + "github.com/gravitl/netmaker/models" + "github.com/gravitl/netmaker/netclient/ncutils" + "golang.zx2c4.com/wireguard/wgctrl/wgtypes" +) + +func CalculatePeers(thisNode models.Node, peernodes []models.Node, dualstack, egressgateway, server string) ([]wgtypes.Peer, error) { + //hasGateway := false + var gateways []string + var peers []wgtypes.Peer + + keepalive := thisNode.PersistentKeepalive + keepalivedur, _ := time.ParseDuration(strconv.FormatInt(int64(keepalive), 10) + "s") + keepaliveserver, err := time.ParseDuration(strconv.FormatInt(int64(5), 10) + "s") + if err != nil { + log.Fatalf("Issue with format of keepalive value. Please update netconfig: %v", err) + } + for _, node := range peernodes { + pubkey, err := wgtypes.ParseKey(node.PublicKey) + if err != nil { + log.Println("error parsing key") + //return peers, hasGateway, gateways, err + } + + if thisNode.PublicKey == node.PublicKey { + continue + } + if thisNode.Endpoint == node.Endpoint { + if thisNode.LocalAddress != node.LocalAddress && node.LocalAddress != "" { + node.Endpoint = node.LocalAddress + } else { + continue + } + } + + var peer wgtypes.Peer + var peeraddr = net.IPNet{ + IP: net.ParseIP(node.Address), + Mask: net.CIDRMask(32, 32), + } + var allowedips []net.IPNet + allowedips = append(allowedips, peeraddr) + // handle manually set peers + for _, allowedIp := range node.AllowedIPs { + if _, ipnet, err := net.ParseCIDR(allowedIp); err == nil { + nodeEndpointArr := strings.Split(node.Endpoint, ":") + if !ipnet.Contains(net.IP(nodeEndpointArr[0])) && ipnet.IP.String() != node.Address { // don't need to add an allowed ip that already exists.. + allowedips = append(allowedips, *ipnet) + } + } else if appendip := net.ParseIP(allowedIp); appendip != nil && allowedIp != node.Address { + ipnet := net.IPNet{ + IP: net.ParseIP(allowedIp), + Mask: net.CIDRMask(32, 32), + } + allowedips = append(allowedips, ipnet) + } + } + // handle egress gateway peers + if node.IsEgressGateway == "yes" { + //hasGateway = true + ranges := node.EgressGatewayRanges + for _, iprange := range ranges { // go through each cidr for egress gateway + _, ipnet, err := net.ParseCIDR(iprange) // confirming it's valid cidr + if err != nil { + ncutils.PrintLog("could not parse gateway IP range. Not adding "+iprange, 1) + continue // if can't parse CIDR + } + nodeEndpointArr := strings.Split(node.Endpoint, ":") // getting the public ip of node + if ipnet.Contains(net.ParseIP(nodeEndpointArr[0])) { // ensuring egress gateway range does not contain public ip of node + ncutils.PrintLog("egress IP range of "+iprange+" overlaps with "+node.Endpoint+", omitting", 2) + continue // skip adding egress range if overlaps with node's ip + } + if ipnet.Contains(net.ParseIP(thisNode.LocalAddress)) { // ensuring egress gateway range does not contain public ip of node + ncutils.PrintLog("egress IP range of "+iprange+" overlaps with "+thisNode.LocalAddress+", omitting", 2) + continue // skip adding egress range if overlaps with node's local ip + } + gateways = append(gateways, iprange) + if err != nil { + log.Println("ERROR ENCOUNTERED SETTING GATEWAY") + } else { + allowedips = append(allowedips, *ipnet) + } + } + } + if node.Address6 != "" && dualstack == "yes" { + var addr6 = net.IPNet{ + IP: net.ParseIP(node.Address6), + Mask: net.CIDRMask(128, 128), + } + allowedips = append(allowedips, addr6) + } + if thisNode.IsServer == "yes" && !(node.IsServer == "yes") { + peer = wgtypes.Peer{ + PublicKey: pubkey, + PersistentKeepaliveInterval: keepaliveserver, + AllowedIPs: allowedips, + } + } else if keepalive != 0 { + peer = wgtypes.Peer{ + PublicKey: pubkey, + PersistentKeepaliveInterval: keepalivedur, + Endpoint: &net.UDPAddr{ + IP: net.ParseIP(node.Endpoint), + Port: int(node.ListenPort), + }, + AllowedIPs: allowedips, + } + } else { + peer = wgtypes.Peer{ + PublicKey: pubkey, + Endpoint: &net.UDPAddr{ + IP: net.ParseIP(node.Endpoint), + Port: int(node.ListenPort), + }, + AllowedIPs: allowedips, + } + } + peers = append(peers, peer) + } + return peers, nil +} + +func CalculateExtPeers(thisNode models.Node, extPeers []models.ExtPeersResponse) ([]wgtypes.Peer, error) { + var peers []wgtypes.Peer + var err error + for _, extPeer := range extPeers { + pubkey, err := wgtypes.ParseKey(extPeer.PublicKey) + if err != nil { + log.Println("error parsing key") + return peers, err + } + + if thisNode.PublicKey == extPeer.PublicKey { + continue + } + + var peer wgtypes.Peer + var peeraddr = net.IPNet{ + IP: net.ParseIP(extPeer.Address), + Mask: net.CIDRMask(32, 32), + } + var allowedips []net.IPNet + allowedips = append(allowedips, peeraddr) + + if extPeer.Address6 != "" && thisNode.IsDualStack == "yes" { + var addr6 = net.IPNet{ + IP: net.ParseIP(extPeer.Address6), + Mask: net.CIDRMask(128, 128), + } + allowedips = append(allowedips, addr6) + } + peer = wgtypes.Peer{ + PublicKey: pubkey, + AllowedIPs: allowedips, + } + peers = append(peers, peer) + } + return peers, err +} From 537e200ebefca4b3cde440140751582b6541a425 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Sat, 1 Jan 2022 18:22:06 +0000 Subject: [PATCH 092/116] update mosquitto broker conf and volume info --- docker/mosquitto.conf | 1 - 1 file changed, 1 deletion(-) diff --git a/docker/mosquitto.conf b/docker/mosquitto.conf index 23c53bc1..dbd3bfac 100644 --- a/docker/mosquitto.conf +++ b/docker/mosquitto.conf @@ -2,7 +2,6 @@ persistence true persistence file mosquitto.db persistance_location mosquitto/data - log_dest_file mosquitto/log/mosquitto.log per_listener_settings true From e1cf1aed762f4d1fbddcd99f4428c3d5ad7827bc Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Sun, 2 Jan 2022 16:02:59 +0000 Subject: [PATCH 093/116] work in progress for message queue --- go.mod | 3 + go.sum | 6 + netclient/command/commands.go | 5 + netclient/functions/daemon.go | 403 ++++++++++++---------------------- 4 files changed, 158 insertions(+), 259 deletions(-) diff --git a/go.mod b/go.mod index b4df5780..689a467c 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,9 @@ require ( cloud.google.com/go v0.34.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/eclipse/paho.mqtt.golang v1.3.5 // indirect github.com/felixge/httpsnoop v1.0.1 // indirect + github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534 // indirect github.com/go-playground/locales v0.14.0 // indirect github.com/go-playground/universal-translator v0.18.0 // indirect github.com/google/go-cmp v0.5.5 // indirect @@ -46,5 +48,6 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/russross/blackfriday/v2 v2.0.1 // indirect github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect + golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect google.golang.org/appengine v1.4.0 // indirect ) diff --git a/go.sum b/go.sum index e36273a2..84dbc91f 100644 --- a/go.sum +++ b/go.sum @@ -36,6 +36,8 @@ github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8S github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534 h1:dhy9OQKGBh4zVXbjwbxxHjRxMJtLXj3zfgpBYQaR4Q4= +github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk= github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= @@ -192,6 +194,7 @@ golang.org/x/net v0.0.0-20201216054612-986b41b23924/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210504132125-bbd867fde50d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985 h1:4CSI6oo7cOjJKajidEljs9h+uP0rRZBPPPhcCbj5mw8= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -202,6 +205,8 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -223,6 +228,7 @@ golang.org/x/sys v0.0.0-20210123111255-9b0068b26619/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210216163648-f7da38b97c65/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210309040221-94ec62e08169/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210503173754-0981d6026fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/netclient/command/commands.go b/netclient/command/commands.go index 1aecdb4b..60a35e7f 100644 --- a/netclient/command/commands.go +++ b/netclient/command/commands.go @@ -215,3 +215,8 @@ func Daemon() error { err := functions.Daemon() return err } + +func Daemon() error { + err := functions.Daemon() + return err +} diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index 6e212c77..afda9c3e 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -1,329 +1,214 @@ package functions import ( - "context" "encoding/json" + "fmt" "log" - "os" - "os/signal" - "runtime" - "strings" - "syscall" "time" mqtt "github.com/eclipse/paho.mqtt.golang" - "github.com/gravitl/netmaker/models" + "github.com/go-ping/ping" "github.com/gravitl/netmaker/netclient/config" "github.com/gravitl/netmaker/netclient/ncutils" - "github.com/gravitl/netmaker/netclient/wireguard" "golang.zx2c4.com/wireguard/wgctrl" - "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) -// Daemon runs netclient daemon from command line func Daemon() error { - ctx, cancel := context.WithCancel(context.Background()) networks, err := ncutils.GetSystemNetworks() if err != nil { - cancel() return err } for _, network := range networks { - go Netclient(ctx, network) + go Netclient(network) + } + for { } - quit := make(chan os.Signal, 1) - signal.Notify(quit, syscall.SIGTERM, os.Interrupt) - <-quit - cancel() - ncutils.Log("all done") return nil } -// SetupMQTT creates a connection to broker and return client -func SetupMQTT(cfg config.ClientConfig) mqtt.Client { +func Netclient(network string) { + var cfg config.ClientConfig + cfg.Network = network + cfg.ReadConfig() + ncutils.Log("daemon started for network:" + network) + //setup MQTT opts := mqtt.NewClientOptions() ncutils.Log("setting broker to " + cfg.Server.CoreDNSAddr + ":1883") opts.AddBroker(cfg.Server.CoreDNSAddr + ":1883") opts.SetDefaultPublishHandler(All) + opts.SetClientID("netclient-mqtt") client := mqtt.NewClient(opts) if token := client.Connect(); token.Wait() && token.Error() != nil { log.Fatal(token.Error()) } - return client -} - -// Netclient sets up Message Queue and subsribes/publishes updates to/from server -func Netclient(ctx context.Context, network string) { - ncutils.Log("netclient go routine started for " + network) - var cfg config.ClientConfig - cfg.Network = network - cfg.ReadConfig() - //fix NodeID to remove ### so NodeID can be used as message topic - //remove with GRA-73 - cfg.Node.ID = strings.Replace(cfg.Node.ID, "###", "-", 1) - ncutils.Log("daemon started for network:" + network) - client := SetupMQTT(cfg) if token := client.Subscribe("#", 0, nil); token.Wait() && token.Error() != nil { log.Fatal(token.Error()) } - client.AddRoute("update/"+cfg.Node.ID, NodeUpdate) - client.AddRoute("update/peers/"+cfg.Node.ID, UpdatePeers) - //handle key updates in node update - //client.AddRoute("update/keys/"+cfg.Node.ID, UpdateKeys) + client.AddRoute("update/"+network+"/"+cfg.Node.MacAddress, NodeUpdate) + client.AddRoute("update/"+network+"/peers", UpdatePeers) + client.AddRoute("update/"+network+"/keys", UpdateKeys) + client.AddRoute("update/"+network+"/keys/"+cfg.Node.MacAddress, UpdateKeys) defer client.Disconnect(250) - go Checkin(ctx, cfg, network) - go Metrics(ctx, cfg, network) - <-ctx.Done() - ncutils.Log("shutting down daemon") + go Checkin(client, network) + //go Metrics(client, network) + //go Connectivity(client, network) + for { + } } -// All -- mqtt message hander for all ('#') topics var All mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("Topic: " + string(msg.Topic())) ncutils.Log("Message: " + string(msg.Payload())) } -// NodeUpdate -- mqtt message handler for /update/ topic var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update node " + string(msg.Payload())) - //potentiall blocking i/o so do this in a go routine - go func() { - var newNode models.Node - var cfg config.ClientConfig - cfg.Network = newNode.Network - cfg.ReadConfig() - err := json.Unmarshal(msg.Payload(), &newNode) - if err != nil { - ncutils.Log("error unmarshalling node update data" + err.Error()) - return - } - //check if interface name has changed if so delete. - if cfg.Node.Interface != newNode.Interface { - if err = wireguard.RemoveConf(cfg.Node.Interface, true); err != nil { - ncutils.PrintLog("could not delete old interface "+cfg.Node.Interface+": "+err.Error(), 1) - } - } - newNode.PullChanges = "no" - //ensure that OS never changes - newNode.OS = runtime.GOOS - cfg.Node = newNode - switch newNode.Action { - case models.NODE_DELETE: - if err := RemoveLocalInstance(&cfg, cfg.Network); err != nil { - ncutils.PrintLog("error deleting local instance: "+err.Error(), 1) - return - } - case models.NODE_UPDATE_KEY: - UpdateKeys(&cfg, client) - case models.NODE_NOOP: - default: - } - //Save new config - if err := config.Write(&cfg, cfg.Network); err != nil { - ncutils.PrintLog("error updating node configuration: "+err.Error(), 1) - } - nameserver := cfg.Server.CoreDNSAddr - privateKey, err := wireguard.RetrievePrivKey(newNode.Network) - if err != nil { - ncutils.Log("error reading PrivateKey " + err.Error()) - return - } - if err := wireguard.UpdateWgInterface(cfg.Node.Interface, privateKey, nameserver, newNode); err != nil { - ncutils.Log("error updating wireguard config " + err.Error()) - return - } - // path hardcoded for now... should be updated - err = wireguard.ApplyWGQuickConf("/etc/netclient/config/" + cfg.Node.Interface + ".conf") - if err != nil { - ncutils.Log("error restarting wg after node update " + err.Error()) - return - } - }() } -// UpdatePeers -- mqtt message handler for /update/peers/ topic var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update peers " + string(msg.Payload())) - go func() { - var peerUpdate models.PeerUpdate - err := json.Unmarshal(msg.Payload(), &peerUpdate) - if err != nil { - ncutils.Log("error unmarshalling peer data") - return - } - var cfg config.ClientConfig - cfg.Network = peerUpdate.Network - cfg.ReadConfig() - peers, err := CalculatePeers(cfg.Node, peerUpdate.Nodes, cfg.Node.IsDualStack, cfg.Node.IsEgressGateway, cfg.Node.IsServer) - if err != nil { - ncutils.Log("error calculating Peers " + err.Error()) - return - } - extpeers, err := CalculateExtPeers(cfg.Node, peerUpdate.ExtPeers) - if err != nil { - ncutils.Log("error updated external wireguard peers " + err.Error()) - } - peers = append(peers, extpeers...) - err = wireguard.UpdateWgPeers(cfg.Node.Interface, peers) - if err != nil { - ncutils.Log("error updating wireguard peers" + err.Error()) - return - } - // path hardcoded for now... should be updated - err = wireguard.ApplyWGQuickConf("/etc/netclient/config/" + cfg.Node.Interface + ".conf") - if err != nil { - ncutils.Log("error restarting wg after peer update " + err.Error()) - return - } - }() } -// UpdateKeys -- updates private key and returns new publickey -func UpdateKeys(cfg *config.ClientConfig, client mqtt.Client) (*config.ClientConfig, error) { - ncutils.Log("received message to update keys") - //potentiall blocking i/o so do this in a go routine - key, err := wgtypes.GeneratePrivateKey() - if err != nil { - ncutils.Log("error generating privatekey " + err.Error()) - return cfg, err - } - if err := wireguard.UpdatePrivateKey(cfg.Node.Interface, key.String()); err != nil { - ncutils.Log("error updating wireguard key " + err.Error()) - return cfg, err - } - publicKey := key.PublicKey() - if token := client.Publish("update/publickey/"+cfg.Node.ID, 0, false, publicKey.String()); token.Wait() && token.Error() != nil { - ncutils.Log("error publishing publickey update " + token.Error().Error()) - client.Disconnect(250) - return cfg, err - } - if err := config.ModConfig(&cfg.Node); err != nil { - ncutils.Log("error updating local config " + err.Error()) - } - return cfg, nil +var UpdateKeys mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { + ncutils.Log("received message to update keys " + string(msg.Payload())) } -// Checkin -- go routine that checks for public or local ip changes, publishes changes -// if there are no updates, simply "pings" the server as a checkin -func Checkin(ctx context.Context, cfg config.ClientConfig, network string) { +func Checkin(client mqtt.Client, network string) { + var cfg config.ClientConfig + cfg.Network = network + cfg.ReadConfig() for { - select { - case <-ctx.Done(): - ncutils.Log("Checkin cancelled") - return - //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? - case <-time.After(time.Second * 10): - ncutils.Log("Checkin running") - //read latest config - cfg.ReadConfig() - //fix NodeID to remove ### so NodeID can be used as message topic - //remove with GRA-73 - cfg.Node.ID = strings.Replace(cfg.Node.ID, "###", "-", 1) - if cfg.Node.Roaming == "yes" && cfg.Node.IsStatic != "yes" { - extIP, err := ncutils.GetPublicIP() - if err != nil { - ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) - } - if cfg.Node.Endpoint != extIP && extIP != "" { - ncutils.PrintLog("endpoint has changed from "+cfg.Node.Endpoint+" to "+extIP, 1) - UpdateEndpoint(cfg, network, extIP) - } - intIP, err := getPrivateAddr() - if err != nil { - ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) - } - if cfg.Node.LocalAddress != intIP && intIP != "" { - ncutils.PrintLog("local Address has changed from "+cfg.Node.LocalAddress+" to "+intIP, 1) - UpdateLocalAddress(cfg, network, intIP) - } - } else { - localIP, err := ncutils.GetLocalIP(cfg.Node.LocalRange) - if err != nil { - ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) - } - if cfg.Node.Endpoint != localIP && localIP != "" { - ncutils.PrintLog("endpoint has changed from "+cfg.Node.Endpoint+" to "+localIP, 1) - UpdateEndpoint(cfg, network, localIP) - } + time.Sleep(time.Duration(cfg.Node.NetworkSettings.DefaultCheckInInterval) * time.Second) + ncutils.Log("Checkin running") + if cfg.Node.Roaming == "yes" && cfg.Node.IsStatic != "yes" { + extIP, err := ncutils.GetPublicIP() + if err != nil { + ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) + } + if cfg.Node.Endpoint != extIP && extIP != "" { + ncutils.PrintLog("endpoint has changed from "+cfg.Node.Endpoint+" to "+extIP, 1) + UpdateEndpoint(client, network, extIP) + } + intIP, err := getPrivateAddr() + if err != nil { + ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) + } + if cfg.Node.LocalAddress != intIP && intIP != "" { + ncutils.PrintLog("local Address has changed from "+cfg.Node.LocalAddress+" to "+intIP, 1) + UpdateLocalAddress(client, network, intIP) + } + } else { + localIP, err := ncutils.GetLocalIP(cfg.Node.LocalRange) + if err != nil { + ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) + } + if cfg.Node.Endpoint != localIP && localIP != "" { + ncutils.PrintLog("endpoint has changed from "+cfg.Node.Endpoint+" to "+localIP, 1) + UpdateEndpoint(client, network, localIP) } - Hello(cfg, network) - ncutils.Log("Checkin complete") } + Ping(client, network) } } -// UpdateEndpoint -- publishes an endpoint update to broker -func UpdateEndpoint(cfg config.ClientConfig, network, ip string) { - ncutils.Log("Updating endpoint") - client := SetupMQTT(cfg) - if token := client.Publish("update/ip/"+cfg.Node.ID, 0, false, ip); token.Wait() && token.Error() != nil { - ncutils.Log("error publishing endpoint update " + token.Error().Error()) - } - cfg.Node.Endpoint = ip - if err := config.Write(&cfg, cfg.Network); err != nil { - ncutils.Log("error updating local config " + err.Error()) - } - client.Disconnect(250) -} - -// UpdateLocalAddress -- publishes a local address update to broker -func UpdateLocalAddress(cfg config.ClientConfig, network, ip string) { - ncutils.Log("Updating local address") - client := SetupMQTT(cfg) - if token := client.Publish("update/localaddress/"+cfg.Node.ID, 0, false, ip); token.Wait() && token.Error() != nil { - ncutils.Log("error publishing local address update " + token.Error().Error()) - } - cfg.Node.LocalAddress = ip - ncutils.Log("updating local address in local config to: " + cfg.Node.LocalAddress) - if err := config.Write(&cfg, cfg.Network); err != nil { - ncutils.Log("error updating local config " + err.Error()) - } - client.Disconnect(250) -} - -// Hello -- ping the broker to let server know node is alive and doing fine -func Hello(cfg config.ClientConfig, network string) { - client := SetupMQTT(cfg) - ncutils.Log("sending ping " + cfg.Node.ID) - if token := client.Publish("ping/"+cfg.Node.ID, 2, false, "hello world!"); token.Wait() && token.Error() != nil { +func Ping(client mqtt.Client, network string) { + var cfg config.ClientConfig + cfg.Network = network + cfg.ReadConfig() + if token := client.Publish("ping/"+network+"/"+cfg.Node.ID, 0, false, []byte("ping")); token.Wait() && token.Error() != nil { ncutils.Log("error publishing ping " + token.Error().Error()) } - client.Disconnect(250) } -// Metics -- go routine that collects wireguard metrics and publishes to broker -func Metrics(ctx context.Context, cfg config.ClientConfig, network string) { +func Metrics(client mqtt.Client, network string) { + if token := client.Connect(); token.Wait() && token.Error() != nil { + log.Fatal(token.Error()) + } + var cfg config.ClientConfig + cfg.Network = network + cfg.ReadConfig() for { - select { - case <-ctx.Done(): - ncutils.Log("Metrics collection cancelled") - return - //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? - case <-time.After(time.Second * 60): - ncutils.Log("Metrics collection running") - ncutils.Log("Metrics running") - wg, err := wgctrl.New() + time.Sleep(time.Second * 60) + ncutils.Log("Metrics running") + wg, err := wgctrl.New() + if err != nil { + ncutils.Log("error getting devices " + err.Error()) + break + } + device, err := wg.Device(cfg.Node.Interface) + if err != nil { + ncutils.Log("error readind wg device " + err.Error()) + break + } + bytes, err := json.Marshal(device.Peers) + if err != nil { + ncutils.Log("error marshaling peers " + err.Error()) + break + } + if token := client.Publish("metrics/"+network+"/"+cfg.Node.ID, 1, false, bytes); token.Wait() && token.Error() != nil { + ncutils.Log("error publishing metrics " + token.Error().Error()) + break + } + wg.Close() + } +} + +type PingStat struct { + Name string + Reachable bool +} + +func Connectivity(client mqtt.Client, network string) { + if token := client.Connect(); token.Wait() && token.Error() != nil { + log.Fatal(token.Error()) + } + var cfg config.ClientConfig + cfg.Network = network + cfg.ReadConfig() + for { + time.Sleep(time.Duration(cfg.NetworkSettings.DefaultCheckInInterval) * time.Second) + ncutils.Log("Connectivity running") + var pingStats []PingStat + peers, err := ncutils.GetPeers(cfg.Node.Interface) + if err != nil { + ncutils.Log("error retriving peers " + err.Error()) + break + } + for _, peer := range peers { + var pingStat PingStat + pingStat.Name = peer.PublicKey.String() + pingStat.Reachable = true + ip := peer.Endpoint.IP.String() + fmt.Println("----------", peer.Endpoint.IP, ip) + pinger, err := ping.NewPinger(ip) if err != nil { - ncutils.Log("error getting devices " + err.Error()) + ncutils.Log("error creating pinger " + err.Error()) break } - device, err := wg.Device(cfg.Node.Interface) - if err != nil { - ncutils.Log("error readind wg device " + err.Error()) - break + pinger.Timeout = 2 * time.Second + pinger.Run() + stats := pinger.Statistics() + if stats.PacketLoss == 100 { + pingStat.Reachable = false } - bytes, err := json.Marshal(device.Peers) - if err != nil { - ncutils.Log("error marshaling peers " + err.Error()) - break - } - client := SetupMQTT(cfg) - if token := client.Publish("metrics/"+cfg.Node.ID, 1, false, bytes); token.Wait() && token.Error() != nil { - ncutils.Log("error publishing metrics " + token.Error().Error()) - } - wg.Close() - client.Disconnect(250) - ncutils.Log("metrics collection complete") + pingStats = append(pingStats, pingStat) + } + bytes, err := json.Marshal(pingStats) + if err != nil { + ncutils.Log("error marshaling stats" + err.Error()) + break + } + if token := client.Publish("connectivity/"+network+"/"+cfg.Node.ID, 1, false, bytes); token.Wait() && token.Error() != nil { + ncutils.Log("error publishing ping stats " + token.Error().Error()) + break } } } + +func UpdateEndpoint(client mqtt.Client, network, ip string) { + ncutils.Log("Updating endpoint") +} + +func UpdateLocalAddress(client mqtt.Client, network, ip string) { + ncutils.Log("Updating local address") +} From f6b1eafbb38db0f312e97466cb21d1a7ea79a8d1 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Mon, 3 Jan 2022 15:22:26 -0500 Subject: [PATCH 094/116] Replaced ### with - in Node.ID (local copy) to fix mqtt publishing errors added context to all go routines removed connectivity function --- netclient/functions/daemon.go | 191 ++++++++++++++++------------------ 1 file changed, 87 insertions(+), 104 deletions(-) diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index afda9c3e..2e31d37a 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -1,18 +1,22 @@ package functions import ( + "context" "encoding/json" - "fmt" "log" + "os" + "os/signal" + "strings" + "syscall" "time" mqtt "github.com/eclipse/paho.mqtt.golang" - "github.com/go-ping/ping" "github.com/gravitl/netmaker/netclient/config" "github.com/gravitl/netmaker/netclient/ncutils" "golang.zx2c4.com/wireguard/wgctrl" ) +//Daemon runs netclient daemon from command line func Daemon() error { networks, err := ncutils.GetSystemNetworks() if err != nil { @@ -26,59 +30,75 @@ func Daemon() error { return nil } -func Netclient(network string) { - var cfg config.ClientConfig - cfg.Network = network - cfg.ReadConfig() - ncutils.Log("daemon started for network:" + network) - //setup MQTT +//SetupMQTT creates a connection to broker and return client +func SetupMQTT(cfg config.ClientConfig) mqtt.Client { opts := mqtt.NewClientOptions() ncutils.Log("setting broker to " + cfg.Server.CoreDNSAddr + ":1883") opts.AddBroker(cfg.Server.CoreDNSAddr + ":1883") opts.SetDefaultPublishHandler(All) - opts.SetClientID("netclient-mqtt") client := mqtt.NewClient(opts) if token := client.Connect(); token.Wait() && token.Error() != nil { log.Fatal(token.Error()) } + return client +} + +//Netclient sets up Message Queue and subsribes/publishes updates to/from server +func Netclient(network string) { + ctx, cancel := context.WithCancel(context.Background()) + var cfg config.ClientConfig + cfg.Network = network + cfg.ReadConfig() + //fix NodeID to remove ### so NodeID can be used as message topic + //remove with GRA-73 + cfg.Node.ID = strings.ReplaceAll(cfg.Node.ID, "###", "-") + ncutils.Log("daemon started for network:" + network) + client := SetupMQTT(cfg) if token := client.Subscribe("#", 0, nil); token.Wait() && token.Error() != nil { log.Fatal(token.Error()) } - client.AddRoute("update/"+network+"/"+cfg.Node.MacAddress, NodeUpdate) - client.AddRoute("update/"+network+"/peers", UpdatePeers) - client.AddRoute("update/"+network+"/keys", UpdateKeys) - client.AddRoute("update/"+network+"/keys/"+cfg.Node.MacAddress, UpdateKeys) + client.AddRoute("update/"+cfg.Node.ID, NodeUpdate) + client.AddRoute("update/peers/"+cfg.Node.ID, UpdatePeers) + client.AddRoute("update/keys/"+cfg.Node.ID, UpdateKeys) defer client.Disconnect(250) - go Checkin(client, network) - //go Metrics(client, network) - //go Connectivity(client, network) - for { - } + go Checkin(ctx, cfg, network) + go Metrics(ctx, cfg, network) + quit := make(chan os.Signal, 1) + signal.Notify(quit, syscall.SIGTERM, os.Interrupt) + <-quit + cancel() } +//All -- mqtt message hander for all ('#') topics var All mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("Topic: " + string(msg.Topic())) ncutils.Log("Message: " + string(msg.Payload())) } +//NodeUpdate -- mqtt message handler for /update/ topic var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update node " + string(msg.Payload())) } +//NodeUpdate -- mqtt message handler for /update/peers/ topic var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update peers " + string(msg.Payload())) } +//NodeUpdate -- mqtt message handler for /update/keys/ topic var UpdateKeys mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update keys " + string(msg.Payload())) } -func Checkin(client mqtt.Client, network string) { - var cfg config.ClientConfig - cfg.Network = network - cfg.ReadConfig() - for { - time.Sleep(time.Duration(cfg.Node.NetworkSettings.DefaultCheckInInterval) * time.Second) +//Checkin -- go routine that checks for public or local ip changes, publishes changes +// if there are no updates, simply "pings" the server as a checkin +func Checkin(ctx context.Context, cfg config.ClientConfig, network string) { + select { + case <-ctx.Done(): + ncutils.Log("Checkin cancelled") + return + //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? + case <-time.After(time.Second * 10): ncutils.Log("Checkin running") if cfg.Node.Roaming == "yes" && cfg.Node.IsStatic != "yes" { extIP, err := ncutils.GetPublicIP() @@ -87,7 +107,7 @@ func Checkin(client mqtt.Client, network string) { } if cfg.Node.Endpoint != extIP && extIP != "" { ncutils.PrintLog("endpoint has changed from "+cfg.Node.Endpoint+" to "+extIP, 1) - UpdateEndpoint(client, network, extIP) + UpdateEndpoint(cfg, network, extIP) } intIP, err := getPrivateAddr() if err != nil { @@ -95,7 +115,7 @@ func Checkin(client mqtt.Client, network string) { } if cfg.Node.LocalAddress != intIP && intIP != "" { ncutils.PrintLog("local Address has changed from "+cfg.Node.LocalAddress+" to "+intIP, 1) - UpdateLocalAddress(client, network, intIP) + UpdateLocalAddress(cfg, network, intIP) } } else { localIP, err := ncutils.GetLocalIP(cfg.Node.LocalRange) @@ -104,31 +124,52 @@ func Checkin(client mqtt.Client, network string) { } if cfg.Node.Endpoint != localIP && localIP != "" { ncutils.PrintLog("endpoint has changed from "+cfg.Node.Endpoint+" to "+localIP, 1) - UpdateEndpoint(client, network, localIP) + UpdateEndpoint(cfg, network, localIP) } } - Ping(client, network) + Hello(cfg, network) + ncutils.Log("Checkin complete") } } -func Ping(client mqtt.Client, network string) { - var cfg config.ClientConfig - cfg.Network = network - cfg.ReadConfig() - if token := client.Publish("ping/"+network+"/"+cfg.Node.ID, 0, false, []byte("ping")); token.Wait() && token.Error() != nil { +//UpdateEndpoint -- publishes an endpoint update to broker +func UpdateEndpoint(cfg config.ClientConfig, network, ip string) { + ncutils.Log("Updating endpoint") + client := SetupMQTT(cfg) + if token := client.Publish("update/ip/"+cfg.Node.ID, 0, false, ip); token.Wait() && token.Error() != nil { + ncutils.Log("error publishing endpoint update " + token.Error().Error()) + } + client.Disconnect(250) +} + +//UpdateLocalAddress -- publishes a local address update to broker +func UpdateLocalAddress(cfg config.ClientConfig, network, ip string) { + ncutils.Log("Updating local address") + client := SetupMQTT(cfg) + if token := client.Publish("update/localaddress/"+cfg.Node.ID, 0, false, ip); token.Wait() && token.Error() != nil { + ncutils.Log("error publishing local address update " + token.Error().Error()) + } + client.Disconnect(250) +} + +//Hello -- ping the broker to let server know node is alive and doing fine +func Hello(cfg config.ClientConfig, network string) { + client := SetupMQTT(cfg) + if token := client.Publish("ping/"+network+"/"+cfg.Node.ID, 0, false, "hello world!"); token.Wait() && token.Error() != nil { ncutils.Log("error publishing ping " + token.Error().Error()) } + client.Disconnect(250) } -func Metrics(client mqtt.Client, network string) { - if token := client.Connect(); token.Wait() && token.Error() != nil { - log.Fatal(token.Error()) - } - var cfg config.ClientConfig - cfg.Network = network - cfg.ReadConfig() - for { - time.Sleep(time.Second * 60) +//Metics -- go routine that collects wireguard metrics and publishes to broker +func Metrics(ctx context.Context, cfg config.ClientConfig, network string) { + select { + case <-ctx.Done(): + ncutils.Log("Metrics collection cancelled") + return + //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? + case <-time.After(time.Second * 60): + ncutils.Log("Metrics collection running") ncutils.Log("Metrics running") wg, err := wgctrl.New() if err != nil { @@ -145,70 +186,12 @@ func Metrics(client mqtt.Client, network string) { ncutils.Log("error marshaling peers " + err.Error()) break } - if token := client.Publish("metrics/"+network+"/"+cfg.Node.ID, 1, false, bytes); token.Wait() && token.Error() != nil { + client := SetupMQTT(cfg) + if token := client.Publish("metrics/"+cfg.Node.ID, 1, false, bytes); token.Wait() && token.Error() != nil { ncutils.Log("error publishing metrics " + token.Error().Error()) - break } wg.Close() + client.Disconnect(250) + ncutils.Log("metrics collection complete") } } - -type PingStat struct { - Name string - Reachable bool -} - -func Connectivity(client mqtt.Client, network string) { - if token := client.Connect(); token.Wait() && token.Error() != nil { - log.Fatal(token.Error()) - } - var cfg config.ClientConfig - cfg.Network = network - cfg.ReadConfig() - for { - time.Sleep(time.Duration(cfg.NetworkSettings.DefaultCheckInInterval) * time.Second) - ncutils.Log("Connectivity running") - var pingStats []PingStat - peers, err := ncutils.GetPeers(cfg.Node.Interface) - if err != nil { - ncutils.Log("error retriving peers " + err.Error()) - break - } - for _, peer := range peers { - var pingStat PingStat - pingStat.Name = peer.PublicKey.String() - pingStat.Reachable = true - ip := peer.Endpoint.IP.String() - fmt.Println("----------", peer.Endpoint.IP, ip) - pinger, err := ping.NewPinger(ip) - if err != nil { - ncutils.Log("error creating pinger " + err.Error()) - break - } - pinger.Timeout = 2 * time.Second - pinger.Run() - stats := pinger.Statistics() - if stats.PacketLoss == 100 { - pingStat.Reachable = false - } - pingStats = append(pingStats, pingStat) - } - bytes, err := json.Marshal(pingStats) - if err != nil { - ncutils.Log("error marshaling stats" + err.Error()) - break - } - if token := client.Publish("connectivity/"+network+"/"+cfg.Node.ID, 1, false, bytes); token.Wait() && token.Error() != nil { - ncutils.Log("error publishing ping stats " + token.Error().Error()) - break - } - } -} - -func UpdateEndpoint(client mqtt.Client, network, ip string) { - ncutils.Log("Updating endpoint") -} - -func UpdateLocalAddress(client mqtt.Client, network, ip string) { - ncutils.Log("Updating local address") -} From cf6d1895b66e033a2988f29ea777a998e5ebb3d6 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Mon, 3 Jan 2022 16:26:40 -0500 Subject: [PATCH 095/116] move context up a level --- netclient/functions/daemon.go | 58 +++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index 2e31d37a..43dae42f 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -18,15 +18,18 @@ import ( //Daemon runs netclient daemon from command line func Daemon() error { + ctx, cancel := context.WithCancel(context.Background()) networks, err := ncutils.GetSystemNetworks() if err != nil { return err } for _, network := range networks { - go Netclient(network) - } - for { + go Netclient(ctx, network) } + quit := make(chan os.Signal, 1) + signal.Notify(quit, syscall.SIGTERM, os.Interrupt) + <-quit + cancel() return nil } @@ -44,29 +47,30 @@ func SetupMQTT(cfg config.ClientConfig) mqtt.Client { } //Netclient sets up Message Queue and subsribes/publishes updates to/from server -func Netclient(network string) { - ctx, cancel := context.WithCancel(context.Background()) - var cfg config.ClientConfig - cfg.Network = network - cfg.ReadConfig() - //fix NodeID to remove ### so NodeID can be used as message topic - //remove with GRA-73 - cfg.Node.ID = strings.ReplaceAll(cfg.Node.ID, "###", "-") - ncutils.Log("daemon started for network:" + network) - client := SetupMQTT(cfg) - if token := client.Subscribe("#", 0, nil); token.Wait() && token.Error() != nil { - log.Fatal(token.Error()) +func Netclient(ctx context.Context, network string) { + select { + case <-ctx.Done(): + ncutils.Log("shutting down daemon") + return + default: + var cfg config.ClientConfig + cfg.Network = network + cfg.ReadConfig() + //fix NodeID to remove ### so NodeID can be used as message topic + //remove with GRA-73 + cfg.Node.ID = strings.ReplaceAll(cfg.Node.ID, "###", "-") + ncutils.Log("daemon started for network:" + network) + client := SetupMQTT(cfg) + if token := client.Subscribe("#", 0, nil); token.Wait() && token.Error() != nil { + log.Fatal(token.Error()) + } + client.AddRoute("update/"+cfg.Node.ID, NodeUpdate) + client.AddRoute("update/peers/"+cfg.Node.ID, UpdatePeers) + client.AddRoute("update/keys/"+cfg.Node.ID, UpdateKeys) + defer client.Disconnect(250) + go Checkin(ctx, cfg, network) + go Metrics(ctx, cfg, network) } - client.AddRoute("update/"+cfg.Node.ID, NodeUpdate) - client.AddRoute("update/peers/"+cfg.Node.ID, UpdatePeers) - client.AddRoute("update/keys/"+cfg.Node.ID, UpdateKeys) - defer client.Disconnect(250) - go Checkin(ctx, cfg, network) - go Metrics(ctx, cfg, network) - quit := make(chan os.Signal, 1) - signal.Notify(quit, syscall.SIGTERM, os.Interrupt) - <-quit - cancel() } //All -- mqtt message hander for all ('#') topics @@ -80,12 +84,12 @@ var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) ncutils.Log("received message to update node " + string(msg.Payload())) } -//NodeUpdate -- mqtt message handler for /update/peers/ topic +//UpdatePeers -- mqtt message handler for /update/peers/ topic var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update peers " + string(msg.Payload())) } -//NodeUpdate -- mqtt message handler for /update/keys/ topic +//UpdateKeys -- mqtt message handler for /update/keys/ topic var UpdateKeys mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update keys " + string(msg.Payload())) } From e4bb2e8d38a2a1f23ee2a84b1d3df438cbbc4377 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Mon, 3 Jan 2022 22:21:52 +0000 Subject: [PATCH 096/116] go routines now run forever like they are supposed to --- netclient/functions/daemon.go | 176 +++++++++++++++++----------------- 1 file changed, 90 insertions(+), 86 deletions(-) diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index 43dae42f..e48e8c19 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -30,6 +30,7 @@ func Daemon() error { signal.Notify(quit, syscall.SIGTERM, os.Interrupt) <-quit cancel() + ncutils.Log("all done") return nil } @@ -48,29 +49,28 @@ func SetupMQTT(cfg config.ClientConfig) mqtt.Client { //Netclient sets up Message Queue and subsribes/publishes updates to/from server func Netclient(ctx context.Context, network string) { - select { - case <-ctx.Done(): - ncutils.Log("shutting down daemon") - return - default: - var cfg config.ClientConfig - cfg.Network = network - cfg.ReadConfig() - //fix NodeID to remove ### so NodeID can be used as message topic - //remove with GRA-73 - cfg.Node.ID = strings.ReplaceAll(cfg.Node.ID, "###", "-") - ncutils.Log("daemon started for network:" + network) - client := SetupMQTT(cfg) - if token := client.Subscribe("#", 0, nil); token.Wait() && token.Error() != nil { - log.Fatal(token.Error()) - } - client.AddRoute("update/"+cfg.Node.ID, NodeUpdate) - client.AddRoute("update/peers/"+cfg.Node.ID, UpdatePeers) - client.AddRoute("update/keys/"+cfg.Node.ID, UpdateKeys) - defer client.Disconnect(250) - go Checkin(ctx, cfg, network) - go Metrics(ctx, cfg, network) + ncutils.Log("netclient go routine started for " + network) + var cfg config.ClientConfig + cfg.Network = network + cfg.ReadConfig() + //fix NodeID to remove ### so NodeID can be used as message topic + //remove with GRA-73 + cfg.Node.ID = strings.ReplaceAll(cfg.Node.ID, "###", "-") + ncutils.Log("daemon started for network:" + network) + client := SetupMQTT(cfg) + if token := client.Subscribe("#", 0, nil); token.Wait() && token.Error() != nil { + log.Fatal(token.Error()) } + client.AddRoute("update/"+cfg.Node.ID, NodeUpdate) + client.AddRoute("update/peers/"+cfg.Node.ID, UpdatePeers) + client.AddRoute("update/keys/"+cfg.Node.ID, UpdateKeys) + defer client.Disconnect(250) + go Checkin(ctx, cfg, network) + go Metrics(ctx, cfg, network) + <-ctx.Done() + ncutils.Log("shutting down daemon") + return + ncutils.Log("netclient go routine ended for " + network) } //All -- mqtt message hander for all ('#') topics @@ -97,42 +97,44 @@ var UpdateKeys mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) //Checkin -- go routine that checks for public or local ip changes, publishes changes // if there are no updates, simply "pings" the server as a checkin func Checkin(ctx context.Context, cfg config.ClientConfig, network string) { - select { - case <-ctx.Done(): - ncutils.Log("Checkin cancelled") - return - //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? - case <-time.After(time.Second * 10): - ncutils.Log("Checkin running") - if cfg.Node.Roaming == "yes" && cfg.Node.IsStatic != "yes" { - extIP, err := ncutils.GetPublicIP() - if err != nil { - ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) - } - if cfg.Node.Endpoint != extIP && extIP != "" { - ncutils.PrintLog("endpoint has changed from "+cfg.Node.Endpoint+" to "+extIP, 1) - UpdateEndpoint(cfg, network, extIP) - } - intIP, err := getPrivateAddr() - if err != nil { - ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) - } - if cfg.Node.LocalAddress != intIP && intIP != "" { - ncutils.PrintLog("local Address has changed from "+cfg.Node.LocalAddress+" to "+intIP, 1) - UpdateLocalAddress(cfg, network, intIP) - } - } else { - localIP, err := ncutils.GetLocalIP(cfg.Node.LocalRange) - if err != nil { - ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) - } - if cfg.Node.Endpoint != localIP && localIP != "" { - ncutils.PrintLog("endpoint has changed from "+cfg.Node.Endpoint+" to "+localIP, 1) - UpdateEndpoint(cfg, network, localIP) + for { + select { + case <-ctx.Done(): + ncutils.Log("Checkin cancelled") + return + //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? + case <-time.After(time.Second * 10): + ncutils.Log("Checkin running") + if cfg.Node.Roaming == "yes" && cfg.Node.IsStatic != "yes" { + extIP, err := ncutils.GetPublicIP() + if err != nil { + ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) + } + if cfg.Node.Endpoint != extIP && extIP != "" { + ncutils.PrintLog("endpoint has changed from "+cfg.Node.Endpoint+" to "+extIP, 1) + UpdateEndpoint(cfg, network, extIP) + } + intIP, err := getPrivateAddr() + if err != nil { + ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) + } + if cfg.Node.LocalAddress != intIP && intIP != "" { + ncutils.PrintLog("local Address has changed from "+cfg.Node.LocalAddress+" to "+intIP, 1) + UpdateLocalAddress(cfg, network, intIP) + } + } else { + localIP, err := ncutils.GetLocalIP(cfg.Node.LocalRange) + if err != nil { + ncutils.PrintLog("error encountered checking ip addresses: "+err.Error(), 1) + } + if cfg.Node.Endpoint != localIP && localIP != "" { + ncutils.PrintLog("endpoint has changed from "+cfg.Node.Endpoint+" to "+localIP, 1) + UpdateEndpoint(cfg, network, localIP) + } } + Hello(cfg, network) + ncutils.Log("Checkin complete") } - Hello(cfg, network) - ncutils.Log("Checkin complete") } } @@ -159,7 +161,7 @@ func UpdateLocalAddress(cfg config.ClientConfig, network, ip string) { //Hello -- ping the broker to let server know node is alive and doing fine func Hello(cfg config.ClientConfig, network string) { client := SetupMQTT(cfg) - if token := client.Publish("ping/"+network+"/"+cfg.Node.ID, 0, false, "hello world!"); token.Wait() && token.Error() != nil { + if token := client.Publish("ping/"+cfg.Node.ID, 0, false, "hello world!"); token.Wait() && token.Error() != nil { ncutils.Log("error publishing ping " + token.Error().Error()) } client.Disconnect(250) @@ -167,35 +169,37 @@ func Hello(cfg config.ClientConfig, network string) { //Metics -- go routine that collects wireguard metrics and publishes to broker func Metrics(ctx context.Context, cfg config.ClientConfig, network string) { - select { - case <-ctx.Done(): - ncutils.Log("Metrics collection cancelled") - return - //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? - case <-time.After(time.Second * 60): - ncutils.Log("Metrics collection running") - ncutils.Log("Metrics running") - wg, err := wgctrl.New() - if err != nil { - ncutils.Log("error getting devices " + err.Error()) - break + for { + select { + case <-ctx.Done(): + ncutils.Log("Metrics collection cancelled") + return + //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? + case <-time.After(time.Second * 60): + ncutils.Log("Metrics collection running") + ncutils.Log("Metrics running") + wg, err := wgctrl.New() + if err != nil { + ncutils.Log("error getting devices " + err.Error()) + break + } + device, err := wg.Device(cfg.Node.Interface) + if err != nil { + ncutils.Log("error readind wg device " + err.Error()) + break + } + bytes, err := json.Marshal(device.Peers) + if err != nil { + ncutils.Log("error marshaling peers " + err.Error()) + break + } + client := SetupMQTT(cfg) + if token := client.Publish("metrics/"+cfg.Node.ID, 1, false, bytes); token.Wait() && token.Error() != nil { + ncutils.Log("error publishing metrics " + token.Error().Error()) + } + wg.Close() + client.Disconnect(250) + ncutils.Log("metrics collection complete") } - device, err := wg.Device(cfg.Node.Interface) - if err != nil { - ncutils.Log("error readind wg device " + err.Error()) - break - } - bytes, err := json.Marshal(device.Peers) - if err != nil { - ncutils.Log("error marshaling peers " + err.Error()) - break - } - client := SetupMQTT(cfg) - if token := client.Publish("metrics/"+cfg.Node.ID, 1, false, bytes); token.Wait() && token.Error() != nil { - ncutils.Log("error publishing metrics " + token.Error().Error()) - } - wg.Close() - client.Disconnect(250) - ncutils.Log("metrics collection complete") } } From 6704456cfd11a633296e99255dae1144abf7cef5 Mon Sep 17 00:00:00 2001 From: 0xdcarns Date: Mon, 3 Jan 2022 18:27:13 -0500 Subject: [PATCH 097/116] linting fixes --- netclient/functions/daemon.go | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index e48e8c19..45a49d9b 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -16,11 +16,12 @@ import ( "golang.zx2c4.com/wireguard/wgctrl" ) -//Daemon runs netclient daemon from command line +// Daemon runs netclient daemon from command line func Daemon() error { ctx, cancel := context.WithCancel(context.Background()) networks, err := ncutils.GetSystemNetworks() if err != nil { + cancel() return err } for _, network := range networks { @@ -34,7 +35,7 @@ func Daemon() error { return nil } -//SetupMQTT creates a connection to broker and return client +// SetupMQTT creates a connection to broker and return client func SetupMQTT(cfg config.ClientConfig) mqtt.Client { opts := mqtt.NewClientOptions() ncutils.Log("setting broker to " + cfg.Server.CoreDNSAddr + ":1883") @@ -47,7 +48,7 @@ func SetupMQTT(cfg config.ClientConfig) mqtt.Client { return client } -//Netclient sets up Message Queue and subsribes/publishes updates to/from server +// Netclient sets up Message Queue and subsribes/publishes updates to/from server func Netclient(ctx context.Context, network string) { ncutils.Log("netclient go routine started for " + network) var cfg config.ClientConfig @@ -55,7 +56,7 @@ func Netclient(ctx context.Context, network string) { cfg.ReadConfig() //fix NodeID to remove ### so NodeID can be used as message topic //remove with GRA-73 - cfg.Node.ID = strings.ReplaceAll(cfg.Node.ID, "###", "-") + cfg.Node.ID = strings.Replace(cfg.Node.ID, "###", "-", 1) ncutils.Log("daemon started for network:" + network) client := SetupMQTT(cfg) if token := client.Subscribe("#", 0, nil); token.Wait() && token.Error() != nil { @@ -69,32 +70,30 @@ func Netclient(ctx context.Context, network string) { go Metrics(ctx, cfg, network) <-ctx.Done() ncutils.Log("shutting down daemon") - return - ncutils.Log("netclient go routine ended for " + network) } -//All -- mqtt message hander for all ('#') topics +// All -- mqtt message hander for all ('#') topics var All mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("Topic: " + string(msg.Topic())) ncutils.Log("Message: " + string(msg.Payload())) } -//NodeUpdate -- mqtt message handler for /update/ topic +// NodeUpdate -- mqtt message handler for /update/ topic var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update node " + string(msg.Payload())) } -//UpdatePeers -- mqtt message handler for /update/peers/ topic +// UpdatePeers -- mqtt message handler for /update/peers/ topic var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update peers " + string(msg.Payload())) } -//UpdateKeys -- mqtt message handler for /update/keys/ topic +// UpdateKeys -- mqtt message handler for /update/keys/ topic var UpdateKeys mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update keys " + string(msg.Payload())) } -//Checkin -- go routine that checks for public or local ip changes, publishes changes +// Checkin -- go routine that checks for public or local ip changes, publishes changes // if there are no updates, simply "pings" the server as a checkin func Checkin(ctx context.Context, cfg config.ClientConfig, network string) { for { @@ -138,7 +137,7 @@ func Checkin(ctx context.Context, cfg config.ClientConfig, network string) { } } -//UpdateEndpoint -- publishes an endpoint update to broker +// UpdateEndpoint -- publishes an endpoint update to broker func UpdateEndpoint(cfg config.ClientConfig, network, ip string) { ncutils.Log("Updating endpoint") client := SetupMQTT(cfg) @@ -148,7 +147,7 @@ func UpdateEndpoint(cfg config.ClientConfig, network, ip string) { client.Disconnect(250) } -//UpdateLocalAddress -- publishes a local address update to broker +// UpdateLocalAddress -- publishes a local address update to broker func UpdateLocalAddress(cfg config.ClientConfig, network, ip string) { ncutils.Log("Updating local address") client := SetupMQTT(cfg) @@ -158,7 +157,7 @@ func UpdateLocalAddress(cfg config.ClientConfig, network, ip string) { client.Disconnect(250) } -//Hello -- ping the broker to let server know node is alive and doing fine +// Hello -- ping the broker to let server know node is alive and doing fine func Hello(cfg config.ClientConfig, network string) { client := SetupMQTT(cfg) if token := client.Publish("ping/"+cfg.Node.ID, 0, false, "hello world!"); token.Wait() && token.Error() != nil { @@ -167,7 +166,7 @@ func Hello(cfg config.ClientConfig, network string) { client.Disconnect(250) } -//Metics -- go routine that collects wireguard metrics and publishes to broker +// Metics -- go routine that collects wireguard metrics and publishes to broker func Metrics(ctx context.Context, cfg config.ClientConfig, network string) { for { select { From d7828c19830ef3bba02740b636edc440314cf4ae Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Tue, 4 Jan 2022 17:24:50 -0500 Subject: [PATCH 098/116] Rebase to develop (#4) * add nameserver in call to CreateUserSpaceConf * fixed user deletion * changed log * go mod tidy and conver azure tenant to env/conf var * added egress relayed addrs to relayed nodes * added post commands for wg quick * refactored ncutils x-platform * log fix * adding egress to relay * fixing egress on relay Co-authored-by: dcarns <75687250+0xdcarns@users.noreply.github.com> Co-authored-by: 0xdcarns Co-authored-by: afeiszli --- .gitignore | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitignore b/.gitignore index 18da4b52..defe793f 100644 --- a/.gitignore +++ b/.gitignore @@ -16,5 +16,3 @@ netclient/netclient.exe config/dnsconfig/ data/ .vscode/ -.idea/ -.vscode/ From d5cd88cae8fbe7822a0349503d6874d55b58240d Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Wed, 5 Jan 2022 10:05:51 -0500 Subject: [PATCH 099/116] subscribed message handlers implemented --- go.mod | 1 + netclient/functions/daemon.go | 75 +++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/go.mod b/go.mod index 689a467c..5bb5725f 100644 --- a/go.mod +++ b/go.mod @@ -50,4 +50,5 @@ require ( github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect google.golang.org/appengine v1.4.0 // indirect + gopkg.in/ini.v1 v1.66.2 // indirect ) diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index 45a49d9b..fc926bda 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -11,9 +11,12 @@ import ( "time" mqtt "github.com/eclipse/paho.mqtt.golang" + "github.com/gravitl/netmaker/models" "github.com/gravitl/netmaker/netclient/config" "github.com/gravitl/netmaker/netclient/ncutils" + "github.com/gravitl/netmaker/netclient/wireguard" "golang.zx2c4.com/wireguard/wgctrl" + "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) // Daemon runs netclient daemon from command line @@ -81,16 +84,88 @@ var All mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { // NodeUpdate -- mqtt message handler for /update/ topic var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update node " + string(msg.Payload())) + //potentiall blocking i/o so do this in a go routine + go func() { + var data models.Node + err := json.Unmarshal(msg.Payload(), &data) + if err != nil { + ncutils.Log("error unmarshalling node update data" + err.Error()) + return + } + var cfg config.ClientConfig + cfg.Network = data.Network + cfg.ReadConfig() + nameserver := cfg.Server.CoreDNSAddr + privateKey, err := wireguard.RetrievePrivKey(data.Network) + if err := wireguard.UpdateWgInterface(cfg.Node.Interface, privateKey, nameserver, data); err != nil { + ncutils.Log("error updating wireguard config " + err.Error()) + return + } + // path hardcoded for now... should be updated + err = wireguard.ApplyWGQuickConf("/etc/netclient/config/" + cfg.Node.Interface + ".conf") + if err != nil { + ncutils.Log("error restarting wg after peer update " + err.Error()) + return + } + }() } // UpdatePeers -- mqtt message handler for /update/peers/ topic var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update peers " + string(msg.Payload())) + //potentiall blocking i/o so do this in a go routine + go func() { + var peerUpdate models.PeerUpdate + err := json.Unmarshal(msg.Payload(), &peerUpdate) + if err != nil { + ncutils.Log("error unmarshalling peer data") + return + } + var cfg config.ClientConfig + cfg.Network = peerUpdate.Network + cfg.ReadConfig() + err = wireguard.UpdateWgPeers(cfg.Node.Interface, peerUpdate.Peers) + if err != nil { + ncutils.Log("error updating peers" + err.Error()) + return + } + // path hardcoded for now... should be updated + err = wireguard.ApplyWGQuickConf("/etc/netclient/config/" + cfg.Node.Interface + ".conf") + if err != nil { + ncutils.Log("error restarting wg after peer update " + err.Error()) + return + } + }() } // UpdateKeys -- mqtt message handler for /update/keys/ topic var UpdateKeys mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update keys " + string(msg.Payload())) + //potentiall blocking i/o so do this in a go routine + go func() { + var data models.KeyUpdate + if err := json.Unmarshal(msg.Payload(), &data); err != nil { + ncutils.Log("error unmarshalling key update data" + err.Error()) + return + } + var cfg config.ClientConfig + cfg.Network = data.Network + cfg.ReadConfig() + key, err := wgtypes.GeneratePrivateKey() + if err != nil { + ncutils.Log("error generating privatekey " + err.Error()) + return + } + if err := wireguard.UpdatePrivateKey(data.Interface, key.String()); err != nil { + ncutils.Log("error updating wireguard key " + err.Error()) + return + } + publicKey := key.PublicKey() + if token := client.Publish("update/publickey/"+cfg.Node.ID, 0, false, publicKey.String()); token.Wait() && token.Error() != nil { + ncutils.Log("error publishing publickey update " + token.Error().Error()) + } + client.Disconnect(250) + }() } // Checkin -- go routine that checks for public or local ip changes, publishes changes From 2201aef4b247cbe5ad8651e11964d62bde5e19d0 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Wed, 5 Jan 2022 11:07:09 -0500 Subject: [PATCH 100/116] add error handling on failed key generation --- netclient/functions/daemon.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index fc926bda..8baaa392 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -97,6 +97,10 @@ var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) cfg.ReadConfig() nameserver := cfg.Server.CoreDNSAddr privateKey, err := wireguard.RetrievePrivKey(data.Network) + if err != nil { + ncutils.Log("error generating PrivateKey " + err.Error()) + return + } if err := wireguard.UpdateWgInterface(cfg.Node.Interface, privateKey, nameserver, data); err != nil { ncutils.Log("error updating wireguard config " + err.Error()) return From 5e5f85b51f34cd638db04dbff01a28c97887ae00 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Mon, 10 Jan 2022 14:35:53 -0500 Subject: [PATCH 101/116] refactor NodeUpdate message queue handler --- netclient/functions/daemon.go | 89 +++++++++++++++++++++-------------- 1 file changed, 54 insertions(+), 35 deletions(-) diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index 8baaa392..639436ae 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -6,6 +6,7 @@ import ( "log" "os" "os/signal" + "runtime" "strings" "syscall" "time" @@ -67,7 +68,8 @@ func Netclient(ctx context.Context, network string) { } client.AddRoute("update/"+cfg.Node.ID, NodeUpdate) client.AddRoute("update/peers/"+cfg.Node.ID, UpdatePeers) - client.AddRoute("update/keys/"+cfg.Node.ID, UpdateKeys) + //handle key updates in node update + //client.AddRoute("update/keys/"+cfg.Node.ID, UpdateKeys) defer client.Disconnect(250) go Checkin(ctx, cfg, network) go Metrics(ctx, cfg, network) @@ -86,19 +88,44 @@ var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) ncutils.Log("received message to update node " + string(msg.Payload())) //potentiall blocking i/o so do this in a go routine go func() { - var data models.Node - err := json.Unmarshal(msg.Payload(), &data) + var newNode models.Node + var cfg config.ClientConfig + cfg.Network = newNode.Network + cfg.ReadConfig() + err := json.Unmarshal(msg.Payload(), &newNode) if err != nil { ncutils.Log("error unmarshalling node update data" + err.Error()) return } - var cfg config.ClientConfig - cfg.Network = data.Network - cfg.ReadConfig() + //check if interface name has changed if so delete. + if cfg.Node.Interface != newNode.Interface { + if err = wireguard.RemoveConf(cfg.Node.Interface, true); err != nil { + ncutils.PrintLog("could not delete old interface "+cfg.Node.Interface+": ", err.Error(), 1) + } + } + newNode.PullChanges = "no" + //ensure that OS never changes + newNode.OS = runtime.GOOS + cfg.Node = newNode + switch newNode.Action { + case models.NODE_DELETE: + if err := RemoveLocalInstance(cfg, cfg.Network); err != nil { + ncutils.Printlog("error deleting local instance: "+err.Error(), 1) + return + } + case models.NODE_UPDATE_KEY: + UpdateKeys(cfg) + case models.NODE_NOOP: + default: + } + //Save new config + if err := config.Write(&cfg, cfg.Network); err != nil { + ncutils.PrintLog("error updating node configuration: "+err.Error(), 1) + } nameserver := cfg.Server.CoreDNSAddr privateKey, err := wireguard.RetrievePrivKey(data.Network) if err != nil { - ncutils.Log("error generating PrivateKey " + err.Error()) + ncutils.Log("error reading PrivateKey " + err.Error()) return } if err := wireguard.UpdateWgInterface(cfg.Node.Interface, privateKey, nameserver, data); err != nil { @@ -108,7 +135,7 @@ var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) // path hardcoded for now... should be updated err = wireguard.ApplyWGQuickConf("/etc/netclient/config/" + cfg.Node.Interface + ".conf") if err != nil { - ncutils.Log("error restarting wg after peer update " + err.Error()) + ncutils.Log("error restarting wg after node update " + err.Error()) return } }() @@ -117,7 +144,6 @@ var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) // UpdatePeers -- mqtt message handler for /update/peers/ topic var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { ncutils.Log("received message to update peers " + string(msg.Payload())) - //potentiall blocking i/o so do this in a go routine go func() { var peerUpdate models.PeerUpdate err := json.Unmarshal(msg.Payload(), &peerUpdate) @@ -142,34 +168,27 @@ var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) }() } -// UpdateKeys -- mqtt message handler for /update/keys/ topic -var UpdateKeys mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { - ncutils.Log("received message to update keys " + string(msg.Payload())) +// UpdateKeys -- updates private key and returns new publickey +func UpdateKeys(cfg *config.ClientConfig, client mqtt.Client) (*config.ClientConfig, error) { + ncutils.Log("received message to update keys") //potentiall blocking i/o so do this in a go routine - go func() { - var data models.KeyUpdate - if err := json.Unmarshal(msg.Payload(), &data); err != nil { - ncutils.Log("error unmarshalling key update data" + err.Error()) - return - } - var cfg config.ClientConfig - cfg.Network = data.Network - cfg.ReadConfig() - key, err := wgtypes.GeneratePrivateKey() - if err != nil { - ncutils.Log("error generating privatekey " + err.Error()) - return - } - if err := wireguard.UpdatePrivateKey(data.Interface, key.String()); err != nil { - ncutils.Log("error updating wireguard key " + err.Error()) - return - } - publicKey := key.PublicKey() - if token := client.Publish("update/publickey/"+cfg.Node.ID, 0, false, publicKey.String()); token.Wait() && token.Error() != nil { - ncutils.Log("error publishing publickey update " + token.Error().Error()) - } + key, err := wgtypes.GeneratePrivateKey() + if err != nil { + ncutils.Log("error generating privatekey " + err.Error()) + return cfg, err + } + if err := wireguard.UpdatePrivateKey(data.Interface, key.String()); err != nil { + ncutils.Log("error updating wireguard key " + err.Error()) + return cfg, err + } + publicKey := key.PublicKey() + if token := client.Publish("update/publickey/"+cfg.Node.ID, 0, false, publicKey.String()); token.Wait() && token.Error() != nil { + ncutils.Log("error publishing publickey update " + token.Error().Error()) client.Disconnect(250) - }() + return cfg, err + } + client.Disconnect(250) + return cfg, nil } // Checkin -- go routine that checks for public or local ip changes, publishes changes From fcc14fb1e4180dda60323bc28d5f4a6b1d62fec6 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Wed, 12 Jan 2022 16:23:34 -0500 Subject: [PATCH 102/116] WIP commit --- .gitignore | 2 ++ models/mqtt.go | 7 ++++--- netclient/functions/daemon.go | 14 +++++++------- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index defe793f..bf873a65 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,6 @@ netclient/netclient32 netclient/netclient.exe config/dnsconfig/ data/ +.idea/ .vscode/ + diff --git a/models/mqtt.go b/models/mqtt.go index 07bb2157..da7265f3 100644 --- a/models/mqtt.go +++ b/models/mqtt.go @@ -1,9 +1,10 @@ package models +import "golang.zx2c4.com/wireguard/wgctrl/wgtypes" + type PeerUpdate struct { - Network string - Nodes []Node - ExtPeers []ExtPeersResponse + Network string + Peers []wgtypes.Peer } type KeyUpdate struct { diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index 639436ae..a5360319 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -100,7 +100,7 @@ var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) //check if interface name has changed if so delete. if cfg.Node.Interface != newNode.Interface { if err = wireguard.RemoveConf(cfg.Node.Interface, true); err != nil { - ncutils.PrintLog("could not delete old interface "+cfg.Node.Interface+": ", err.Error(), 1) + ncutils.PrintLog("could not delete old interface "+cfg.Node.Interface+": "+err.Error(), 1) } } newNode.PullChanges = "no" @@ -109,12 +109,12 @@ var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) cfg.Node = newNode switch newNode.Action { case models.NODE_DELETE: - if err := RemoveLocalInstance(cfg, cfg.Network); err != nil { - ncutils.Printlog("error deleting local instance: "+err.Error(), 1) + if err := RemoveLocalInstance(&cfg, cfg.Network); err != nil { + ncutils.PrintLog("error deleting local instance: "+err.Error(), 1) return } case models.NODE_UPDATE_KEY: - UpdateKeys(cfg) + UpdateKeys(&cfg, client) case models.NODE_NOOP: default: } @@ -123,12 +123,12 @@ var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) ncutils.PrintLog("error updating node configuration: "+err.Error(), 1) } nameserver := cfg.Server.CoreDNSAddr - privateKey, err := wireguard.RetrievePrivKey(data.Network) + privateKey, err := wireguard.RetrievePrivKey(newNode.Network) if err != nil { ncutils.Log("error reading PrivateKey " + err.Error()) return } - if err := wireguard.UpdateWgInterface(cfg.Node.Interface, privateKey, nameserver, data); err != nil { + if err := wireguard.UpdateWgInterface(cfg.Node.Interface, privateKey, nameserver, newNode); err != nil { ncutils.Log("error updating wireguard config " + err.Error()) return } @@ -177,7 +177,7 @@ func UpdateKeys(cfg *config.ClientConfig, client mqtt.Client) (*config.ClientCon ncutils.Log("error generating privatekey " + err.Error()) return cfg, err } - if err := wireguard.UpdatePrivateKey(data.Interface, key.String()); err != nil { + if err := wireguard.UpdatePrivateKey(cfg.Node.Interface, key.String()); err != nil { ncutils.Log("error updating wireguard key " + err.Error()) return cfg, err } From 8fe732be413dab4db3d3392eda232b980823ed7f Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Fri, 14 Jan 2022 14:30:26 -0500 Subject: [PATCH 103/116] WIP commit to enable rebasing to uuid feature --- models/mqtt.go | 7 +++---- netclient/functions/daemon.go | 35 +++++++++++++++++++++++++++++++---- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/models/mqtt.go b/models/mqtt.go index da7265f3..07bb2157 100644 --- a/models/mqtt.go +++ b/models/mqtt.go @@ -1,10 +1,9 @@ package models -import "golang.zx2c4.com/wireguard/wgctrl/wgtypes" - type PeerUpdate struct { - Network string - Peers []wgtypes.Peer + Network string + Nodes []Node + ExtPeers []ExtPeersResponse } type KeyUpdate struct { diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index a5360319..6e212c77 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -154,9 +154,19 @@ var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) var cfg config.ClientConfig cfg.Network = peerUpdate.Network cfg.ReadConfig() - err = wireguard.UpdateWgPeers(cfg.Node.Interface, peerUpdate.Peers) + peers, err := CalculatePeers(cfg.Node, peerUpdate.Nodes, cfg.Node.IsDualStack, cfg.Node.IsEgressGateway, cfg.Node.IsServer) if err != nil { - ncutils.Log("error updating peers" + err.Error()) + ncutils.Log("error calculating Peers " + err.Error()) + return + } + extpeers, err := CalculateExtPeers(cfg.Node, peerUpdate.ExtPeers) + if err != nil { + ncutils.Log("error updated external wireguard peers " + err.Error()) + } + peers = append(peers, extpeers...) + err = wireguard.UpdateWgPeers(cfg.Node.Interface, peers) + if err != nil { + ncutils.Log("error updating wireguard peers" + err.Error()) return } // path hardcoded for now... should be updated @@ -187,7 +197,9 @@ func UpdateKeys(cfg *config.ClientConfig, client mqtt.Client) (*config.ClientCon client.Disconnect(250) return cfg, err } - client.Disconnect(250) + if err := config.ModConfig(&cfg.Node); err != nil { + ncutils.Log("error updating local config " + err.Error()) + } return cfg, nil } @@ -202,6 +214,11 @@ func Checkin(ctx context.Context, cfg config.ClientConfig, network string) { //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? case <-time.After(time.Second * 10): ncutils.Log("Checkin running") + //read latest config + cfg.ReadConfig() + //fix NodeID to remove ### so NodeID can be used as message topic + //remove with GRA-73 + cfg.Node.ID = strings.Replace(cfg.Node.ID, "###", "-", 1) if cfg.Node.Roaming == "yes" && cfg.Node.IsStatic != "yes" { extIP, err := ncutils.GetPublicIP() if err != nil { @@ -242,6 +259,10 @@ func UpdateEndpoint(cfg config.ClientConfig, network, ip string) { if token := client.Publish("update/ip/"+cfg.Node.ID, 0, false, ip); token.Wait() && token.Error() != nil { ncutils.Log("error publishing endpoint update " + token.Error().Error()) } + cfg.Node.Endpoint = ip + if err := config.Write(&cfg, cfg.Network); err != nil { + ncutils.Log("error updating local config " + err.Error()) + } client.Disconnect(250) } @@ -252,13 +273,19 @@ func UpdateLocalAddress(cfg config.ClientConfig, network, ip string) { if token := client.Publish("update/localaddress/"+cfg.Node.ID, 0, false, ip); token.Wait() && token.Error() != nil { ncutils.Log("error publishing local address update " + token.Error().Error()) } + cfg.Node.LocalAddress = ip + ncutils.Log("updating local address in local config to: " + cfg.Node.LocalAddress) + if err := config.Write(&cfg, cfg.Network); err != nil { + ncutils.Log("error updating local config " + err.Error()) + } client.Disconnect(250) } // Hello -- ping the broker to let server know node is alive and doing fine func Hello(cfg config.ClientConfig, network string) { client := SetupMQTT(cfg) - if token := client.Publish("ping/"+cfg.Node.ID, 0, false, "hello world!"); token.Wait() && token.Error() != nil { + ncutils.Log("sending ping " + cfg.Node.ID) + if token := client.Publish("ping/"+cfg.Node.ID, 2, false, "hello world!"); token.Wait() && token.Error() != nil { ncutils.Log("error publishing ping " + token.Error().Error()) } client.Disconnect(250) From 1e199665c0593256ab8ca08c86d76e427eac5416 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Fri, 14 Jan 2022 15:35:15 -0500 Subject: [PATCH 104/116] use uuid in message queue functions --- go.mod | 3 ++- mq/mq.go | 44 +++++++++++------------------------ netclient/functions/daemon.go | 13 ++--------- 3 files changed, 18 insertions(+), 42 deletions(-) diff --git a/go.mod b/go.mod index 5bb5725f..984754b1 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/go-playground/validator/v10 v10.10.0 github.com/golang-jwt/jwt/v4 v4.2.0 github.com/golang/protobuf v1.5.2 // indirect + github.com/google/uuid v1.3.0 github.com/gorilla/handlers v1.5.1 github.com/gorilla/mux v1.8.0 github.com/lib/pq v1.10.4 @@ -40,7 +41,7 @@ require ( github.com/go-playground/locales v0.14.0 // indirect github.com/go-playground/universal-translator v0.18.0 // indirect github.com/google/go-cmp v0.5.5 // indirect - github.com/google/uuid v1.3.0 // indirect + github.com/gorilla/websocket v1.4.2 // indirect github.com/josharian/native v0.0.0-20200817173448-b6b71def0850 // indirect github.com/leodido/go-urn v1.2.1 // indirect github.com/mdlayher/genetlink v1.0.0 // indirect diff --git a/mq/mq.go b/mq/mq.go index fd9657a7..9b5197b2 100644 --- a/mq/mq.go +++ b/mq/mq.go @@ -24,16 +24,15 @@ var Metrics mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { var Ping mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { logger.Log(0, "Ping Handler: "+msg.Topic()) go func() { - mac, net, err := GetMacNetwork(msg.Topic()) + id, err := GetID(msg.Topic()) if err != nil { logger.Log(0, "error getting node.ID sent on ping topic ") return } - logger.Log(0, "ping recieved from "+mac+" on net "+net) - node, err := logic.GetNodeByMacAddress(net, mac) + node, err := logic.GetNodeByID(id) if err != nil { logger.Log(0, "mq-ping error getting node: "+err.Error()) - record, err := database.FetchRecord(database.NODES_TABLE_NAME, mac+"###"+net) + record, err := database.FetchRecord(database.NODES_TABLE_NAME, id) if err != nil { logger.Log(0, "error reading database ", err.Error()) return @@ -54,11 +53,11 @@ var PublicKeyUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Mess go func() { logger.Log(0, "public key update "+msg.Topic()) key := string(msg.Payload()) - mac, network, err := GetMacNetwork(msg.Topic()) + id, err := GetID(msg.Topic()) if err != nil { logger.Log(0, "error getting node.ID sent on "+msg.Topic()+" "+err.Error()) } - node, err := logic.GetNode(mac, network) + node, err := logic.GetNodeByID(id) if err != nil { logger.Log(0, "error retrieving node "+msg.Topic()+" "+err.Error()) } @@ -74,13 +73,13 @@ var IPUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { go func() { ip := string(msg.Payload()) logger.Log(0, "IPUpdate Handler") - mac, network, err := GetMacNetwork(msg.Topic()) - logger.Log(0, "ipUpdate recieved from "+mac+" on net "+network) + id, err := GetID(msg.Topic()) + logger.Log(0, "ipUpdate recieved from "+id) if err != nil { logger.Log(0, "error getting node.ID sent on update/ip topic ") return } - node, err := logic.GetNode(mac, network) + node, err := logic.GetNodeByID(id) if err != nil { logger.Log(0, "invalid ID recieved on update/ip topic: "+err.Error()) return @@ -110,7 +109,8 @@ func UpdatePeers(client mqtt.Client, node models.Node) error { continue } peerUpdate.Nodes = append(peerUpdate.Nodes, peer) - peerUpdate.ExtPeers, err = logic.GetExtPeersList(node.MacAddress, node.Network) + peerUpdate.ExtPeers, err = logic.GetExtPeersList(&node) + if err != nil { logger.Log(0) } @@ -150,12 +150,12 @@ var LocalAddressUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.M logger.Log(0, "LocalAddressUpdate Handler") go func() { logger.Log(0, "LocalAddressUpdate handler") - mac, net, err := GetMacNetwork(msg.Topic()) + id, err := GetID(msg.Topic()) if err != nil { logger.Log(0, "error getting node.ID "+msg.Topic()) return } - node, err := logic.GetNode(mac, net) + node, err := logic.GetNodeByID(id) if err != nil { logger.Log(0, "error get node "+msg.Topic()) return @@ -168,28 +168,12 @@ var LocalAddressUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.M }() } -func GetMacNetwork(topic string) (string, string, error) { - parts := strings.Split(topic, "/") - count := len(parts) - if count == 1 { - return "", "", errors.New("invalid topic") - } - macnet := strings.Split(parts[count-1], "-") - if len(macnet) != 2 { - return "", "", errors.New("topic id not in mac---network format") - } - return macnet[0], macnet[1], nil -} - func GetID(topic string) (string, error) { parts := strings.Split(topic, "/") count := len(parts) if count == 1 { return "", errors.New("invalid topic") } - macnet := strings.Split(parts[count-1], "-") - if len(macnet) != 2 { - return "", errors.New("topic id not in mac---network format") - } - return macnet[0] + "###" + macnet[1], nil + //the last part of the topic will be the node.ID + return parts[count], nil } diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index 6e212c77..bd27ee4d 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -7,7 +7,6 @@ import ( "os" "os/signal" "runtime" - "strings" "syscall" "time" @@ -58,9 +57,6 @@ func Netclient(ctx context.Context, network string) { var cfg config.ClientConfig cfg.Network = network cfg.ReadConfig() - //fix NodeID to remove ### so NodeID can be used as message topic - //remove with GRA-73 - cfg.Node.ID = strings.Replace(cfg.Node.ID, "###", "-", 1) ncutils.Log("daemon started for network:" + network) client := SetupMQTT(cfg) if token := client.Subscribe("#", 0, nil); token.Wait() && token.Error() != nil { @@ -216,9 +212,6 @@ func Checkin(ctx context.Context, cfg config.ClientConfig, network string) { ncutils.Log("Checkin running") //read latest config cfg.ReadConfig() - //fix NodeID to remove ### so NodeID can be used as message topic - //remove with GRA-73 - cfg.Node.ID = strings.Replace(cfg.Node.ID, "###", "-", 1) if cfg.Node.Roaming == "yes" && cfg.Node.IsStatic != "yes" { extIP, err := ncutils.GetPublicIP() if err != nil { @@ -301,15 +294,15 @@ func Metrics(ctx context.Context, cfg config.ClientConfig, network string) { //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? case <-time.After(time.Second * 60): ncutils.Log("Metrics collection running") - ncutils.Log("Metrics running") wg, err := wgctrl.New() + defer wg.Close() if err != nil { ncutils.Log("error getting devices " + err.Error()) break } device, err := wg.Device(cfg.Node.Interface) if err != nil { - ncutils.Log("error readind wg device " + err.Error()) + ncutils.Log("error reading wg device " + err.Error()) break } bytes, err := json.Marshal(device.Peers) @@ -321,8 +314,6 @@ func Metrics(ctx context.Context, cfg config.ClientConfig, network string) { if token := client.Publish("metrics/"+cfg.Node.ID, 1, false, bytes); token.Wait() && token.Error() != nil { ncutils.Log("error publishing metrics " + token.Error().Error()) } - wg.Close() - client.Disconnect(250) ncutils.Log("metrics collection complete") } } From 3e890f4d8d37f87f124f5b3dfa4df6b283c8bae6 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Fri, 14 Jan 2022 22:22:11 +0000 Subject: [PATCH 105/116] fix off by one error in GetID --- mq/mq.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mq/mq.go b/mq/mq.go index 9b5197b2..3521a165 100644 --- a/mq/mq.go +++ b/mq/mq.go @@ -175,5 +175,5 @@ func GetID(topic string) (string, error) { return "", errors.New("invalid topic") } //the last part of the topic will be the node.ID - return parts[count], nil + return parts[count-1], nil } From 05dd87887eb06bfe1e6398b2af769359243f606c Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Sat, 15 Jan 2022 18:16:44 -0500 Subject: [PATCH 106/116] moved peer determination to server --- models/mqtt.go | 7 +- mq/mq.go | 67 +++++--------- netclient/functions/daemon.go | 19 +--- netclient/functions/peers.go | 167 ---------------------------------- netclient/wireguard/common.go | 2 +- 5 files changed, 32 insertions(+), 230 deletions(-) delete mode 100644 netclient/functions/peers.go diff --git a/models/mqtt.go b/models/mqtt.go index 07bb2157..3ccab619 100644 --- a/models/mqtt.go +++ b/models/mqtt.go @@ -1,9 +1,10 @@ package models +import "golang.zx2c4.com/wireguard/wgctrl/wgtypes" + type PeerUpdate struct { - Network string - Nodes []Node - ExtPeers []ExtPeersResponse + Network string + Peers []wgtypes.PeerConfig } type KeyUpdate struct { diff --git a/mq/mq.go b/mq/mq.go index 3521a165..cb32b430 100644 --- a/mq/mq.go +++ b/mq/mq.go @@ -1,8 +1,8 @@ package mq import ( + "encoding/json" "errors" - "fmt" "strings" mqtt "github.com/eclipse/paho.mqtt.golang" @@ -86,61 +86,38 @@ var IPUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { } node.Endpoint = ip node.SetLastCheckIn() - if err := UpdatePeers(client, node); err != nil { + if err != UpdatePeers(client, node) { logger.Log(0, "error updating peers "+err.Error()) } }() } func UpdatePeers(client mqtt.Client, node models.Node) error { - var peerUpdate models.PeerUpdate - peerUpdate.Network = node.Network - - nodes, err := logic.GetNetworkNodes(node.Network) + peersToUpdate, err := logic.GetNetworkNodes(node.Network) if err != nil { - return fmt.Errorf("unable to get network nodes %v: ", err) + logger.Log(0, "error retrieving peers to be updated "+err.Error()) + return err } - if token := client.Connect(); token.Wait() && token.Error() != nil { - return token.Error() - } - for _, peer := range nodes { - //don't need to update the initiatiing client - if peer.ID == node.ID { - continue - } - peerUpdate.Nodes = append(peerUpdate.Nodes, peer) - peerUpdate.ExtPeers, err = logic.GetExtPeersList(&node) - + for _, peerToUpdate := range peersToUpdate { + peers, _, _, err := logic.GetServerPeers(&peerToUpdate) if err != nil { - logger.Log(0) + logger.Log(0, "error retrieving peers "+err.Error()) + return err } - if token := client.Publish("update/peers/"+peer.ID, 0, false, nodes); token.Wait() && token.Error() != nil { - logger.Log(0, "error publishing peer update "+peer.ID+" "+token.Error().Error()) - } - } - - return nil -} - -func UpdateLocalPeers(client mqtt.Client, node models.Node) error { - nodes, err := logic.GetNetworkNodes(node.Network) - if err != nil { - return fmt.Errorf("unable to get network nodes %v: ", err) - } - if token := client.Connect(); token.Wait() && token.Error() != nil { - return token.Error() - } - for _, peer := range nodes { - //don't need to update the initiatiing client - if peer.ID == node.ID { + if peerToUpdate.ID == node.ID { continue } - //if peer.Endpoint is on same lan as node.LocalAddress - //if TODO{ - //continue - //} - if token := client.Publish("update/peers/"+peer.ID, 0, false, nodes); token.Wait() && token.Error() != nil { - logger.Log(0, "error publishing peer update "+peer.ID+" "+token.Error().Error()) + var peerUpdate models.PeerUpdate + peerUpdate.Network = node.Network + peerUpdate.Peers = peers + data, err := json.Marshal(peerUpdate) + if err != nil { + logger.Log(0, "error marshaling peer update "+err.Error()) + return err + } + if token := client.Publish("/update/peers/"+peerToUpdate.ID, 0, false, data); token.Wait() && token.Error() != nil { + logger.Log(0, "error sending peer updatte to no") + return err } } return nil @@ -162,7 +139,7 @@ var LocalAddressUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.M } node.LocalAddress = string(msg.Payload()) node.SetLastCheckIn() - if err := UpdateLocalPeers(client, node); err != nil { + if err := UpdatePeers(client, node); err != nil { logger.Log(0, "error updating peers "+err.Error()) } }() diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index bd27ee4d..ec569e7c 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -28,7 +28,7 @@ func Daemon() error { return err } for _, network := range networks { - go Netclient(ctx, network) + go MessageQueue(ctx, network) } quit := make(chan os.Signal, 1) signal.Notify(quit, syscall.SIGTERM, os.Interrupt) @@ -51,8 +51,8 @@ func SetupMQTT(cfg config.ClientConfig) mqtt.Client { return client } -// Netclient sets up Message Queue and subsribes/publishes updates to/from server -func Netclient(ctx context.Context, network string) { +// MessageQueue sets up Message Queue and subsribes/publishes updates to/from server +func MessageQueue(ctx context.Context, network string) { ncutils.Log("netclient go routine started for " + network) var cfg config.ClientConfig cfg.Network = network @@ -150,17 +150,7 @@ var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) var cfg config.ClientConfig cfg.Network = peerUpdate.Network cfg.ReadConfig() - peers, err := CalculatePeers(cfg.Node, peerUpdate.Nodes, cfg.Node.IsDualStack, cfg.Node.IsEgressGateway, cfg.Node.IsServer) - if err != nil { - ncutils.Log("error calculating Peers " + err.Error()) - return - } - extpeers, err := CalculateExtPeers(cfg.Node, peerUpdate.ExtPeers) - if err != nil { - ncutils.Log("error updated external wireguard peers " + err.Error()) - } - peers = append(peers, extpeers...) - err = wireguard.UpdateWgPeers(cfg.Node.Interface, peers) + err = wireguard.UpdateWgPeers(cfg.Node.Interface, peerUpdate.Peers) if err != nil { ncutils.Log("error updating wireguard peers" + err.Error()) return @@ -315,6 +305,7 @@ func Metrics(ctx context.Context, cfg config.ClientConfig, network string) { ncutils.Log("error publishing metrics " + token.Error().Error()) } ncutils.Log("metrics collection complete") + client.Disconnect(250) } } } diff --git a/netclient/functions/peers.go b/netclient/functions/peers.go deleted file mode 100644 index 833ebc90..00000000 --- a/netclient/functions/peers.go +++ /dev/null @@ -1,167 +0,0 @@ -package functions - -import ( - "log" - "net" - "strconv" - "strings" - "time" - - "github.com/gravitl/netmaker/models" - "github.com/gravitl/netmaker/netclient/ncutils" - "golang.zx2c4.com/wireguard/wgctrl/wgtypes" -) - -func CalculatePeers(thisNode models.Node, peernodes []models.Node, dualstack, egressgateway, server string) ([]wgtypes.Peer, error) { - //hasGateway := false - var gateways []string - var peers []wgtypes.Peer - - keepalive := thisNode.PersistentKeepalive - keepalivedur, _ := time.ParseDuration(strconv.FormatInt(int64(keepalive), 10) + "s") - keepaliveserver, err := time.ParseDuration(strconv.FormatInt(int64(5), 10) + "s") - if err != nil { - log.Fatalf("Issue with format of keepalive value. Please update netconfig: %v", err) - } - for _, node := range peernodes { - pubkey, err := wgtypes.ParseKey(node.PublicKey) - if err != nil { - log.Println("error parsing key") - //return peers, hasGateway, gateways, err - } - - if thisNode.PublicKey == node.PublicKey { - continue - } - if thisNode.Endpoint == node.Endpoint { - if thisNode.LocalAddress != node.LocalAddress && node.LocalAddress != "" { - node.Endpoint = node.LocalAddress - } else { - continue - } - } - - var peer wgtypes.Peer - var peeraddr = net.IPNet{ - IP: net.ParseIP(node.Address), - Mask: net.CIDRMask(32, 32), - } - var allowedips []net.IPNet - allowedips = append(allowedips, peeraddr) - // handle manually set peers - for _, allowedIp := range node.AllowedIPs { - if _, ipnet, err := net.ParseCIDR(allowedIp); err == nil { - nodeEndpointArr := strings.Split(node.Endpoint, ":") - if !ipnet.Contains(net.IP(nodeEndpointArr[0])) && ipnet.IP.String() != node.Address { // don't need to add an allowed ip that already exists.. - allowedips = append(allowedips, *ipnet) - } - } else if appendip := net.ParseIP(allowedIp); appendip != nil && allowedIp != node.Address { - ipnet := net.IPNet{ - IP: net.ParseIP(allowedIp), - Mask: net.CIDRMask(32, 32), - } - allowedips = append(allowedips, ipnet) - } - } - // handle egress gateway peers - if node.IsEgressGateway == "yes" { - //hasGateway = true - ranges := node.EgressGatewayRanges - for _, iprange := range ranges { // go through each cidr for egress gateway - _, ipnet, err := net.ParseCIDR(iprange) // confirming it's valid cidr - if err != nil { - ncutils.PrintLog("could not parse gateway IP range. Not adding "+iprange, 1) - continue // if can't parse CIDR - } - nodeEndpointArr := strings.Split(node.Endpoint, ":") // getting the public ip of node - if ipnet.Contains(net.ParseIP(nodeEndpointArr[0])) { // ensuring egress gateway range does not contain public ip of node - ncutils.PrintLog("egress IP range of "+iprange+" overlaps with "+node.Endpoint+", omitting", 2) - continue // skip adding egress range if overlaps with node's ip - } - if ipnet.Contains(net.ParseIP(thisNode.LocalAddress)) { // ensuring egress gateway range does not contain public ip of node - ncutils.PrintLog("egress IP range of "+iprange+" overlaps with "+thisNode.LocalAddress+", omitting", 2) - continue // skip adding egress range if overlaps with node's local ip - } - gateways = append(gateways, iprange) - if err != nil { - log.Println("ERROR ENCOUNTERED SETTING GATEWAY") - } else { - allowedips = append(allowedips, *ipnet) - } - } - } - if node.Address6 != "" && dualstack == "yes" { - var addr6 = net.IPNet{ - IP: net.ParseIP(node.Address6), - Mask: net.CIDRMask(128, 128), - } - allowedips = append(allowedips, addr6) - } - if thisNode.IsServer == "yes" && !(node.IsServer == "yes") { - peer = wgtypes.Peer{ - PublicKey: pubkey, - PersistentKeepaliveInterval: keepaliveserver, - AllowedIPs: allowedips, - } - } else if keepalive != 0 { - peer = wgtypes.Peer{ - PublicKey: pubkey, - PersistentKeepaliveInterval: keepalivedur, - Endpoint: &net.UDPAddr{ - IP: net.ParseIP(node.Endpoint), - Port: int(node.ListenPort), - }, - AllowedIPs: allowedips, - } - } else { - peer = wgtypes.Peer{ - PublicKey: pubkey, - Endpoint: &net.UDPAddr{ - IP: net.ParseIP(node.Endpoint), - Port: int(node.ListenPort), - }, - AllowedIPs: allowedips, - } - } - peers = append(peers, peer) - } - return peers, nil -} - -func CalculateExtPeers(thisNode models.Node, extPeers []models.ExtPeersResponse) ([]wgtypes.Peer, error) { - var peers []wgtypes.Peer - var err error - for _, extPeer := range extPeers { - pubkey, err := wgtypes.ParseKey(extPeer.PublicKey) - if err != nil { - log.Println("error parsing key") - return peers, err - } - - if thisNode.PublicKey == extPeer.PublicKey { - continue - } - - var peer wgtypes.Peer - var peeraddr = net.IPNet{ - IP: net.ParseIP(extPeer.Address), - Mask: net.CIDRMask(32, 32), - } - var allowedips []net.IPNet - allowedips = append(allowedips, peeraddr) - - if extPeer.Address6 != "" && thisNode.IsDualStack == "yes" { - var addr6 = net.IPNet{ - IP: net.ParseIP(extPeer.Address6), - Mask: net.CIDRMask(128, 128), - } - allowedips = append(allowedips, addr6) - } - peer = wgtypes.Peer{ - PublicKey: pubkey, - AllowedIPs: allowedips, - } - peers = append(peers, peer) - } - return peers, err -} diff --git a/netclient/wireguard/common.go b/netclient/wireguard/common.go index 34acb962..3f11fd36 100644 --- a/netclient/wireguard/common.go +++ b/netclient/wireguard/common.go @@ -343,7 +343,7 @@ func WriteWgConfig(cfg config.ClientConfig, privateKey string, peers []wgtypes.P } // UpdateWgPeers - updates the peers of a network -func UpdateWgPeers(wgInterface string, peers []wgtypes.Peer) error { +func UpdateWgPeers(wgInterface string, peers []wgtypes.PeerConfig) error { //update to get path properly file := ncutils.GetNetclientPathSpecific() + wgInterface + ".conf" wireguard, err := ini.ShadowLoad(file) From 3ffcce14cc482beb221441097cdc995bd1544e59 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Tue, 18 Jan 2022 22:32:12 +0000 Subject: [PATCH 107/116] fix publish peers --- controllers/node_grpc.go | 5 +++ logic/nodes.go | 54 +++++++++++++++++++++--- main.go | 4 -- mq/mq.go | 90 +++++++++++++++++++++++++++++++--------- 4 files changed, 124 insertions(+), 29 deletions(-) diff --git a/controllers/node_grpc.go b/controllers/node_grpc.go index f606a187..06591ca9 100644 --- a/controllers/node_grpc.go +++ b/controllers/node_grpc.go @@ -10,6 +10,7 @@ import ( "github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/logic" "github.com/gravitl/netmaker/models" + "github.com/gravitl/netmaker/mq" "github.com/gravitl/netmaker/servercfg" ) @@ -85,6 +86,10 @@ func (s *NodeServiceServer) CreateNode(ctx context.Context, req *nodepb.Object) if err != nil { return nil, err } + // notify other nodes on network of new peer + if err := mq.NewPeer(node); err != nil { + logger.Log(0, "failed to inform peers of new node "+err.Error()) + } return response, nil } diff --git a/logic/nodes.go b/logic/nodes.go index 6b35c4bc..0c8c6b81 100644 --- a/logic/nodes.go +++ b/logic/nodes.go @@ -4,7 +4,9 @@ import ( "encoding/json" "errors" "fmt" + "net" "sort" + "strconv" "strings" "time" @@ -14,6 +16,7 @@ import ( "github.com/gravitl/netmaker/models" "github.com/gravitl/netmaker/servercfg" "github.com/gravitl/netmaker/validation" + "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) // GetNetworkNodes - gets the nodes of a network @@ -74,7 +77,7 @@ func UncordonNode(nodeid string) (models.Node, error) { node.SetLastModified() node.IsPending = "no" node.PullChanges = "yes" - data, err := json.Marshal(&node) + data, err := json.Marshal(&node) if err != nil { return node, err } @@ -83,11 +86,52 @@ func UncordonNode(nodeid string) (models.Node, error) { return node, err } -// GetPeers - gets the peers of a given node -func GetPeers(node *models.Node) ([]models.Node, error) { - if IsLeader(node) { - SetNetworkServerPeers(node) +// GetWGNodePeers - gets the wg peers of a given node +func GetWGNodePeers(node *models.Node) ([]wgtypes.PeerConfig, error){ + var peers []wgtypes.PeerConfig + var peerData wgtypes.PeerConfig + nodes, err := GetPeers(node) + if err != nil { + return peers, err } + logger.Log(0, "the peers of " + node.Name + " are:") + for _, peer := range nodes { + logger.Log(0, "peer: " + peer.Name) + } + for _, peer := range nodes { + //this should not happen but it does + if peer.Name == node.Name { + logger.Log(0, "GetPeers returned me " + node.Name) + continue + } + pubkey, err :=wgtypes.ParseKey(peer.PublicKey) + if err != nil { + logger.Log(0, "ParseKey failed " +err.Error()) + continue + } + endpoint := peer.Endpoint + ":" + strconv.Itoa(int(peer.ListenPort)) + address, err := net.ResolveUDPAddr("udp", endpoint) + if err != nil { + logger.Log(0, "could not resolve endpoint " + err.Error()) + continue + } + ///Persitent Keepalive + //Allowed IPs + peerData = wgtypes.PeerConfig{ + PublicKey: pubkey, + Endpoint: address, + } + peers = append (peers, peerData) + } + return peers, nil +} + +// GetPeers - gets a list of nodes that are peers of a given node +func GetPeers(node *models.Node) ([]models.Node, error) { + //if IsLeader(node) { + // logger.Log(0, node.Name + " is a leader") + // SetNetworkServerPeers(node) + //} excludeIsRelayed := node.IsRelay != "yes" var relayedNode string if node.IsRelayed == "yes" { diff --git a/main.go b/main.go index 3d527a0b..b48ed5f7 100644 --- a/main.go +++ b/main.go @@ -208,10 +208,6 @@ func runMessageQueue(wg *sync.WaitGroup) { client.Disconnect(240) logger.Log(0, "ping sub failed") } - if token := client.Subscribe("metrics/#", 0, mq.Metrics); token.Wait() && token.Error() != nil { - client.Disconnect(240) - logger.Log(0, "metrics sub failed") - } if token := client.Subscribe("update/localaddress/#", 0, mq.LocalAddressUpdate); token.Wait() && token.Error() != nil { client.Disconnect(240) logger.Log(0, "metrics sub failed") diff --git a/mq/mq.go b/mq/mq.go index cb32b430..6cd80dcc 100644 --- a/mq/mq.go +++ b/mq/mq.go @@ -3,24 +3,24 @@ package mq import ( "encoding/json" "errors" + "net" + "strconv" "strings" + "time" mqtt "github.com/eclipse/paho.mqtt.golang" "github.com/gravitl/netmaker/database" "github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/logic" "github.com/gravitl/netmaker/models" + "github.com/gravitl/netmaker/servercfg" + "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) var DefaultHandler mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { logger.Log(0, "MQTT Message: Topic: "+string(msg.Topic())+" Message: "+string(msg.Payload())) } -var Metrics mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { - logger.Log(0, "Metrics Handler") - //TODOD -- handle metrics data ---- store to database? -} - var Ping mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { logger.Log(0, "Ping Handler: "+msg.Topic()) go func() { @@ -42,6 +42,9 @@ var Ping mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { return } node.SetLastCheckIn() + if err := logic.UpdateNode(&node, &node) ; err != nil { + logger.Log(0, "error updating node "+ err.Error()) + } logger.Log(0, "ping processed") // --TODO --set client version once feature is implemented. //node.SetClientVersion(msg.Payload()) @@ -63,6 +66,9 @@ var PublicKeyUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Mess } node.PublicKey = key node.SetLastCheckIn() + if err := logic.UpdateNode(&node, &node) ; err != nil { + logger.Log(0, "error updating node "+ err.Error()) + } if err := UpdatePeers(client, node); err != nil { logger.Log(0, "error updating peers "+err.Error()) } @@ -86,36 +92,64 @@ var IPUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { } node.Endpoint = ip node.SetLastCheckIn() + if err := logic.UpdateNode(&node, &node) ; err != nil { + logger.Log(0, "error updating node "+ err.Error()) + } if err != UpdatePeers(client, node) { logger.Log(0, "error updating peers "+err.Error()) } }() } -func UpdatePeers(client mqtt.Client, node models.Node) error { - peersToUpdate, err := logic.GetNetworkNodes(node.Network) +func UpdatePeers(client mqtt.Client, newnode models.Node) error { + networkNodes, err := logic.GetNetworkNodes(newnode.Network) if err != nil { - logger.Log(0, "error retrieving peers to be updated "+err.Error()) return err } - for _, peerToUpdate := range peersToUpdate { - peers, _, _, err := logic.GetServerPeers(&peerToUpdate) - if err != nil { - logger.Log(0, "error retrieving peers "+err.Error()) - return err - } - if peerToUpdate.ID == node.ID { - continue - } + keepalive, _ := time.ParseDuration(string(newnode.PersistentKeepalive)+"s") + for _, node := range networkNodes { + var peers []wgtypes.PeerConfig var peerUpdate models.PeerUpdate + for _, peer := range networkNodes{ + if peer.ID == node.ID { + //skip + continue + } + pubkey, err := wgtypes.ParseKey(peer.PublicKey) + if err != nil { + return err + } + if node.Endpoint == peer.Endpoint { + if node.LocalAddress != peer.LocalAddress && peer.LocalAddress != "" { + peer.Endpoint = peer.LocalAddress + }else { + continue + } + } + endpoint := peer.Endpoint + ":" + strconv.Itoa(int(peer.ListenPort)) + //fmt.Println("endpoint: ", endpoint, peer.Endpoint, peer.ListenPort) + address, err := net.ResolveUDPAddr("udp", endpoint) + if err != nil { + return err + } + //calculate Allowed IPs. + var peerData wgtypes.PeerConfig + peerData = wgtypes.PeerConfig{ + PublicKey: pubkey, + Endpoint: address, + PersistentKeepaliveInterval: &keepalive, + //AllowedIPs: allowedIPs + } + peers = append (peers, peerData) + } peerUpdate.Network = node.Network - peerUpdate.Peers = peers - data, err := json.Marshal(peerUpdate) + peerUpdate.Peers = peers + data, err := json.Marshal(&peerUpdate) if err != nil { logger.Log(0, "error marshaling peer update "+err.Error()) return err } - if token := client.Publish("/update/peers/"+peerToUpdate.ID, 0, false, data); token.Wait() && token.Error() != nil { + if token := client.Publish("/update/peers/"+node.ID, 0, false, data); token.Wait() && token.Error() != nil { logger.Log(0, "error sending peer updatte to no") return err } @@ -154,3 +188,19 @@ func GetID(topic string) (string, error) { //the last part of the topic will be the node.ID return parts[count-1], nil } + +func NewPeer(node models.Node) error { + opts := mqtt.NewClientOptions() + broker := servercfg.GetMessageQueueEndpoint() + logger.Log(0, "broker: "+broker) + opts.AddBroker(broker) + client := mqtt.NewClient(opts) + if token := client.Connect(); token.Wait() && token.Error() != nil { + return token.Error() + } + + if err := UpdatePeers(client, node); err != nil { + return err + } + return nil +} From d5939e255a8c8f91a3491d755d772f3bc710bbbb Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Tue, 18 Jan 2022 17:36:10 -0500 Subject: [PATCH 108/116] remove metrics from client --- netclient/functions/daemon.go | 40 +---------------------------------- 1 file changed, 1 insertion(+), 39 deletions(-) diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index ec569e7c..dcb16e1a 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -15,7 +15,6 @@ import ( "github.com/gravitl/netmaker/netclient/config" "github.com/gravitl/netmaker/netclient/ncutils" "github.com/gravitl/netmaker/netclient/wireguard" - "golang.zx2c4.com/wireguard/wgctrl" "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) @@ -68,7 +67,6 @@ func MessageQueue(ctx context.Context, network string) { //client.AddRoute("update/keys/"+cfg.Node.ID, UpdateKeys) defer client.Disconnect(250) go Checkin(ctx, cfg, network) - go Metrics(ctx, cfg, network) <-ctx.Done() ncutils.Log("shutting down daemon") } @@ -198,7 +196,7 @@ func Checkin(ctx context.Context, cfg config.ClientConfig, network string) { ncutils.Log("Checkin cancelled") return //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? - case <-time.After(time.Second * 10): + case <-time.After(time.Second * 60): ncutils.Log("Checkin running") //read latest config cfg.ReadConfig() @@ -273,39 +271,3 @@ func Hello(cfg config.ClientConfig, network string) { } client.Disconnect(250) } - -// Metics -- go routine that collects wireguard metrics and publishes to broker -func Metrics(ctx context.Context, cfg config.ClientConfig, network string) { - for { - select { - case <-ctx.Done(): - ncutils.Log("Metrics collection cancelled") - return - //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? - case <-time.After(time.Second * 60): - ncutils.Log("Metrics collection running") - wg, err := wgctrl.New() - defer wg.Close() - if err != nil { - ncutils.Log("error getting devices " + err.Error()) - break - } - device, err := wg.Device(cfg.Node.Interface) - if err != nil { - ncutils.Log("error reading wg device " + err.Error()) - break - } - bytes, err := json.Marshal(device.Peers) - if err != nil { - ncutils.Log("error marshaling peers " + err.Error()) - break - } - client := SetupMQTT(cfg) - if token := client.Publish("metrics/"+cfg.Node.ID, 1, false, bytes); token.Wait() && token.Error() != nil { - ncutils.Log("error publishing metrics " + token.Error().Error()) - } - ncutils.Log("metrics collection complete") - client.Disconnect(250) - } - } -} From b48cb8a9d726cba556bfec4baf3f353c82bf2041 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Wed, 19 Jan 2022 09:44:35 -0500 Subject: [PATCH 109/116] calculate allowed ips --- mq/mq.go | 177 ++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 135 insertions(+), 42 deletions(-) diff --git a/mq/mq.go b/mq/mq.go index 6cd80dcc..f1f5553d 100644 --- a/mq/mq.go +++ b/mq/mq.go @@ -3,6 +3,7 @@ package mq import ( "encoding/json" "errors" + "log" "net" "strconv" "strings" @@ -13,6 +14,7 @@ import ( "github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/logic" "github.com/gravitl/netmaker/models" + "github.com/gravitl/netmaker/netclient/ncutils" "github.com/gravitl/netmaker/servercfg" "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) @@ -42,8 +44,8 @@ var Ping mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { return } node.SetLastCheckIn() - if err := logic.UpdateNode(&node, &node) ; err != nil { - logger.Log(0, "error updating node "+ err.Error()) + if err := logic.UpdateNode(&node, &node); err != nil { + logger.Log(0, "error updating node "+err.Error()) } logger.Log(0, "ping processed") // --TODO --set client version once feature is implemented. @@ -66,8 +68,8 @@ var PublicKeyUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Mess } node.PublicKey = key node.SetLastCheckIn() - if err := logic.UpdateNode(&node, &node) ; err != nil { - logger.Log(0, "error updating node "+ err.Error()) + if err := logic.UpdateNode(&node, &node); err != nil { + logger.Log(0, "error updating node "+err.Error()) } if err := UpdatePeers(client, node); err != nil { logger.Log(0, "error updating peers "+err.Error()) @@ -92,8 +94,8 @@ var IPUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { } node.Endpoint = ip node.SetLastCheckIn() - if err := logic.UpdateNode(&node, &node) ; err != nil { - logger.Log(0, "error updating node "+ err.Error()) + if err := logic.UpdateNode(&node, &node); err != nil { + logger.Log(0, "error updating node "+err.Error()) } if err != UpdatePeers(client, node) { logger.Log(0, "error updating peers "+err.Error()) @@ -106,50 +108,141 @@ func UpdatePeers(client mqtt.Client, newnode models.Node) error { if err != nil { return err } - keepalive, _ := time.ParseDuration(string(newnode.PersistentKeepalive)+"s") - for _, node := range networkNodes { - var peers []wgtypes.PeerConfig + dualstack := false + keepalive, _ := time.ParseDuration(string(newnode.PersistentKeepalive) + "s") + defaultkeepalive, _ := time.ParseDuration("25s") + for _, node := range networkNodes { + var peers []wgtypes.PeerConfig var peerUpdate models.PeerUpdate - for _, peer := range networkNodes{ - if peer.ID == node.ID { - //skip - continue - } - pubkey, err := wgtypes.ParseKey(peer.PublicKey) - if err != nil { + var gateways []string + + for _, peer := range networkNodes { + if peer.ID == node.ID { + //skip + continue + } + var allowedips []net.IPNet + var peeraddr = net.IPNet{ + IP: net.ParseIP(peer.Address), + Mask: net.CIDRMask(32, 32), + } + //hasGateway := false + pubkey, err := wgtypes.ParseKey(peer.PublicKey) + if err != nil { return err - } - if node.Endpoint == peer.Endpoint { - if node.LocalAddress != peer.LocalAddress && peer.LocalAddress != "" { - peer.Endpoint = peer.LocalAddress - }else { - continue - } - } - endpoint := peer.Endpoint + ":" + strconv.Itoa(int(peer.ListenPort)) - //fmt.Println("endpoint: ", endpoint, peer.Endpoint, peer.ListenPort) - address, err := net.ResolveUDPAddr("udp", endpoint) - if err != nil { + } + if node.Endpoint == peer.Endpoint { + if node.LocalAddress != peer.LocalAddress && peer.LocalAddress != "" { + peer.Endpoint = peer.LocalAddress + } else { + continue + } + } + endpoint := peer.Endpoint + ":" + strconv.Itoa(int(peer.ListenPort)) + //fmt.Println("endpoint: ", endpoint, peer.Endpoint, peer.ListenPort) + address, err := net.ResolveUDPAddr("udp", endpoint) + if err != nil { return err - } - //calculate Allowed IPs. - var peerData wgtypes.PeerConfig - peerData = wgtypes.PeerConfig{ - PublicKey: pubkey, - Endpoint: address, - PersistentKeepaliveInterval: &keepalive, - //AllowedIPs: allowedIPs - } - peers = append (peers, peerData) - } + } + //calculate Allowed IPs. + allowedips = append(allowedips, peeraddr) + // handle manually set peers + for _, allowedIp := range node.AllowedIPs { + if _, ipnet, err := net.ParseCIDR(allowedIp); err == nil { + nodeEndpointArr := strings.Split(node.Endpoint, ":") + if !ipnet.Contains(net.IP(nodeEndpointArr[0])) && ipnet.IP.String() != node.Address { // don't need to add an allowed ip that already exists.. + allowedips = append(allowedips, *ipnet) + } + } else if appendip := net.ParseIP(allowedIp); appendip != nil && allowedIp != node.Address { + ipnet := net.IPNet{ + IP: net.ParseIP(allowedIp), + Mask: net.CIDRMask(32, 32), + } + allowedips = append(allowedips, ipnet) + } + } + // handle egress gateway peers + if node.IsEgressGateway == "yes" { + //hasGateway = true + ranges := node.EgressGatewayRanges + for _, iprange := range ranges { // go through each cidr for egress gateway + _, ipnet, err := net.ParseCIDR(iprange) // confirming it's valid cidr + if err != nil { + ncutils.PrintLog("could not parse gateway IP range. Not adding "+iprange, 1) + continue // if can't parse CIDR + } + nodeEndpointArr := strings.Split(node.Endpoint, ":") // getting the public ip of node + if ipnet.Contains(net.ParseIP(nodeEndpointArr[0])) { // ensuring egress gateway range does not contain public ip of node + ncutils.PrintLog("egress IP range of "+iprange+" overlaps with "+node.Endpoint+", omitting", 2) + continue // skip adding egress range if overlaps with node's ip + } + if ipnet.Contains(net.ParseIP(node.LocalAddress)) { // ensuring egress gateway range does not contain public ip of node + ncutils.PrintLog("egress IP range of "+iprange+" overlaps with "+node.LocalAddress+", omitting", 2) + continue // skip adding egress range if overlaps with node's local ip + } + gateways = append(gateways, iprange) + if err != nil { + log.Println("ERROR ENCOUNTERED SETTING GATEWAY") + } else { + allowedips = append(allowedips, *ipnet) + } + } + } + var peerData wgtypes.PeerConfig + if node.Address6 != "" && dualstack { + var addr6 = net.IPNet{ + IP: net.ParseIP(node.Address6), + Mask: net.CIDRMask(128, 128), + } + allowedips = append(allowedips, addr6) + } + if node.IsServer == "yes" && !(node.IsServer == "yes") { + peerData = wgtypes.PeerConfig{ + PublicKey: pubkey, + PersistentKeepaliveInterval: &defaultkeepalive, + ReplaceAllowedIPs: true, + AllowedIPs: allowedips, + } + } else if keepalive != 0 { + peerData = wgtypes.PeerConfig{ + PublicKey: pubkey, + PersistentKeepaliveInterval: &defaultkeepalive, + //Endpoint: &net.UDPAddr{ + // IP: net.ParseIP(node.Endpoint), + // Port: int(node.ListenPort), + //}, + Endpoint: address, + ReplaceAllowedIPs: true, + AllowedIPs: allowedips, + } + } else { + peerData = wgtypes.PeerConfig{ + PublicKey: pubkey, + //Endpoint: &net.UDPAddr{ + // IP: net.ParseIP(node.Endpoint), + // Port: int(node.ListenPort), + //}, + Endpoint: address, + ReplaceAllowedIPs: true, + AllowedIPs: allowedips, + } + } + //peerData = wgtypes.PeerConfig{ + // PublicKey: pubkey, + // Endpoint: address, + // PersistentKeepaliveInterval: &keepalive, + //AllowedIPs: allowedIPs + //} + peers = append(peers, peerData) + } peerUpdate.Network = node.Network - peerUpdate.Peers = peers + peerUpdate.Peers = peers data, err := json.Marshal(&peerUpdate) if err != nil { logger.Log(0, "error marshaling peer update "+err.Error()) return err } - if token := client.Publish("/update/peers/"+node.ID, 0, false, data); token.Wait() && token.Error() != nil { + if token := client.Publish("/update/peers/"+node.ID, 0, false, data); token.Wait() && token.Error() != nil { logger.Log(0, "error sending peer updatte to no") return err } @@ -198,7 +291,7 @@ func NewPeer(node models.Node) error { if token := client.Connect(); token.Wait() && token.Error() != nil { return token.Error() } - + if err := UpdatePeers(client, node); err != nil { return err } From 9539e783697386b82c2b40711bdcc8f982b08a97 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Wed, 19 Jan 2022 15:00:03 -0500 Subject: [PATCH 110/116] fix UpdateWgPeers --- netclient/functions/daemon.go | 29 +++++++++++++++++++++++------ netclient/wireguard/common.go | 26 ++++++++++++++++++-------- netclient/wireguard/unix.go | 15 +++++++++++++-- 3 files changed, 54 insertions(+), 16 deletions(-) diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index dcb16e1a..b339e1b4 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -61,8 +61,16 @@ func MessageQueue(ctx context.Context, network string) { if token := client.Subscribe("#", 0, nil); token.Wait() && token.Error() != nil { log.Fatal(token.Error()) } - client.AddRoute("update/"+cfg.Node.ID, NodeUpdate) - client.AddRoute("update/peers/"+cfg.Node.ID, UpdatePeers) + if token := client.Subscribe("update/"+cfg.Node.ID, 0, NodeUpdate); token.Wait() && token.Error() != nil { + log.Fatal(token.Error()) + } + if token := client.Subscribe("/update/peers/"+cfg.Node.ID, 0, UpdatePeers); token.Wait() && token.Error() != nil { + log.Fatal(token.Error()) + } + + //addroute doesn't seem to work consistently + //client.AddRoute("update/"+cfg.Node.ID, NodeUpdate) + //client.AddRoute("update/peers/"+cfg.Node.ID, UpdatePeers) //handle key updates in node update //client.AddRoute("update/keys/"+cfg.Node.ID, UpdateKeys) defer client.Disconnect(250) @@ -73,8 +81,9 @@ func MessageQueue(ctx context.Context, network string) { // All -- mqtt message hander for all ('#') topics var All mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { + ncutils.Log("default message handler -- received message but not handling") ncutils.Log("Topic: " + string(msg.Topic())) - ncutils.Log("Message: " + string(msg.Payload())) + //ncutils.Log("Message: " + string(msg.Payload())) } // NodeUpdate -- mqtt message handler for /update/ topic @@ -137,7 +146,6 @@ var NodeUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) // UpdatePeers -- mqtt message handler for /update/peers/ topic var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { - ncutils.Log("received message to update peers " + string(msg.Payload())) go func() { var peerUpdate models.PeerUpdate err := json.Unmarshal(msg.Payload(), &peerUpdate) @@ -145,6 +153,14 @@ var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) ncutils.Log("error unmarshalling peer data") return } + ncutils.Log("update peer handler") + ncutils.Log("recieved " + string(len(peerUpdate.Peers)) + "peers to update") + ncutils.Log(string(msg.Payload())) + ncutils.Log(peerUpdate.Network) + for _, peer := range peerUpdate.Peers { + key := peer.PublicKey.String() + ncutils.Log(key) + } var cfg config.ClientConfig cfg.Network = peerUpdate.Network cfg.ReadConfig() @@ -153,8 +169,9 @@ var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) ncutils.Log("error updating wireguard peers" + err.Error()) return } - // path hardcoded for now... should be updated - err = wireguard.ApplyWGQuickConf("/etc/netclient/config/" + cfg.Node.Interface + ".conf") + file := ncutils.GetNetclientPathSpecific() + cfg.Node.Interface + ".conf" + ncutils.Log("applyWGQuickConf to " + file) + err = wireguard.ApplyWGQuickConf(file) if err != nil { ncutils.Log("error restarting wg after peer update " + err.Error()) return diff --git a/netclient/wireguard/common.go b/netclient/wireguard/common.go index 3f11fd36..123705ad 100644 --- a/netclient/wireguard/common.go +++ b/netclient/wireguard/common.go @@ -327,8 +327,12 @@ func WriteWgConfig(cfg config.ClientConfig, privateKey string, peers []wgtypes.P } if peer.AllowedIPs != nil { var allowedIPs string - for _, ip := range peer.AllowedIPs { - allowedIPs = allowedIPs + ", " + ip.String() + for i, ip := range peer.AllowedIPs { + if i == 0 { + allowedIPs = ip.String() + } else { + allowedIPs = allowedIPs + ", " + ip.String() + } } wireguard.SectionWithIndex(section_peers, i).Key("AllowedIps").SetValue(allowedIPs) } @@ -344,21 +348,27 @@ func WriteWgConfig(cfg config.ClientConfig, privateKey string, peers []wgtypes.P // UpdateWgPeers - updates the peers of a network func UpdateWgPeers(wgInterface string, peers []wgtypes.PeerConfig) error { - //update to get path properly file := ncutils.GetNetclientPathSpecific() + wgInterface + ".conf" + ncutils.Log("updating " + file) wireguard, err := ini.ShadowLoad(file) if err != nil { return err } + //delete the peers sections as they are going to be replaced + wireguard.DeleteSection(section_peers) for i, peer := range peers { wireguard.SectionWithIndex(section_peers, i).Key("PublicKey").SetValue(peer.PublicKey.String()) - if peer.PresharedKey.String() != "" { - wireguard.SectionWithIndex(section_peers, i).Key("PreSharedKey").SetValue(peer.PresharedKey.String()) - } + //if peer.PresharedKey.String() != "" { + //wireguard.SectionWithIndex(section_peers, i).Key("PreSharedKey").SetValue(peer.PresharedKey.String()) + //} if peer.AllowedIPs != nil { var allowedIPs string - for _, ip := range peer.AllowedIPs { - allowedIPs = allowedIPs + ", " + ip.String() + for i, ip := range peer.AllowedIPs { + if i == 0 { + allowedIPs = ip.String() + } else { + allowedIPs = allowedIPs + ", " + ip.String() + } } wireguard.SectionWithIndex(section_peers, i).Key("AllowedIps").SetValue(allowedIPs) } diff --git a/netclient/wireguard/unix.go b/netclient/wireguard/unix.go index 142aa920..303d1636 100644 --- a/netclient/wireguard/unix.go +++ b/netclient/wireguard/unix.go @@ -53,8 +53,19 @@ func SetWGKeyConfig(network string, serveraddr string) error { // ApplyWGQuickConf - applies wg-quick commands if os supports func ApplyWGQuickConf(confPath string) error { - _, _ = ncutils.RunCmd("wg-quick down "+confPath, false) - _, err := ncutils.RunCmd("wg-quick up "+confPath, false) + _, err := os.Stat(confPath) + if err != nil { + ncutils.Log(confPath + " does not exist " + err.Error()) + return err + } + _, err = ncutils.RunCmd("wg-quick down "+confPath, false) + if err != nil { + ncutils.Log("err runing wg-quick down " + confPath + err.Error()) + } + _, err = ncutils.RunCmd("wg-quick up "+confPath, false) + if err != nil { + ncutils.Log("err runing wg-quick up " + confPath + err.Error()) + } return err } From 5147bb61d000de85d79352e81b41a55f485a6202 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Wed, 19 Jan 2022 15:12:09 -0500 Subject: [PATCH 111/116] fix UpdateWgPeers to enable multiple peer sections --- netclient/wireguard/common.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/netclient/wireguard/common.go b/netclient/wireguard/common.go index 123705ad..77b64530 100644 --- a/netclient/wireguard/common.go +++ b/netclient/wireguard/common.go @@ -348,15 +348,20 @@ func WriteWgConfig(cfg config.ClientConfig, privateKey string, peers []wgtypes.P // UpdateWgPeers - updates the peers of a network func UpdateWgPeers(wgInterface string, peers []wgtypes.PeerConfig) error { + options := ini.LoadOptions{ + AllowNonUniqueSections: true, + AllowShadows: true, + } file := ncutils.GetNetclientPathSpecific() + wgInterface + ".conf" ncutils.Log("updating " + file) - wireguard, err := ini.ShadowLoad(file) + wireguard, err := ini.LoadSources(options, file) if err != nil { return err } //delete the peers sections as they are going to be replaced wireguard.DeleteSection(section_peers) for i, peer := range peers { + ncutils.Log("adding peer section for peer #: " + string(i) + peer.PublicKey.String()) wireguard.SectionWithIndex(section_peers, i).Key("PublicKey").SetValue(peer.PublicKey.String()) //if peer.PresharedKey.String() != "" { //wireguard.SectionWithIndex(section_peers, i).Key("PreSharedKey").SetValue(peer.PresharedKey.String()) From 70cf2a26b1c8f086510c1460f375882a245f6f56 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Wed, 19 Jan 2022 15:25:39 -0500 Subject: [PATCH 112/116] fixed tests and removed some debugging logs --- netclient/functions/daemon.go | 7 ------- netclient/wireguard/common.go | 1 - 2 files changed, 8 deletions(-) diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index b339e1b4..d38ebf30 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -154,13 +154,6 @@ var UpdatePeers mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) return } ncutils.Log("update peer handler") - ncutils.Log("recieved " + string(len(peerUpdate.Peers)) + "peers to update") - ncutils.Log(string(msg.Payload())) - ncutils.Log(peerUpdate.Network) - for _, peer := range peerUpdate.Peers { - key := peer.PublicKey.String() - ncutils.Log(key) - } var cfg config.ClientConfig cfg.Network = peerUpdate.Network cfg.ReadConfig() diff --git a/netclient/wireguard/common.go b/netclient/wireguard/common.go index 77b64530..728c6b77 100644 --- a/netclient/wireguard/common.go +++ b/netclient/wireguard/common.go @@ -361,7 +361,6 @@ func UpdateWgPeers(wgInterface string, peers []wgtypes.PeerConfig) error { //delete the peers sections as they are going to be replaced wireguard.DeleteSection(section_peers) for i, peer := range peers { - ncutils.Log("adding peer section for peer #: " + string(i) + peer.PublicKey.String()) wireguard.SectionWithIndex(section_peers, i).Key("PublicKey").SetValue(peer.PublicKey.String()) //if peer.PresharedKey.String() != "" { //wireguard.SectionWithIndex(section_peers, i).Key("PreSharedKey").SetValue(peer.PresharedKey.String()) From 04ff830c76b62aada79dd3003c6165f494033c04 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Wed, 19 Jan 2022 15:33:29 -0500 Subject: [PATCH 113/116] add logic to grpc leave handler to publish peer update message --- controllers/node_grpc.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/controllers/node_grpc.go b/controllers/node_grpc.go index 06591ca9..774ce61d 100644 --- a/controllers/node_grpc.go +++ b/controllers/node_grpc.go @@ -142,6 +142,10 @@ func (s *NodeServiceServer) DeleteNode(ctx context.Context, req *nodepb.Object) if err != nil { return nil, err } + // notify other nodes on network of deleted peer + if err := mq.NewPeer(node); err != nil { + logger.Log(0, "failed to inform peers of deleted node "+err.Error()) + } return &nodepb.Object{ Data: "success", From c456537affb7cd526efee9a863820f60daacd050 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Wed, 19 Jan 2022 16:16:12 -0500 Subject: [PATCH 114/116] updated service files for linux and darwin to start netclient daemon vice netclient checkin --- netclient/daemon/systemd.go | 51 ++++++++----------------------------- 1 file changed, 11 insertions(+), 40 deletions(-) diff --git a/netclient/daemon/systemd.go b/netclient/daemon/systemd.go index 015f4626..6b1ecc4a 100644 --- a/netclient/daemon/systemd.go +++ b/netclient/daemon/systemd.go @@ -29,12 +29,10 @@ func SetupSystemDDaemon(interval string) error { log.Println("couldnt find or create /etc/netclient") return err } - - if !ncutils.FileExists("/usr/local/bin/netclient") { - os.Symlink("/etc/netclient/netclient", "/usr/local/bin/netclient") - } - if !ncutils.FileExists("/etc/netclient/netclient") { - err = ncutils.Copy(binarypath, "/etc/netclient/netclient") + //install binary + //should check if the existing binary is the corect version -- for now only copy if file doesn't exist + if !ncutils.FileExists("/usr/sbin/netclient") { + err = ncutils.Copy(binarypath, "/usr/sbin/netclient") if err != nil { log.Println(err) return err @@ -42,36 +40,17 @@ func SetupSystemDDaemon(interval string) error { } systemservice := `[Unit] -Description=Network Check -Wants=netclient.timer +Description=Netclient message queue [Service] Type=simple -ExecStart=/etc/netclient/netclient checkin -n all +ExecStart=/usr/sbin/netclient daemon [Install] WantedBy=multi-user.target -` - - systemtimer := `[Unit] -Description=Calls the Netmaker Mesh Client Service -Requires=netclient.service - -[Timer] -Unit=netclient.service - -` - systemtimer = systemtimer + "OnCalendar=*:*:0/" + interval - - systemtimer = systemtimer + - ` - -[Install] -WantedBy=timers.target ` servicebytes := []byte(systemservice) - timerbytes := []byte(systemtimer) if !ncutils.FileExists("/etc/systemd/system/netclient.service") { err = os.WriteFile("/etc/systemd/system/netclient.service", servicebytes, 0644) @@ -80,25 +59,17 @@ WantedBy=timers.target return err } } - - if !ncutils.FileExists("/etc/systemd/system/netclient.timer") { - err = os.WriteFile("/etc/systemd/system/netclient.timer", timerbytes, 0644) - if err != nil { - log.Println(err) - return err - } - } - _, _ = ncutils.RunCmd("systemctl enable netclient.service", true) _, _ = ncutils.RunCmd("systemctl daemon-reload", true) - _, _ = ncutils.RunCmd("systemctl enable netclient.timer", true) - _, _ = ncutils.RunCmd("systemctl start netclient.timer", true) + _, _ = ncutils.RunCmd("systemctl start netclient.server", true) return nil } func CleanupLinux() { - err := os.RemoveAll(ncutils.GetNetclientPath()) - if err != nil { + if err := os.RemoveAll(ncutils.GetNetclientPath()); err != nil { + ncutils.PrintLog("Removing netclient configs: "+err.Error(), 1) + } + if err := os.Remove("/usr/sbin/netclient"); err != nil { ncutils.PrintLog("Removing netclient binary: "+err.Error(), 1) } } From b28e1de50f4cd835eb11ce0e251795de1fda2e50 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Wed, 19 Jan 2022 16:27:19 -0500 Subject: [PATCH 115/116] write node to database when localAddress update received. --- mq/mq.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mq/mq.go b/mq/mq.go index f1f5553d..32a8a031 100644 --- a/mq/mq.go +++ b/mq/mq.go @@ -266,6 +266,9 @@ var LocalAddressUpdate mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.M } node.LocalAddress = string(msg.Payload()) node.SetLastCheckIn() + if err := logic.UpdateNode(&node, &node); err != nil { + logger.Log(0, "error updating node "+err.Error()) + } if err := UpdatePeers(client, node); err != nil { logger.Log(0, "error updating peers "+err.Error()) } From 3c6208a2dcecd018cbe2727010e5e9f2fe8ceae2 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Thu, 20 Jan 2022 09:34:07 -0500 Subject: [PATCH 116/116] added extclient peers and persitent keepalive --- mq/mq.go | 43 +++++++++++++------------------------------ 1 file changed, 13 insertions(+), 30 deletions(-) diff --git a/mq/mq.go b/mq/mq.go index 32a8a031..573fae39 100644 --- a/mq/mq.go +++ b/mq/mq.go @@ -109,8 +109,11 @@ func UpdatePeers(client mqtt.Client, newnode models.Node) error { return err } dualstack := false - keepalive, _ := time.ParseDuration(string(newnode.PersistentKeepalive) + "s") - defaultkeepalive, _ := time.ParseDuration("25s") + var keepalive time.Duration + //keepalive = time.Duration{} + if newnode.PersistentKeepalive != 0 { + keepalive, _ = time.ParseDuration(strconv.FormatInt(int64(newnode.PersistentKeepalive), 10) + "s") + } for _, node := range networkNodes { var peers []wgtypes.PeerConfig var peerUpdate models.PeerUpdate @@ -144,6 +147,7 @@ func UpdatePeers(client mqtt.Client, newnode models.Node) error { if err != nil { return err } + //calculate Allowed IPs. allowedips = append(allowedips, peeraddr) // handle manually set peers @@ -196,43 +200,22 @@ func UpdatePeers(client mqtt.Client, newnode models.Node) error { } allowedips = append(allowedips, addr6) } - if node.IsServer == "yes" && !(node.IsServer == "yes") { + if &keepalive == nil { peerData = wgtypes.PeerConfig{ - PublicKey: pubkey, - PersistentKeepaliveInterval: &defaultkeepalive, - ReplaceAllowedIPs: true, - AllowedIPs: allowedips, - } - } else if keepalive != 0 { - peerData = wgtypes.PeerConfig{ - PublicKey: pubkey, - PersistentKeepaliveInterval: &defaultkeepalive, - //Endpoint: &net.UDPAddr{ - // IP: net.ParseIP(node.Endpoint), - // Port: int(node.ListenPort), - //}, + PublicKey: pubkey, Endpoint: address, ReplaceAllowedIPs: true, AllowedIPs: allowedips, } } else { peerData = wgtypes.PeerConfig{ - PublicKey: pubkey, - //Endpoint: &net.UDPAddr{ - // IP: net.ParseIP(node.Endpoint), - // Port: int(node.ListenPort), - //}, - Endpoint: address, - ReplaceAllowedIPs: true, - AllowedIPs: allowedips, + PublicKey: pubkey, + PersistentKeepaliveInterval: &keepalive, + Endpoint: address, + ReplaceAllowedIPs: true, + AllowedIPs: allowedips, } } - //peerData = wgtypes.PeerConfig{ - // PublicKey: pubkey, - // Endpoint: address, - // PersistentKeepaliveInterval: &keepalive, - //AllowedIPs: allowedIPs - //} peers = append(peers, peerData) } peerUpdate.Network = node.Network