Posted on
Artificial Intelligence

Artificial Intelligence Security Automation

Author
  • User
    linuxbash
    Posts by this author
    Posts by this author

Artificial Intelligence Security Automation on Linux: A Bash-First Guide

If your Linux servers are exposed to the internet, they’re already being probed. The problem isn’t the lack of logs—it’s the overload. AI-driven security automation helps you separate signal from noise, flag true anomalies, and auto-remediate the obvious threats before a human even looks.

This article shows you how to build a simple, Linux-native, Bash-first AI security pipeline:

  • Collect signals with shell tools

  • Train a lightweight anomaly detector

  • Score in near-real-time and auto-block offenders with nftables

  • Automate everything with cron or systemd timers

No heavyweight SIEM required—just a few packages, shell scripts, and a pinch of Python.


Why AI Security Automation is Worth Your Time

  • Volume and speed: Attack traffic and system events grow faster than manual triage can handle.

  • Context over rules: Static rules alone miss novel behavior; anomaly detection adapts to your environment.

  • Linux-native automation: Journald, ps, ss, nftables, and cron give you a robust backbone for data, scoring, and action with minimal overhead.


Prerequisites: Install the Tools

We’ll use:

  • journalctl, ss, ps (already available on systemd-based distros)

  • jq for JSON parsing

  • nftables for blocking

  • Python 3 + pip for a tiny ML model (scikit-learn)

  • Optional: auditd and inotify-tools for richer signals

Run the appropriate commands for your distro (use sudo where needed).

Debian/Ubuntu (apt):

apt update
apt install -y auditd inotify-tools python3 python3-pip jq nftables
pip3 install --user --upgrade pip
pip3 install --user scikit-learn pandas numpy joblib

Fedora/RHEL/CentOS Stream (dnf):

dnf install -y audit inotify-tools python3 python3-pip jq nftables
pip3 install --user --upgrade pip
pip3 install --user scikit-learn pandas numpy joblib

openSUSE Leap/Tumbleweed (zypper):

zypper refresh
zypper install -y audit inotify-tools python3-pip jq nftables
pip3 install --user --upgrade pip
pip3 install --user scikit-learn pandas numpy joblib

Make sure your user’s local bin is in PATH if you used --user:

echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

Step 1: Collect Security Signals with Bash

We’ll gather a few robust metrics every 15 minutes:

  • SSH failures and unique source IPs

  • Count of listening TCP ports

  • Count of high-CPU processes

  • Count of SUID binaries (basic privilege-escalation risk indicator)

Create the working directory and the collector:

sudo mkdir -p /var/lib/ai-sec
sudo chown "$USER":"$USER" /var/lib/ai-sec

cat > /var/lib/ai-sec/collect_features.sh << 'EOF'
#!/usr/bin/env bash
set -euo pipefail

STATE_DIR="/var/lib/ai-sec"
CSV="$STATE_DIR/features.csv"
SINCE="15 min ago"

# Metrics
fail_ssh=$(journalctl -u ssh -u sshd --since "$SINCE" 2>/dev/null \
  | grep -Eci 'Failed password|Invalid user|authentication failure' || true)

unique_ips=$(journalctl -u ssh -u sshd --since "$SINCE" 2>/dev/null \
  | grep -Eo 'from ([0-9]{1,3}\.){3}[0-9]{1,3}' \
  | awk '{print $2}' | sort -u | wc -l | awk '{print $1}')

listening_ports=$(ss -ltn 2>/dev/null | awk 'NR>1{print $4}' \
  | sed 's/.*://g' | sort -u | wc -l | awk '{print $1}')

high_cpu_procs=$(ps -eo pcpu= 2>/dev/null \
  | awk '$1>=80{c++} END{print (c+0)}')

suid_count=$(find /usr/bin /usr/sbin -perm -4000 -type f 2>/dev/null | wc -l | awk '{print $1}')

timestamp=$(date -Iseconds)

# Initialize CSV with header if missing
if [[ ! -f "$CSV" ]]; then
  echo "timestamp,fail_ssh,unique_ips,listening_ports,high_cpu_procs,suid_count" > "$CSV"
fi

echo "$timestamp,$fail_ssh,$unique_ips,$listening_ports,$high_cpu_procs,$suid_count" >> "$CSV"
echo "[collect] $timestamp OK"
EOF

chmod +x /var/lib/ai-sec/collect_features.sh

