Reorg and add host flag, and catch error when not root:
- A previous workaround done to recover from a panic on nil
    ref is now not needed and removed. The issue was that I assumed
    cli.Exit(err, int) was a way to exit; i.e. it uses os.Exit()
    under the hood. However, it only constructs a struct that implements
    error. Hence, we should return it, not just execute it.
    - Also warn on root and Windows
    - Move IPPool init to setup rather than run
			
			
This commit is contained in:
		
							parent
							
								
									1a611616bd
								
							
						
					
					
						commit
						a9ad981137
					
				@ -1,10 +1,10 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"log/slog"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"net/netip"
 | 
			
		||||
	"os"
 | 
			
		||||
	"os/signal"
 | 
			
		||||
	"time"
 | 
			
		||||
@ -15,7 +15,13 @@ import (
 | 
			
		||||
	hvpnnode3 "gitea.hbanafa.com/HeshamTB/hvpn-node3"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var IPPool *hvpnnode3.IPPool
 | 
			
		||||
/*
 | 
			
		||||
   Can change all therse vars to local func vars
 | 
			
		||||
   IPPool can be internal to wglink or other abstraction. As well as
 | 
			
		||||
   POrt, ifname and CIDR and so on. Use Clie.ctx to get the values
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
var IPPool hvpnnode3.IPPool
 | 
			
		||||
var VPNIPCIDR string
 | 
			
		||||
var PrivateKeyPath cli.Path
 | 
			
		||||
var InterfaceName string
 | 
			
		||||
@ -30,6 +36,13 @@ func main() {
 | 
			
		||||
    // TODO: Define error exit codes
 | 
			
		||||
    slog.SetLogLoggerLevel(slog.LevelDebug)
 | 
			
		||||
 | 
			
		||||
    uid := os.Getuid()
 | 
			
		||||
    if uid == -1 {
 | 
			
		||||
        slog.Warn("Running on windows! whatrr u doing?")
 | 
			
		||||
    } else if uid == 0 {
 | 
			
		||||
        slog.Warn("Running as root! avoid running as root by setting CAP_NET_ADMIN")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    app := createCliApp()
 | 
			
		||||
    err := app.Run(os.Args)
 | 
			
		||||
    if err != nil {
 | 
			
		||||
@ -40,27 +53,8 @@ func main() {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func run() {
 | 
			
		||||
    IPPool, err := hvpnnode3.NewPool(VPNIPCIDR)
 | 
			
		||||
    if err != nil {
 | 
			
		||||
        slog.Error(fmt.Sprintf("main.IPPool: %s", err))
 | 
			
		||||
        os.Exit(1)
 | 
			
		||||
    }
 | 
			
		||||
    slog.Info(fmt.Sprintf("Init ip pool %s", VPNIPCIDR))
 | 
			
		||||
 | 
			
		||||
    testVip, err := IPPool.Allocate()
 | 
			
		||||
    if err != nil {
 | 
			
		||||
        slog.Error("main.testVip: ", err)
 | 
			
		||||
        os.Exit(1)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    slog.Info(fmt.Sprintf("main.testVip: IP Pool Test IP: %s", testVip.String()))
 | 
			
		||||
    err = IPPool.Free(testVip)
 | 
			
		||||
    if err != nil {
 | 
			
		||||
        slog.Error("main.testVip: Could not free test Vip from IPPool!", err)
 | 
			
		||||
        os.Exit(1)
 | 
			
		||||
    }
 | 
			
		||||
    slog.Info("main.testVip: Test IP Freed")
 | 
			
		||||
func run(ctx *cli.Context) {
 | 
			
		||||
    slog.Debug("Starting run()")
 | 
			
		||||
 | 
			
		||||
    apiMux := http.NewServeMux()
 | 
			
		||||
    apiMux.HandleFunc("GET /peer", hvpnnode3.HandleGetPeer(wgLink))
 | 
			
		||||
@ -71,7 +65,11 @@ func run() {
 | 
			
		||||
    handler = hvpnnode3.HttpLogHandler2(handler)
 | 
			
		||||
 | 
			
		||||
    port := fmt.Sprintf("%d", httpPort)
 | 
			
		||||
    host := "0.0.0.0"
 | 
			
		||||
    host := ctx.String("host")
 | 
			
		||||
    if host == "" {
 | 
			
		||||
        slog.Info("Host is not set. Using 0.0.0.0")
 | 
			
		||||
        host = "0.0.0.0"
 | 
			
		||||
    }
 | 
			
		||||
    hostPort := fmt.Sprintf("%s:%s", host, port)
 | 
			
		||||
 | 
			
		||||
    slog.Info(fmt.Sprintf("Starting HVPN node on %s", hostPort))
 | 
			
		||||
@ -156,6 +154,20 @@ func createCliApp() *cli.App {
 | 
			
		||||
    }
 | 
			
		||||
    app.Flags = append(app.Flags, &wgPort)
 | 
			
		||||
 | 
			
		||||
    httpListenAddr := cli.StringFlag{
 | 
			
		||||
        Name: "host",
 | 
			
		||||
        Usage: "IP address to listen on for HTTP API requests",
 | 
			
		||||
        Value: "0.0.0.0",
 | 
			
		||||
        Action: func(ctx *cli.Context, s string) error {
 | 
			
		||||
            _, err := netip.ParseAddr(s)
 | 
			
		||||
            if err != nil {
 | 
			
		||||
                return cli.Exit(fmt.Sprintf("Can not parse %s as a network IP", s), 1)
 | 
			
		||||
            }
 | 
			
		||||
            return nil
 | 
			
		||||
        },
 | 
			
		||||
    }
 | 
			
		||||
    app.Flags = append(app.Flags, &httpListenAddr)
 | 
			
		||||
 | 
			
		||||
    httpPort := cli.IntFlag{
 | 
			
		||||
        Name: "http-port",
 | 
			
		||||
        Usage: "TCP Port for HTTP API",
 | 
			
		||||
@ -170,7 +182,7 @@ func createCliApp() *cli.App {
 | 
			
		||||
        if err != nil {
 | 
			
		||||
            return err
 | 
			
		||||
        }
 | 
			
		||||
        run()
 | 
			
		||||
        run(ctx)
 | 
			
		||||
        return nil
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -178,6 +190,7 @@ func createCliApp() *cli.App {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func setup() error {
 | 
			
		||||
    slog.Debug("Starting setup()")
 | 
			
		||||
    privKeyFile, err := os.Open(PrivateKeyPath)
 | 
			
		||||
    if err != nil {
 | 
			
		||||
        return cli.Exit(err, 1)
 | 
			
		||||
@ -208,24 +221,14 @@ func setup() error {
 | 
			
		||||
        WgPort,
 | 
			
		||||
    )
 | 
			
		||||
    if err != nil {
 | 
			
		||||
        slog.Warn("Error while initlizing Wireguard netlink and device!")
 | 
			
		||||
        slog.Warn("Ensure to run as root or with CAP_NET_ADMIN")
 | 
			
		||||
        return cli.Exit(err, 1)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    wgLink = wg
 | 
			
		||||
 | 
			
		||||
    // this is done to recover from the next call to wgLink.Device call
 | 
			
		||||
    // idk a better way to recover or prevent the panic when running user
 | 
			
		||||
    // does not have root or CAP_NET_ADMIN.
 | 
			
		||||
    defer func() {
 | 
			
		||||
        if r := recover(); r != nil {
 | 
			
		||||
            slog.Error(fmt.Sprint(r))
 | 
			
		||||
            slog.Error("Recovered from panic. Ensure to run as root or with CAP_NET_ADMIN")
 | 
			
		||||
            cli.Exit(errors.New("Recovered from panic. Ensure to run as root or with CAP_NET_ADMIN"),1)
 | 
			
		||||
            os.Exit(-1)
 | 
			
		||||
        }
 | 
			
		||||
    }()
 | 
			
		||||
 | 
			
		||||
    slog.Info("Wireguard device is setup and running")
 | 
			
		||||
    slog.Info("Wireguard netlink is setup and running")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    dev, err := wgLink.Device(InterfaceName)
 | 
			
		||||
@ -241,6 +244,29 @@ func setup() error {
 | 
			
		||||
        ),
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    ipPool, err := hvpnnode3.NewPool(VPNIPCIDR)
 | 
			
		||||
    if err != nil {
 | 
			
		||||
        slog.Error(fmt.Sprintf("main.IPPool: %s", err))
 | 
			
		||||
        os.Exit(1)
 | 
			
		||||
    }
 | 
			
		||||
    slog.Info(fmt.Sprintf("Init ip pool %s", VPNIPCIDR))
 | 
			
		||||
 | 
			
		||||
    testVip, err := ipPool.Allocate()
 | 
			
		||||
    if err != nil {
 | 
			
		||||
        slog.Error("main.testVip: ", err)
 | 
			
		||||
        os.Exit(1)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    slog.Info(fmt.Sprintf("main.testVip: IP Pool Test IP: %s", testVip.String()))
 | 
			
		||||
    err = ipPool.Free(testVip)
 | 
			
		||||
    if err != nil {
 | 
			
		||||
        slog.Error("main.testVip: Could not free test Vip from IPPool!", err)
 | 
			
		||||
        os.Exit(1)
 | 
			
		||||
    }
 | 
			
		||||
    slog.Info("main.testVip: Test IP Freed")
 | 
			
		||||
 | 
			
		||||
    IPPool = ipPool
 | 
			
		||||
 | 
			
		||||
    //defer wgLink.Close()
 | 
			
		||||
    c := make(chan os.Signal, 1)
 | 
			
		||||
    signal.Notify(c, os.Interrupt, os.Kill)
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user