EtherGuard-VPN/main_edge.go

295 lines
8.7 KiB
Go
Raw Normal View History

2021-08-16 20:58:15 +02:00
/* SPDX-License-Identifier: MIT
*
2021-12-04 15:46:36 +01:00
* Copyright (C) 2017-2021 Kusakabe Si. All Rights Reserved.
2021-08-16 20:58:15 +02:00
*/
package main
import (
2021-12-04 04:51:50 +01:00
"encoding/binary"
2021-08-20 19:32:50 +02:00
"errors"
2021-08-16 20:58:15 +02:00
"fmt"
"os"
2021-11-06 10:47:06 +01:00
"os/exec"
2021-08-16 20:58:15 +02:00
"os/signal"
"strconv"
"strings"
2021-08-16 20:58:15 +02:00
"syscall"
2021-11-06 10:47:06 +01:00
"github.com/google/shlex"
2021-12-02 18:13:48 +01:00
"github.com/KusakabeSi/EtherGuard-VPN/conn"
"github.com/KusakabeSi/EtherGuard-VPN/device"
2021-12-07 21:39:19 +01:00
"github.com/KusakabeSi/EtherGuard-VPN/gencfg"
2021-12-02 18:13:48 +01:00
"github.com/KusakabeSi/EtherGuard-VPN/mtypes"
"github.com/KusakabeSi/EtherGuard-VPN/path"
"github.com/KusakabeSi/EtherGuard-VPN/tap"
2021-08-16 20:58:15 +02:00
yaml "gopkg.in/yaml.v2"
)
2021-08-20 19:32:50 +02:00
func printExampleEdgeConf() {
2021-12-13 05:20:58 +01:00
tconfig, _ := gencfg.GetExampleEdgeConf("", true)
2021-12-05 22:36:50 +01:00
toprint, _ := yaml.Marshal(tconfig)
fmt.Print(string(toprint))
}
func Edge(configPath string, useUAPI bool, printExample bool, bindmode string) (err error) {
2021-08-20 19:32:50 +02:00
if printExample {
printExampleEdgeConf()
return nil
}
2021-12-02 18:13:48 +01:00
var econfig mtypes.EdgeConfig
2021-08-16 20:58:15 +02:00
//printExampleConf()
//return
2021-12-07 21:39:19 +01:00
err = mtypes.ReadYaml(configPath, &econfig)
2021-08-16 20:58:15 +02:00
if err != nil {
2021-09-21 22:03:11 +02:00
fmt.Printf("Error read config: %v\t%v\n", configPath, err)
2021-08-16 20:58:15 +02:00
return err
}
2021-09-20 22:20:00 +02:00
NodeName := econfig.NodeName
2021-08-25 13:54:13 +02:00
if len(NodeName) > 32 {
return errors.New("Node name can't longer than 32 :" + NodeName)
}
2021-12-09 23:39:37 +01:00
if econfig.DynamicRoute.DampingResistance < 0 || econfig.DynamicRoute.DampingResistance >= 1 {
return fmt.Errorf("DampingResistance must in range [0,1) : %v", econfig.DynamicRoute.DampingResistance)
2021-12-09 21:23:02 +01:00
}
2021-08-16 20:58:15 +02:00
var logLevel int
2021-09-20 22:20:00 +02:00
switch econfig.LogLevel.LogLevel {
2021-08-16 20:58:15 +02:00
case "verbose", "debug":
logLevel = device.LogLevelVerbose
case "error":
logLevel = device.LogLevelError
case "silent":
logLevel = device.LogLevelSilent
2021-08-26 11:06:40 +02:00
default:
logLevel = device.LogLevelError
2021-08-16 20:58:15 +02:00
}
logger := device.NewLogger(
logLevel,
2021-08-25 13:54:13 +02:00
fmt.Sprintf("(%s) ", NodeName),
2021-08-16 20:58:15 +02:00
)
if err != nil {
logger.Errorf("UAPI listen error: %v", err)
os.Exit(ExitSetupFailed)
return
}
var thetap tap.Device
// open TUN device (or use supplied fd)
2021-12-04 15:46:36 +01:00
switch econfig.Interface.IType {
2021-08-16 20:58:15 +02:00
case "dummy":
thetap, err = tap.CreateDummyTAP()
case "stdio":
2021-09-20 22:20:00 +02:00
thetap, err = tap.CreateStdIOTAP(econfig.Interface, econfig.NodeID)
2021-08-16 20:58:15 +02:00
case "udpsock":
thetap, err = tap.CreateUDPSockTAP(econfig.Interface, econfig.NodeID)
case "tcpsock":
2021-10-09 12:22:27 +02:00
thetap, err = tap.CreateSockTAP(econfig.Interface, "tcp", econfig.NodeID, econfig.LogLevel)
case "unixsock":
2021-10-09 12:22:27 +02:00
thetap, err = tap.CreateSockTAP(econfig.Interface, "unix", econfig.NodeID, econfig.LogLevel)
case "unixgramsock":
thetap, err = tap.CreateSockTAP(econfig.Interface, "unixgram", econfig.NodeID, econfig.LogLevel)
case "unixpacketsock":
thetap, err = tap.CreateSockTAP(econfig.Interface, "unixpacket", econfig.NodeID, econfig.LogLevel)
case "fd":
thetap, err = tap.CreateFdTAP(econfig.Interface, econfig.NodeID)
2021-08-24 10:43:55 +02:00
case "vpp":
2021-09-20 22:20:00 +02:00
thetap, err = tap.CreateVppTAP(econfig.Interface, econfig.NodeID, econfig.LogLevel.LogLevel)
2021-08-24 15:26:20 +02:00
case "tap":
2021-09-20 22:20:00 +02:00
thetap, err = tap.CreateTAP(econfig.Interface, econfig.NodeID)
2021-08-24 10:43:55 +02:00
default:
2021-12-04 15:46:36 +01:00
return errors.New("Unknow interface type:" + econfig.Interface.IType)
2021-08-16 20:58:15 +02:00
}
if err != nil {
2021-08-20 19:32:50 +02:00
logger.Errorf("Failed to create TAP device: %v", err)
2021-08-16 20:58:15 +02:00
os.Exit(ExitSetupFailed)
}
2021-09-20 22:20:00 +02:00
if econfig.DefaultTTL <= 0 {
return errors.New("DefaultTTL must > 0")
}
2021-08-16 20:58:15 +02:00
////////////////////////////////////////////////////
// Config
2021-12-09 08:46:15 +01:00
if !econfig.DynamicRoute.P2P.UseP2P && !econfig.DynamicRoute.SuperNode.UseSuperNode {
2021-09-20 22:20:00 +02:00
econfig.LogLevel.LogNTP = false // NTP in static mode is useless
2021-08-25 13:54:13 +02:00
}
2021-12-09 08:46:15 +01:00
graph, err := path.NewGraph(3, false, econfig.DynamicRoute.P2P.GraphRecalculateSetting, econfig.DynamicRoute.NTPConfig, econfig.LogLevel)
if err != nil {
return err
}
2021-12-04 03:32:59 +01:00
graph.SetNHTable(econfig.NextHopTable)
2021-08-20 19:32:50 +02:00
the_device := device.NewDevice(thetap, econfig.NodeID, conn.NewDefaultBind(true, true, bindmode), logger, graph, false, configPath, &econfig, nil, nil, Version)
2021-08-16 20:58:15 +02:00
defer the_device.Close()
2021-09-21 03:15:23 +02:00
pk, err := device.Str2PriKey(econfig.PrivKey)
if err != nil {
fmt.Println("Error decode base64 ", err)
return err
}
the_device.SetPrivateKey(pk)
2021-08-16 20:58:15 +02:00
the_device.IpcSet("fwmark=0\n")
2021-09-20 22:20:00 +02:00
the_device.IpcSet("listen_port=" + strconv.Itoa(econfig.ListenPort) + "\n")
2021-08-16 20:58:15 +02:00
the_device.IpcSet("replace_peers=true\n")
2021-09-20 22:20:00 +02:00
for _, peerconf := range econfig.Peers {
2021-09-21 03:15:23 +02:00
pk, err := device.Str2PubKey(peerconf.PubKey)
if err != nil {
fmt.Println("Error decode base64 ", err)
return err
}
2021-12-09 08:46:15 +01:00
the_device.NewPeer(pk, peerconf.NodeID, false, peerconf.PersistentKeepalive)
2021-08-16 20:58:15 +02:00
if peerconf.EndPoint != "" {
2021-09-21 03:15:23 +02:00
peer := the_device.LookupPeer(pk)
2021-12-17 08:02:42 +01:00
err = peer.SetEndpointFromConnURL(peerconf.EndPoint, 0, econfig.AfPrefer, peerconf.Static)
2021-08-16 20:58:15 +02:00
if err != nil {
logger.Errorf("Failed to set endpoint %v: %w", peerconf.EndPoint, err)
return err
}
}
}
2021-09-20 22:20:00 +02:00
if econfig.DynamicRoute.SuperNode.UseSuperNode {
S4 := true
S6 := true
2021-12-04 15:46:36 +01:00
if econfig.DynamicRoute.SuperNode.EndpointV4 != "" {
2021-09-21 03:15:23 +02:00
pk, err := device.Str2PubKey(econfig.DynamicRoute.SuperNode.PubKeyV4)
if err != nil {
fmt.Println("Error decode base64 ", err)
return err
}
psk, err := device.Str2PSKey(econfig.DynamicRoute.SuperNode.PSKey)
2021-08-20 19:32:50 +02:00
if err != nil {
fmt.Println("Error decode base64 ", err)
2021-08-20 19:32:50 +02:00
return err
}
2021-12-09 08:46:15 +01:00
peer, err := the_device.NewPeer(pk, mtypes.NodeID_SuperNode, true, 0)
2021-08-20 19:32:50 +02:00
if err != nil {
return err
}
peer.SetPSK(psk)
StaticSuper := true
sc := econfig.DynamicRoute.SuperNode.EndpointV4
if strings.Contains(sc, ":") {
i := strings.LastIndex(sc, ":")
sch := sc[:i]
if sch == "127.0.0.1" {
StaticSuper = false
}
}
err = peer.SetEndpointFromConnURL(econfig.DynamicRoute.SuperNode.EndpointV4, 4, 0, StaticSuper)
if err != nil {
2021-12-04 15:46:36 +01:00
logger.Errorf("Failed to set endpoint for supernode v4 %v: %v", econfig.DynamicRoute.SuperNode.EndpointV4, err)
S4 = false
}
2021-08-20 19:32:50 +02:00
}
2021-12-04 15:46:36 +01:00
if econfig.DynamicRoute.SuperNode.EndpointV6 != "" {
2021-09-21 03:15:23 +02:00
pk, err := device.Str2PubKey(econfig.DynamicRoute.SuperNode.PubKeyV6)
if err != nil {
fmt.Println("Error decode base64 ", err)
}
psk, err := device.Str2PSKey(econfig.DynamicRoute.SuperNode.PSKey)
2021-08-20 19:32:50 +02:00
if err != nil {
fmt.Println("Error decode base64 ", err)
2021-08-20 19:32:50 +02:00
return err
}
2021-12-09 08:46:15 +01:00
peer, err := the_device.NewPeer(pk, mtypes.NodeID_SuperNode, true, 0)
2021-08-20 19:32:50 +02:00
if err != nil {
return err
}
peer.SetPSK(psk)
StaticSuper := true
sc := econfig.DynamicRoute.SuperNode.EndpointV6
if strings.Contains(sc, ":") {
i := strings.LastIndex(sc, ":")
sch := sc[:i]
if sch == "[::1]" {
StaticSuper = false
}
}
err = peer.SetEndpointFromConnURL(econfig.DynamicRoute.SuperNode.EndpointV6, 6, 0, StaticSuper)
if err != nil {
2021-12-04 15:46:36 +01:00
logger.Errorf("Failed to set endpoint for supernode v6 %v: %v", econfig.DynamicRoute.SuperNode.EndpointV6, err)
S6 = false
}
if !(S4 || S6) {
2021-12-09 08:46:15 +01:00
return errors.New("failed to connect to supernode")
}
2021-08-20 19:32:50 +02:00
}
}
2021-08-16 20:58:15 +02:00
logger.Verbosef("Device started")
errs := make(chan error)
term := make(chan os.Signal, 1)
if useUAPI {
2021-08-25 13:54:13 +02:00
startUAPI(NodeName, logger, the_device, errs)
2021-08-16 20:58:15 +02:00
}
2021-11-06 10:47:06 +01:00
if econfig.PostScript != "" {
2021-12-04 04:51:50 +01:00
envs := make(map[string]string)
nid := econfig.NodeID
nid_bytearr := []byte{0, 0}
2021-12-04 15:46:36 +01:00
MacAddr, _ := tap.GetMacAddr(econfig.Interface.MacAddrPrefix, uint32(nid))
2021-12-04 04:51:50 +01:00
binary.LittleEndian.PutUint16(nid_bytearr, uint16(nid))
envs["EG_MODE"] = "edge"
envs["EG_NODE_NAME"] = econfig.NodeName
envs["EG_NODE_ID_INT_DEC"] = fmt.Sprintf("%d", nid)
envs["EG_NODE_ID_BYTE0_DEC"] = fmt.Sprintf("%d", nid_bytearr[0])
envs["EG_NODE_ID_BYTE1_DEC"] = fmt.Sprintf("%d", nid_bytearr[1])
envs["EG_NODE_ID_INT_HEX"] = fmt.Sprintf("%x", nid)
envs["EG_NODE_ID_BYTE0_HEX"] = fmt.Sprintf("%X", nid_bytearr[0])
envs["EG_NODE_ID_BYTE1_HEX"] = fmt.Sprintf("%X", nid_bytearr[1])
envs["EG_INTERFACE_NAME"] = econfig.Interface.Name
2021-12-04 15:46:36 +01:00
envs["EG_INTERFACE_TYPE"] = econfig.Interface.IType
envs["EG_INTERFACE_MAC_PREFIX"] = econfig.Interface.MacAddrPrefix
envs["EG_INTERFACE_MAC_ADDR"] = MacAddr.String()
2021-12-04 04:51:50 +01:00
2021-11-06 10:47:06 +01:00
cmdarg, err := shlex.Split(econfig.PostScript)
if err != nil {
2021-12-09 08:46:15 +01:00
return fmt.Errorf("error parse PostScript %v", err)
2021-11-06 10:47:06 +01:00
}
if econfig.LogLevel.LogInternal {
fmt.Printf("PostScript: exec.Command(%v)\n", cmdarg)
}
cmd := exec.Command(cmdarg[0], cmdarg[1:]...)
2021-12-04 04:51:50 +01:00
cmd.Env = os.Environ()
for k, v := range envs {
cmd.Env = append(cmd.Env, k+"="+v)
}
2021-11-06 10:47:06 +01:00
out, err := cmd.CombinedOutput()
if err != nil {
2021-12-09 08:46:15 +01:00
return fmt.Errorf("exec.Command(%v) failed with %v", cmdarg, err)
2021-11-06 10:47:06 +01:00
}
if econfig.LogLevel.LogInternal {
fmt.Printf("PostScript output: %s\n", string(out))
}
}
2021-08-16 20:58:15 +02:00
2021-11-06 10:47:06 +01:00
// wait for program to terminate
2021-08-16 20:58:15 +02:00
signal.Notify(term, syscall.SIGTERM)
signal.Notify(term, os.Interrupt)
2021-12-16 03:56:02 +01:00
the_device.Chan_Device_Initialized <- struct{}{}
2021-12-10 19:21:35 +01:00
mtypes.SdNotify(false, mtypes.SdNotifyReady)
SdNotify, err := mtypes.SdNotify(false, mtypes.SdNotifyReady)
if econfig.LogLevel.LogInternal {
fmt.Printf("Internal: SdNotify:%v err:%v\n", SdNotify, err)
2021-12-10 19:21:35 +01:00
}
2021-08-16 20:58:15 +02:00
select {
case <-term:
case <-errs:
2021-12-02 18:13:48 +01:00
case errcode := <-the_device.Wait():
if errcode != 0 {
return syscall.Errno(errcode)
}
2021-08-16 20:58:15 +02:00
}
logger.Verbosef("Shutting down")
return
}