-
Notifications
You must be signed in to change notification settings - Fork 0
/
tarpit.py
executable file
·132 lines (95 loc) · 3.88 KB
/
tarpit.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#!/usr/bin/env python3
##
## Inspired by the post https://nullprogram.com/blog/2019/03/22/. All credit to
## Chris Wellons for the initial implementation of both HTTP and SSH tarpits, which
## I have shamelessly smashed together here
##
import argparse
import asyncio
import random
try:
r = random.SystemRandom()
except:
r = random.Random()
verbosity = 0
async def ssh_handler(_reader, writer):
if (verbosity >= 1):
addr = writer.get_extra_info('peername')
print(f'SSH connected: {addr!r}')
try:
while True:
await asyncio.sleep(r.randint(10,20))
writer.write(b'%x\r\n' % r.randint(0, 2**32))
await writer.drain()
except ConnectionResetError:
if (verbosity >= 1):
print(f'SSH disconnected: {addr!r}')
async def ssh_tarpit(port):
if(verbosity >= 1):
print(f'SSH tarpit enabled on port {port}')
server = await asyncio.start_server(ssh_handler, '0.0.0.0', port)
async with server:
await server.serve_forever()
async def http_handler(_reader, writer):
if (verbosity >= 1):
addr = writer.get_extra_info('peername')
print(f'HTTP connected: {addr!r}')
writer.write(b'HTTP/1.1 200 OK\r\n')
try:
while True:
await asyncio.sleep(r.randint(10,20))
writer.write(b'X-%x: %x\r\n' % (r.randint(0, 2**32), r.randint(0, 2**32)))
await writer.drain()
except ConnectionResetError:
if (verbosity >= 1):
print(f'HTTP disconnected: {addr!r}')
async def http_tarpit(port):
if(verbosity >= 1):
print(f'HTTP tarpit enabled on port {port}')
server = await asyncio.start_server(http_handler, '0.0.0.0', port)
async with server:
await server.serve_forever()
async def smtp_handler(_reader, writer):
if (verbosity >= 1):
addr = writer.get_extra_info('peername')
print(f'SMTP connected: {addr!r}')
try:
while True:
await asyncio.sleep(r.randint(10,20))
writer.write(b'220-%x\r\n' % r.randint(0, 2**32))
await writer.drain()
except ConnectionResetError:
if (verbosity >= 1):
print(f'SMTP disconnected: {addr!r}')
async def smtp_tarpit(port):
if(verbosity >= 1):
print(f'SMTP tarpit enabled on port {port}')
server = await asyncio.start_server(smtp_handler, '0.0.0.0', port, limit=1024)
async with server:
await server.serve_forever()
def parse_args():
parser = argparse.ArgumentParser(description='Tarpit for various services', formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('--verbose', '-v', action='count', default=verbosity)
parser.add_argument('mode', action='store', nargs='+', choices=['ssh','http','smtp', 'all'], help='enable the specified tarpit(s)')
parser.add_argument('--ssh-port', action='store', type=int, default=2222, help='serve the SSH tarpit on the specified port', metavar='port')
parser.add_argument('--http-port', action='store', type=int, default=8080, help='serve the HTTP tarpit on the specified port', metavar='port')
parser.add_argument('--smtp-port', action='store', type=int, default=2525, help='serve the SMTP tarpit on the specified port', metavar='port')
return parser.parse_args()
def main():
tasks = list()
args = parse_args()
global verbosity
verbosity = args.verbose
if('ssh' in args.mode or 'all' in args.mode):
tasks.append(ssh_tarpit(args.ssh_port))
if('http' in args.mode or 'all' in args.mode):
tasks.append(http_tarpit(args.http_port))
if('smtp' in args.mode or 'all' in args.mode):
tasks.append(smtp_tarpit(args.smtp_port))
try:
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))
except KeyboardInterrupt:
print('Terminated')
if __name__ == '__main__':
main()