Files
b3nw 3b7d6bb67c Initial commit: custom OpenClaw skills from docker-test
- workspace: capmetro-monitor, github-notifications, model-selector
- workspace-security: vt-monitor, monitor-unauthorized
- workspace-home: cron-manager, monitor-unauthorized
- extensions: vt-sentinel (VT-Sentinel plugin)

Includes sync.sh for pull/push, README, AGENTS.md, .gitignore.
2026-02-16 15:32:44 +00:00

7.0 KiB

name, description, metadata
name description metadata
monitor-unauthorized Monitor and report unauthorized WebSocket gateway connections. Parses logs every 30 minutes, detects new and returning IPs, and manages per-IP Discord threads for tracking unauthorized access attempts.
openclaw
emoji
🚨

Monitor Unauthorized Gateway Connections

Detects and tracks unauthorized WebSocket connection attempts to the OpenClaw gateway. Maintains per-IP Discord threads for ongoing tracking.

Usage

# Cron tool (every 30 minutes)
bash skills/monitor-unauthorized/scripts/cron-wrapper.sh

Architecture

Scripts (data layer — no Discord/OpenClaw calls)

Script Purpose
scripts/log-splitter.sh Extracts unauthorized connection entries from the gateway log into /tmp/openclaw/unauthorized-connections.log (incremental, byte-offset tracked)
scripts/check.sh Reads new entries from the unauthorized log, categorizes IPs as new_ips or returning_ips, updates seen-connections.json
scripts/index-threads.sh Manages the thread index — lookup, record, and staleness checks. The index maps IPs to their Discord thread session keys
scripts/cron-wrapper.sh Orchestrates the above scripts and outputs structured ACTION blocks for the agent

Agent (action layer — thread management via OpenClaw tools)

The agent parses the cron-wrapper output and handles all Discord thread operations using OpenClaw's built-in session and thread tools.

Cron Behavior

  1. log-splitter.sh extracts new unauthorized connection log lines (incremental)
  2. check.sh processes new entries, outputs JSON with new_ips[] and returning_ips[]
  3. cron-wrapper.sh formats ACTION blocks the agent must parse and act on
  4. If no new activity: script produces no output → agent replies NO_REPLY

Parsing Cron Output

The cron-wrapper outputs ACTION blocks. Parse them as follows:

ACTION:INDEX_THREADS

The thread index is missing or stale. You must refresh it before processing connections.

Steps:

  1. List all threads in the security Discord channel (1471181304782389381)
  2. For each thread whose name starts with 🚨 and contains unauthorized gateway access:
    • Extract the IP address from the thread name (format: 🚨 <ip> — unauthorized gateway access)
    • Record it: bash scripts/index-threads.sh record "<ip>" "<session_key>" "<thread_name>"
  3. The session key format is: agent:security:discord:channel:1471181304782389381:thread:<thread_name>

ACTION:NEW_THREAD

A new unauthorized IP was detected. Create a thread and report.

Format:

ACTION:NEW_THREAD
IP:<ip_address>
---
<report content>
---END_ACTION---

Steps:

  1. Construct the thread name: 🚨 <ip> — unauthorized gateway access
  2. Construct the session key: agent:security:discord:channel:1471181304782389381:thread:<thread_name>
  3. Use sessions_send to send the report content (between --- and ---END_ACTION---) to that session key. This creates the thread if it doesn't exist.
  4. Record the thread in the index: bash scripts/index-threads.sh record "<ip>" "<session_key>"

ACTION:UPDATE_THREAD

A previously-seen IP has new connection attempts. Update the existing thread.

Format:

ACTION:UPDATE_THREAD
IP:<ip_address>
SESSION_KEY:<session_key or empty>
---
<update content>
---END_ACTION---

Steps:

  1. If SESSION_KEY is provided and non-empty, use it directly
  2. If SESSION_KEY is empty, construct it: agent:security:discord:channel:1471181304782389381:thread:🚨 <ip> — unauthorized gateway access
  3. Use sessions_send to post the update content to that session key
  4. Update the index: bash scripts/index-threads.sh record "<ip>" "<session_key>"

Thread Index Management

The thread index (memory/thread-index.json) maps IPs to their Discord thread session keys. This avoids redundant thread creation and enables reliable updates.

One-Time Bootstrap

On first run (or when the index is missing), the agent must:

  1. List all existing threads in channel 1471181304782389381
  2. Identify threads matching the 🚨 <ip> — unauthorized gateway access pattern
  3. Record each one via scripts/index-threads.sh record

Ongoing Maintenance

  • After creating a new thread (ACTION:NEW_THREAD), always record it in the index
  • After sending an update (ACTION:UPDATE_THREAD), always record it to refresh timestamps
  • The index auto-expires after 24 hours; the cron-wrapper will emit ACTION:INDEX_THREADS when a refresh is needed

Index Script Commands

# Check if index needs refresh
bash scripts/index-threads.sh needs-refresh
# Returns: "fresh" (exit 1), "stale" (exit 0), or "missing" (exit 0)

# Look up a thread by IP
bash scripts/index-threads.sh lookup "1.2.3.4"
# Returns: JSON with session_key, thread_name, etc. (exit 0 = found, exit 1 = not found)

# Record/update a thread entry
bash scripts/index-threads.sh record "1.2.3.4" "agent:security:discord:channel:...:thread:..." "🚨 1.2.3.4 — unauthorized gateway access"

# Check index status
bash scripts/index-threads.sh status
# Returns: JSON with entry count, age, staleness

Storage Files

File Location Purpose
seen-connections.json Skill directory All IPs ever seen — first_seen, last_seen, total_attempts, metadata
authorized-ips.json Skill directory Whitelist — these IPs are silently skipped
memory/thread-index.json State directory Maps IPs to Discord thread session keys
memory/unauth-splitter-offset State directory Byte offset for log-splitter (gateway log)
memory/unauth-check-offset State directory Byte offset for check (unauthorized log)

Authorized IPs (Whitelist)

Edit authorized-ips.json to suppress reporting for known IPs:

{
  "whitelist": ["127.0.0.1", "::1", "localhost", "192.168.1.100"]
}

Log Files

Log Path Contents
Gateway log /tmp/openclaw/openclaw.log Full OpenClaw gateway log (source)
Unauthorized log /tmp/openclaw/unauthorized-connections.log Extracted unauthorized connection entries only

What This Monitors

Gateway WebSocket authorization failures containing forwardedFor IP addresses. Specifically:

  • Entries with "forwardedFor" in the JSON log
  • Entries with cause "unauthorized" or "pairing-required"

Example Agent Flow

1. Cron fires → bash scripts/cron-wrapper.sh
2. Output contains ACTION:INDEX_THREADS → agent lists threads, records them
3. Output contains ACTION:NEW_THREAD for IP 203.0.113.42 →
   a. agent constructs session key
   b. agent calls sessions_send with report content
   c. agent runs: bash scripts/index-threads.sh record "203.0.113.42" "<key>"
4. Output contains ACTION:UPDATE_THREAD for IP 198.51.100.7 →
   a. agent uses SESSION_KEY from output (or constructs it)
   b. agent calls sessions_send with update content
   c. agent runs: bash scripts/index-threads.sh record "198.51.100.7" "<key>"
5. No output → agent replies NO_REPLY