all: implement router setup for openwrt

This commit is contained in:
Cuong Manh Le
2023-03-22 00:18:04 +07:00
committed by Cuong Manh Le
parent 4b6a976747
commit c94be0df35
9 changed files with 237 additions and 29 deletions
+18 -14
View File
@@ -200,7 +200,7 @@ func initCLI() {
os.Exit(0)
}
if runtime.GOOS == "linux" && onRouter {
if router.Name() != "" {
mainLog.Debug().Msg("Router setup")
err := router.Configure(&cfg)
if errors.Is(err, router.ErrNotSupported) {
@@ -230,8 +230,6 @@ func initCLI() {
_ = runCmd.Flags().MarkHidden("homedir")
runCmd.Flags().StringVarP(&iface, "iface", "", "", `Update DNS setting for iface, "auto" means the default interface gateway`)
_ = runCmd.Flags().MarkHidden("iface")
runCmd.Flags().BoolVarP(&onRouter, "router", "", false, `Configure onRouter for running ctrld`)
_ = runCmd.Flags().MarkHidden("router")
rootCmd.AddCommand(runCmd)
@@ -249,6 +247,7 @@ func initCLI() {
}
setDependencies(sc)
sc.Arguments = append([]string{"run"}, osArgs...)
router.ConfigureService(sc)
// No config path, generating config in HOME directory.
noConfigStart := isNoConfigStart(cmd)
@@ -276,12 +275,12 @@ func initCLI() {
cfg.Service.LogPath = logPath
processCDFlags()
// On Windows, the service will be run as SYSTEM, so if ctrld start as Admin,
// the user home dir is different, so pass specific arguments that relevant here.
if runtime.GOOS == "windows" {
if configPath == "" {
sc.Arguments = append(sc.Arguments, "--config="+defaultConfigFile)
}
// Explicitly passing config, so on system where home directory could not be obtained,
// or sub-process env is different with the parent, we still behave correctly and use
// the expected config file.
if configPath == "" {
sc.Arguments = append(sc.Arguments, "--config="+defaultConfigFile)
}
prog := &prog{}
@@ -297,7 +296,11 @@ func initCLI() {
{s.Start, true},
}
if doTasks(tasks) {
status, err := s.Status()
if err := router.PostInstall(); err != nil {
mainLog.Warn().Err(err).Msg("post installation failed, please check system/service log for details error")
return
}
status, err := serviceStatus(s)
if err != nil {
mainLog.Warn().Err(err).Msg("could not get service status")
return
@@ -329,8 +332,6 @@ func initCLI() {
startCmd.Flags().IntVarP(&cacheSize, "cache_size", "", 0, "Enable cache with size items")
startCmd.Flags().StringVarP(&cdUID, "cd", "", "", "Control D resolver uid")
startCmd.Flags().StringVarP(&iface, "iface", "", "", `Update DNS setting for iface, "auto" means the default interface gateway`)
startCmd.Flags().BoolVarP(&onRouter, "router", "", false, `Configure onRouter for running ctrld`)
_ = startCmd.Flags().MarkHidden("router")
stopCmd := &cobra.Command{
PreRun: checkHasElevatedPrivilege,
@@ -381,7 +382,7 @@ func initCLI() {
stderrMsg(err.Error())
return
}
status, err := s.Status()
status, err := serviceStatus(s)
if err != nil {
stderrMsg(err.Error())
os.Exit(1)
@@ -429,6 +430,9 @@ NOTE: Uninstalling will set DNS to values provided by DHCP.`,
iface = "auto"
}
prog.resetDNS()
if err := router.Cleanup(); err != nil {
mainLog.Warn().Err(err).Msg("could not cleanup router")
}
mainLog.Info().Msg("Service uninstalled")
return
}
@@ -815,5 +819,5 @@ func selfCheckStatus(status service.Status) service.Status {
}
func unsupportedPlatformHelp(cmd *cobra.Command) {
cmd.PrintErrln("Unsupported or incorrectly chosen onRouter platform. Please open an issue and provide all relevant information: https://github.com/Control-D-Inc/ctrld/issues/new")
cmd.PrintErrln("Unsupported or incorrectly chosen router platform. Please open an issue and provide all relevant information: https://github.com/Control-D-Inc/ctrld/issues/new")
}
+26 -3
View File
@@ -14,7 +14,7 @@ import (
func initRouterCLI() {
validArgs := append(router.SupportedPlatforms(), "auto")
var b strings.Builder
b.WriteString("Auto-setup Control D on a onRouter.\n\nSupported platforms:\n\n")
b.WriteString("Auto-setup Control D on a router.\n\nSupported platforms:\n\n")
for _, arg := range validArgs {
b.WriteString(" ₒ ")
b.WriteString(arg)
@@ -52,8 +52,7 @@ func initRouterCLI() {
}
cmdArgs := []string{"start"}
cmdArgs = append(cmdArgs, os.Args[3:]...)
cmdArgs = append(cmdArgs, "--router=true")
cmdArgs = append(cmdArgs, osArgs(platform)...)
command := exec.Command(exe, cmdArgs...)
command.Stdout = os.Stdout
command.Stderr = os.Stderr
@@ -63,8 +62,32 @@ func initRouterCLI() {
}
},
}
// Keep these flags in sync with startCmd, except for "--router".
routerCmd.Flags().StringVarP(&configPath, "config", "c", "", "Path to config file")
routerCmd.Flags().StringVarP(&configBase64, "base64_config", "", "", "Base64 encoded config")
routerCmd.Flags().StringVarP(&listenAddress, "listen", "", "", "Listener address and port, in format: address:port")
routerCmd.Flags().StringVarP(&primaryUpstream, "primary_upstream", "", "", "Primary upstream endpoint")
routerCmd.Flags().StringVarP(&secondaryUpstream, "secondary_upstream", "", "", "Secondary upstream endpoint")
routerCmd.Flags().StringSliceVarP(&domains, "domains", "", nil, "List of domain to apply in a split DNS policy")
routerCmd.Flags().StringVarP(&logPath, "log", "", "", "Path to log file")
routerCmd.Flags().IntVarP(&cacheSize, "cache_size", "", 0, "Enable cache with size items")
routerCmd.Flags().StringVarP(&cdUID, "cd", "", "", "Control D resolver uid")
routerCmd.Flags().StringVarP(&iface, "iface", "", "", `Update DNS setting for iface, "auto" means the default interface gateway`)
tmpl := routerCmd.UsageTemplate()
tmpl = strings.Replace(tmpl, "{{.UseLine}}", "{{.UseLine}} [platform]", 1)
routerCmd.SetUsageTemplate(tmpl)
rootCmd.AddCommand(routerCmd)
}
func osArgs(platform string) []string {
args := os.Args[2:]
n := 0
for _, x := range args {
if x != platform && x != "auto" {
args[n] = x
n++
}
}
return args[:n]
}
+18 -6
View File
@@ -17,10 +17,17 @@ import (
"github.com/Control-D-Inc/ctrld"
"github.com/Control-D-Inc/ctrld/internal/dnscache"
ctrldnet "github.com/Control-D-Inc/ctrld/internal/net"
"github.com/Control-D-Inc/ctrld/internal/router"
)
const staleTTL = 60 * time.Second
var osUpstreamConfig = &ctrld.UpstreamConfig{
Name: "OS resolver",
Type: ctrld.ResolverTypeOS,
Timeout: 2000,
}
func (p *prog) serveDNS(listenerNum string) error {
listenerConfig := p.cfg.Listener[listenerNum]
// make sure ip is allocated
@@ -61,7 +68,7 @@ func (p *prog) serveDNS(listenerNum string) error {
proto := proto
// On Windows, there's no easy way for disabling/removing IPv6 DNS resolver, so we check whether we can
// listen on ::1, then spawn a listener for receiving DNS requests.
if runtime.GOOS == "windows" && ctrldnet.SupportsIPv6ListenLocal() {
if needLocalIPv6Listener() {
g.Go(func() error {
s := &dns.Server{
Addr: net.JoinHostPort("::1", strconv.Itoa(listenerConfig.Port)),
@@ -80,7 +87,7 @@ func (p *prog) serveDNS(listenerNum string) error {
}
g.Go(func() error {
s := &dns.Server{
Addr: net.JoinHostPort(listenerConfig.IP, strconv.Itoa(listenerConfig.Port)),
Addr: dnsListenAddress(listenerConfig),
Net: proto,
Handler: handler,
}
@@ -353,8 +360,13 @@ func ttlFromMsg(msg *dns.Msg) uint32 {
return 0
}
var osUpstreamConfig = &ctrld.UpstreamConfig{
Name: "OS resolver",
Type: ctrld.ResolverTypeOS,
Timeout: 2000,
func needLocalIPv6Listener() bool {
return ctrldnet.SupportsIPv6ListenLocal() && runtime.GOOS == "windows"
}
func dnsListenAddress(lc *ctrld.ListenerConfig) string {
if addr := router.ListenAddress(); addr != "" {
return addr
}
return net.JoinHostPort(lc.IP, strconv.Itoa(lc.Port))
}
-1
View File
@@ -29,7 +29,6 @@ var (
cdUID string
iface string
ifaceStartStop string
onRouter bool
mainLog = zerolog.New(io.Discard)
)
+1
View File
@@ -25,6 +25,7 @@ var errWindowsAddrInUse = syscall.Errno(0x2740)
var svcConfig = &service.Config{
Name: "ctrld",
DisplayName: "Control-D Helper Service",
Option: service.KeyValue{},
}
type prog struct {
+24
View File
@@ -1,9 +1,12 @@
package main
import (
"bytes"
"fmt"
"os"
"os/exec"
"github.com/kardianos/service"
"github.com/spf13/cobra"
)
@@ -43,3 +46,24 @@ func checkHasElevatedPrivilege(cmd *cobra.Command, args []string) {
os.Exit(1)
}
}
func serviceStatus(s service.Service) (service.Status, error) {
status, err := s.Status()
if err != nil && service.Platform() == "unix-systemv" {
return unixSystemVServiceStatus()
}
return status, err
}
func unixSystemVServiceStatus() (service.Status, error) {
out, err := exec.Command("/etc/init.d/ctrld", "status").CombinedOutput()
if err != nil {
return service.StatusUnknown, nil
}
switch string(bytes.TrimSpace(out)) {
case "running":
return service.StatusRunning, nil
default:
return service.StatusStopped, nil
}
}