Bonus: Add a simple file integrity watch channel (optional). This logs changes instantly; you can later wire it into your model or alerting:

inotifywait -m -e modify,attrib,move,create,delete /etc /var/www 2>/dev/null

Tip: auditd can capture syscalls and privileged operations comprehensively. Keep it installed and tuned if you want deeper signals (rules depend on your environment).


Step 2: Train a Lightweight Anomaly Detector

We’ll use IsolationForest from scikit-learn. First, collect a day or two of “normal” data with the collector running periodically. Then train:

Training script:

cat > /var/lib/ai-sec/train_iforest.py << 'EOF'
#!/usr/bin/env python3
import json, sys
import numpy as np
import pandas as pd
from sklearn.ensemble import IsolationForest
from sklearn.preprocessing import StandardScaler
from joblib import dump

state_dir = "/var/lib/ai-sec"
csv_path = f"{state_dir}/features.csv"
model_path = f"{state_dir}/model.joblib"
scaler_path = f"{state_dir}/scaler.joblib"
meta_path = f"{state_dir}/meta.json"

df = pd.read_csv(csv_path)
# Basic sanity: drop rows with NaN or non-numeric
cols = ["fail_ssh","unique_ips","listening_ports","high_cpu_procs","suid_count"]
X = df[cols].fillna(0).astype(float).values

scaler = StandardScaler()
Xn = scaler.fit_transform(X)

# Assume small contamination; tune for your environment
clf = IsolationForest(n_estimators=200, contamination=0.02, random_state=42)
clf.fit(Xn)

# Compute training score distribution to set a threshold
scores = clf.decision_function(Xn)  # higher is more normal
threshold = float(np.percentile(scores, 2))  # bottom 2% as anomalies

dump(clf, model_path)
dump(scaler, scaler_path)
with open(meta_path, "w") as f:
    json.dump({"cols": cols, "threshold": threshold}, f)

print(json.dumps({"trained": True, "samples": len(X), "threshold": threshold}))
EOF

chmod +x /var/lib/ai-sec/train_iforest.py

Run training after you have some data:

/var/lib/ai-sec/train_iforest.py

Step 3: Score, Alert, and Auto-Block Offenders

Create a scoring script that reads the latest row, compares it to the learned threshold, and emits JSON:

cat > /var/lib/ai-sec/detect.py << 'EOF'
#!/usr/bin/env python3
import json, sys, pandas as pd
from joblib import load

state_dir = "/var/lib/ai-sec"
csv_path = f"{state_dir}/features.csv"
model_path = f"{state_dir}/model.joblib"
scaler_path = f"{state_dir}/scaler.joblib"
meta_path = f"{state_dir}/meta.json"

df = pd.read_csv(csv_path)
last = df.tail(1)

with open(meta_path) as f:
    meta = json.load(f)
cols = meta["cols"]
threshold = float(meta["threshold"])

X = last[cols].fillna(0).astype(float).values
scaler = load(scaler_path)
clf = load(model_path)
score = float(clf.decision_function(scaler.transform(X))[0])

is_anom = score < threshold

out = {
  "timestamp": str(last["timestamp"].values[0]),
  "score": score,
  "threshold": threshold,
  "is_anomaly": bool(is_anom),
  "metrics": {c: float(last[c].values[0]) for c in cols}
}
print(json.dumps(out))
EOF

chmod +x /var/lib/ai-sec/detect.py

Prepare a minimal nftables policy and a blocklist set (run once; ignore errors if they exist already):

sudo nft add table inet filter 2>/dev/null || true
sudo nft add set inet filter blocklist '{ type ipv4_addr; flags interval; }' 2>/dev/null || true
sudo nft add chain inet filter input '{ type filter hook input priority 0; policy accept; }' 2>/dev/null || true
sudo nft add rule inet filter input ip saddr @blocklist drop 2>/dev/null || true

Now wire detection to auto-block abusive SSH sources if the model flags an anomaly and failed attempts are high:

cat > /var/lib/ai-sec/detect_and_respond.sh << 'EOF'
#!/usr/bin/env bash
set -euo pipefail
STATE_DIR="/var/lib/ai-sec"

# Run collector first to get fresh data
"$STATE_DIR/collect_features.sh" >/dev/null

# Score
result=$("$STATE_DIR/detect.py")
echo "$result"

is_anom=$(echo "$result" | jq -r '.is_anomaly')
fail_ssh=$(echo "$result" | jq -r '.metrics.fail_ssh' | awk '{print int($1)}')

