diff --git a/.gitignore b/.gitignore index 0e6d7bb..9ce6d70 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ hyp.secret *.exe hypd/hypd hyp/hyp +hypdconfig.json \ No newline at end of file diff --git a/hypd/cmd/defaultconfig.go b/hypd/cmd/defaultconfig.go index 29957f0..d05e868 100644 --- a/hypd/cmd/defaultconfig.go +++ b/hypd/cmd/defaultconfig.go @@ -16,7 +16,9 @@ var defaultconfigCmd = &cobra.Command{ Use: "defaultconfig", Short: "Prints the default configuration to stdout", Long: `The default configuration is used if one is not set. The default configuration - can be used as a reference to build your own. `, +can be used as a reference to build your own. + +hypd generate defaultconfig | tee hypdconfig.json`, Run: func(cmd *cobra.Command, args []string) { config := configuration.DefaultConfig() b, err := json.MarshalIndent(config, "", " ") diff --git a/hypd/cmd/server.go b/hypd/cmd/server.go index 8fb62e0..8f9ddf3 100644 --- a/hypd/cmd/server.go +++ b/hypd/cmd/server.go @@ -5,6 +5,7 @@ package cmd import ( "fmt" + "os/user" "deadbeef.codes/steven/hyp/hypd/configuration" "deadbeef.codes/steven/hyp/hypd/server" @@ -13,34 +14,43 @@ import ( // serverCmd represents the server command var serverCmd = &cobra.Command{ - Use: "server ", + Use: "server ", Args: cobra.ExactArgs(1), Short: "Runs hyp in server mode", - Long: `Runs the hyp server and begins capture on the NIC specified + Long: `Runs the hyp server and begins watching for authentic knock sequences. + +Before running this command, you must first have a configuration file. You can +generate a configuration file with: hypd generate defaultconfig > hypdconfig.json + +You should then edit the config file to meet your needs. + +In addition to a config file you will need to generate pre-shared keys: +mkdir -p ./secrets +hypd generate secret > secrets/mykey.secret Example Usage: - # Linux - capture enp0s0 - hyp server enp0s0 - - # Linux - capture eth0 - hyp server eth0 - - # Windows - get-netadapter | where {$_.Name -eq “Ethernet”} | Select-Object -Property DeviceName - hyp.exe server "\\Device\\NPF_{A6F067DE-C2DC-4B4E-9C74-BE649C4C0F03}" + # Use config file in local directory + hypd server hypdconfig.json + # Use config file in /etc/hyp/ + hypd server /etc/hyp/hypdconfig.json `, Run: func(cmd *cobra.Command, args []string) { - configFile, err := cmd.Flags().GetString("configfile") + + currentUser, err := user.Current() if err != nil { - panic(fmt.Errorf("failed to get configfile flag: %w", err)) + panic(fmt.Errorf("could not determine current user: %w", err)) } - hypdConfiguration, err := configuration.LoadConfiguration(configFile) + if currentUser.Username != "root" { + fmt.Println("WARNING: It's recommended you run this as root, but will proceed anyways...") + } + + hypdConfiguration, err := configuration.LoadConfiguration(args[0]) if err != nil { panic(fmt.Errorf("failed to start packet server: %w", err)) } - - err = server.PacketServer(args[0], hypdConfiguration) + err = server.PacketServer(hypdConfiguration) if err != nil { panic(fmt.Errorf("failed to start packet server: %w", err)) } @@ -50,6 +60,4 @@ Example Usage: func init() { rootCmd.AddCommand(serverCmd) - serverCmd.PersistentFlags().String("configfile", "", "Path to the file containing the hypd configuration.") - } diff --git a/hypd/configuration/configuration.go b/hypd/configuration/configuration.go index a6ff44a..38ce2db 100644 --- a/hypd/configuration/configuration.go +++ b/hypd/configuration/configuration.go @@ -7,6 +7,7 @@ import ( ) type HypdConfiguration struct { + NetworkInterface string `json:"networkInterface"` 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. @@ -19,6 +20,7 @@ type HypdConfiguration struct { 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", @@ -33,6 +35,7 @@ func LoadConfiguration(configFilePath string) (*HypdConfiguration, error) { } // 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 } @@ -45,17 +48,18 @@ func LoadConfiguration(configFilePath string) (*HypdConfiguration, error) { return nil, fmt.Errorf("failed to read config file '%s': %w", configFilePath, err) } - var hypdConfiguration *HypdConfiguration + 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 nil, nil + 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, diff --git a/hypd/server/packet.go b/hypd/server/packet.go index e1f08b7..a90b4f0 100644 --- a/hypd/server/packet.go +++ b/hypd/server/packet.go @@ -49,11 +49,11 @@ var ( // 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(captureDevice string, config *configuration.HypdConfiguration) error { +func PacketServer(config *configuration.HypdConfiguration) error { - iface, err := net.InterfaceByName(captureDevice) + iface, err := net.InterfaceByName(config.NetworkInterface) if err != nil { - log.Fatalf("lookup network iface %q: %v", captureDevice, err) + log.Fatalf("lookup network iface %q: %v", config.NetworkInterface, err) } secretBytes, err := os.ReadFile("hyp.secret")