Merge pull request #1129 from gravitl/v0.14.1

V0.14.1
This commit is contained in:
dcarns 2022-05-24 16:07:06 -04:00 committed by GitHub
commit d592a1bf01
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 320 additions and 332 deletions

View file

@ -31,6 +31,7 @@ body:
label: Version label: Version
description: What version are you running? description: What version are you running?
options: options:
- v0.14.1
- v0.14.0 - v0.14.0
- v0.13.1 - v0.13.1
- v0.13.0 - v0.13.0

View file

@ -0,0 +1,61 @@
name: Publish Netclient-go Docker
on:
workflow_dispatch:
inputs:
tag:
description: 'docker tag'
required: true
release:
types: [published]
jobs:
docker:
runs-on: ubuntu-latest
steps:
-
name: Set tag
run: |
if [[ -n "${{ github.event.inputs.tag }}" ]]; then
TAG=${{ github.event.inputs.tag }}
elif [[ "${{ github.ref_name }}" == 'master' ]]; then
TAG="latest"
else
TAG="${{ github.ref_name }}"
fi
echo "TAG=${TAG}" >> $GITHUB_ENV
-
name: Checkout
uses: actions/checkout@v2
-
name: Set up QEMU
uses: docker/setup-qemu-action@v1
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
-
name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Build x86 and export to Docker
uses: docker/build-push-action@v2
with:
context: .
load: true
platforms: linux/amd64
file: ./docker/Dockerfile-netclient-multiarch-go
tags: ${{ env.TAG }}
build-args: version=${{ env.TAG }}
-
name: Build and push
uses: docker/build-push-action@v2
with:
context: .
platforms: linux/amd64
file: ./docker/Dockerfile-netclient-multiarch-go
push: true
tags: gravitl/netclient-go:${{ env.TAG }}, gravitl/netclient-go:latest
build-args: version=${{ env.TAG }}

View file

