Steven Polley
05e37193b4
Instead of using the hardcoded proof of concept for iptables, the success action is now read from the hypd configuration file and whatever is defined there is executed.
69 lines
2.6 KiB
Go
69 lines
2.6 KiB
Go
package configuration
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
)
|
|
|
|
type HypdConfiguration struct {
|
|
NetworkInterface string `json:"networkInterface"` // The network interface that the eBPF program attaches to
|
|
PreSharedKeyDirectory string `json:"preSharedKeyDirectory"` // hypd will load all *.secret files from this directory
|
|
SuccessAction string `json:"successAction"` // The action to take for a successful knock, each argument is a separate string
|
|
TimeoutSeconds int `json:"timeoutSeconds"` // If > 0, once a knock sequence has been successful this value will count down and when it reaches 0, it will perform the TimeoutAction on the client
|
|
TimeoutAction string `json:"timeoutAction"` // The action to take after TimeoutSeconds has elapsed. only applicable if TimeoutSeconds is > 0, each argument is a separate string
|
|
|
|
}
|
|
|
|
// LoadConfiguration opens and parses the configuration file into a HypdConfiguration struct
|
|
// If a configFilePath is not specified, it will search in common locations
|
|
func LoadConfiguration(configFilePath string) (*HypdConfiguration, error) {
|
|
if configFilePath == "" {
|
|
commonLocations := []string{"hypdconfig.json",
|
|
"~/.hypdconfig.json",
|
|
"~/.config/hyp/hypdConfig.json",
|
|
"/etc/hyp/hypdConfig.json",
|
|
"/usr/local/etc/hyp/hypdConfig.json",
|
|
}
|
|
|
|
for _, loc := range commonLocations {
|
|
if _, err := os.Stat(loc); err == nil {
|
|
configFilePath = loc
|
|
break
|
|
}
|
|
}
|
|
}
|
|
// if it's still not found after checking common locations, load default config
|
|
if configFilePath == "" {
|
|
fmt.Println("no configuration file found. You can generate one with ./hypd generate defaultconfig | tee hypdconfig.json")
|
|
return DefaultConfig(), nil
|
|
}
|
|
|
|
// Otherwise if a config is specified, try to load it and error if it fails.
|
|
// I think it's better to error here if a config was intended and failed
|
|
// rather than failing back to default
|
|
|
|
b, err := os.ReadFile(configFilePath)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to read config file '%s': %w", configFilePath, err)
|
|
}
|
|
|
|
hypdConfiguration := &HypdConfiguration{}
|
|
err = json.Unmarshal(b, hypdConfiguration)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to unmarshal config file json to HypdConfiguration (is the config file malformed?): %w", err)
|
|
}
|
|
|
|
return hypdConfiguration, nil
|
|
}
|
|
|
|
func DefaultConfig() *HypdConfiguration {
|
|
return &HypdConfiguration{
|
|
NetworkInterface: "enp0s3",
|
|
PreSharedKeyDirectory: "./secrets/",
|
|
SuccessAction: "iptables -A INPUT -p tcp -s %s --dport 22 -j ACCEPT",
|
|
TimeoutSeconds: 1440,
|
|
TimeoutAction: "iptables -D INPUT -p tcp -s %s --dport 22 -j ACCEPT",
|
|
}
|
|
}
|