From 7b5ae7ce6ede03a3981dfda0135022afb294945a Mon Sep 17 00:00:00 2001 From: yo Date: Mon, 18 Apr 2022 13:52:44 +0200 Subject: [PATCH] start : Check if nat doesnt conflict with running jails, get default router --- cmd/start.go | 117 ++++++++++++++++++++++++++++++++++++++++++++------ cmd/struct.go | 8 ++++ go.mod | 1 + 3 files changed, 113 insertions(+), 13 deletions(-) diff --git a/cmd/start.go b/cmd/start.go index 964c2d3..f084c43 100644 --- a/cmd/start.go +++ b/cmd/start.go @@ -6,6 +6,8 @@ import ( "errors" "regexp" "strings" + "strconv" + "io/ioutil" ) // FIXME : Do not work?! @@ -226,7 +228,58 @@ func prepareJailedZfsDatasets(jail *Jail) error { return nil } +type NatDesc struct { + Proto string + JailPort string + HostPort string +} +// tcp(80:8080),tcp(3300-3310:33060-33070) +func getNatForwardsArray(nat_forwards string, decompose_range bool) ([]NatDesc, error) { + var res []NatDesc + + regx := `(tcp|udp)\(([0-9]{1,5}(?:-[0-9]{1,5})?):([0-9]{1,5}(?:-[0-9]{1,5})?)\)` + re := regexp.MustCompile(regx) + + for _, match := range re.FindAllStringSubmatch(nat_forwards, -1) { + if strings.Contains(match[2], "-") == true && decompose_range == true { + sjrange, err := strconv.Atoi(strings.Split(match[2], "-")[0]) + if err != nil { + return res, err + } + ejrange, err := strconv.Atoi(strings.Split(match[2], "-")[1]) + if err != nil { + return res, err + } + shrange, err := strconv.Atoi(strings.Split(match[3], "-")[0]) + if err != nil { + return res, err + } + ehrange, err := strconv.Atoi(strings.Split(match[3], "-")[1]) + if err != nil { + return res, err + } + if (ejrange - sjrange) != (ehrange - shrange) { + return res, errors.New(fmt.Sprintf("Invalid port range in nat_forwards: %s", match[0])) + } + for i := sjrange ; i <= ejrange ; i++ { + nd := NatDesc{Proto: match[1], + JailPort: strconv.Itoa(i), + HostPort: strconv.Itoa(shrange + (i - sjrange)), + } + res = append(res, nd) + } + } else { + nd := NatDesc{Proto: match[1], + JailPort: match[2], + HostPort: match[3], + } + res = append(res, nd) + } + } + + return res, nil +} /* Start jail: @@ -277,13 +330,14 @@ func StartJail(args []string) { continue } - if len(cj.hostid) > 0 && cj.Hostid_strict_check == true { + if len(cj.Config.Hostid) > 0 && cj.Config.Hostid_strict_check > 0 { hostid, err := ioutil.ReadFile("/etc/hostid") if err != nil { - return err + fmt.Printf(err.Error()) + return } hostid = []byte(strings.Replace(string(hostid), "\n", "", -1)) - if strings.EqualFold(hostid, cj.hostid) == false { + if strings.EqualFold(string(hostid), cj.Config.Hostid) == false { fmt.Printf("hostid is not matching and hostid_strict_check is on. Not starting jail.\n") return } @@ -291,29 +345,66 @@ func StartJail(args []string) { var props_missing []string // DHCP can also be set with "DHCP" value in ip4_addr - if cj.Dhcp == true || strings.EqualFold(cj.Ip4_addr, "DHCP") == true { - if cj.Bpf == 0 { + if cj.Config.Dhcp > 0 || strings.EqualFold(cj.Config.Ip4_addr, "DHCP") == true { + if cj.Config.Bpf == 0 { props_missing = append(props_missing, fmt.Sprintf("%s: dhcp requires bpf", cj.Name)) } - if cj.Vnet == 0 { + if cj.Config.Vnet == 0 { props_missing = append(props_missing, fmt.Sprintf("%s: dhcp requires vnet", cj.Name)) } } - // TODO : Check that this nat_forwards exemple is OK : - // tcp(80:8080),tcp(3300-3310:33060-33070) - // If OK, it should map jail port 80 to 8080 on the host - // and range 3300-3310 on jail to 33060-33070 on the host - if cj.Nat > 0 && strings.EqualFold(cj.Nat_forwards, "none") == false { + + // tcp(80:8080),tcp(3300-3310:33000-33010) + if cj.Config.Nat > 0 && strings.EqualFold(cj.Config.Nat_forwards, "none") == false { // If NAT && port forwarding is enabled, check that port does not conflict // with another running jail for _, j := range gJails { - if j.Running == false { + if j.Running == false || strings.EqualFold(j.Config.Nat_forwards, "none") == false || j.Config.Nat != 1 { continue + } else { + jnd, err := getNatForwardsArray(j.Config.Nat_forwards, true) + if err != nil { + fmt.Printf(err.Error()) + return + } + cjnd, err := getNatForwardsArray(cj.Config.Nat_forwards, true) + if err != nil { + fmt.Printf(err.Error()) + return + } + for _, jn := range jnd { + for _, cjn := range cjnd { + if jn == cjn { + fmt.Printf("nat_forwards rule \"%s\" is in conflict with jail %s, won't start\n", + fmt.Sprintf("%s(%s:%s)", cjn.Proto, cjn.JailPort, cjn.HostPort), j.Name) + return + } + } + } } - // TODO : check! } } + if cj.Config.Nat > 0 && strings.EqualFold(cj.Config.Nat_interface, "none") == true { + var jhost JailHost + cj.Config.Nat_interface = jhost.GetDefaultInterface() + cj.ConfigUpdated = true + } + + if cj.Config.Vnet > 0 && strings.EqualFold(cj.Config.Defaultrouter, "auto") == true { + var jhost JailHost + cj.Config.Defaultrouter = jhost.GetDefaultGateway4() + // "auto" default Gateway should not be updated to support jailhost route change + } + + if cj.Config.Vnet > 0 && strings.EqualFold(cj.Config.Defaultrouter6, "auto") == true { + var jhost JailHost + cj.Config.Defaultrouter6 = jhost.GetDefaultGateway6() + // "auto" default Gateway should not be updated to support jailhost route change + } + + // Continue here + fmt.Printf(" > Mount special filesystems:\n") err := mountAllJailFsFromHost(cj) if err != nil { diff --git a/cmd/struct.go b/cmd/struct.go index e7057c3..876c36e 100644 --- a/cmd/struct.go +++ b/cmd/struct.go @@ -500,3 +500,11 @@ type SnapshotSort struct { CreationInc snapshotLessFunc CreationDec snapshotLessFunc } + +type JailHost struct { + hostname string + hostid string + default_gateway4 string + default_gateway6 string + default_interface string +} diff --git a/go.mod b/go.mod index 8c634c9..64ef63e 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.17 require ( github.com/spf13/cobra v1.2.1 github.com/spf13/viper v1.9.0 + golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420 ) require (