dissertation-2-code/main.go

151 lines
2.7 KiB
Go
Raw Normal View History

2020-10-22 21:19:26 +01:00
package main
import (
2021-03-26 11:58:03 +00:00
"errors"
"fmt"
2020-10-25 15:36:34 +00:00
"log"
"mpbl3p/config"
2021-03-25 13:50:48 +00:00
"mpbl3p/flags"
2021-03-26 11:58:03 +00:00
"mpbl3p/tun"
2020-10-24 17:44:14 +01:00
"os"
"os/signal"
2021-03-26 11:58:03 +00:00
"strconv"
2020-10-24 17:44:14 +01:00
"syscall"
)
2020-10-22 21:19:26 +01:00
2021-03-26 11:58:03 +00:00
const (
ENV_NC_TUN_FD = "NC_TUN_FD"
ENV_NC_CONFIG_PATH = "NC_CONFIG_PATH"
)
2020-10-22 21:19:26 +01:00
func main() {
2020-10-25 15:36:34 +00:00
log.SetFlags(log.Ldate | log.Ltime | log.Llongfile)
2021-03-26 11:58:03 +00:00
if _, exists := os.LookupEnv(ENV_NC_TUN_FD); !exists {
// we are the parent process
// 1) process arguments
// 2) validate config
// 2) create a tun adapter
// 3) spawn a child
// 4) exit
2021-03-26 18:13:39 +00:00
2021-03-26 11:58:03 +00:00
o, err := flags.ParseFlags()
if err != nil {
if errors.Is(err, flags.PrintedHelpErr) {
return
}
panic(err)
}
log.Println("loading config...")
c, err := config.LoadConfig(o.ConfigFile)
if err != nil {
panic(err)
}
log.Println("creating tun adapter...")
t, err := tun.NewTun(o.Positional.InterfaceName, int(c.Host.MTU))
if err != nil {
panic(err)
}
if o.Foreground {
if err := os.Setenv(ENV_NC_TUN_FD, fmt.Sprintf("%d", t.File().Fd())); err != nil {
panic(err)
}
if err := os.Setenv(ENV_NC_CONFIG_PATH, o.ConfigFile); err != nil {
panic(err)
}
2021-03-26 18:13:39 +00:00
log.Println("switching to foreground")
2021-03-26 11:58:03 +00:00
goto FOREGROUND
}
2021-03-26 18:13:39 +00:00
files := make([]*os.File, 4)
files[0], _ = os.Open(os.DevNull) // stdin
files[1], _ = os.Open(os.DevNull) // stderr
files[2], _ = os.Open(os.DevNull) // stdout
files[3] = t.File()
env := os.Environ()
env = append(env, fmt.Sprintf("%s=3", ENV_NC_TUN_FD))
env = append(env, fmt.Sprintf("%s=%s", ENV_NC_CONFIG_PATH, o.ConfigFile))
attr := os.ProcAttr{
Env: env,
Files: files,
}
path, err := os.Executable()
if err != nil {
panic(err)
}
process, err := os.StartProcess(
path,
os.Args,
&attr,
)
if err != nil {
panic(err)
}
2021-03-26 20:59:54 +00:00
pidFile, err := os.Create(o.PidFile)
if err != nil {
panic(err)
}
if _, err := fmt.Fprintf(pidFile, "%d", process.Pid); err != nil {
panic(err)
}
2021-03-26 18:13:39 +00:00
_ = process.Release()
2021-03-26 11:58:03 +00:00
return
2020-11-26 22:10:37 +00:00
}
2021-03-26 11:58:03 +00:00
// we are the child process
// 1) recreate tun adapter from file descriptor
// 2) launch proxy
FOREGROUND:
2021-03-25 13:50:48 +00:00
log.Println("loading config...")
2021-03-26 11:58:03 +00:00
c, err := config.LoadConfig(os.Getenv(ENV_NC_CONFIG_PATH))
if err != nil {
panic(err)
}
2021-03-26 11:58:03 +00:00
log.Println("connecting tun adapter...")
tunFd, err := strconv.ParseUint(os.Getenv(ENV_NC_TUN_FD), 10, 64)
2020-10-24 17:44:14 +01:00
if err != nil {
panic(err)
}
2021-03-26 11:58:03 +00:00
t, err := tun.NewFromFile(uintptr(tunFd), int(c.Host.MTU))
2021-03-25 13:50:48 +00:00
if err != nil {
panic(err)
}
2021-03-25 16:56:11 +00:00
defer func() {
2021-03-26 11:58:03 +00:00
if err := t.Close(); err != nil {
2021-03-25 16:56:11 +00:00
panic(err)
}
}()
2021-03-26 11:58:03 +00:00
log.Println("building config...")
p, err := c.Build(t, t)
if err != nil {
panic(err)
}
log.Println("starting proxy...")
p.Start()
log.Println("proxy started")
2020-10-24 17:44:14 +01:00
signals := make(chan os.Signal)
signal.Notify(signals, syscall.SIGTERM, syscall.SIGINT)
<-signals
2021-03-26 11:58:03 +00:00
log.Println("exiting...")
2020-10-22 21:19:26 +01:00
}