diff --git a/.gitignore b/.gitignore index 035fc7b..2dffc27 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ hyp.secret *.exe -hypd -hyp \ No newline at end of file +hypd/hypd +hyp/hyp \ No newline at end of file diff --git a/client/go.mod b/client/go.mod deleted file mode 100644 index 7bf4322..0000000 --- a/client/go.mod +++ /dev/null @@ -1,5 +0,0 @@ -module deadbeef.codes/steven/hyp - -go 1.22.0 - -require deadbeef.codes/steven/hyp/otphyp v0.0.0-20240407135923-27c2f284299f diff --git a/client/go.sum b/client/go.sum deleted file mode 100644 index 2e3122d..0000000 --- a/client/go.sum +++ /dev/null @@ -1,4 +0,0 @@ -deadbeef.codes/steven/hyp/otphyp v0.0.0-20240407035202-7ccdf4d89fee h1:r9xdoIGPhc/tXzyOj+lCDb+ReYa/zkysqK3ZRCqpyIU= -deadbeef.codes/steven/hyp/otphyp v0.0.0-20240407035202-7ccdf4d89fee/go.mod h1:NANpGD/K+nDkW+bkomchwaXMrsXWza58+8AR7Sau3fs= -deadbeef.codes/steven/hyp/otphyp v0.0.0-20240407135923-27c2f284299f h1:M+QxtB9hQ/+9MmvPtqOvXSL+LGU/f54VlPZHsM4Knao= -deadbeef.codes/steven/hyp/otphyp v0.0.0-20240407135923-27c2f284299f/go.mod h1:NANpGD/K+nDkW+bkomchwaXMrsXWza58+8AR7Sau3fs= diff --git a/client/main.go b/client/main.go deleted file mode 100644 index 1e866bd..0000000 --- a/client/main.go +++ /dev/null @@ -1,60 +0,0 @@ -package main - -import ( - "fmt" - "log" - "net" - "os" - "time" - - "deadbeef.codes/steven/hyp/otphyp" -) - -// MaxNetworkLatency specifies the number of milliseconds -// A packet-switched network... more like "race condition factory" -const MaxNetworkLatency = 500 - -func main() { - - // validate number of input arguments - if len(os.Args) < 2 { - usage() - os.Exit(1) - } - - // load secret and generate ports using secret and current time - secretBytes, err := os.ReadFile("hyp.secret") - if err != nil { - log.Fatalf("failed to read file 'hyp.secret': %v", err) - } - sharedSecret := string(secretBytes) - - ports, err := otphyp.GeneratePorts(sharedSecret, time.Now()) - if err != nil { - log.Fatalf("failed to generate ports from shared secret: %v", err) - } - - // Transmit - fmt.Println("Transmitting knock sequence:", ports) - for _, port := range ports { - conn, _ := net.Dial("udp", fmt.Sprintf("%s:%d", os.Args[1], port)) - conn.Write([]byte{0}) - conn.Close() - time.Sleep(time.Millisecond * MaxNetworkLatency) - } -} - -func usage() { - fmt.Print(`hyp - - Example Usage: - - # Transmit an authentic knock sequence to a server - hyp 10.69.4.20 - - # You can use a DNS name too - hyp hyp.stevenpolley.net - -`) - os.Exit(1) -} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..9b71328 --- /dev/null +++ b/go.mod @@ -0,0 +1,15 @@ +module deadbeef.codes/steven/hyp + +go 1.22.0 + +require ( + github.com/google/gopacket v1.1.19 + github.com/spf13/cobra v1.8.0 +) + +require ( + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + golang.org/x/net v0.19.0 // indirect + golang.org/x/sys v0.15.0 // indirect +) diff --git a/server/go.sum b/go.sum similarity index 55% rename from server/go.sum rename to go.sum index d652827..b443ba0 100644 --- a/server/go.sum +++ b/go.sum @@ -1,21 +1,28 @@ -deadbeef.codes/steven/hyp/otphyp v0.0.0-20240407035202-7ccdf4d89fee h1:r9xdoIGPhc/tXzyOj+lCDb+ReYa/zkysqK3ZRCqpyIU= -deadbeef.codes/steven/hyp/otphyp v0.0.0-20240407035202-7ccdf4d89fee/go.mod h1:NANpGD/K+nDkW+bkomchwaXMrsXWza58+8AR7Sau3fs= -deadbeef.codes/steven/hyp/otphyp v0.0.0-20240407135923-27c2f284299f h1:M+QxtB9hQ/+9MmvPtqOvXSL+LGU/f54VlPZHsM4Knao= -deadbeef.codes/steven/hyp/otphyp v0.0.0-20240407135923-27c2f284299f/go.mod h1:NANpGD/K+nDkW+bkomchwaXMrsXWza58+8AR7Sau3fs= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/go.work b/go.work deleted file mode 100644 index 9b1a11a..0000000 --- a/go.work +++ /dev/null @@ -1,7 +0,0 @@ -go 1.22.0 - -use ( - ./client - ./otphyp - ./server -) diff --git a/client/README.md b/hyp/README.md similarity index 69% rename from client/README.md rename to hyp/README.md index dcd7884..a307bb7 100644 --- a/client/README.md +++ b/hyp/README.md @@ -1,9 +1,9 @@ # hyp-client -The client expects there to be a file named hyp.secret in the same directory. This file is generated by the hypd server using ./hypd generatesecret. +The client expects there to be a file named hyp.secret in the same directory. This file is generated by the hypd server using ./hypd generate secret. ```bash # Example Usage -# ./hyp-client -./hyp-client 192.168.50.5 +# ./hyp knock +./hyp knock 192.168.50.5 ``` \ No newline at end of file diff --git a/hyp/cmd/knock.go b/hyp/cmd/knock.go new file mode 100644 index 0000000..c3e9829 --- /dev/null +++ b/hyp/cmd/knock.go @@ -0,0 +1,59 @@ +/* +Copyright © 2024 Steven Polley +*/ +package cmd + +import ( + "fmt" + "log" + "net" + "os" + "time" + + "deadbeef.codes/steven/hyp/otphyp" + "github.com/spf13/cobra" +) + +// knockCmd represents the knock command +var knockCmd = &cobra.Command{ + Use: "knock ", + Short: "Sends an authenticated knock sequence to the server specified", + Long: `Runs the hyp client and performs an authentic knock sequence +against the server provided. + +Example usage: + + hyp knock + + hyp knock hyp.deadbeef.codes + + hyp knock 10.69.4.20 + `, + Args: cobra.ExactArgs(1), + Run: func(cmd *cobra.Command, args []string) { + // load secret and generate ports using secret and current time + secretBytes, err := os.ReadFile("hyp.secret") + if err != nil { + log.Fatalf("failed to read file 'hyp.secret': %v", err) + } + sharedSecret := string(secretBytes) + + ports, err := otphyp.GeneratePorts(sharedSecret, time.Now()) + if err != nil { + log.Fatalf("failed to generate ports from shared secret: %v", err) + } + + // Transmit + fmt.Println("Transmitting knock sequence:", ports) + for _, port := range ports { + conn, _ := net.Dial("udp", fmt.Sprintf("%s:%d", os.Args[1], port)) + conn.Write([]byte{0}) + conn.Close() + time.Sleep(time.Millisecond * 200) // TBD: Make this configurable with flag (maxJitter) + } + }, +} + +func init() { + rootCmd.AddCommand(knockCmd) +} diff --git a/hyp/cmd/root.go b/hyp/cmd/root.go new file mode 100644 index 0000000..d6be390 --- /dev/null +++ b/hyp/cmd/root.go @@ -0,0 +1,33 @@ +/* +Copyright © 2024 Steven Polley +*/ +package cmd + +import ( + "os" + + "github.com/spf13/cobra" +) + +// rootCmd represents the base command when called without any subcommands +var rootCmd = &cobra.Command{ + Use: "hyp", + Short: "Hide Your Ports Client", + Long: `Hide Your Ports (hyp) is a combination of Port Knocking and One Time Passwords: + +hyp uses a pre-shared key distributed between the server and client, as well as the time +to calculate a unique authentic knock sequence which is only valid for 90 seconds.`, +} + +// Execute adds all child commands to the root command and sets flags appropriately. +// This is called by main.main(). It only needs to happen once to the rootCmd. +func Execute() { + err := rootCmd.Execute() + if err != nil { + os.Exit(1) + } +} + +func init() { + +} diff --git a/hyp/main.go b/hyp/main.go new file mode 100644 index 0000000..715187a --- /dev/null +++ b/hyp/main.go @@ -0,0 +1,10 @@ +/* +Copyright © 2024 Steven Polley +*/ +package main + +import "deadbeef.codes/steven/hyp/hyp/cmd" + +func main() { + cmd.Execute() +} diff --git a/hypd/README.md b/hypd/README.md new file mode 100644 index 0000000..fa4436b --- /dev/null +++ b/hypd/README.md @@ -0,0 +1,12 @@ +# hyp server + +hyp server is the port knocking daemon which listens for incoming authentic knock sequences. + +### Usage + +##### Starting the server + +```bash +# As root - or user that can capture packets and modify IPTables +./hypd server eth0 +``` \ No newline at end of file diff --git a/hypd/cmd/generate.go b/hypd/cmd/generate.go new file mode 100644 index 0000000..c44a429 --- /dev/null +++ b/hypd/cmd/generate.go @@ -0,0 +1,18 @@ +/* +Copyright © 2024 Steven Polley +*/ +package cmd + +import ( + "github.com/spf13/cobra" +) + +// generateCmd represents the generate command +var generateCmd = &cobra.Command{ + Use: "generate", + Short: "Generates configuration for Hide Your Ports", +} + +func init() { + rootCmd.AddCommand(generateCmd) +} diff --git a/hypd/cmd/root.go b/hypd/cmd/root.go new file mode 100644 index 0000000..7374d11 --- /dev/null +++ b/hypd/cmd/root.go @@ -0,0 +1,33 @@ +/* +Copyright © 2024 Steven Polley +*/ +package cmd + +import ( + "os" + + "github.com/spf13/cobra" +) + +// rootCmd represents the base command when called without any subcommands +var rootCmd = &cobra.Command{ + Use: "hypd", + Short: "Hide Your Ports Daemon", + Long: `Hide Your Ports (hyp) is a combination of Port Knocking and One Time Passwords: + +hyp uses a pre-shared key distributed between the server and client, as well as the time +to calculate a unique authentic knock sequence which is only valid for 90 seconds.`, +} + +// Execute adds all child commands to the root command and sets flags appropriately. +// This is called by main.main(). It only needs to happen once to the rootCmd. +func Execute() { + err := rootCmd.Execute() + if err != nil { + os.Exit(1) + } +} + +func init() { + +} diff --git a/hypd/cmd/secret.go b/hypd/cmd/secret.go new file mode 100644 index 0000000..a3f5223 --- /dev/null +++ b/hypd/cmd/secret.go @@ -0,0 +1,44 @@ +/* +Copyright © 2024 Steven Polley +*/ +package cmd + +import ( + "fmt" + + "deadbeef.codes/steven/hyp/otphyp" + "github.com/spf13/cobra" +) + +// secretCmd represents the secret command +var secretCmd = &cobra.Command{ + Use: "secret", + Short: "Generates a secret key for hyp", + Long: `Generates a secret for hyp which should be distributed to both the +server and to clients. + +Example: + +hypd generatesecret > hyp.secret`, + Run: func(cmd *cobra.Command, args []string) { + sharedSecret, err := otphyp.GenerateSecret() + if err != nil { + panic(fmt.Errorf("failed to generate shared secret: %w", err)) + } + fmt.Println(sharedSecret) + }, +} + +func init() { + generateCmd.AddCommand(secretCmd) + + // Here you will define your flags and configuration settings. + + // Cobra supports Persistent Flags which will work for this command + // and all subcommands, e.g.: + // secretCmd.PersistentFlags().String("foo", "", "A help for foo") + + // Cobra supports local flags which will only run when this command + // is called directly, e.g.: + // secretCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") +} diff --git a/hypd/cmd/server.go b/hypd/cmd/server.go new file mode 100644 index 0000000..8a2cfeb --- /dev/null +++ b/hypd/cmd/server.go @@ -0,0 +1,61 @@ +/* +Copyright © 2024 Steven Polley +*/ +package cmd + +import ( + "fmt" + + "deadbeef.codes/steven/hyp/hypd/server" + "github.com/spf13/cobra" +) + +// serverCmd represents the server command +var serverCmd = &cobra.Command{ + Use: "server ", + Args: cobra.ExactArgs(1), + Short: "Runs hyp in server mode", + Long: `Runs the hyp server and begins capture on the NIC specified + +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}" + + `, + Run: func(cmd *cobra.Command, args []string) { + err := server.PacketServer(args[0]) + if err != nil { + panic(fmt.Errorf("failed to start packet server: %w", err)) + } + + }, +} + +func init() { + rootCmd.AddCommand(serverCmd) + /* + viper.SetConfigName("hypconfig") + viper.SetConfigType("yaml") + viper.AddConfigPath("/etc/hyp/") + viper.AddConfigPath("$HOME/.hyp") + viper.AddConfigPath(".") + viper.SetDefault("RefreshInterval", 7200) + + if err := viper.ReadInConfig(); err != nil { + if _, ok := err.(viper.ConfigFileNotFoundError); ok { + // Config file not found + // TBD: Implement + } else { + // Config file was found, but another error was produced + panic(fmt.Errorf("failed reading existing config file: %w", err)) + } + }*/ + +} diff --git a/hypd/main.go b/hypd/main.go new file mode 100644 index 0000000..32b1c8e --- /dev/null +++ b/hypd/main.go @@ -0,0 +1,10 @@ +/* +Copyright © 2024 Steven Polley +*/ +package main + +import "deadbeef.codes/steven/hyp/hypd/cmd" + +func main() { + cmd.Execute() +} diff --git a/server/packet.go b/hypd/server/packet.go similarity index 78% rename from server/packet.go rename to hypd/server/packet.go index d310e67..c02b63f 100644 --- a/server/packet.go +++ b/hypd/server/packet.go @@ -1,9 +1,15 @@ -package main +/* +Copyright © 2024 Steven Polley +*/ + +package server import ( "encoding/binary" "fmt" "log" + "os" + "os/exec" "time" "deadbeef.codes/steven/hyp/otphyp" @@ -13,8 +19,9 @@ import ( // Client is used to keep track of a client attempting to perform an authentic knock sequence type Client struct { - Progress int // index of current progress in sequence. Value of 1 means first port has been matched - Sequence [4]uint16 // stores the knock sequence the current client is attempting. It's set and tracked here to prevent race conditions during a knock sequence being received and key rotations + Progress int // index of current progress in sequence. Value of 1 means first port has been matched + Sequence [4]uint16 // stores the knock sequence the current client is attempting. It's set and tracked here to prevent race conditions during a knock sequence being received and key rotations + LastUpdated time.Time // The last time the client sent a correct packet in the sequence } // KnockSequence is used keep track of an ordered knock sequence and whether it's been marked for use (to prevent replay attacks) @@ -32,14 +39,20 @@ 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) { - clients = make(map[string]*Client, 0) // key is source IP address, value is the current progress through the sequence. i.e. value of 1 means that the first port in the sequence was successful - knockSequences = []KnockSequence{} // Slice of accepted port sequences, there have to be several to account for clock skew between client and server +func PacketServer(captureDevice string) error { + secretBytes, err := os.ReadFile("hyp.secret") + if err != nil { + log.Fatalf("failed to read file 'hyp.secret': %v", err) + } + sharedSecret = string(secretBytes) + + clients = make(map[string]*Client, 0) + knockSequences = []KnockSequence{} // Open pcap handle on device handle, err := pcap.OpenLive(captureDevice, 1600, true, pcap.BlockForever) if err != nil { - log.Fatalf("failed to open adapter") + return fmt.Errorf("failed to open pcap on capture device: %w", err) } packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) @@ -50,6 +63,7 @@ func packetServer(captureDevice string) { for packet := range packetSource.Packets() { handlePacket(packet) // Do something with a packet here. } + return nil } // packets that match the BPF filter get passed to handlePacket @@ -139,3 +153,14 @@ func setPacketFilter(handle *pcap.Handle) error { } return nil } + +// TBD: Implement - this is a temporary routine to demonstrate an application +func handleSuccess(srcip string) { + fmt.Println("Success for ", srcip) + + cmd := exec.Command("iptables", "-A", "INPUT", "-p", "tcp", "-s", srcip, "--dport", "22", "-j", "ACCEPT") + err := cmd.Run() + if err != nil { + log.Printf("failed to execute iptables command for '%s': %v", srcip, err) + } +} diff --git a/otphyp/go.mod b/otphyp/go.mod deleted file mode 100644 index 5b74e82..0000000 --- a/otphyp/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module deadbeef.codes/steven/hyp/otphyp - -go 1.22.0 diff --git a/server/README.md b/server/README.md deleted file mode 100644 index 809f90a..0000000 --- a/server/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# hypd - -hypd is the hyp (Hide Your Ports) server. - -### Requirements - -On the server, libpcap-dev needs to be installed on linux or pcap from nmap.org on Windows. - -### Usage - -##### Generating a new shared key - -```bash -# As user that can write to current directory -./hypd generatesecret -``` - -Then copy the file to a client - -##### Starting the server - -```bash -# As root - or user that can capture packets and modify IPTables -./hypd server eth0 -``` \ No newline at end of file diff --git a/server/go.mod b/server/go.mod deleted file mode 100644 index bc3d01a..0000000 --- a/server/go.mod +++ /dev/null @@ -1,10 +0,0 @@ -module deadbeef.codes/steven/hypd - -go 1.22.0 - -require ( - deadbeef.codes/steven/hyp/otphyp v0.0.0-20240407135923-27c2f284299f - github.com/google/gopacket v1.1.19 -) - -require golang.org/x/sys v0.19.0 // indirect diff --git a/server/main.go b/server/main.go deleted file mode 100644 index 0f22d8c..0000000 --- a/server/main.go +++ /dev/null @@ -1,81 +0,0 @@ -package main - -import ( - "fmt" - "log" - "os" - "os/exec" - - "deadbeef.codes/steven/hyp/otphyp" -) - -func main() { - - if len(os.Args) < 2 { - usage() - } - - switch os.Args[1] { - case "generatesecret": - sharedSecret, err := otphyp.GenerateSecret() - if err != nil { - log.Fatalf("failed to generate shared secret: %v", err) - } - f, err := os.Create("hyp.secret") - if err != nil { - log.Fatalf("failed to create file 'hyp.secret': %v", err) - } - _, err = f.WriteString(sharedSecret) - if err != nil { - log.Fatalf("failed to write to file 'hyp.secret': %v", err) - } - f.Close() - fmt.Println("Created file hyp.secret") - case "server": - secretBytes, err := os.ReadFile("hyp.secret") - if err != nil { - log.Fatalf("failed to read file 'hyp.secret': %v", err) - } - sharedSecret = string(secretBytes) - if len(os.Args) < 3 { - usage() - } - packetServer(os.Args[2]) - default: - usage() - } - -} - -func usage() { - fmt.Print(`hypd - - Commands: - generatesecret - creates a pre shared key file named hyp.secret which can be distributed to a trusted client - server - runs the hypd server watching for an authentic knock sequence - - Example Usage: - - # Generate a secret, to be shared with a trusted client - hypd generatesecret - - # Linux - ip link - hypd server eth0 - - # Windows - get-netadapter | where {$_.Name -eq “Ethernet”} | Select-Object -Property DeviceName - hypd server "\\Device\\NPF_{A066F7DE-CC2D-4E4B-97C4-BF0EC4C03649}" - -`) - os.Exit(1) -} - -// TBD: Implement - this is a temporary routine to demonstrate an application -func handleSuccess(srcip string) { - fmt.Println("Success for ", srcip) - - cmd := exec.Command("iptables", "-A", "INPUT", "-p", "tcp", "-s", srcip, "--dport", "22", "-j", "ACCEPT") - err := cmd.Run() - if err != nil { - log.Printf("failed to execute iptables command for '%s': %v", srcip, err) - } -}