diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index c5ec3cf..1cf452b 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -1,6 +1,8 @@ # Based on https://github.com/mvdan/github-actions-golang on: [push, pull_request, workflow_dispatch] + name: Tests + jobs: test: strategy: @@ -19,7 +21,7 @@ jobs: steps: - uses: golang/govulncheck-action@v1 with: - go-version-input: 1.22.2 + go-version-input: 1.22.4 gocritic: runs-on: ubuntu-latest steps: diff --git a/hpot.go b/hpot.go index b984236..3c70b45 100644 --- a/hpot.go +++ b/hpot.go @@ -1,8 +1,10 @@ package hpot import ( + "encoding/json" "flag" "fmt" + "log/slog" "net" "net/http" "os" @@ -20,6 +22,8 @@ type Pot struct { mu sync.Mutex records []net.Addr + + Log slog.Logger } // NewHoneyPotServer returns default, unstarted HoneyPot @@ -28,6 +32,7 @@ func NewHoneyPotServer() *Pot { return &Pot{ Verbose: false, AdminPort: 8085, + Log: *slog.New(slog.NewJSONHandler(os.Stdout, nil)), } } @@ -58,8 +63,17 @@ func (p *Pot) ListenAndServe() error { mux.HandleFunc("/metrics", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "%d\n", p.NumConnections()) }) + mux.HandleFunc("/ports", func(w http.ResponseWriter, r *http.Request) { - fmt.Fprintf(w, "%d\n", p.OpenPorts()) + openPorts := struct { + OpenPorts []int `json:"openPorts"` + }{ + OpenPorts: p.OpenPorts(), + } + err := json.NewEncoder(w).Encode(openPorts) + if err != nil { + return + } }) s := &http.Server{ @@ -70,9 +84,7 @@ func (p *Pot) ListenAndServe() error { } go func() { - if p.Verbose { - fmt.Println("Starting admin server on:", s.Addr) - } + p.Log.Info("starting admin server", "port", s.Addr) if err := s.ListenAndServe(); err != nil { panic(err) } @@ -83,9 +95,7 @@ func (p *Pot) ListenAndServe() error { if err != nil { return err } - if p.Verbose { - fmt.Println("Starting listener on:", l.Addr().String()) - } + p.Log.Info("starting listener", "port", l.Addr().String()) go p.serve(l) } // implement context @@ -99,13 +109,10 @@ func (p *Pot) serve(l net.Listener) { if err != nil { fmt.Fprintln(os.Stdout, err) } - if p.Verbose { - fmt.Println("Incomming connection from: ", conn.RemoteAddr()) - } + p.Log.Info("incomming connection", "address", conn.RemoteAddr().String()) p.mu.Lock() p.records = append(p.records, conn.RemoteAddr()) p.mu.Unlock() - conn.Close() } } @@ -124,9 +131,9 @@ func parsePorts(ports string) ([]int, error) { return prts, nil } -var usage = `Usage: hpot [-v] port,port,port +var usage = `Usage: hpot [-v] [--admin=port] port1,port2,port3 -Start the HopneyPot and listen on incoming connections on provided, coma separated ports. +Start the HopneyPot and listen on incoming connections on provided, comma-separated ports. In verbose mode (-v), reports all incoming connections.` diff --git a/hpot_test.go b/hpot_test.go index 3bd72af..682bf48 100644 --- a/hpot_test.go +++ b/hpot_test.go @@ -3,6 +3,7 @@ package hpot_test import ( "fmt" "io" + "log/slog" "net" "net/http" "testing" @@ -21,6 +22,7 @@ func TestHoneypotAcceptsConection(t *testing.T) { pot := hpot.NewHoneyPotServer() pot.AdminPort = randomFreePort() pot.Ports = []int{port1, port2} + pot.Log = *slog.New(slog.NewJSONHandler(io.Discard, nil)) go func() { if err := pot.ListenAndServe(); err != nil { @@ -55,6 +57,7 @@ func TestPotReturnsConnectionCount(t *testing.T) { pot := hpot.NewHoneyPotServer() pot.AdminPort = randomFreePort() pot.Ports = []int{port} + pot.Log = *slog.New(slog.NewJSONHandler(io.Discard, nil)) go func() { if err := pot.ListenAndServe(); err != nil { @@ -80,13 +83,15 @@ func TestPotReturnsConnectionCount(t *testing.T) { } } -func TestPotReturnOpenPorts(t *testing.T) { +func TestPotReportsOpenPortsItsListeningOn(t *testing.T) { t.Parallel() - port := randomFreePort() + port1 := randomFreePort() + port2 := randomFreePort() pot := hpot.NewHoneyPotServer() pot.AdminPort = randomFreePort() - pot.Ports = []int{port} + pot.Ports = []int{port1, port2} + pot.Log = *slog.New(slog.NewJSONHandler(io.Discard, nil)) go func() { if err := pot.ListenAndServe(); err != nil { @@ -95,7 +100,7 @@ func TestPotReturnOpenPorts(t *testing.T) { }() got := getOpenPorts(t, pot.AdminPort) - want := fmt.Sprintf("[%d]\n", port) + want := fmt.Sprintf("{\"openPorts\":[%d,%d]}\n", port1, port2) if want != got { t.Error(cmp.Diff(want, got))