From 05e37193b4baff06d49eb0249e16197b95eccddd Mon Sep 17 00:00:00 2001 From: Steven Polley Date: Thu, 18 Apr 2024 11:22:03 -0600 Subject: [PATCH] Make the success action configurable 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. --- hypd/configuration/configuration.go | 8 ++++---- hypd/server/packet.go | 17 +++++++++++------ 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/hypd/configuration/configuration.go b/hypd/configuration/configuration.go index 38ce2db..3c50d36 100644 --- a/hypd/configuration/configuration.go +++ b/hypd/configuration/configuration.go @@ -7,11 +7,11 @@ import ( ) type HypdConfiguration struct { - NetworkInterface string `json:"networkInterface"` + 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 - 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 + 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 } diff --git a/hypd/server/packet.go b/hypd/server/packet.go index a8d2414..e85ed91 100644 --- a/hypd/server/packet.go +++ b/hypd/server/packet.go @@ -44,15 +44,17 @@ var ( clients map[uint32]*Client // Contains a map of clients, key is IPv4 address knockSequences []KnockSequence // We have 3 valid knock sequences at any time to account for clock skew sharedSecret string // base32 encoded shared secret used for totp + serverConfig *configuration.HypdConfiguration ) // PacketServer is the main function when operating in server mode // it sets up the pcap on the capture device and starts a goroutine // to rotate the knock sequence func PacketServer(config *configuration.HypdConfiguration) error { - iface, err := net.InterfaceByName(config.NetworkInterface) + serverConfig = config + iface, err := net.InterfaceByName(serverConfig.NetworkInterface) if err != nil { - log.Fatalf("lookup network iface %q: %v", config.NetworkInterface, err) + log.Fatalf("lookup network iface %q: %v", serverConfig.NetworkInterface, err) } secretBytes, err := os.ReadFile("hyp.secret") @@ -197,12 +199,15 @@ func rotateSequence() { } } -// TBD: Implement - this is a temporary routine to demonstrate an application +// handleSuccess is ran when a source IP successfully enters the authentic knock sequence +// the configured success action is ran func handleSuccess(srcip net.IP) { - fmt.Println("Success for ", srcip) - cmd := exec.Command("iptables", "-A", "INPUT", "-p", "tcp", "-s", fmt.Sprint(srcip), "--dport", "22", "-j", "ACCEPT") + fmt.Println("Successful knock from:", srcip) + // Don't care about command injection, the configuration file providing the command literally NEEDS to be trusted + // TBD: Use template / substitution instead of string formatting directive - allows for srcip token to be used multiple times + cmd := exec.Command("sh", "-c", fmt.Sprintf(serverConfig.SuccessAction, srcip)) err := cmd.Run() if err != nil { - log.Printf("failed to execute iptables command for '%s': %v", srcip, err) + log.Printf("failed to execute success action command for '%s': %v", srcip, err) } }