# Auto-response policy: only block when anomaly is true and failures are high
if [[ "$is_anom" == "true" && "$fail_ssh" -ge 20 ]]; then
  echo "[respond] anomaly with high SSH failures; populating blocklist"

  # Find noisy IPs (>=5 failures in last 15 minutes)
  mapfile -t bad_ips < <(journalctl -u ssh -u sshd --since "15 min ago" 2>/dev/null \
    | grep -Eo 'from ([0-9]{1,3}\.){3}[0-9]{1,3}' \
    | awk '{print $2}' | sort | uniq -c | awk '$1>=5{print $2}')

  if [[ ${#bad_ips[@]} -gt 0 ]]; then
    # Ensure nftables set exists
    sudo nft add table inet filter 2>/dev/null || true
    sudo nft add set inet filter blocklist '{ type ipv4_addr; flags interval; }' 2>/dev/null || true
    sudo nft add chain inet filter input '{ type filter hook input priority 0; policy accept; }' 2>/dev/null || true
    sudo nft add rule inet filter input ip saddr @blocklist drop 2>/dev/null || true

    for ip in "${bad_ips[@]}"; do
      sudo nft add element inet filter blocklist { "$ip" } 2>/dev/null || true
      echo "[respond] blocked $ip"
    done
  else
    echo "[respond] no offending IPs found"
  fi
else
  echo "[respond] no action (either not anomalous or low SSH failures)"
fi
EOF

chmod +x /var/lib/ai-sec/detect_and_respond.sh

Test:

/var/lib/ai-sec/detect_and_respond.sh

Example output:

{"timestamp":"2026-07-12T11:45:33+00:00","score":-0.21,"threshold":-0.15,"is_anomaly":true,"metrics":{"fail_ssh":64,"unique_ips":9,"listening_ports":17,"high_cpu_procs":0,"suid_count":24}}
[respond] anomaly with high SSH failures; populating blocklist
[respond] blocked 203.0.113.24
[respond] blocked 198.51.100.7

Step 4: Automate with cron or systemd

With cron (every 15 minutes):

crontab -e

Add:

*/15 * * * * /var/lib/ai-sec/detect_and_respond.sh >> /var/log/ai-sec.log 2>&1

Or with systemd timers:

sudo tee /etc/systemd/system/ai-sec.service >/dev/null << 'EOF'
[Unit]
Description=AI Security Detect and Respond

[Service]
Type=oneshot
ExecStart=/var/lib/ai-sec/detect_and_respond.sh
EOF

sudo tee /etc/systemd/system/ai-sec.timer >/dev/null << 'EOF'
[Unit]
Description=Run AI Security Detect and Respond every 15 minutes

[Timer]
OnCalendar=*:0/15
Persistent=true

[Install]
WantedBy=timers.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now ai-sec.timer

Real-World Notes and Tuning Tips

  • Baseline first: Let the collector run during “known-good” periods before training.

  • Contamination: If you see too many false positives, reduce contamination (e.g., 0.01) and retrain.

  • Feature engineering: Add richer metrics (e.g., per-protocol connection spikes, process start rates, auditd counts of execve by unprivileged users).

  • Safe responses: Start in “alert-only” mode. Log anomalies to a channel (syslog, email, Slack webhook via curl) before auto-blocking in production.

  • Persistence: Rotate /var/lib/ai-sec/features.csv and /var/log/ai-sec.log to prevent growth.

Slack webhook example (optional):

curl -X POST -H 'Content-type: application/json' \
  --data "$(jq -n --arg t "AI-Sec Alert" --arg b "$(/var/lib/ai-sec/detect.py)" '{text: ($t + "\n" + $b)}')" \
  https://hooks.slack.com/services/XXX/YYY/ZZZ

Conclusion and Next Steps

You just stood up a practical AI-assisted security loop using Bash, system tools, and a small ML model:

  • Collect signals

  • Learn “normal”

  • Detect anomalies

  • Auto-remediate the obvious

Next steps:

  • Add more features (auditd counts, file integrity deltas, per-user process bursts)

  • Send alerts to your chat/ops stack

  • Extend nftables logic to expire blocks or maintain sets per interface

  • Store training data in a Git-controlled repo or an S3 bucket for reproducibility

Security is a journey. Start small, automate safely, learn from alerts, and iterate fast—Linux and Bash give you all the levers you need.