Browse Source

Merge remote-tracking branch 'origin/develop' into feature_v0.10.0_serverPings

Matthew R Kasun 3 years ago
parent
commit
20569ee8ec

+ 9 - 0
Dockerfile-builder

@@ -0,0 +1,9 @@
+#first stage - builder
+FROM golang:1.17
+ARG version
+WORKDIR /app
+COPY . .
+ENV GO111MODULE=auto
+
+# RUN GOOS=linux CGO_ENABLED=1 go build -tags debug -ldflags="-s -X 'main.version=$version'" -o netmaker main.go
+RUN GOOS=linux CGO_ENABLED=1 go build -ldflags="-s -X 'main.version=$version'" -o netmaker main.go

+ 9 - 5
compose/docker-compose.contained.yml

@@ -10,8 +10,12 @@ services:
       - sqldata:/root/data
     cap_add: 
       - NET_ADMIN
+      - NET_RAW
+      - SYS_MODULE
+    sysctls:
+      - net.ipv4.ip_forward=1
+      - net.ipv4.conf.all.src_valid_mark=1
     restart: always
-    privileged: true
     environment:
       SERVER_HOST: "SERVER_PUBLIC_IP"
       SERVER_API_CONN_STRING: "api.NETMAKER_BASE_DOMAIN:443"
@@ -25,11 +29,14 @@ services:
       GRPC_PORT: "50051"
       CLIENT_MODE: "on"
       MASTER_KEY: "REPLACE_MASTER_KEY"
-      SERVER_GRPC_WIREGUARD: "off"
       CORS_ALLOWED_ORIGIN: "*"
       DISPLAY_KEYS: "on"
       DATABASE: "sqlite"
       NODE_ID: "netmaker-server-1"
+      HOST_NETWORK: "off"
+      MANAGE_IPTABLES: "on"
+      PORT_FORWARD_SERVICES: "dns"
+      VERBOSITY: "1"
     ports:
       - "51821-51830:51821-51830/udp"
       - "8081:8081"
@@ -53,9 +60,6 @@ services:
     command: -conf /root/dnsconfig/Corefile
     container_name: coredns
     restart: always
-    ports:
-      - "COREDNS_IP:53:53/udp"
-      - "COREDNS_IP:53:53/tcp"
     volumes:
       - dnsconfig:/root/dnsconfig
   caddy:

+ 12 - 11
compose/docker-compose.hostnetwork.yml

@@ -5,19 +5,16 @@ services:
     container_name: netmaker
     image: gravitl/netmaker:v0.9.4
     volumes:
-      - /var/run/dbus/system_bus_socket:/var/run/dbus/system_bus_socket
-      - /run/systemd/system:/run/systemd/system
-      - /etc/systemd/system:/etc/systemd/system
-      - /sys/fs/cgroup:/sys/fs/cgroup
-      - /usr/bin/wg:/usr/bin/wg
       - dnsconfig:/root/config/dnsconfig
+      - /usr/bin/wg:/usr/bin/wg
       - sqldata:/root/data
-    cap_add: 
+      - /run/xtables.lock:/run/xtables.lock
+    cap_add:
       - NET_ADMIN
-      - SYS_ADMIN
-    restart: always
+      - NET_RAW
+      - SYS_MODULE
     network_mode: host
-    privileged: true
+    restart: always
     environment:
       SERVER_HOST: "SERVER_PUBLIC_IP"
       SERVER_API_CONN_STRING: "api.NETMAKER_BASE_DOMAIN:443"
@@ -35,7 +32,11 @@ services:
       CORS_ALLOWED_ORIGIN: "*"
       DISPLAY_KEYS: "on"
       DATABASE: "sqlite"
+      HOST_NETWORK: "on"
       NODE_ID: "netmaker-server-1"
+      MANAGE_IPTABLES: "on"
+      PORT_FORWARD_SERVICES: ""
+      VERBOSITY: "1"
   netmaker-ui:
     container_name: netmaker-ui
     depends_on:
@@ -56,8 +57,8 @@ services:
     container_name: coredns
     restart: always
     ports:
