-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathproxy.py
More file actions
100 lines (86 loc) · 3.07 KB
/
Copy pathproxy.py
File metadata and controls
100 lines (86 loc) · 3.07 KB
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
#!/usr/bin/env python3
import asyncio
import binascii
import logging
import os
import signal
import sys
# Pfade fest vorgegeben:
LISTEN_PATH = "/tmp/clamd-proxy.sock"
TARGET_PATH = "/tmp/clamd.sock"
TARGET_PATH = "/tmp/clamd-python.sock"
logging.basicConfig(level=logging.INFO, format='%(asctime)s [%(levelname)s] %(message)s')
def hexdump(data: bytes, direction: str, width: int = 16) -> str:
"""
Erstellt einen Hexdump mit:
- Offset (in Hex)
- Hex-Werte (links)
- ASCII-Darstellung (rechts, nicht-druckbare als '.')
- Zeilenpräfix mit der Richtung (C→S oder S→C)
"""
lines = []
for offset in range(0, len(data), width):
chunk = data[offset:offset+width]
# Hex-Teil
hex_bytes = ' '.join(f"{b:02x}" for b in chunk)
# ASCII-Teil
ascii_bytes = ''.join((chr(b) if 32 <= b < 127 else '.') for b in chunk)
# Formatiere so, dass Hex-Teil immer gleich breit ist
hex_part = f"{hex_bytes:<{width*3}}"
# Zeile mit Richtung
lines.append(f"[{direction}] {offset:08x} {hex_part} {ascii_bytes}")
return '\n'.join(lines)
async def handle_client(reader: asyncio.StreamReader, writer: asyncio.StreamWriter):
peer = writer.get_extra_info('peername')
logging.info(f"Neue Verbindung von {peer}")
# Verbindung zum echten clamd-Socket herstellen
try:
target_reader, target_writer = await asyncio.open_unix_connection(TARGET_PATH)
except Exception as e:
logging.error(f"Fehler beim Verbinden mit {TARGET_PATH}: {e}")
writer.close()
await writer.wait_closed()
return
async def forward(src, dst, direction: str):
try:
while True:
data = await src.read(4096)
if not data:
break
logging.info(f"{len(data)} Bytes übertragen:\n{hexdump(data, direction)}")
dst.write(data)
await dst.drain()
except Exception as e:
logging.warning(f"Forwarding-Fehler ({direction}): {e}")
finally:
try:
dst.close()
except:
pass
# Client→Clamd und Clamd→Client gleichzeitig
await asyncio.gather(
forward(reader, target_writer, "C→S"),
forward(target_reader, writer, "S→C")
)
async def main():
# Alten Proxy-Socket löschen, falls vorhanden
try:
os.unlink(LISTEN_PATH)
except FileNotFoundError:
pass
server = await asyncio.start_unix_server(handle_client, path=LISTEN_PATH)
logging.info(f"Proxy lauscht auf {LISTEN_PATH}, leitet weiter an {TARGET_PATH}")
# Auf SIGINT/SIGTERM warten, um sauber zu beenden
loop = asyncio.get_running_loop()
stop = loop.create_future()
for sig in (signal.SIGINT, signal.SIGTERM):
loop.add_signal_handler(sig, stop.set_result, None)
await stop
server.close()
await server.wait_closed()
logging.info("Proxy beendet.")
if __name__ == "__main__":
try:
asyncio.run(main())
except KeyboardInterrupt:
sys.exit(0)