aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarin Ivanov <[email protected]>2019-04-26 10:41:44 +0300
committerMarin Ivanov <[email protected]>2019-04-26 16:17:07 +0300
commit174e6b2bbdd299b478ae00875d265c06459c5ad0 (patch)
tree91a698f0d0d04e4817df71b737ba80965e7c856f
parent71de5fe35cf826f700459c511ecfd89c6d9f789f (diff)
Add HTTP protocol tarpit
-rw-r--r--README.md9
-rw-r--r--handle.go8
-rw-r--r--http.go39
-rw-r--r--main.go14
4 files changed, 58 insertions, 12 deletions
diff --git a/README.md b/README.md
index 4cdc323..41576ed 100644
--- a/README.md
+++ b/README.md
@@ -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
diff --git a/handle.go b/handle.go
index 918f3a8..c153b7d 100644
--- a/handle.go
+++ b/handle.go
@@ -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)
}
}
diff --git a/http.go b/http.go
new file mode 100644
index 0000000..c8199a3
--- /dev/null
+++ b/http.go
@@ -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
+ }
+ }
+ }
+}
diff --git a/main.go b/main.go
index d83f018..4033688 100644
--- a/main.go
+++ b/main.go
@@ -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)
}