-      - "COREDNS_IP:53:53/udp"
-      - "COREDNS_IP:53:53/tcp"
+      - "53053:53/udp"
+      - "53053:53/tcp"
     volumes:
       - dnsconfig:/root/dnsconfig
   caddy:

+ 3 - 0
config/config.go

@@ -74,6 +74,9 @@ type ServerConfig struct {
 	RCE                   string `yaml:"rce"`
 	Debug                 bool   `yaml:"debug"`
 	Telemetry             string `yaml:"telemetry"`
+	ManageIPTables        string `yaml:"manageiptables"`
+	PortForwardServices   string `yaml:"portforwardservices"`
+	HostNetwork           string `yaml:"hostnetwork"`
 }
 
 // SQLConfig - Generic SQL Config

+ 6 - 2
functions/local.go

@@ -22,13 +22,16 @@ func SetDNSDir() error {
 	if err != nil {
 		return err
 	}
+
 	_, err = os.Stat(dir + "/config/dnsconfig")
 	if os.IsNotExist(err) {
-		os.Mkdir(dir+"/config/dnsconfig", 0744)
-	} else if err != nil {
+		err = os.MkdirAll(dir+"/config/dnsconfig", 0744)
+	}
+	if err != nil {
 		logger.Log(0, "couldnt find or create /config/dnsconfig")
 		return err
 	}
+
 	_, err = os.Stat(dir + "/config/dnsconfig/Corefile")
 	if os.IsNotExist(err) {
 		err = logic.SetCorefile(".")
@@ -36,6 +39,7 @@ func SetDNSDir() error {
 			logger.Log(0, err.Error())
 		}
 	}
+
 	_, err = os.Stat(dir + "/config/dnsconfig/netmaker.hosts")
 	if os.IsNotExist(err) {
 		_, err = os.Create(dir + "/config/dnsconfig/netmaker.hosts")

+ 4 - 2
logic/dns.go

@@ -115,10 +115,12 @@ func SetCorefile(domains string) error {
 	if err != nil {
 		return err
 	}
+
 	_, err = os.Stat(dir + "/config/dnsconfig")
 	if os.IsNotExist(err) {
-		os.Mkdir(dir+"/config/dnsconfig", 744)
-	} else if err != nil {
+		err = os.MkdirAll(dir+"/config/dnsconfig", 744)
+	}
+	if err != nil {
 		logger.Log(0, "couldnt find or create /config/dnsconfig")
 		return err
 	}

+ 7 - 0
main.go

@@ -71,6 +71,13 @@ func initialize() { // Client Mode Prereq Check
 			logger.FatalLog("Did not find netclient to use CLIENT_MODE")
 		}
 	}
+	// initialize iptables to ensure gateways work correctly and mq is forwarded if containerized
+	if servercfg.ManageIPTables() != "off" {
+		if err = serverctl.InitIPTables(); err != nil {
+			logger.FatalLog("Unable to initialize iptables on host:", err.Error())
+
+		}
+	}
 
 	if servercfg.IsDNSMode() {
 		err := functions.SetDNSDir()

+ 18 - 17
netclient/functions/daemon.go

@@ -247,12 +247,8 @@ func UpdatePeers(client mqtt.Client, msg mqtt.Message) {
 		cfg.ReadConfig()
 		var shouldReSub = shouldResub(cfg.Node.NetworkSettings.DefaultServerAddrs, peerUpdate.ServerAddrs)
 		if shouldReSub {
-			if err := config.ModConfig(&cfg.Node); err == nil {
 				Resubscribe(client, &cfg)
 				cfg.Node.NetworkSettings.DefaultServerAddrs = peerUpdate.ServerAddrs
-			} else {
-				ncutils.Log("resub required but mod config failed")
-			}
 			file := ncutils.GetNetclientPathSpecific() + cfg.Node.Interface + ".conf"
 			err = wireguard.UpdateWgPeers(file, peerUpdate.Peers)
 			if err != nil {
@@ -312,20 +308,25 @@ func ServerKeepAlive(client mqtt.Client, msg mqtt.Message) {
 
 // Resubscribe --- handles resubscribing if needed
 func Resubscribe(client mqtt.Client, cfg *config.ClientConfig) error {
-	ncutils.Log("resubbing on network " + cfg.Node.Network)
-	client.Disconnect(250)
-	client = SetupMQTT(cfg)
-	if token := client.Subscribe("update/"+cfg.Node.ID, 0, NodeUpdate); token.Wait() && token.Error() != nil {
-		log.Fatal(token.Error())
-	}
-	if cfg.DebugOn {
-		ncutils.Log("subscribed to node updates for node " + cfg.Node.Name + " update/" + cfg.Node.ID)
-	}
-	if token := client.Subscribe("update/peers/"+cfg.Node.ID, 0, UpdatePeers); token.Wait() && token.Error() != nil {
-		log.Fatal(token.Error())
+	if err := config.ModConfig(&cfg.Node); err == nil {
+		ncutils.Log("resubbing on network " + cfg.Node.Network)
+		client.Disconnect(250)
+		client = SetupMQTT(cfg)
+		if token := client.Subscribe("update/"+cfg.Node.ID, 0, NodeUpdate); token.Wait() && token.Error() != nil {
+			log.Fatal(token.Error())
+		}
+		if cfg.DebugOn {
+			ncutils.Log("subscribed to node updates for node " + cfg.Node.Name + " update/" + cfg.Node.ID)
+		}
+		if token := client.Subscribe("update/peers/"+cfg.Node.ID, 0, UpdatePeers); token.Wait() && token.Error() != nil {
+			log.Fatal(token.Error())
+		}
+		ncutils.Log("finished re subbing")
+		return nil
+	} else {
+		ncutils.Log("could not mod config when re-subbing")
+		return err
 	}
-	ncutils.Log("finished re subbing")
-	return nil
 }
 
 // UpdateKeys -- updates private key and returns new publickey

+ 39 - 0
servercfg/serverconf.go

@@ -87,6 +87,9 @@ func GetServerConfig() config.ServerConfig {
 	}
 	cfg.Debug = GetDebug()
 	cfg.Telemetry = Telemetry()
+	cfg.ManageIPTables = ManageIPTables()
+	services := strings.Join(GetPortForwardServiceList(), ",")
+	cfg.PortForwardServices = services
 
 	return cfg
 }
@@ -360,6 +363,18 @@ func Telemetry() string {
 	return telemetry
 }
 
+// ManageIPTables - checks if iptables should be manipulated on host
+func ManageIPTables() string {
+	manage := "on"
+	if os.Getenv("MANAGE_IPTABLES") == "off" {
+		manage = "off"
+	}
+	if config.Config.Server.ManageIPTables == "off" {
+		manage = "off"
+	}
+	return manage
+}
+
 // IsDNSMode - should it run with DNS
 func IsDNSMode() bool {
 	isdns := true
@@ -474,6 +489,19 @@ func GetPlatform() string {
 	return platform
 }
 
+// GetIPForwardServiceList - get the list of services that the server should be forwarding
+func GetPortForwardServiceList() []string {
+	//services := "mq,dns,ssh"
+	services := ""
+	if os.Getenv("PORT_FORWARD_SERVICES") != "" {
+		services = os.Getenv("PORT_FORWARD_SERVICES")
+	} else if config.Config.Server.PortForwardServices != "" {
+		services = config.Config.Server.PortForwardServices
+	}
+	serviceSlice := strings.Split(services, ",")
+	return serviceSlice
+}
+
 // GetSQLConn - get the sql connection string
 func GetSQLConn() string {
 	sqlconn := "http://"
@@ -496,6 +524,17 @@ func IsSplitDNS() bool {
 	return issplit
 }
 
+// IsSplitDNS - checks if split dns is on
+func IsHostNetwork() bool {
+	ishost := false
+	if os.Getenv("HOST_NETWORK") == "on" {
+		ishost = true
+	} else if config.Config.Server.HostNetwork == "on" {
+		ishost = true
+	}
+	return ishost
+}
+
 // GetNodeID - gets the node id
 func GetNodeID() string {
 	var id string

+ 130 - 0
serverctl/iptables.go

@@ -0,0 +1,130 @@
+package serverctl
+
+import (
+	"errors"
+	"net"
+	"os"
+	"os/exec"
+	"strings"
+	"time"
+
+	"github.com/gravitl/netmaker/logger"
+	"github.com/gravitl/netmaker/netclient/ncutils"
+	"github.com/gravitl/netmaker/servercfg"
+)
+
+const netmakerProcessName = "netmaker"
+
+// InitServerNetclient - intializes the server netclient
+func InitIPTables() error {
+	_, err := exec.LookPath("iptables")
+	if err != nil {
+		return err
+	}
+	err = setForwardPolicy()
+	if err != nil {
+		logger.Log(0, "error setting iptables forward policy: "+err.Error())
+	}
+
+	err = portForwardServices()
+	if err != nil {
+		return err
+	}
+	if isContainerized() && servercfg.IsHostNetwork() {
+		err = setHostCoreDNSMapping()
+	}
+	return err
+}
+
+// set up port forwarding for services listed in config
+func portForwardServices() error {
+	var err error
+	services := servercfg.GetPortForwardServiceList()
+	if len(services) == 0 || services[0] == "" {
+		return nil
+	}
+	for _, service := range services {
+		switch service {
+		case "mq":
+			err = iptablesPortForward("mq", "1883", "1883", false)
+		case "dns":
+			err = iptablesPortForward("coredns", "53", "53", false)
+		case "ssh":
+			err = iptablesPortForward("127.0.0.1", "22", "22", true)
+		default:
+			params := strings.Split(service, ":")
+			err = iptablesPortForward(params[0], params[1], params[2], true)
+		}
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// determine if process is running in container
+func isContainerized() bool {
+	fileBytes, err := os.ReadFile("/proc/1/sched")
+	if err != nil {
+		logger.Log(1, "error determining containerization: "+err.Error())
+		return false
+	}
+	fileString := string(fileBytes)
+	return strings.Contains(fileString, netmakerProcessName)
+}
+
+// make sure host allows forwarding
+func setForwardPolicy() error {
+	logger.Log(1, "setting iptables forward policy")
+	_, err := ncutils.RunCmd("iptables --policy FORWARD ACCEPT", false)
+	return err
+}
+
+// port forward from an entry, can contain a dns name for lookup
+func iptablesPortForward(entry string, inport string, outport string, isIP bool) error {
+	logger.Log(1, "forwarding "+entry+" traffic from host port "+inport+" to container port "+outport)
+
+	var address string
+	if !isIP {
+	out:
+		for i := 1; i < 4; i++ {
+			ips, err := net.LookupIP(entry)
+			if err != nil && i > 2 {
+				return err
+			}
+			for _, ip := range ips {
+				if ipv4 := ip.To4(); ipv4 != nil {
+					address = ipv4.String()
+				}
+			}
+			if address != "" {
+				break out
+			}
+			time.Sleep(time.Second)
+		}
+	} else {
+		address = entry
+	}
+	if address == "" {
+		return errors.New("could not locate ip for " + entry)
+	}
+
+	_, err := ncutils.RunCmd("iptables -t nat -A PREROUTING -p tcp --dport "+inport+" -j DNAT --to-destination "+address+":"+outport, false)
+	if err != nil {
+		return err
+	}
+	_, err = ncutils.RunCmd("iptables -t nat -A PREROUTING -p udp --dport "+inport+" -j DNAT --to-destination "+address+":"+outport, false)
+	if err != nil {
+		return err
+	}
+	_, err = ncutils.RunCmd("iptables -t nat -A POSTROUTING -j MASQUERADE", false)
+	return err
+}
+
+// if running in host networking mode, run iptables to map to CoreDNS container
+func setHostCoreDNSMapping() error {
+	logger.Log(1, "forwarding dns traffic on host from netmaker interfaces to 53053")
+	ncutils.RunCmd("iptables -t nat -A PREROUTING -i nm-+ -p tcp --match tcp --dport 53 --jump REDIRECT --to-ports 53053", true)
+	_, err := ncutils.RunCmd("iptables -t nat -A PREROUTING -i nm-+ -p udp --match udp --dport 53 --jump REDIRECT --to-ports 53053", true)
+	return err
+}