diff --git a/cmds/modules/netlightd/main.go b/cmds/modules/netlightd/main.go index 193f27321..3ef51572f 100644 --- a/cmds/modules/netlightd/main.go +++ b/cmds/modules/netlightd/main.go @@ -11,6 +11,7 @@ import ( "github.com/oasisprotocol/curve25519-voi/primitives/x25519" "github.com/pkg/errors" + "github.com/threefoldtech/zos/pkg/kernel" "github.com/threefoldtech/zos/pkg/netlight" "github.com/threefoldtech/zos/pkg/netlight/nft" "github.com/threefoldtech/zos/pkg/netlight/resource" @@ -68,6 +69,8 @@ func action(cli *cli.Context) error { workerNr uint = cli.Uint("workers") ) + configFileUrl, _ := kernel.GetParams().GetOne("config-url") + if err := os.MkdirAll(root, 0755); err != nil { return errors.Wrap(err, "fail to create module root") } @@ -107,6 +110,11 @@ func action(cli *cli.Context) error { return fmt.Errorf("failed to apply host nft rules: %w", err) } rules.Close() + + if err := nft.UpdateNFTWhitelist(configFileUrl); err != nil { + return fmt.Errorf("failed to allow whitelist outgoing traffic") + } + bridge, err := netlight.CreateNDMZBridge() if err != nil { return fmt.Errorf("failed to create ndmz bridge: %w", err) diff --git a/pkg/environment/config.go b/pkg/environment/config.go index 9a0595ff8..1640a1ab7 100644 --- a/pkg/environment/config.go +++ b/pkg/environment/config.go @@ -27,6 +27,9 @@ type Config struct { Users struct { Authorized []string `json:"authorized"` } `json:"users"` + Whitelist struct { + Ips []string `json:"ips"` + } `json:"whitelist"` } // Merge, updates current config with cfg merging and override config @@ -55,6 +58,19 @@ func GetConfigForMode(mode RunMode) (Config, error) { return getConfig(mode, baseExtendedURL, httpClient) } +func GetConfigForUrl(configRepo string) (Config, error) { + env, err := Get() + if err != nil { + return Config{}, err + } + + httpClient := &http.Client{ + Timeout: defaultHttpTimeout, + } + + return getConfig(env.RunningMode, configRepo, httpClient) +} + func uniqueStr(slice []string) []string { keys := make(map[string]struct{}) list := slice[:0] diff --git a/pkg/netlight/nft/nft.go b/pkg/netlight/nft/nft.go index e3486aa57..9c6880b36 100644 --- a/pkg/netlight/nft/nft.go +++ b/pkg/netlight/nft/nft.go @@ -1,10 +1,14 @@ package nft import ( + "fmt" "io" "os/exec" + "time" + "github.com/go-co-op/gocron" "github.com/rs/zerolog/log" + "github.com/threefoldtech/zos/pkg/environment" "github.com/pkg/errors" ) @@ -32,3 +36,82 @@ func Apply(r io.Reader, ns string) error { } return nil } + +// UpdateNFTWhitelist periodically pull list of ips from config repo and +// update the nft white list +func UpdateNFTWhitelist(configFileUrl string) error { + scheduler := gocron.NewScheduler(time.UTC) + cron := "0 * * * *" + + updateWhitelist := func() error { + ips, err := whiteList(configFileUrl) + if err != nil { + return err + } + + cmds := []string{ + "nft flush chain inet filter output", + "nft add rule inet filter output ct state established,related accept", + "nft add rule inet filter output tcp dport 22 accept", + } + + ipCmdTemplate := "nft add rule inet filter output ip daddr %s accept" + blockCmd := "nft add rule inet filter output drop" + + for _, cmd := range cmds { + if err := runCommand(cmd); err != nil { + return nil + } + } + + for _, ip := range ips { + if err := runCommand(fmt.Sprintf(ipCmdTemplate, ip)); err != nil { + return nil + } + } + + if err := runCommand(blockCmd); err != nil { + return nil + } + + return nil + } + + if err := updateWhitelist(); err != nil { + return err + } + + if _, err := scheduler.Cron(cron).Do(updateWhitelist); err != nil { + return err + } + scheduler.StartAsync() + + return nil +} + +func runCommand(cmdStr string) error { + cmd := exec.Command("sh", "-c", cmdStr) + if output, err := cmd.CombinedOutput(); err != nil { + return fmt.Errorf("command failed: %s, output: %s", err, output) + } + return nil +} + +func whiteList(configFileUrl string) ([]string, error) { + var cfg environment.Config + var err error + + if configFileUrl != "" { + cfg, err = environment.GetConfigForUrl(configFileUrl) + if err != nil { + return nil, err + } + } else { + cfg, err = environment.GetConfig() + if err != nil { + return nil, err + } + } + + return cfg.Whitelist.Ips, nil +}