apiary/honeypot/ports/server.go
2021-10-28 16:09:28 +02:00

97 lines
2.1 KiB
Go

package ports
import (
"context"
"fmt"
"net"
"time"
"go.uber.org/zap"
)
type Server struct {
EnabledPortsTCP []string
EnabledPortsUDP []string
IP string
Logger *zap.SugaredLogger
store Store
}
func New(store Store) *Server {
return &Server{store: store, Logger: zap.NewNop().Sugar()}
}
func (s *Server) Start(ctx context.Context) error {
for _, port := range s.EnabledPortsTCP {
portCtx, cancel := context.WithCancel(ctx)
go s.doListenTCP(portCtx, port)
defer cancel()
}
<-ctx.Done()
return nil
}
func (s *Server) AddTCPPort(port string) {
s.EnabledPortsTCP = append(s.EnabledPortsTCP, port)
}
func (s *Server) doListenTCP(ctx context.Context, port string) error {
lAddr, err := net.ResolveTCPAddr("tcp", net.JoinHostPort(s.IP, port))
if err != nil {
s.Logger.Warnw("Error resoling listening addr.", "network", "tcp", "port", port)
return fmt.Errorf("error resolving listening address: %w", err)
}
listener, err := net.ListenTCP("tcp", lAddr)
if err != nil {
return fmt.Errorf("error starting listener: %w", err)
}
defer listener.Close()
go func() {
<-ctx.Done()
s.Logger.Debug("Listener context cancelled.")
listener.Close()
}()
s.Logger.Infow("Listening for connections to TCP port.", "port", port)
for {
conn, err := listener.Accept()
if err != nil {
select {
case <-ctx.Done():
s.Logger.Infow("Listener shutting down.", "port", port, "network", "tcp")
return nil
default:
s.Logger.Infow("Error accepting connection.", "error", err)
continue
}
}
s.Logger.Infow("Got connection on port.", "port", port, "network", "tcp", "remote_addr", conn.RemoteAddr().String())
conn.SetReadDeadline(time.Now().Add(time.Second * 15))
buf := make([]byte, 256)
_, err = conn.Read(buf)
if err != nil {
buf = []byte{}
}
attempt := &ConnectionAttempt{
Port: port,
Network: "tcp",
From: conn.RemoteAddr().String(),
Data: buf,
}
conn.Close()
if err := s.store.Add(attempt); err != nil {
s.Logger.Warnw("Error storing attempt in store.", "error", err)
}
}
}