@ -10,7 +10,7 @@ a platform for modern, blazing fast virtual networks
<p align="center"> <p align="center">
<a href="https://github.com/gravitl/netmaker/releases"> <a href="https://github.com/gravitl/netmaker/releases">
<img src="https://img.shields.io/badge/Version-0.14.0-informational?style=flat-square" /> <img src="https://img.shields.io/badge/Version-0.14.1-informational?style=flat-square" />
</a> </a>
<a href="https://hub.docker.com/r/gravitl/netmaker/tags"> <a href="https://hub.docker.com/r/gravitl/netmaker/tags">
<img src="https://img.shields.io/docker/pulls/gravitl/netmaker" /> <img src="https://img.shields.io/docker/pulls/gravitl/netmaker" />
@ -21,8 +21,8 @@ a platform for modern, blazing fast virtual networks
<a href="https://github.com/gravitl/netmaker/graphs/contributors"> <a href="https://github.com/gravitl/netmaker/graphs/contributors">
<img src="https://img.shields.io/github/commit-activity/m/gravitl/netmaker?color=blue" /> <img src="https://img.shields.io/github/commit-activity/m/gravitl/netmaker?color=blue" />
</a> </a>
<a href="https://twitter.com/intent/follow?screen_name=gravitlcorp"> <a href="https://twitter.com/intent/follow?screen_name=netmaker_io">
<img src="https://img.shields.io/twitter/follow/gravitlcorp?style=social" /> <img src="https://img.shields.io/twitter/follow/netmaker_io?style=social" />
</a> </a>
<a href="https://www.youtube.com/channel/UCach3lJY_xBV7rGrbUSvkZQ"> <a href="https://www.youtube.com/channel/UCach3lJY_xBV7rGrbUSvkZQ">
<img src="https://img.shields.io/youtube/channel/views/UCach3lJY_xBV7rGrbUSvkZQ?style=social" /> <img src="https://img.shields.io/youtube/channel/views/UCach3lJY_xBV7rGrbUSvkZQ?style=social" />
@ -48,7 +48,9 @@ a platform for modern, blazing fast virtual networks
`wget -qO - https://raw.githubusercontent.com/gravitl/netmaker/master/scripts/nm-quick.sh | sudo bash` `wget -qO - https://raw.githubusercontent.com/gravitl/netmaker/master/scripts/nm-quick.sh | sudo bash`
<img src="./img/visit-website.gif" width="50%" /><img src="./img/graph-readme.gif" width="50%" /> <p float="left" align="middle">
<img src="./img/readme.gif" />
</p>
Upon completion, the logs will display the instructions to connect various devices. These can also be retrieved from the UI under "Access Keys." Upon completion, the logs will display the instructions to connect various devices. These can also be retrieved from the UI under "Access Keys."
@ -106,6 +108,9 @@ After installing Netmaker, check out the [Walkthrough](https://itnext.io/getting
- [Terraform Provider](https://github.com/madacluster/netmaker-terraform-provider) - [Terraform Provider](https://github.com/madacluster/netmaker-terraform-provider)
- [VyOS Integration](https://github.com/kylechase/vyos-netmaker)
- [Netmaker K3S](https://github.com/geragcp/netmaker-k3s)
## Disclaimer ## Disclaimer
[WireGuard](https://wireguard.com/) is a registered trademark of Jason A. Donenfeld. [WireGuard](https://wireguard.com/) is a registered trademark of Jason A. Donenfeld.

View file

@ -3,7 +3,7 @@ version: "3.4"
services: services:
netmaker: netmaker:
container_name: netmaker container_name: netmaker
image: gravitl/netmaker:v0.14.0 image: gravitl/netmaker:v0.14.1
volumes: volumes:
- dnsconfig:/root/config/dnsconfig - dnsconfig:/root/config/dnsconfig
- sqldata:/root/data - sqldata:/root/data
@ -43,7 +43,7 @@ services:
container_name: netmaker-ui container_name: netmaker-ui
depends_on: depends_on:
- netmaker - netmaker
image: gravitl/netmaker-ui:v0.14.0 image: gravitl/netmaker-ui:v0.14.1
links: links:
- "netmaker:api" - "netmaker:api"
environment: environment:

View file

@ -3,7 +3,7 @@ version: "3.4"
services: services:
netmaker: netmaker:
container_name: netmaker container_name: netmaker
image: gravitl/netmaker:v0.13.1 image: gravitl/netmaker:v0.14.1
volumes: volumes:
- dnsconfig:/root/config/dnsconfig - dnsconfig:/root/config/dnsconfig
- /usr/bin/wg:/usr/bin/wg - /usr/bin/wg:/usr/bin/wg
@ -38,7 +38,7 @@ services:
container_name: netmaker-ui container_name: netmaker-ui
depends_on: depends_on:
- netmaker - netmaker
image: gravitl/netmaker-ui:v0.13.1 image: gravitl/netmaker-ui:v0.14.1
links: links:
- "netmaker:api" - "netmaker:api"
ports: ports:

View file

@ -3,7 +3,7 @@ version: "3.4"
services: services:
netmaker: netmaker:
container_name: netmaker container_name: netmaker
image: gravitl/netmaker:v0.14.0 image: gravitl/netmaker:v0.14.1
volumes: volumes:
- dnsconfig:/root/config/dnsconfig - dnsconfig:/root/config/dnsconfig
- sqldata:/root/data - sqldata:/root/data
@ -44,7 +44,7 @@ services:
container_name: netmaker-ui container_name: netmaker-ui
depends_on: depends_on:
- netmaker - netmaker
image: gravitl/netmaker-ui:v0.14.0 image: gravitl/netmaker-ui:v0.14.1
links: links:
- "netmaker:api" - "netmaker:api"
ports: ports:
@ -73,6 +73,7 @@ services:
- "8883:8883" - "8883:8883"
volumes: volumes:
- /root/mosquitto.conf:/mosquitto/config/mosquitto.conf - /root/mosquitto.conf:/mosquitto/config/mosquitto.conf
- /root/certs/:/mosquitto/certs/
- mosquitto_data:/mosquitto/data - mosquitto_data:/mosquitto/data
- mosquitto_logs:/mosquitto/log - mosquitto_logs:/mosquitto/log
volumes: volumes:

View file

@ -3,7 +3,7 @@ version: "3.4"
services: services:
netmaker: netmaker:
container_name: netmaker container_name: netmaker
image: gravitl/netmaker:v0.14.0 image: gravitl/netmaker:v0.14.1
volumes: volumes:
- dnsconfig:/root/config/dnsconfig - dnsconfig:/root/config/dnsconfig
- sqldata:/root/data - sqldata:/root/data
@ -45,7 +45,7 @@ services:
container_name: netmaker-ui container_name: netmaker-ui
depends_on: depends_on:
- netmaker - netmaker
image: gravitl/netmaker-ui:v0.13.1 image: gravitl/netmaker-ui:v0.14.1
links: links:
- "netmaker:api" - "netmaker:api"
ports: ports:

View file

@ -2,7 +2,7 @@ services:
netmaker: # The Primary Server for running Netmaker netmaker: # The Primary Server for running Netmaker
privileged: true # Necessary to run sudo/root level commands on host system. Likely using this if running with host networking on. privileged: true # Necessary to run sudo/root level commands on host system. Likely using this if running with host networking on.
container_name: netmaker container_name: netmaker
image: gravitl/netmaker:v0.14.0 image: gravitl/netmaker:v0.14.1
volumes: # Volume mounts necessary for CLIENT_MODE to control wireguard networking on host (except dnsconfig, which is where dns config files are stored for use by CoreDNS) volumes: # Volume mounts necessary for CLIENT_MODE to control wireguard networking on host (except dnsconfig, which is where dns config files are stored for use by CoreDNS)
- dnsconfig:/root/config/dnsconfig # Netmaker writes Corefile to this location, which gets mounted by CoreDNS for DNS configuration. - dnsconfig:/root/config/dnsconfig # Netmaker writes Corefile to this location, which gets mounted by CoreDNS for DNS configuration.
- sqldata:/root/data - sqldata:/root/data
@ -46,7 +46,7 @@ services:
container_name: netmaker-ui container_name: netmaker-ui
depends_on: depends_on:
- netmaker - netmaker
image: gravitl/netmaker-ui:v0.14.0 image: gravitl/netmaker-ui:v0.14.1
links: links:
- "netmaker:api" - "netmaker:api"
ports: ports:

View file

@ -3,7 +3,7 @@ version: "3.4"
services: services:
netmaker: netmaker:
container_name: netmaker container_name: netmaker
image: gravitl/netmaker:v0.14.0 image: gravitl/netmaker:v0.14.1
volumes: volumes:
- dnsconfig:/root/config/dnsconfig - dnsconfig:/root/config/dnsconfig
- sqldata:/root/data - sqldata:/root/data
@ -35,20 +35,17 @@ services:
MQ_HOST: "mq" MQ_HOST: "mq"
HOST_NETWORK: "off" HOST_NETWORK: "off"
VERBOSITY: "1" VERBOSITY: "1"
PORT_FORWARD_SERVICES: "dns"
MANAGE_IPTABLES: "on" MANAGE_IPTABLES: "on"
PORT_FORWARD_SERVICES: "dns"
ports: ports:
- "51821-51830:51821-51830/udp" - "51821-51830:51821-51830/udp"
- "8081:8081"
netmaker-ui: netmaker-ui:
container_name: netmaker-ui container_name: netmaker-ui
depends_on: depends_on:
- netmaker - netmaker
image: gravitl/netmaker-ui:v0.14.0 image: gravitl/netmaker-ui:v0.14.1
links: links:
- "netmaker:api" - "netmaker:api"
ports:
- "8082:80"
environment: environment:
BACKEND_URL: "https://api.NETMAKER_BASE_DOMAIN" BACKEND_URL: "https://api.NETMAKER_BASE_DOMAIN"
restart: always restart: always
@ -65,7 +62,9 @@ services:
image: caddy:latest image: caddy:latest
container_name: caddy container_name: caddy
restart: unless-stopped restart: unless-stopped
network_mode: host # Wants ports 80 and 443! ports:
- "80:80"
- "443:443"
volumes: volumes:
- /root/Caddyfile:/etc/caddy/Caddyfile - /root/Caddyfile:/etc/caddy/Caddyfile
# - $PWD/site:/srv # you could also serve a static site in site folder # - $PWD/site:/srv # you could also serve a static site in site folder
@ -78,7 +77,6 @@ services:
container_name: mq container_name: mq
restart: unless-stopped restart: unless-stopped
ports: ports:
- "127.0.0.1:1883:1883"
- "8883:8883" - "8883:8883"
volumes: volumes:
- /root/mosquitto.conf:/mosquitto/config/mosquitto.conf - /root/mosquitto.conf:/mosquitto/config/mosquitto.conf

View file

@ -38,9 +38,6 @@ func nodeHandlers(r *mux.Router) {
func authenticate(response http.ResponseWriter, request *http.Request) { func authenticate(response http.ResponseWriter, request *http.Request) {
var params = mux.Vars(request)
networkname := params["network"]
var authRequest models.AuthParams var authRequest models.AuthParams
var result models.Node var result models.Node
var errorResponse = models.ErrorResponse{ var errorResponse = models.ErrorResponse{
@ -58,8 +55,8 @@ func authenticate(response http.ResponseWriter, request *http.Request) {
return return
} else { } else {
errorResponse.Code = http.StatusBadRequest errorResponse.Code = http.StatusBadRequest
if authRequest.MacAddress == "" { if authRequest.ID == "" {
errorResponse.Message = "W1R3: MacAddress can't be empty" errorResponse.Message = "W1R3: ID can't be empty"
returnErrorResponse(response, request, errorResponse) returnErrorResponse(response, request, errorResponse)
return return
} else if authRequest.Password == "" { } else if authRequest.Password == "" {
@ -67,22 +64,8 @@ func authenticate(response http.ResponseWriter, request *http.Request) {
returnErrorResponse(response, request, errorResponse) returnErrorResponse(response, request, errorResponse)
return return
} else { } else {
var err error
collection, err := database.FetchRecords(database.NODES_TABLE_NAME) result, err = logic.GetNodeByID(authRequest.ID)
if err != nil {
errorResponse.Code = http.StatusBadRequest
errorResponse.Message = err.Error()
returnErrorResponse(response, request, errorResponse)
return
}
for _, value := range collection {
if err := json.Unmarshal([]byte(value), &result); err != nil {
continue
}
if (result.ID == authRequest.ID || result.MacAddress == authRequest.MacAddress) && result.IsPending != "yes" && result.Network == networkname {
break
}
}
if err != nil { if err != nil {
errorResponse.Code = http.StatusBadRequest errorResponse.Code = http.StatusBadRequest
@ -109,10 +92,10 @@ func authenticate(response http.ResponseWriter, request *http.Request) {
var successResponse = models.SuccessResponse{ var successResponse = models.SuccessResponse{
Code: http.StatusOK, Code: http.StatusOK,
Message: "W1R3: Device " + authRequest.MacAddress + " Authorized", Message: "W1R3: Device " + authRequest.ID + " Authorized",
Response: models.SuccessfulLoginResponse{ Response: models.SuccessfulLoginResponse{
AuthToken: tokenString, AuthToken: tokenString,
MacAddress: authRequest.MacAddress, ID: authRequest.ID,
}, },
} }
successJSONResponse, jsonError := json.Marshal(successResponse) successJSONResponse, jsonError := json.Marshal(successResponse)

View file

@ -0,0 +1,39 @@
FROM gravitl/go-builder:latest as builder
# add glib support daemon manager
WORKDIR /app
COPY . .
ENV GO111MODULE=auto
RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 /usr/local/go/bin/go build -ldflags="-w -s" -o netclient-app netclient/main.go
WORKDIR /root/
RUN apk add --update git build-base libmnl-dev iptables
RUN git clone https://git.zx2c4.com/wireguard-go && \
cd wireguard-go && \
make && \
make install
ENV WITH_WGQUICK=yes
RUN git clone https://git.zx2c4.com/wireguard-tools && \
cd wireguard-tools && \
cd src && \
make && \
make install
FROM alpine:3.13.6
WORKDIR /root/
RUN apk add --no-cache --update bash libmnl gcompat iptables openresolv iproute2
COPY --from=builder /usr/bin/wireguard-go /usr/bin/wg* /usr/bin/
COPY --from=builder /app/netclient-app ./netclient
COPY --from=builder /app/scripts/netclient.sh .
RUN chmod 0755 netclient && chmod 0755 netclient.sh
ENV WG_QUICK_USERSPACE_IMPLEMENTATION=wireguard-go
ENTRYPOINT ["/bin/sh", "./netclient.sh"]

6
go.mod
View file

@ -10,13 +10,13 @@ require (
github.com/google/uuid v1.3.0 github.com/google/uuid v1.3.0
github.com/gorilla/handlers v1.5.1 github.com/gorilla/handlers v1.5.1
github.com/gorilla/mux v1.8.0 github.com/gorilla/mux v1.8.0
github.com/lib/pq v1.10.5 github.com/lib/pq v1.10.6
github.com/mattn/go-sqlite3 v1.14.10 github.com/mattn/go-sqlite3 v1.14.10
github.com/rqlite/gorqlite v0.0.0-20210514125552-08ff1e76b22f github.com/rqlite/gorqlite v0.0.0-20210514125552-08ff1e76b22f
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/stretchr/testify v1.7.1 github.com/stretchr/testify v1.7.1
github.com/txn2/txeh v1.3.0 github.com/txn2/txeh v1.3.0
github.com/urfave/cli/v2 v2.6.0 github.com/urfave/cli/v2 v2.8.0
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd
golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
@ -32,6 +32,7 @@ require (
require ( require (
filippo.io/edwards25519 v1.0.0-rc.1 filippo.io/edwards25519 v1.0.0-rc.1
fyne.io/fyne/v2 v2.1.4 fyne.io/fyne/v2 v2.1.4
github.com/cloverstd/tcping v0.1.1
github.com/guumaster/hostctl v1.1.2 github.com/guumaster/hostctl v1.1.2
github.com/kr/pretty v0.3.0 github.com/kr/pretty v0.3.0
github.com/posthog/posthog-go v0.0.0-20211028072449-93c17c49e2b0 github.com/posthog/posthog-go v0.0.0-20211028072449-93c17c49e2b0
@ -41,6 +42,7 @@ require (
require ( require (
cloud.google.com/go v0.34.0 // indirect cloud.google.com/go v0.34.0 // indirect
github.com/Microsoft/go-winio v0.4.14 // indirect github.com/Microsoft/go-winio v0.4.14 // indirect
github.com/antzucaro/matchr v0.0.0-20210222213004-b04723ef80f0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/docker/distribution v2.7.1+incompatible // indirect github.com/docker/distribution v2.7.1+incompatible // indirect

12
go.sum
View file

@ -14,11 +14,15 @@ github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAE
github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/antzucaro/matchr v0.0.0-20210222213004-b04723ef80f0 h1:R/qAiUxFT3mNgQaNqJe0IVznjKRNm23ohAIh9lgtlzc=
github.com/antzucaro/matchr v0.0.0-20210222213004-b04723ef80f0/go.mod h1:v3ZDlfVAL1OrkKHbGSFFK60k0/7hruHPDq2XMs9Gu6U=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloverstd/tcping v0.1.1 h1:3Yp9nvSDI7Z63zoVQDJzVk1PUczrF9tJoOrKGV30iOk=
github.com/cloverstd/tcping v0.1.1/go.mod h1:NYXTrTDwlwuOKQ0vwksUVUbIr0sxDDsf1J6aFpScCBo=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
@ -137,8 +141,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
github.com/lib/pq v1.10.5 h1:J+gdV2cUmX7ZqL2B0lFcW0m+egaHC2V3lpO8nWxyYiQ= github.com/lib/pq v1.10.6 h1:jbk+ZieJ0D7EVGJYpL9QTz7/YW6UHbmdnZWYyK5cdBs=
github.com/lib/pq v1.10.5/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lucor/goinfo v0.0.0-20210802170112-c078a2b0f08b/go.mod h1:PRq09yoB+Q2OJReAmwzKivcYyremnibWGbK7WfftHzc= github.com/lucor/goinfo v0.0.0-20210802170112-c078a2b0f08b/go.mod h1:PRq09yoB+Q2OJReAmwzKivcYyremnibWGbK7WfftHzc=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
@ -238,8 +242,8 @@ github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGr
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/urfave/cli/v2 v2.6.0 h1:yj2Drkflh8X/zUrkWlWlUjZYHyWN7WMmpVxyxXIUyv8= github.com/urfave/cli/v2 v2.8.0 h1:EZsAB20oRW4nHcB99TTL6PrXpBGIEujMEKdjwruY9KQ=
github.com/urfave/cli/v2 v2.6.0/go.mod h1:oDzoM7pVwz6wHn5ogWgFUU1s4VJayeQS+aEZDqXIEJs= github.com/urfave/cli/v2 v2.8.0/go.mod h1:TYFbtzt/azQoJOrGH5mDfZtS0jIkl/OeFwlRWPR9KRM=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c h1:3lbZUMbMiGUW/LMkfsEABsc5zNT9+b1CvsJx47JzJ8g= github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c h1:3lbZUMbMiGUW/LMkfsEABsc5zNT9+b1CvsJx47JzJ8g=

BIN
img/readme.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

View file

@ -680,7 +680,7 @@ func networkNodesUpdateAction(networkName string, action string) error {
fmt.Println("error in node address assignment!") fmt.Println("error in node address assignment!")
return err return err
} }
if action == models.NODE_UPDATE_KEY && node.IsStatic == "yes" { if action == models.NODE_UPDATE_KEY {
continue continue
} }
if node.Network == networkName { if node.Network == networkName {

View file

@ -80,7 +80,9 @@ func GetNodePeers(network *models.Network, nodeid string, excludeRelayed bool, i
} }
} }
// if udp hole punching is on, but port is still set to default (e.g. 51821), use the LocalListenPort // if udp hole punching is on, but port is still set to default (e.g. 51821), use the LocalListenPort
if node.UDPHolePunch == "yes" && node.IsStatic != "yes" && peer.ListenPort == node.ListenPort { // removing IsStatic check. IsStatic will now ONLY refer to endpoint.
//if node.UDPHolePunch == "yes" && node.IsStatic != "yes" && peer.ListenPort == node.ListenPort {
if node.UDPHolePunch == "yes" && peer.ListenPort == node.ListenPort {
peer.ListenPort = node.LocalListenPort peer.ListenPort = node.LocalListenPort
} }
if node.IsRelay == "yes" { // TODO, check if addressrange6 needs to be appended if node.IsRelay == "yes" { // TODO, check if addressrange6 needs to be appended

View file

@ -406,8 +406,7 @@ func isDeleteError(err error) bool {
} }
func checkNodeActions(node *models.Node) string { func checkNodeActions(node *models.Node) string {
if (node.Action == models.NODE_UPDATE_KEY) && if node.Action == models.NODE_UPDATE_KEY {
node.IsStatic != "yes" {
err := setWGKeyConfig(node) err := setWGKeyConfig(node)
if err != nil { if err != nil {
logger.Log(1, "unable to process reset keys request:", err.Error()) logger.Log(1, "unable to process reset keys request:", err.Error())

View file

@ -35,53 +35,54 @@ var seededRand *rand.Rand = rand.New(
// Node - struct for node model // Node - struct for node model
type Node struct { type Node struct {
ID string `json:"id,omitempty" bson:"id,omitempty" yaml:"id,omitempty" validate:"required,min=5"` 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"` Address string `json:"address" bson:"address" yaml:"address" validate:"omitempty,ipv4"`
Address6 string `json:"address6" bson:"address6" yaml:"address6" validate:"omitempty,ipv6"` Address6 string `json:"address6" bson:"address6" yaml:"address6" validate:"omitempty,ipv6"`
LocalAddress string `json:"localaddress" bson:"localaddress" yaml:"localaddress" validate:"omitempty,ip"` LocalAddress string `json:"localaddress" bson:"localaddress" yaml:"localaddress" validate:"omitempty,ip"`
Name string `json:"name" bson:"name" yaml:"name" validate:"omitempty,max=62,in_charset"` Name string `json:"name" bson:"name" yaml:"name" validate:"omitempty,max=62,in_charset"`
NetworkSettings Network `json:"networksettings" bson:"networksettings" yaml:"networksettings" validate:"-"` NetworkSettings Network `json:"networksettings" bson:"networksettings" yaml:"networksettings" validate:"-"`
ListenPort int32 `json:"listenport" bson:"listenport" yaml:"listenport" validate:"omitempty,numeric,min=1024,max=65535"` ListenPort int32 `json:"listenport" bson:"listenport" yaml:"listenport" validate:"omitempty,numeric,min=1024,max=65535"`
LocalListenPort int32 `json:"locallistenport" bson:"locallistenport" yaml:"locallistenport" validate:"numeric,min=0,max=65535"` LocalListenPort int32 `json:"locallistenport" bson:"locallistenport" yaml:"locallistenport" validate:"numeric,min=0,max=65535"`
PublicKey string `json:"publickey" bson:"publickey" yaml:"publickey" validate:"required,base64"` PublicKey string `json:"publickey" bson:"publickey" yaml:"publickey" validate:"required,base64"`
Endpoint string `json:"endpoint" bson:"endpoint" yaml:"endpoint" validate:"required,ip"` Endpoint string `json:"endpoint" bson:"endpoint" yaml:"endpoint" validate:"required,ip"`
PostUp string `json:"postup" bson:"postup" yaml:"postup"` PostUp string `json:"postup" bson:"postup" yaml:"postup"`
PostDown string `json:"postdown" bson:"postdown" yaml:"postdown"` PostDown string `json:"postdown" bson:"postdown" yaml:"postdown"`
AllowedIPs []string `json:"allowedips" bson:"allowedips" yaml:"allowedips"` AllowedIPs []string `json:"allowedips" bson:"allowedips" yaml:"allowedips"`
PersistentKeepalive int32 `json:"persistentkeepalive" bson:"persistentkeepalive" yaml:"persistentkeepalive" validate:"omitempty,numeric,max=1000"` PersistentKeepalive int32 `json:"persistentkeepalive" bson:"persistentkeepalive" yaml:"persistentkeepalive" validate:"omitempty,numeric,max=1000"`
IsHub string `json:"ishub" bson:"ishub" yaml:"ishub" validate:"checkyesorno"` IsHub string `json:"ishub" bson:"ishub" yaml:"ishub" validate:"checkyesorno"`
AccessKey string `json:"accesskey" bson:"accesskey" yaml:"accesskey"` AccessKey string `json:"accesskey" bson:"accesskey" yaml:"accesskey"`
Interface string `json:"interface" bson:"interface" yaml:"interface"` Interface string `json:"interface" bson:"interface" yaml:"interface"`
LastModified int64 `json:"lastmodified" bson:"lastmodified" yaml:"lastmodified"` LastModified int64 `json:"lastmodified" bson:"lastmodified" yaml:"lastmodified"`
ExpirationDateTime int64 `json:"expdatetime" bson:"expdatetime" yaml:"expdatetime"` ExpirationDateTime int64 `json:"expdatetime" bson:"expdatetime" yaml:"expdatetime"`
LastPeerUpdate int64 `json:"lastpeerupdate" bson:"lastpeerupdate" yaml:"lastpeerupdate"` LastPeerUpdate int64 `json:"lastpeerupdate" bson:"lastpeerupdate" yaml:"lastpeerupdate"`
LastCheckIn int64 `json:"lastcheckin" bson:"lastcheckin" yaml:"lastcheckin"` LastCheckIn int64 `json:"lastcheckin" bson:"lastcheckin" yaml:"lastcheckin"`
MacAddress string `json:"macaddress" bson:"macaddress" yaml:"macaddress" validate:"macaddress_unique"` MacAddress string `json:"macaddress" bson:"macaddress" yaml:"macaddress" validate:"macaddress_unique"`
Password string `json:"password" bson:"password" yaml:"password" validate:"required,min=6"` Password string `json:"password" bson:"password" yaml:"password" validate:"required,min=6"`
Network string `json:"network" bson:"network" yaml:"network" validate:"network_exists"` Network string `json:"network" bson:"network" yaml:"network" validate:"network_exists"`
IsRelayed string `json:"isrelayed" bson:"isrelayed" yaml:"isrelayed"` IsRelayed string `json:"isrelayed" bson:"isrelayed" yaml:"isrelayed"`
IsPending string `json:"ispending" bson:"ispending" yaml:"ispending"` IsPending string `json:"ispending" bson:"ispending" yaml:"ispending"`
IsRelay string `json:"isrelay" bson:"isrelay" yaml:"isrelay" validate:"checkyesorno"` IsRelay string `json:"isrelay" bson:"isrelay" yaml:"isrelay" validate:"checkyesorno"`
IsDocker string `json:"isdocker" bson:"isdocker" yaml:"isdocker" validate:"checkyesorno"` IsDocker string `json:"isdocker" bson:"isdocker" yaml:"isdocker" validate:"checkyesorno"`
IsK8S string `json:"isk8s" bson:"isk8s" yaml:"isk8s" validate:"checkyesorno"` IsK8S string `json:"isk8s" bson:"isk8s" yaml:"isk8s" validate:"checkyesorno"`
IsEgressGateway string `json:"isegressgateway" bson:"isegressgateway" yaml:"isegressgateway"` IsEgressGateway string `json:"isegressgateway" bson:"isegressgateway" yaml:"isegressgateway"`
IsIngressGateway string `json:"isingressgateway" bson:"isingressgateway" yaml:"isingressgateway"` IsIngressGateway string `json:"isingressgateway" bson:"isingressgateway" yaml:"isingressgateway"`
EgressGatewayRanges []string `json:"egressgatewayranges" bson:"egressgatewayranges" yaml:"egressgatewayranges"` EgressGatewayRanges []string `json:"egressgatewayranges" bson:"egressgatewayranges" yaml:"egressgatewayranges"`
RelayAddrs []string `json:"relayaddrs" bson:"relayaddrs" yaml:"relayaddrs"` RelayAddrs []string `json:"relayaddrs" bson:"relayaddrs" yaml:"relayaddrs"`
IngressGatewayRange string `json:"ingressgatewayrange" bson:"ingressgatewayrange" yaml:"ingressgatewayrange"` IngressGatewayRange string `json:"ingressgatewayrange" bson:"ingressgatewayrange" yaml:"ingressgatewayrange"`
IsStatic string `json:"isstatic" bson:"isstatic" yaml:"isstatic" validate:"checkyesorno"` // IsStatic - refers to if the Endpoint is set manually or dynamically
UDPHolePunch string `json:"udpholepunch" bson:"udpholepunch" yaml:"udpholepunch" validate:"checkyesorno"` IsStatic string `json:"isstatic" bson:"isstatic" yaml:"isstatic" validate:"checkyesorno"`
DNSOn string `json:"dnson" bson:"dnson" yaml:"dnson" validate:"checkyesorno"` UDPHolePunch string `json:"udpholepunch" bson:"udpholepunch" yaml:"udpholepunch" validate:"checkyesorno"`
IsServer string `json:"isserver" bson:"isserver" yaml:"isserver" validate:"checkyesorno"` DNSOn string `json:"dnson" bson:"dnson" yaml:"dnson" validate:"checkyesorno"`
Action string `json:"action" bson:"action" yaml:"action"` IsServer string `json:"isserver" bson:"isserver" yaml:"isserver" validate:"checkyesorno"`
IsLocal string `json:"islocal" bson:"islocal" yaml:"islocal" validate:"checkyesorno"` Action string `json:"action" bson:"action" yaml:"action"`
LocalRange string `json:"localrange" bson:"localrange" yaml:"localrange"` IsLocal string `json:"islocal" bson:"islocal" yaml:"islocal" validate:"checkyesorno"`
IPForwarding string `json:"ipforwarding" bson:"ipforwarding" yaml:"ipforwarding" validate:"checkyesorno"` LocalRange string `json:"localrange" bson:"localrange" yaml:"localrange"`
OS string `json:"os" bson:"os" yaml:"os"` IPForwarding string `json:"ipforwarding" bson:"ipforwarding" yaml:"ipforwarding" validate:"checkyesorno"`
MTU int32 `json:"mtu" bson:"mtu" yaml:"mtu"` OS string `json:"os" bson:"os" yaml:"os"`
Version string `json:"version" bson:"version" yaml:"version"` MTU int32 `json:"mtu" bson:"mtu" yaml:"mtu"`
Server string `json:"server" bson:"server" yaml:"server"` Version string `json:"version" bson:"version" yaml:"version"`
TrafficKeys TrafficKeys `json:"traffickeys" bson:"traffickeys" yaml:"traffickeys"` Server string `json:"server" bson:"server" yaml:"server"`
TrafficKeys TrafficKeys `json:"traffickeys" bson:"traffickeys" yaml:"traffickeys"`
} }
// NodesArray - used for node sorting // NodesArray - used for node sorting
@ -255,10 +256,10 @@ func (node *Node) SetDefaultName() {
func (newNode *Node) Fill(currentNode *Node) { func (newNode *Node) Fill(currentNode *Node) {
newNode.ID = currentNode.ID newNode.ID = currentNode.ID
if newNode.Address == "" && newNode.IsStatic != "yes" { if newNode.Address == "" {
newNode.Address = currentNode.Address newNode.Address = currentNode.Address
} }
if newNode.Address6 == "" && newNode.IsStatic != "yes" { if newNode.Address6 == "" {
newNode.Address6 = currentNode.Address6 newNode.Address6 = currentNode.Address6
} }
if newNode.LocalAddress == "" { if newNode.LocalAddress == "" {
@ -267,16 +268,16 @@ func (newNode *Node) Fill(currentNode *Node) {
if newNode.Name == "" { if newNode.Name == "" {
newNode.Name = currentNode.Name newNode.Name = currentNode.Name
} }
if newNode.ListenPort == 0 && newNode.IsStatic != "yes" { if newNode.ListenPort == 0 {
newNode.ListenPort = currentNode.ListenPort newNode.ListenPort = currentNode.ListenPort
} }
if newNode.LocalListenPort == 0 && newNode.IsStatic != "yes" { if newNode.LocalListenPort == 0 {
newNode.LocalListenPort = currentNode.LocalListenPort newNode.LocalListenPort = currentNode.LocalListenPort
} }
if newNode.PublicKey == "" && newNode.IsStatic != "yes" { if newNode.PublicKey == "" {
newNode.PublicKey = currentNode.PublicKey newNode.PublicKey = currentNode.PublicKey
} }
if newNode.Endpoint == "" && newNode.IsStatic != "yes" { if newNode.Endpoint == "" {
newNode.Endpoint = currentNode.Endpoint newNode.Endpoint = currentNode.Endpoint
} }
if newNode.PostUp == "" { if newNode.PostUp == "" {

View file

@ -61,8 +61,8 @@ type Claims struct {
// SuccessfulLoginResponse is struct to send the request response // SuccessfulLoginResponse is struct to send the request response
type SuccessfulLoginResponse struct { type SuccessfulLoginResponse struct {
MacAddress string ID string
AuthToken string AuthToken string
} }
// ErrorResponse is struct for error // ErrorResponse is struct for error

View file

@ -1,8 +1,6 @@
package cli_options package cli_options
import ( import (
"errors"
"github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/logger"
"github.com/gravitl/netmaker/netclient/command" "github.com/gravitl/netmaker/netclient/command"
"github.com/gravitl/netmaker/netclient/config" "github.com/gravitl/netmaker/netclient/config"
@ -22,10 +20,6 @@ func GetCommands(cliFlags []cli.Flag) []*cli.Command {
if err != nil { if err != nil {
return err return err
} }
if cfg.Network == "all" {
err = errors.New("no network provided")
return err
}
err = command.Join(&cfg, pvtKey) err = command.Join(&cfg, pvtKey)
return err return err
}, },

View file

@ -10,6 +10,7 @@ import (
"fmt" "fmt"
"log" "log"
"os" "os"
"sync"
"github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/logger"
"github.com/gravitl/netmaker/models" "github.com/gravitl/netmaker/models"
@ -18,6 +19,10 @@ import (
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
) )
var (
configLock sync.Mutex
)
// ClientConfig - struct for dealing with client configuration // ClientConfig - struct for dealing with client configuration
type ClientConfig struct { type ClientConfig struct {
Server ServerConfig `yaml:"server"` Server ServerConfig `yaml:"server"`
@ -52,6 +57,8 @@ type RegisterResponse struct {
// Write - writes the config of a client to disk // Write - writes the config of a client to disk
func Write(config *ClientConfig, network string) error { func Write(config *ClientConfig, network string) error {
configLock.Lock()
defer configLock.Unlock()
if network == "" { if network == "" {
err := errors.New("no network provided - exiting") err := errors.New("no network provided - exiting")
return err return err
@ -140,7 +147,7 @@ func ModConfig(node *models.Node) error {
return Write(&modconfig, network) return Write(&modconfig, network)
} }
// ModConfig - overwrites the node inside client config on disk // SaveBackup - saves a backup file of a given network
func SaveBackup(network string) error { func SaveBackup(network string) error {
var configPath = ncutils.GetNetclientPathSpecific() + "netconfig-" + network var configPath = ncutils.GetNetclientPathSpecific() + "netconfig-" + network

View file

@ -42,35 +42,36 @@ type cachedMessage struct {
// Daemon runs netclient daemon from command line // Daemon runs netclient daemon from command line
func Daemon() error { func Daemon() error {
serverSet := make(map[string]config.ClientConfig) serverSet := make(map[string]bool)
// == initial pull of all networks == // == initial pull of all networks ==
networks, _ := ncutils.GetSystemNetworks() networks, _ := ncutils.GetSystemNetworks()
if len(networks) == 0 { if len(networks) == 0 {
return errors.New("no networks") return errors.New("no networks")
} }
for _, network := range networks { pubNetworks = append(pubNetworks, networks...)
logger.Log(3, "initializing network", network)
cfg := config.ClientConfig{}
cfg.Network = network
cfg.ReadConfig()
serverSet[cfg.Server.Server] = cfg
if err := wireguard.ApplyConf(&cfg.Node, cfg.Node.Interface, ncutils.GetNetclientPathSpecific()+cfg.Node.Interface+".conf"); err != nil {
logger.Log(0, "failed to start ", cfg.Node.Interface, "wg interface", err.Error())
}
//initialPull(cfg.Network)
}
// set ipforwarding on startup // set ipforwarding on startup
err := local.SetIPForwarding() err := local.SetIPForwarding()
if err != nil { if err != nil {
logger.Log(0, err.Error()) logger.Log(0, err.Error())
} }
// == subscribe to all nodes for each on machine == for _, network := range networks {
for server, config := range serverSet { logger.Log(3, "initializing network", network)
logger.Log(1, "started daemon for server ", server) cfg := config.ClientConfig{}
ctx, cancel := context.WithCancel(context.Background()) cfg.Network = network
networkcontext.Store(server, cancel) cfg.ReadConfig()
go messageQueue(ctx, &config) if err := wireguard.ApplyConf(&cfg.Node, cfg.Node.Interface, ncutils.GetNetclientPathSpecific()+cfg.Node.Interface+".conf"); err != nil {
logger.Log(0, "failed to start ", cfg.Node.Interface, "wg interface", err.Error())
}
server := cfg.Server.Server
if !serverSet[server] {
// == subscribe to all nodes for each on machine ==
serverSet[server] = true
logger.Log(1, "started daemon for server ", server)
ctx, cancel := context.WithCancel(context.Background())
networkcontext.Store(server, cancel)
go messageQueue(ctx, &cfg)
}
} }
// == add waitgroup and cancel for checkin routine == // == add waitgroup and cancel for checkin routine ==
@ -167,7 +168,11 @@ func unsubscribeNode(client mqtt.Client, nodeCfg *config.ClientConfig) {
// the client should subscribe to ALL nodes that exist on server locally // the client should subscribe to ALL nodes that exist on server locally
func messageQueue(ctx context.Context, cfg *config.ClientConfig) { func messageQueue(ctx context.Context, cfg *config.ClientConfig) {
logger.Log(0, "netclient daemon started for server: ", cfg.Server.Server) logger.Log(0, "netclient daemon started for server: ", cfg.Server.Server)
client := setupMQTT(cfg, false) client, err := setupMQTT(cfg, false)
if err != nil {
logger.Log(0, "unable to connect to broker", err.Error())
return
}
defer client.Disconnect(250) defer client.Disconnect(250)
<-ctx.Done() <-ctx.Done()
logger.Log(0, "shutting down daemon for server ", cfg.Server.Server) logger.Log(0, "shutting down daemon for server ", cfg.Server.Server)
@ -201,7 +206,7 @@ func NewTLSConfig(server string) *tls.Config {
// setupMQTT creates a connection to broker and returns client // setupMQTT creates a connection to broker and returns client
// this function is primarily used to create a connection to publish to the broker // this function is primarily used to create a connection to publish to the broker
func setupMQTT(cfg *config.ClientConfig, publish bool) mqtt.Client { func setupMQTT(cfg *config.ClientConfig, publish bool) (mqtt.Client, error) {
opts := mqtt.NewClientOptions() opts := mqtt.NewClientOptions()
server := cfg.Server.Server server := cfg.Server.Server
opts.AddBroker("ssl://" + server + ":8883") // TODO get the appropriate port of the comms mq server opts.AddBroker("ssl://" + server + ":8883") // TODO get the appropriate port of the comms mq server
@ -242,6 +247,9 @@ func setupMQTT(cfg *config.ClientConfig, publish bool) mqtt.Client {
} else { } else {
err = token.Error() err = token.Error()
} }
if err := checkBroker(cfg.Server.Server); err != nil {
return nil, err
}
logger.Log(0, "could not connect to broker", cfg.Server.Server, err.Error()) logger.Log(0, "could not connect to broker", cfg.Server.Server, err.Error())
if strings.Contains(err.Error(), "connectex") || strings.Contains(err.Error(), "connect timeout") { if strings.Contains(err.Error(), "connectex") || strings.Contains(err.Error(), "connect timeout") {
logger.Log(0, "connection issue detected.. attempt connection with new certs") logger.Log(0, "connection issue detected.. attempt connection with new certs")
@ -256,7 +264,7 @@ func setupMQTT(cfg *config.ClientConfig, publish bool) mqtt.Client {
daemon.Restart() daemon.Restart()
} }
} }
return client return client, nil
} }
// publishes a message to server to update peers on this peer's behalf // publishes a message to server to update peers on this peer's behalf

View file

@ -42,6 +42,11 @@ func JoinNetwork(cfg *config.ClientConfig, privateKey string) error {
if cfg.Node.Password == "" { if cfg.Node.Password == "" {
cfg.Node.Password = logic.GenKey() cfg.Node.Password = logic.GenKey()
} }
manualPort := false
if cfg.Node.ListenPort != 0 {
cfg.Node.UDPHolePunch = "no"
manualPort = true
}
var trafficPubKey, trafficPrivKey, errT = box.GenerateKey(rand.Reader) // generate traffic keys var trafficPubKey, trafficPrivKey, errT = box.GenerateKey(rand.Reader) // generate traffic keys
if errT != nil { if errT != nil {
return errT return errT
@ -164,10 +169,11 @@ func JoinNetwork(cfg *config.ClientConfig, privateKey string) error {
} }
} }
logger.Log(1, "node created on remote server...updating configs") logger.Log(1, "node created on remote server...updating configs")
// keep track of the old listenport value
oldListenPort := node.ListenPort
cfg.Node = node cfg.Node = node
setListenPort(oldListenPort, cfg) logger.Log(1, "turn on UDP hole punching (dynamic port setting)? "+cfg.Node.UDPHolePunch)
if !manualPort && (cfg.Node.UDPHolePunch == "no") {
setListenPort(cfg)
}
err = config.ModConfig(&cfg.Node) err = config.ModConfig(&cfg.Node)
if err != nil { if err != nil {
return err return err
@ -215,22 +221,19 @@ func formatName(node models.Node) string {
return node.Name return node.Name
} }
func setListenPort(oldListenPort int32, cfg *config.ClientConfig) { func setListenPort(cfg *config.ClientConfig) {
// keep track of the returned listenport value // keep track of the returned listenport value
newListenPort := cfg.Node.ListenPort newListenPort := cfg.Node.ListenPort
var errN error
// get free port based on returned default listen port
cfg.Node.ListenPort, errN = ncutils.GetFreePort(cfg.Node.ListenPort)
if errN != nil {
cfg.Node.ListenPort = newListenPort
logger.Log(1, "Error retrieving port: ", errN.Error())
}
if newListenPort != oldListenPort { // if newListenPort has been modified to find an available port, publish to server
var errN error if cfg.Node.ListenPort != newListenPort {
// get free port based on returned default listen port PublishNodeUpdate(cfg)
cfg.Node.ListenPort, errN = ncutils.GetFreePort(cfg.Node.ListenPort)
if errN != nil {
cfg.Node.ListenPort = newListenPort
logger.Log(1, "Error retrieving port: ", errN.Error())
}
// if newListenPort has been modified to find an available port, publish to server
if cfg.Node.ListenPort != newListenPort {
PublishNodeUpdate(cfg)
}
} }
} }

View file

@ -5,10 +5,12 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"net"
"os" "os"
"sync" "sync"
"time" "time"
"github.com/cloverstd/tcping/ping"
"github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/logger"
"github.com/gravitl/netmaker/netclient/auth" "github.com/gravitl/netmaker/netclient/auth"
"github.com/gravitl/netmaker/netclient/config" "github.com/gravitl/netmaker/netclient/config"
@ -16,6 +18,9 @@ import (
"github.com/gravitl/netmaker/tls" "github.com/gravitl/netmaker/tls"
) )
// pubNetworks hold the currently publishable networks
var pubNetworks []string
// 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 // if there are no updates, simply "pings" the server as a checkin
func Checkin(ctx context.Context, wg *sync.WaitGroup) { func Checkin(ctx context.Context, wg *sync.WaitGroup) {
@ -27,13 +32,7 @@ func Checkin(ctx context.Context, wg *sync.WaitGroup) {
return return
//delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ?? //delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ??
case <-time.After(time.Second * 60): case <-time.After(time.Second * 60):
// logger.Log(0, "Checkin running") for _, network := range pubNetworks {
//read latest config
networks, err := ncutils.GetSystemNetworks()
if err != nil {
return
}
for _, network := range networks {
var nodeCfg config.ClientConfig var nodeCfg config.ClientConfig
nodeCfg.Network = network nodeCfg.Network = network
nodeCfg.ReadConfig() nodeCfg.ReadConfig()
@ -109,7 +108,7 @@ func Hello(nodeCfg *config.ClientConfig) {
logger.Log(0, "could not run pull on "+nodeCfg.Node.Network+", error: "+err.Error()) logger.Log(0, "could not run pull on "+nodeCfg.Node.Network+", error: "+err.Error())
} }
} }
logger.Log(3, "server checkin complete") logger.Log(3, "checkin for", nodeCfg.Network, "complete")
} }
// node cfg is required in order to fetch the traffic keys of that node for encryption // node cfg is required in order to fetch the traffic keys of that node for encryption
@ -124,7 +123,10 @@ func publish(nodeCfg *config.ClientConfig, dest string, msg []byte, qos byte) er
return err return err
} }
client := setupMQTT(nodeCfg, true) client, err := setupMQTT(nodeCfg, true)
if err != nil {
return fmt.Errorf("mq setup error %w", err)
}
defer client.Disconnect(250) defer client.Disconnect(250)
encrypted, err := ncutils.Chunk(msg, serverPubKey, trafficPrivKey) encrypted, err := ncutils.Chunk(msg, serverPubKey, trafficPrivKey)
if err != nil { if err != nil {
@ -140,7 +142,7 @@ func publish(nodeCfg *config.ClientConfig, dest string, msg []byte, qos byte) er
err = token.Error() err = token.Error()
} }
if err != nil { if err != nil {
return token.Error() return err
} }
} }
return nil return nil
@ -161,3 +163,25 @@ func checkCertExpiry(cfg *config.ClientConfig) error {
} }
return nil return nil
} }
func checkBroker(broker string) error {
_, err := net.LookupIP(broker)
if err != nil {
return errors.New("nslookup failed for broker ... check dns records")
}
pinger := ping.NewTCPing()
pinger.SetTarget(&ping.Target{
Protocol: ping.TCP,
Host: broker,
Port: 8883,
Counter: 3,
Interval: 1 * time.Second,
Timeout: 2 * time.Second,
})
pingerDone := pinger.Start()
<-pingerDone
if pinger.Result().SuccessCounter == 0 {
return errors.New("unable to connect to broker port ... check netmaker server and firewalls")
}
return nil
}

View file

@ -67,6 +67,7 @@ func GetSingleNetworkView(network string) fyne.CanvasObject {
LoadingNotify() LoadingNotify()
nets, err := functions.List(network) nets, err := functions.List(network)
if err != nil || len(nets) < 1 { if err != nil || len(nets) < 1 {
ClearNotification()
return container.NewCenter(widget.NewLabel("No data retrieved.")) return container.NewCenter(widget.NewLabel("No data retrieved."))
} }
var nodecfg config.ClientConfig var nodecfg config.ClientConfig
@ -79,10 +80,10 @@ func GetSingleNetworkView(network string) fyne.CanvasObject {
privateAddr6 := nodecfg.Node.Address6 privateAddr6 := nodecfg.Node.Address6
endpoint := nodecfg.Node.Endpoint endpoint := nodecfg.Node.Endpoint
health := " (HEALTHY)" health := " (HEALTHY)"
if time.Now().After(lastCheckInTime.Add(time.Minute * 5)) { if time.Now().After(lastCheckInTime.Add(time.Minute * 30)) {
health = " (WARNING)"
} else if time.Now().After(lastCheckInTime.Add(time.Minute * 30)) {
health = " (ERROR)" health = " (ERROR)"
} else if time.Now().After(lastCheckInTime.Add(time.Minute * 5)) {
health = " (WARNING)"
} }
lastCheckIn += health lastCheckIn += health
version := nodecfg.Node.Version version := nodecfg.Node.Version

View file

@ -1,149 +0,0 @@
package local
import (
"fmt"
"net"
"os"
"strings"
"time"
//"github.com/davecgh/go-spew/spew"
"log"
"os/exec"
"github.com/gravitl/netmaker/logger"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/netclient/ncutils"
)
const DNS_UNREACHABLE_ERROR = "nameserver unreachable"
// SetDNSWithRetry - Attempt setting dns, if it fails return true (to reset dns)
func SetDNSWithRetry(node models.Node, address string) bool {
var reachable bool
if !hasPrereqs() {
return true
}
for counter := 0; !reachable && counter < 5; counter++ {
reachable = IsDNSReachable(address)
time.Sleep(time.Second << 1)
}
if !reachable {
logger.Log(0, "not setting dns (server unreachable), will try again later: "+address)
return true
} else if err := UpdateDNS(node.Interface, node.Network, address); err != nil {
logger.Log(0, "error applying dns"+err.Error())
} else if IsDNSWorking(node.Network, address) {
return true
}
resetDNS()
return false
}
func resetDNS() {
ncutils.RunCmd("systemctl restart systemd-resolved", true)
}
// SetDNS - sets the DNS of a local machine
func SetDNS(nameserver string) error {
bytes, err := os.ReadFile("/etc/resolv.conf")
if err != nil {
return err
}
resolvstring := string(bytes)
// //check whether s contains substring text
hasdns := strings.Contains(resolvstring, nameserver)
if hasdns {
return nil
}
resolv, err := os.OpenFile("/etc/resolv.conf", os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
return err
}
defer resolv.Close()
_, err = resolv.WriteString("nameserver " + nameserver + "\n")
return err
}
func hasPrereqs() bool {
if !ncutils.IsLinux() {
return false
}
_, err := exec.LookPath("resolvectl")
return err == nil
}
// UpdateDNS - updates local DNS of client
func UpdateDNS(ifacename string, network string, nameserver string) error {
if !ncutils.IsLinux() {
return nil
}
if ifacename == "" {
return fmt.Errorf("cannot set dns: interface name is blank")
}
if network == "" {
return fmt.Errorf("cannot set dns: network name is blank")
}
if nameserver == "" {
return fmt.Errorf("cannot set dns: nameserver is blank")
}
if !IsDNSReachable(nameserver) {
return fmt.Errorf(DNS_UNREACHABLE_ERROR + " : " + nameserver + ":53")
}
_, err := exec.LookPath("resolvectl")
if err != nil {
log.Println(err)
log.Println("WARNING: resolvectl not present. Unable to set dns. Install resolvectl or run manually.")
} else {
_, err = ncutils.RunCmd("resolvectl domain "+ifacename+" ~"+network, true)
if err != nil {
log.Println("WARNING: Error encountered setting domain on dns. Aborted setting dns.")
} else {
_, err = ncutils.RunCmd("resolvectl default-route "+ifacename+" false", true)
if err != nil {
log.Println("WARNING: Error encountered setting default-route on dns. Aborted setting dns.")
} else {
_, err = ncutils.RunCmd("resolvectl dns "+ifacename+" "+nameserver, true)
if err != nil {
log.Println("WARNING: Error encountered running resolvectl dns " + ifacename + " " + nameserver)
}
}
}
}
return err
}
// IsDNSReachable - checks if nameserver is reachable
func IsDNSReachable(nameserver string) bool {
port := "53"
protocols := [2]string{"tcp", "udp"}
for _, proto := range protocols {
timeout := time.Second
conn, err := net.DialTimeout(proto, net.JoinHostPort(nameserver, port), timeout)
if err != nil {
return false
}
if conn != nil {
defer conn.Close()
} else {
return false
}
}
return true
}
// IsDNSWorking - checks if record is returned by correct nameserver
func IsDNSWorking(network string, nameserver string) bool {
var isworking bool
servers, err := net.LookupNS("netmaker" + "." + network)
if err != nil {
return isworking
}
for _, ns := range servers {
if strings.Contains(ns.Host, nameserver) {
isworking = true
}
}
return isworking
}

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity <assemblyIdentity
version="0.14.0.0" version="0.14.1.0"
processorArchitecture="*" processorArchitecture="*"
name="netclient.exe" name="netclient.exe"
type="win32" type="win32"

View file

@ -3,13 +3,13 @@
"FileVersion": { "FileVersion": {
"Major": 0, "Major": 0,
"Minor": 14, "Minor": 14,
"Patch": 0, "Patch": 1,
"Build": 0 "Build": 0
}, },
"ProductVersion": { "ProductVersion": {
"Major": 0, "Major": 0,
"Minor": 14, "Minor": 14,
"Patch": 0, "Patch": 1,
"Build": 0 "Build": 0
}, },
"FileFlagsMask": "3f", "FileFlagsMask": "3f",
@ -29,7 +29,7 @@
"OriginalFilename": "", "OriginalFilename": "",
"PrivateBuild": "", "PrivateBuild": "",
"ProductName": "Netclient", "ProductName": "Netclient",
"ProductVersion": "v0.14.0.0", "ProductVersion": "v0.14.1.0",
"SpecialBuild": "" "SpecialBuild": ""
}, },
"VarFileInfo": { "VarFileInfo": {

View file

@ -40,9 +40,14 @@ func SetPeers(iface string, node *models.Node, peers []wgtypes.PeerConfig) error
return err return err
} }
for _, peer := range peers { for _, peer := range peers {
// make sure peer has AllowedIP's before comparison
hasPeerIP := len(peer.AllowedIPs) > 0
for _, currentPeer := range devicePeers { for _, currentPeer := range devicePeers {
if currentPeer.AllowedIPs[0].String() == peer.AllowedIPs[0].String() && // make sure currenPeer has AllowedIP's before comparison
hascurrentPeerIP := len(currentPeer.AllowedIPs) > 0
if hasPeerIP && hascurrentPeerIP &&
currentPeer.AllowedIPs[0].String() == peer.AllowedIPs[0].String() &&
currentPeer.PublicKey.String() != peer.PublicKey.String() { currentPeer.PublicKey.String() != peer.PublicKey.String() {
_, err := ncutils.RunCmd("wg set "+iface+" peer "+currentPeer.PublicKey.String()+" remove", true) _, err := ncutils.RunCmd("wg set "+iface+" peer "+currentPeer.PublicKey.String()+" remove", true)
if err != nil { if err != nil {
@ -54,7 +59,7 @@ func SetPeers(iface string, node *models.Node, peers []wgtypes.PeerConfig) error
var allowedips string var allowedips string
var iparr []string var iparr []string
for _, ipaddr := range peer.AllowedIPs { for _, ipaddr := range peer.AllowedIPs {
if len(peer.AllowedIPs) > 0 && (&ipaddr) != nil { if hasPeerIP && (&ipaddr) != nil {
iparr = append(iparr, ipaddr.String()) iparr = append(iparr, ipaddr.String())
} }
} }
@ -85,7 +90,9 @@ func SetPeers(iface string, node *models.Node, peers []wgtypes.PeerConfig) error
shouldDelete := true shouldDelete := true
if peers != nil && len(peers) > 0 { if peers != nil && len(peers) > 0 {
for _, peer := range peers { for _, peer := range peers {
if peer.AllowedIPs[0].String() == currentPeer.AllowedIPs[0].String() {
if len(peer.AllowedIPs) > 0 && len(currentPeer.AllowedIPs) > 0 &&
peer.AllowedIPs[0].String() == currentPeer.AllowedIPs[0].String() {
shouldDelete = false shouldDelete = false
} }
// re-check this if logic is not working, added in case of allowedips not working // re-check this if logic is not working, added in case of allowedips not working
@ -238,7 +245,7 @@ func SetWGConfig(network string, peerupdate bool, peers []wgtypes.PeerConfig) er
if err != nil { if err != nil {
return err return err
} }
servercfg := cfg.Server
nodecfg := cfg.Node nodecfg := cfg.Node
privkey, err := RetrievePrivKey(network) privkey, err := RetrievePrivKey(network)
@ -260,9 +267,7 @@ func SetWGConfig(network string, peerupdate bool, peers []wgtypes.PeerConfig) er
} else { } else {
err = InitWireguard(&nodecfg, privkey, peers, false) err = InitWireguard(&nodecfg, privkey, peers, false)
} }
if nodecfg.DNSOn == "yes" {
_ = local.UpdateDNS(nodecfg.Interface, nodecfg.Network, servercfg.CoreDNSAddr)
}
return err return err
} }

View file

@ -40,8 +40,7 @@ func ApplyWithoutWGQuick(node *models.Node, ifacename string, confPath string) e
nodeport := int(node.ListenPort) nodeport := int(node.ListenPort)
if node.UDPHolePunch == "yes" && if node.UDPHolePunch == "yes" &&
node.IsServer == "no" && node.IsServer == "no" &&
node.IsIngressGateway != "yes" && node.IsIngressGateway != "yes" {
node.IsStatic != "yes" {
conf = wgtypes.Config{ conf = wgtypes.Config{
PrivateKey: &key, PrivateKey: &key,
} }