gistfile1.txt
· 2.7 KiB · Text
Bruto
def poll_handshakes():
"""
Poll wg show latest-handshakes periodically.
Log a handshake event only when gap > WG_HANDSHAKE_CHECK_SEC (new session).
"""
global _hs_last_logged
_hs_last_logged = load_hs_cache()
pubkey_to_name = build_pubkey_to_name()
log.info(f"Handshake poller started — {len(pubkey_to_name)} peers, "
f"session threshold {WG_HANDSHAKE_CHECK_SEC}s")
while True:
try:
result = subprocess.run(
["wg", "show", WG_WG_INTERFACE, "latest-handshakes"],
capture_output=True, text=True
)
for line in result.stdout.strip().splitlines():
parts = line.split()
if len(parts) != 2:
continue
pubkey, ts_str = parts
try:
ts = int(ts_str)
except ValueError:
continue
if ts == 0:
continue
client = pubkey_to_name.get(pubkey)
if not client:
continue
last = _hs_last_logged.get(pubkey, 0)
gap = ts - last
# Always update last seen
_hs_last_logged[pubkey] = ts
if gap < WG_HANDSHAKE_CHECK_SEC:
continue # keepalive, skip
# Get endpoint
endpoint = get_endpoint(pubkey) or ''
if not endpoint:
try:
cache = json.loads(ENDPOINT_CACHE_FILE.read_text())
endpoint = cache.get(client, '')
except Exception:
pass
# New session, log it
entry = {
"timestamp": datetime.fromtimestamp(ts, tz=timezone.utc).isoformat(),
"ip": "",
"client": client,
"event": "handshake",
"endpoint": endpoint,
}
try:
with EVENTS_LOG.open("a") as f:
f.write(json.dumps(entry) + "\n")
log.info(f"New session: {client} from {endpoint}")
except Exception as e:
log.error(f"Failed to write handshake event: {e}")
log.debug(f"Gap for {client}: {gap}s (threshold: {WG_HANDSHAKE_CHECK_SEC}s)")
save_hs_cache(_hs_last_logged)
except Exception as e:
log.error(f"Handshake poll error: {e}")
time.sleep(WG_HANDSHAKE_CHECK_SEC // 2) # poll at half the threshold
# ============================================
# Packet Handler
# ============================================
def handle_packet(pkt):
| 1 | def poll_handshakes(): |
| 2 | """ |
| 3 | Poll wg show latest-handshakes periodically. |
| 4 | Log a handshake event only when gap > WG_HANDSHAKE_CHECK_SEC (new session). |
| 5 | """ |
| 6 | global _hs_last_logged |
| 7 | |
| 8 | _hs_last_logged = load_hs_cache() |
| 9 | |
| 10 | pubkey_to_name = build_pubkey_to_name() |
| 11 | log.info(f"Handshake poller started — {len(pubkey_to_name)} peers, " |
| 12 | f"session threshold {WG_HANDSHAKE_CHECK_SEC}s") |
| 13 | |
| 14 | while True: |
| 15 | try: |
| 16 | result = subprocess.run( |
| 17 | ["wg", "show", WG_WG_INTERFACE, "latest-handshakes"], |
| 18 | capture_output=True, text=True |
| 19 | ) |
| 20 | for line in result.stdout.strip().splitlines(): |
| 21 | parts = line.split() |
| 22 | if len(parts) != 2: |
| 23 | continue |
| 24 | pubkey, ts_str = parts |
| 25 | try: |
| 26 | ts = int(ts_str) |
| 27 | except ValueError: |
| 28 | continue |
| 29 | if ts == 0: |
| 30 | continue |
| 31 | |
| 32 | client = pubkey_to_name.get(pubkey) |
| 33 | if not client: |
| 34 | continue |
| 35 | |
| 36 | last = _hs_last_logged.get(pubkey, 0) |
| 37 | gap = ts - last |
| 38 | |
| 39 | # Always update last seen |
| 40 | _hs_last_logged[pubkey] = ts |
| 41 | |
| 42 | if gap < WG_HANDSHAKE_CHECK_SEC: |
| 43 | continue # keepalive, skip |
| 44 | |
| 45 | # Get endpoint |
| 46 | endpoint = get_endpoint(pubkey) or '' |
| 47 | |
| 48 | if not endpoint: |
| 49 | try: |
| 50 | cache = json.loads(ENDPOINT_CACHE_FILE.read_text()) |
| 51 | endpoint = cache.get(client, '') |
| 52 | except Exception: |
| 53 | pass |
| 54 | |
| 55 | |
| 56 | # New session, log it |
| 57 | entry = { |
| 58 | "timestamp": datetime.fromtimestamp(ts, tz=timezone.utc).isoformat(), |
| 59 | "ip": "", |
| 60 | "client": client, |
| 61 | "event": "handshake", |
| 62 | "endpoint": endpoint, |
| 63 | } |
| 64 | try: |
| 65 | with EVENTS_LOG.open("a") as f: |
| 66 | f.write(json.dumps(entry) + "\n") |
| 67 | log.info(f"New session: {client} from {endpoint}") |
| 68 | except Exception as e: |
| 69 | log.error(f"Failed to write handshake event: {e}") |
| 70 | |
| 71 | log.debug(f"Gap for {client}: {gap}s (threshold: {WG_HANDSHAKE_CHECK_SEC}s)") |
| 72 | save_hs_cache(_hs_last_logged) |
| 73 | |
| 74 | except Exception as e: |
| 75 | log.error(f"Handshake poll error: {e}") |
| 76 | |
| 77 | time.sleep(WG_HANDSHAKE_CHECK_SEC // 2) # poll at half the threshold |
| 78 | |
| 79 | # ============================================ |
| 80 | # Packet Handler |
| 81 | # ============================================ |
| 82 | |
| 83 | def handle_packet(pkt): |
| 84 |