#!/bin/bash # Unauthorized connection monitor — cron wrapper # Orchestrates: log-splitter → check → formatted output with agent instructions # # Output is structured for the OpenClaw agent to parse and act on. # The agent reads SKILL.md for detailed instructions on thread management. # # Flow: # 1. Run log-splitter to extract new unauthorized entries from gateway log # 2. Check thread index status (does the agent need to refresh it?) # 3. Run check to categorize IPs as new or returning # 4. Format output with ACTION markers the agent will parse # # Exit: always 0. Empty output = nothing to do (agent replies NO_REPLY) set -e SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # --- Step 1: Split unauthorized entries from gateway log --- SPLIT_RESULT=$("$SCRIPT_DIR/log-splitter.sh" 2>/dev/null) || true # --- Step 2: Check thread index --- INDEX_STATUS=$("$SCRIPT_DIR/index-threads.sh" needs-refresh 2>/dev/null) || INDEX_STATUS="missing" # --- Step 3: Check for new/returning unauthorized connections --- CHECK_RESULT=$("$SCRIPT_DIR/check.sh" 2>/dev/null) || CHECK_RESULT='{}' NEW_COUNT=$(echo "$CHECK_RESULT" | jq '.new_ips | length' 2>/dev/null || echo 0) RETURNING_COUNT=$(echo "$CHECK_RESULT" | jq '.returning_ips | length' 2>/dev/null || echo 0) TOTAL=$(echo "$CHECK_RESULT" | jq '.total_events' 2>/dev/null || echo 0) # Nothing to report if [ "$NEW_COUNT" -eq 0 ] && [ "$RETURNING_COUNT" -eq 0 ] && [ "$INDEX_STATUS" = "fresh" ]; then exit 0 fi OUTPUT="" # --- Thread index refresh needed --- if [ "$INDEX_STATUS" != "fresh" ]; then OUTPUT+="ACTION:INDEX_THREADS The thread index is ${INDEX_STATUS}. Before processing connections, refresh the thread index. See SKILL.md section \"Thread Index Management\" for instructions. ---END_ACTION--- " fi # --- New IPs: agent should create threads --- if [ "$NEW_COUNT" -gt 0 ]; then OUTPUT+=" 🚨 UNAUTHORIZED CONNECTIONS — ${NEW_COUNT} NEW IP(s) DETECTED ============================================================ " # Emit each new IP as an ACTION block for i in $(seq 0 $((NEW_COUNT - 1))); do IP=$(echo "$CHECK_RESULT" | jq -r ".new_ips[$i].ip") FIRST_SEEN=$(echo "$CHECK_RESULT" | jq -r ".new_ips[$i].first_seen") ATTEMPTS=$(echo "$CHECK_RESULT" | jq -r ".new_ips[$i].attempts") REASON=$(echo "$CHECK_RESULT" | jq -r ".new_ips[$i].reason") ORIGIN=$(echo "$CHECK_RESULT" | jq -r ".new_ips[$i].origin") UA=$(echo "$CHECK_RESULT" | jq -r ".new_ips[$i].user_agent") REMOTE=$(echo "$CHECK_RESULT" | jq -r ".new_ips[$i].remote") OUTPUT+=" ACTION:NEW_THREAD IP:${IP} --- 🚨 **NEW UNAUTHORIZED CONNECTION** **IP:** \`${IP}\` **First Seen:** ${FIRST_SEEN} **Attempts:** ${ATTEMPTS} **Reason:** ${REASON} **Origin:** ${ORIGIN} **User Agent:** ${UA} **Remote (proxy):** ${REMOTE} _New IP — thread created by security monitor._ ---END_ACTION--- " done fi # --- Returning IPs: agent should update existing threads --- if [ "$RETURNING_COUNT" -gt 0 ]; then OUTPUT+=" ⚠️ RETURNING CONNECTIONS — ${RETURNING_COUNT} KNOWN IP(s) ========================================================== " for i in $(seq 0 $((RETURNING_COUNT - 1))); do IP=$(echo "$CHECK_RESULT" | jq -r ".returning_ips[$i].ip") LATEST=$(echo "$CHECK_RESULT" | jq -r ".returning_ips[$i].latest") NEW_ATTEMPTS=$(echo "$CHECK_RESULT" | jq -r ".returning_ips[$i].new_attempts") TOTAL_ATTEMPTS=$(echo "$CHECK_RESULT" | jq -r ".returning_ips[$i].total_attempts") REASON=$(echo "$CHECK_RESULT" | jq -r ".returning_ips[$i].reason") ORIGIN=$(echo "$CHECK_RESULT" | jq -r ".returning_ips[$i].origin") UA=$(echo "$CHECK_RESULT" | jq -r ".returning_ips[$i].user_agent") REMOTE=$(echo "$CHECK_RESULT" | jq -r ".returning_ips[$i].remote") # Look up existing thread THREAD_INFO=$("$SCRIPT_DIR/index-threads.sh" lookup "$IP" 2>/dev/null) || THREAD_INFO="" SESSION_KEY="" if [ -n "$THREAD_INFO" ]; then SESSION_KEY=$(echo "$THREAD_INFO" | jq -r '.session_key // empty') fi OUTPUT+=" ACTION:UPDATE_THREAD IP:${IP} SESSION_KEY:${SESSION_KEY} --- ⚠️ **RETURNING UNAUTHORIZED CONNECTION** **IP:** \`${IP}\` **Latest Attempt:** ${LATEST} **New Attempts (this period):** ${NEW_ATTEMPTS} **Total Attempts (all time):** ${TOTAL_ATTEMPTS} **Reason:** ${REASON} **Origin:** ${ORIGIN} **User Agent:** ${UA} **Remote (proxy):** ${REMOTE} _Recurring access attempt — updated by security monitor._ ---END_ACTION--- " done fi echo -e "$OUTPUT"