linuxrouter/routlin/check_captive_users.py
2026-06-06 23:22:02 -04:00

65 lines
1.6 KiB
Python
Executable file

#!/usr/bin/env python3
"""
check_captive_users.py -- Expire captive portal sessions.
Runs every 5 minutes (systemd timer installed by core.py --apply).
Queries .client-credentials for sessions past their expiry time,
deletes them, and appends disallow commands to .captive-queue so
do_captive_queue.sh removes the corresponding nftables entries.
"""
import sys
import time
import sqlite3
from pathlib import Path
SCRIPT_DIR = Path(__file__).parent
DB_FILE = SCRIPT_DIR / ".client-credentials"
QUEUE_FILE = SCRIPT_DIR / ".captive-queue"
def main():
if not DB_FILE.exists():
return
try:
conn = sqlite3.connect(DB_FILE)
conn.row_factory = sqlite3.Row
except Exception as e:
print(f"check_captive_users: cannot open {DB_FILE}: {e}", file=sys.stderr)
return
now = int(time.time())
try:
expired_ips = [
row["ip"]
for row in conn.execute(
"SELECT ip FROM sessions WHERE expires_at IS NOT NULL AND expires_at <= ?",
(now,),
)
]
except sqlite3.OperationalError:
conn.close()
return
if not expired_ips:
conn.close()
return
conn.execute(
"DELETE FROM sessions WHERE expires_at IS NOT NULL AND expires_at <= ?",
(now,),
)
conn.commit()
conn.close()
lines = "".join(f"disallow {ip}\n" for ip in expired_ips)
with open(QUEUE_FILE, "a") as f:
f.write(lines)
print(f"check_captive_users: queued disallow for {len(expired_ips)} expired session(s).")
if __name__ == "__main__":
main()