CitrixPot: NetScaler / Citrix ADC Gateway honeypot (initial public release)
This commit is contained in:
commit
4491b42714
54 files changed
+4532
No files matched your search
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Proxmox-side fail-closed monitor; only the disposable VM223 is stopped."""
|
||||
import json
|
||||
import pathlib
|
||||
import shutil
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
DIRECTORY = pathlib.Path('/var/lib/vz/honeypot')
|
||||
|
||||
|
||||
def qm(*args):
|
||||
return subprocess.run(['/usr/sbin/qm', *args], capture_output=True, text=True, timeout=25, check=True).stdout
|
||||
|
||||
|
||||
def stop(reason):
|
||||
with (DIRECTORY / 'watchdog-events.jsonl').open('a') as output:
|
||||
output.write(json.dumps(dict(time_ns=time.time_ns(), event='execution_vm_stopped', reason=reason)) + '\n')
|
||||
output.flush()
|
||||
qm('stop', '223')
|
||||
# This latch prevents unattended auto-restart. Operator must verify evidence before clearing.
|
||||
(DIRECTORY / 'STOP').touch(mode=0o600)
|
||||
|
||||
|
||||
def main():
|
||||
last_health = 0
|
||||
while True:
|
||||
try:
|
||||
if 'status: running' not in qm('status', '223'):
|
||||
time.sleep(2)
|
||||
continue
|
||||
reason = None
|
||||
pcap = DIRECTORY / 'execution.pcap'
|
||||
if (DIRECTORY / 'STOP').exists():
|
||||
reason = 'host stop latch'
|
||||
elif pcap.exists() and pcap.stat().st_size >= 512 * 1024 * 1024:
|
||||
reason = 'pcap quota'
|
||||
elif shutil.disk_usage(DIRECTORY).free < 4 * 1024**3:
|
||||
reason = 'host free space reserve'
|
||||
elif time.monotonic() - last_health >= 10:
|
||||
last_health = time.monotonic()
|
||||
usage = subprocess.run(['/usr/sbin/lvs', '--noheadings', '-o', 'data_percent', 'pve/data'], capture_output=True, text=True, check=True, timeout=5)
|
||||
if float(usage.stdout.strip()) >= 85:
|
||||
stop('Proxmox thin pool reserve')
|
||||
continue
|
||||
try:
|
||||
result = json.loads(qm('guest', 'exec', '222', '--timeout', '10', '--',
|
||||
'/bin/sh', '-c',
|
||||
'test ! -e /var/lib/decoy/STOP && '
|
||||
'systemctl is-active --quiet decoy.service decoy-network.service'))
|
||||
if result.get('exitcode') != 0 or not result.get('exited'):
|
||||
reason = 'collector services stopped or capture failed'
|
||||
except (OSError, ValueError, subprocess.SubprocessError):
|
||||
reason = 'collector health unavailable'
|
||||
if reason:
|
||||
stop(reason)
|
||||
except (OSError, subprocess.SubprocessError) as error:
|
||||
print(type(error).__name__, flush=True)
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in new issue
Block a user