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
|
#!/usr/bin/python3
import asyncio
import os
import ssl
import re
def manyregex (string, patterns):
for pattern in patterns:
if re.search(pattern, string) != None:
return True
return False
async def cevovod (reader, writer, writer2, compiled):
buffer = b''
while True:
prebral = await reader.read(65536)
buffer += prebral
if manyregex(buffer, compiled):
break ## hacker detected
if len(buffer) > 65536:
buffer = buffer[-32768:]
if len(prebral) == 0:
break
writer.write(prebral)
writer.close()
writer2.close()
async def handle_client (reader, writer):
try:
compiled = []
reflags = re.ASCII | re.MULTILINE | re.DOTALL | re.VERBOSE
with open(os.getenv("WAF_REGEXES"), "rb") as rulesfile:
regexes = rulesfile.read().split(b"\n")
for regex in regexes:
if len(regex) == 0:
continue
compiled.append(re.compile(regex, reflags))
write_to_backend = b''
if os.getenv("WAF_HTTP"):
headers = []
while True:
line = (await reader.readuntil(b'\n')).replace(b'\r', b'').replace(b'\n', b'')
if not line.lower().startswith(b"accept-encoding:"):
write_to_backend += line + b"\r\n"
if len(line) == 0:
break
headers.append(line)
if headers[0].startswith(b"GET /waf HTTP/"):
writer.write(b"HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\n\r\nwaf works (: PID " + str(os.getpid()).encode() + b"\r\n")
writer.close()
return
context = None
if os.getenv("WAF_TLS"):
context = ssl.create_default_context()
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE
backendr, backendw = await asyncio.open_connection(os.getenv("WAF_BACKEND_HOST"), os.getenv("WAF_BACKEND_PORT"), ssl=context)
if manyregex(write_to_backend, compiled):
writer.write(b'HTTP/1.0 469 Hacking\r\nContent-Type: text/plain\r\n\r\nHacking is illegal according to ZEKom-2.\r\n')
backendw.close() ## hacker
writer.close()
return
backendw.write(write_to_backend)
except Exception as e:
writer.write(b"HTTP/1.0 569 Exception\r\nContent-Type: text/plain\r\n\r\n")
writer.write(str(e).encode())
writer.write(b"\r\n")
backendw.close()
writer.close()
raise e
else:
event_loop = asyncio.get_event_loop()
event_loop.create_task(cevovod(reader, backendw, writer, compiled))
event_loop.create_task(cevovod(backendr, writer, backendw, compiled))
async def run_server ():
context = None
if os.getenv("WAF_TLS"):
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
context.load_cert_chain(certfile=os.getenv("WAF_TLS"), keyfile=os.getenv("WAF_TLS_KEY"))
server = await asyncio.start_server(handle_client, os.getenv("WAF_LISTEN_ADDR"), os.getenv("WAF_LISTEN_PORT"), ssl=context)
async with server:
await server.serve_forever()
asyncio.run(run_server())
|