diff options
| author | Marin Ivanov <[email protected]> | 2019-04-26 10:41:44 +0300 |
|---|---|---|
| committer | Marin Ivanov <[email protected]> | 2019-04-26 16:17:07 +0300 |
| commit | 174e6b2bbdd299b478ae00875d265c06459c5ad0 (patch) | |
| tree | 91a698f0d0d04e4817df71b737ba80965e7c856f | |
| parent | 71de5fe35cf826f700459c511ecfd89c6d9f789f (diff) | |
Add HTTP protocol tarpit
| -rw-r--r-- | README.md | 9 | ||||
| -rw-r--r-- | handle.go | 8 | ||||
| -rw-r--r-- | http.go | 39 | ||||
| -rw-r--r-- | main.go | 14 |
4 files changed, 58 insertions, 12 deletions
@@ -3,6 +3,7 @@ Tarpit command application that may slow down malicious attempts to scan a syste Supported Protocols: - SSH +- HTTP # Building and Running @@ -13,11 +14,11 @@ GOOS=linux GOARCH=amd64 go build -o "build/tarpit-linux-amd64" This command will build the application in `build/tarpit-linux-amd64`. We can then run the tarpit on an unprivileged port (e.g. 2222). -`$ ./build/tarpit-linux-amd64 -p 2222` +`$ ./build/tarpit-linux-amd64 -P ssh -p 2222` Or you can run it on a privileged port with `sudo`. -`$ sudo ./build/tarpit-linux-amd64 -p 22` +`$ sudo ./build/tarpit-linux-amd64 -P ssh -p 22` ## Options @@ -26,7 +27,7 @@ Usage of ./tarpit: -b, --bind-address string address to bind the socket to -d, --delay string delay between the tarpit keep-alive data packets (default "10s") -g, --gid uint16 setgid, after creating a listening socket - -p, --port uint16 TCP port (default 22) + -p, --port uint16 TCP port, leave it 0 for service default -P, --proto string protocol to tarpit (default "ssh") -u, --uid uint16 setuid, after creating a listening socket -v, --version show current version @@ -36,7 +37,7 @@ Usage of ./tarpit: The ports `< 1024` require superuser privileges. The command allows to drop superuser privileges (using setuid/setgid), right after it acquires a listening socket. Thus, allowing to bind to a privileged port and start serving as a regular unprivileged user. This is done by running the command as a superuser (e.g. with `sudo`) and setting the `-u/--uid <uid>` and `-g/--gid <gid>` command line flags. -`$ sudo ./build/tarpit-linux-amd64 -p 22 -u "$(id -u)" -g "$(id -g)"` +`$ sudo ./build/tarpit-linux-amd64 -P ssh -p 22 -u "$(id -u)" -g "$(id -g)"` # Acknowledgements @@ -9,12 +9,14 @@ import ( type empty struct{} type protoHandler func(net.Conn, time.Duration) -func protocolHandler(proto string) (protoHandler, error) { +func protocolHandler(proto string) (protoHandler, uint16, error) { switch proto { case "ssh": - return sshHandler, nil + return sshHandler, 22, nil + case "http": + return httpHandler, 80, nil default: - return nil, fmt.Errorf("unknown protocol '%s'", proto) + return nil, 0, fmt.Errorf("unknown protocol '%s'", proto) } } @@ -0,0 +1,39 @@ +package main + +import ( + "bufio" + "fmt" + "io" + "io/ioutil" + "math/rand" + "net" + "time" +) + +func httpHandler(conn net.Conn, delay time.Duration) { + rd := bufio.NewReader(conn) + rd.ReadLine() + _, err := fmt.Fprintf(conn, "HTTP/1.1 200 OK\r\n") + if err != nil { + return + } + + eof := make(chan empty) + go func() { + io.Copy(ioutil.Discard, conn) + eof <- empty{} + }() + + tick := time.Tick(delay) + for { + select { + case <-eof: + return + case <-tick: + _, err := fmt.Fprintf(conn, "X-%x: %x\r\n", rand.Uint32(), rand.Uint32()) + if err != nil { + return + } + } + } +} @@ -29,7 +29,7 @@ func main() { flag.StringVarP(&protocol, "proto", "P", "ssh", "protocol to tarpit") flag.StringVarP(&delayParam, "delay", "d", "10s", "delay between the tarpit keep-alive data packets") flag.StringVarP(&bindAddr, "bind-address", "b", "", "address to bind the socket to") - flag.Uint16VarP(&port, "port", "p", 22, "TCP port") + flag.Uint16VarP(&port, "port", "p", 0, "TCP port, leave it 0 for service default") flag.Uint16VarP(&uid, "uid", "u", 0, "setuid, after creating a listening socket") flag.Uint16VarP(&gid, "gid", "g", 0, "setgid, after creating a listening socket") flag.BoolVarP(&versionFlag, "version", "v", false, "show current version") @@ -40,8 +40,11 @@ func main() { return } - handler, err := protocolHandler(protocol) + handler, defaultPort, err := protocolHandler(protocol) assert(err, "protocol handler", configErrorCode) + if port == 0 { + port = defaultPort + } delay, err := time.ParseDuration(delayParam) assert(err, "parse delay", configErrorCode) @@ -69,8 +72,9 @@ func main() { } func assert(err error, msg string, code int) { - if err != nil { - fmt.Fprintf(os.Stderr, "ERR: %s; %s \n", msg, err.Error()) - os.Exit(code) + if err == nil { + return } + fmt.Fprintf(os.Stderr, "ERR: %s; %s \n", msg, err.Error()) + os.Exit(code) } |
