Blog
DevOpsยท13 min read

Hardening Your Clawdbot Server: A Complete Security Guide

within 60 seconds of setting up fail2ban, it caught an active brute-force attack. here's how to lock down your clawdbot server properly.

Jo VยทJanuary 27, 2026
Hardening Your Clawdbot Server: A Complete Security Guide

I set up fail2ban on my Clawdbot server tonight. Within 60 seconds, it banned its first attacker.

Not a test. An actual bot was actively trying to brute-force SSH while I was configuring the firewall.

Jan 27 02:46:55 sshd: Invalid user oracle from 217.154.38.135
Jan 27 02:47:25 sshd: Invalid user main from 217.154.38.135
Jan 27 02:47:56 sshd: Invalid user HwHiAiUser from 217.154.38.135
Jan 27 02:48:26 sshd: Invalid user guest from 217.154.38.135
Jan 27 02:48:57 sshd: Invalid user git from 217.154.38.135

Every 30 seconds. Different usernames. Automated. Relentless.

Then fail2ban kicked in:

2026-01-27 02:50:54 NOTICE [sshd] Ban 217.154.38.135

Done. 30-day ban. If you're running Clawdbot on a VPS, you need this.

Why Clawdbot Servers Are Targets

Clawdbot servers are juicy targets because they typically have:

  • Shell access โ€” The agent can run commands
  • API credentials โ€” Anthropic, OpenAI, messaging platforms
  • Personal data โ€” Session logs, memory files, contacts
  • Always-on connectivity โ€” 24/7 uptime on cloud VPS

An attacker who compromises your Clawdbot server gets access to your AI assistant's full capabilities. They could read your conversations, impersonate you on messaging platforms, or rack up API bills.

Let's fix that.

Step 1: SSH Key Authentication (Critical)

This is the single most important security step. Password authentication is the weakest link. SSH keys are cryptographically secure and impossible to brute-force.

On your local machine, generate a key pair:

ssh-keygen -t ed25519 -C "your_email@example.com"

This creates two files:

  • ~/.ssh/id_ed25519 โ€” Your private key (never share this)
  • ~/.ssh/id_ed25519.pub โ€” Your public key (goes on the server)

Copy your public key to the server:

ssh-copy-id user@your-server-ip

Or manually:

# On your local machine
cat ~/.ssh/id_ed25519.pub
# Copy the output, then on your server:
echo "your-public-key-here" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

Test it works:

ssh user@your-server-ip

If you get in without a password prompt, it's working.

Step 2: Disable Password Authentication

Once SSH keys work, disable password authentication entirely:

sudo nano /etc/ssh/sshd_config

Find and change these lines:

PasswordAuthentication no
PubkeyAuthentication yes
ChallengeResponseAuthentication no

Restart SSH:

sudo systemctl restart sshd

Now the only way in is with your private key. Brute-force attacks become completely pointless โ€” they're trying to guess a password that doesn't exist.

Step 3: Install fail2ban

Even with SSH keys, we want fail2ban as a backup layer to keep logs clean and stop wasted resources.

sudo apt update
sudo apt install -y fail2ban

Create a local config:

sudo tee /etc/fail2ban/jail.local << 'EOF'
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 2592000
findtime = 600
EOF

What this does:

  • maxretry = 3 โ€” Three failed attempts = banned
  • bantime = 2592000 โ€” 30-day ban (if you use SSH keys, any failed attempt is definitely an attacker)
  • findtime = 600 โ€” Attempts counted within 10-minute window

Start it:

sudo systemctl enable fail2ban
sudo systemctl restart fail2ban

Check if it's working:

sudo fail2ban-client status sshd

Step 4: Configure ufw Firewall

# Default: block everything incoming
sudo ufw default deny incoming
sudo ufw default allow outgoing
# Allow only what Clawdbot needs
sudo ufw allow 22/tcp # SSH (we'll change this later)
sudo ufw allow 80/tcp # HTTP (if using webhooks)
sudo ufw allow 443/tcp # HTTPS
# Enable
sudo ufw --force enable

Verify:

sudo ufw status verbose

Step 5: SSH Tarpit with endlessh (The Fun Part)

Here's where it gets interesting. The idea: move real SSH to a non-standard port, put endlessh on port 22. Bots connect to port 22 and get trapped in an infinitely slow banner that sends one random byte every 10 seconds. They never get a login prompt. Meanwhile, real SSH runs unbothered on a different port.

What endlessh Does

endlessh is an SSH tarpit. When a bot connects, it sends an SSH banner infinitely slowly โ€” one random byte every 10 seconds. The SSH spec allows banners up to 255 characters, but it doesn't specify a minimum speed. Most bots will wait patiently for the full banner, consuming a connection slot and wasting their time.

It's like digital quicksand for SSH bots.

Install endlessh

sudo apt install endlessh

Move Real SSH to Port 2222

On modern Ubuntu, SSH is managed by systemd sockets, so we need to override the socket config:

sudo mkdir -p /etc/systemd/system/ssh.socket.d/
sudo tee /etc/systemd/system/ssh.socket.d/override.conf << 'EOF'
[Socket]
ListenStream=
ListenStream=2222
EOF

Reload and restart:

sudo systemctl daemon-reload
sudo systemctl restart ssh.socket
sudo systemctl restart ssh

Verify SSH is now on 2222:

ss -tlnp | grep :2222

Configure endlessh for Port 22

sudo mkdir -p /etc/endlessh
sudo tee /etc/endlessh/config << 'EOF'
Port 22
Delay 10000
MaxLineLength 32
MaxClients 4096
LogLevel 1
EOF

This configures:

  • Port 22 โ€” The standard SSH port (bots will find this)
  • Delay 10000 โ€” Send one byte every 10 seconds
  • MaxClients 4096 โ€” Handle lots of trapped bots
  • LogLevel 1 โ€” Log connections for entertainment

Fix the systemd Service

endlessh might fail with a NAMESPACE error on modern systems. Create a service override:

sudo mkdir -p /etc/systemd/system/endlessh.service.d/
sudo tee /etc/systemd/system/endlessh.service.d/override.conf << 'EOF'
[Service]
PrivateUsers=false
EOF

Start endlessh

sudo systemctl daemon-reload
sudo systemctl enable endlessh
sudo systemctl start endlessh

Check it's working:

sudo systemctl status endlessh
ss -tlnp | grep :22

Update ufw for New SSH Port

# Allow the new SSH port
sudo ufw allow 2222/tcp
# Remove the old SSH rule (port 22 is now the tarpit)
sudo ufw delete allow 22/tcp

Test the Tarpit

From another machine, try connecting to port 22:

ssh user@your-server-ip -p 22

It should just hang there, sending one character every 10 seconds. After a while you'll see a super slow, garbled banner. Press Ctrl+C to escape.

Now try the real SSH:

ssh user@your-server-ip -p 2222

Instant connection with your SSH key.

The Results

Bots waste their time on port 22 while your real SSH runs unbothered on 2222. Your logs stay clean because failed attempts hit the tarpit, not your real SSH service. Watching journalctl -f -u endlessh is surprisingly entertaining โ€” bots connecting and just... waiting.

How Effective Is It Really?

One researcher ran endlessh for months and collected data on trapped bots. The results are hilarious:

  • One bot held 416 concurrent connections open at the same time โ€” just kept opening new ones without closing the old
  • A single IP stayed connected for 690,172 seconds โ€” that's 8 days straight โ€” downloading 1.2MB of random garbage thinking it was an SSH banner
  • Some connections lasted 12,000+ seconds (3.3 hours) before the bot gave up
  • The median trap time was 17 seconds (the "smart" bots with timeouts), but the mean was 119 seconds โ€” dragged up by the dumb ones that wait forever

The quality of underground scanning software varies immensely. Some bots have a 15-second timeout and move on. Others have no timeout at all โ€” they'll sit there until the heat death of the universe waiting for a login prompt that never comes.

And the best part: endlessh uses virtually zero resources. It's a single process handling thousands of connections with minimal CPU and memory. The bots are the ones burning resources, not you.

Monitor the Tarpit

Watch bots get trapped in real time:

journalctl -f -u endlessh

Count current trapped connections:

ss -tn | grep :22 | grep ESTAB | wc -l

Step 6: Change SSH Port (Brief)

We already moved SSH to 2222 for the tarpit, but here's the general approach if you just want to change ports without endlessh:

# In /etc/ssh/sshd_config
Port 2222

Update firewall:

sudo ufw allow 2222/tcp
sudo ufw delete allow 22/tcp
sudo systemctl restart sshd

Security through obscurity isn't real security, but it does reduce noise from random scans. Combined with SSH keys and fail2ban, it's effective.

Step 7: Secrets Management with pass

Don't store API keys and passwords in plaintext config files. Use pass โ€” the standard Unix password manager.

Install it:

sudo apt install pass gnupg

Set it up:

# Generate a GPG key (if you don't have one)
gpg --gen-key
# Initialize pass with your GPG key
pass init "your-email@example.com"

Store secrets:

pass insert api/anthropic
pass insert api/openai
pass insert gmail/app-password

Retrieve secrets in scripts:

export ANTHROPIC_API_KEY=$(pass show api/anthropic)

Why this matters:

  • Secrets are GPG-encrypted at rest
  • Even if someone accesses your filesystem, they can't read the passwords without your GPG key
  • You can sync your password store via git (safely, since everything is encrypted)
  • Works great with Clawdbot โ€” store your API keys and channel tokens securely

Your ~/.password-store/ directory is encrypted. Your ~/.clawdbot/clawdbot.json with plaintext tokens? Not so much.

Step 8: Clawdbot Security Audit

Clawdbot has a built-in security scanner. Run it:

clawdbot security audit

For a deeper check:

clawdbot security audit --deep

To auto-fix common issues:

clawdbot security audit --fix

What the Audit Checks

  • Inbound access โ€” Can strangers message your bot?
  • Tool blast radius โ€” Could prompt injection lead to shell access?
  • Network exposure โ€” Is your Gateway exposed without auth?
  • Browser control โ€” Is remote browser control secured?
  • Disk permissions โ€” Are credentials and logs protected?
  • Plugins โ€” Are untrusted extensions loaded?

Fix Workspace Permissions

The audit will likely warn about permissions. Fix them:

chmod 700 ~/.clawdbot
chmod 600 ~/.clawdbot/clawdbot.json

This ensures only your user can read Clawdbot's config and credentials.

Credential Storage Locations

Know where your secrets live:

  • Telegram token: config or channels.telegram.tokenFile
  • WhatsApp auth: ~/.clawdbot/credentials/whatsapp/*/creds.json
  • Pairing allowlists: ~/.clawdbot/credentials/*-allowFrom.json
  • Session logs: ~/.clawdbot/agents/*/sessions/*.jsonl

All of these should be readable only by your user (not group/world).

Step 9: Channel Security

Lock Down DMs

By default, Clawdbot might accept messages from anyone. Tighten it:

In your config, set DM policies to allowlist:

{
"channels": {
"telegram": {
"dmPolicy": "allowlist",
"dmAllowFrom": ["your_telegram_id"]
}
}
}

Lock Down Groups

Same for groups โ€” use allowlists instead of open:

{
"groupPolicy": "allowlist",
"groupAllowFrom": ["allowed_group_id"]
}

The security audit will flag open policies.

Step 10: Report Attackers to AbuseIPDB

Blocking attackers locally is good. Getting them blacklisted globally is better.

AbuseIPDB is a community database of abusive IPs. When you report an attacker, every other server using their blocklist benefits. It's collective defense.

Get a Free API Key

Sign up at abuseipdb.com โ€” the free tier allows 1000 reports/day.

Store it securely:

pass insert abuseipdb/api-key

Report a Banned IP

ABUSEIPDB_KEY=$(pass show abuseipdb/api-key)
curl -s https://api.abuseipdb.com/api/v2/report \
-H "Key: $ABUSEIPDB_KEY" \
-H "Accept: application/json" \
--data-urlencode "ip=2.57.122.209" \
-d "categories=18,22" \
--data-urlencode "comment=SSH brute-force (fail2ban auto-ban)"

Categories 18,22 = brute-force + SSH.

Auto-Report with Clawdbot

I built a Clawdbot skill that auto-reports every new ban to AbuseIPDB. If you're running Clawdbot, install it:

clawdhub install fail2ban-reporter

Or grab it from GitHub:

git clone https://github.com/jestersimpps/clawdbot-fail2ban-reporter.git
sudo bash clawdbot-fail2ban-reporter/scripts/install.sh

After setup, every fail2ban ban automatically reports to AbuseIPDB. Zero effort, maximum community impact.

Step 11: Monitor Ongoing Attacks

Check who's been banned:

sudo fail2ban-client status sshd

Watch live bans:

sudo tail -f /var/log/fail2ban.log | grep Ban

Check recent SSH attempts:

journalctl -u ssh -n 50 | grep -E "Failed|Invalid"

Watch endlessh trap bots in real-time:

sudo journalctl -f -u endlessh

You'll see connections that just hang there. Each one is a bot wasting time instead of bothering your real SSH.

What Attackers Actually Try

From my server logs in just one hour:

  • oracle โ€” Oracle DB default user
  • postgres โ€” PostgreSQL default
  • git โ€” GitLab/Gitea servers
  • solana โ€” Crypto node operators (popular target)
  • HwHiAiUser โ€” Huawei device default
  • admin, root โ€” The classics
  • ftpuser โ€” Legacy FTP

They spray common usernames hoping something sticks. fail2ban stops them after 3 attempts, but now they hit the tarpit first.

The Complete 5-Minute Setup

Copy-paste this entire block to harden a fresh Clawdbot server:

# Install security tools
sudo apt update && sudo apt install -y fail2ban ufw endlessh gnupg pass
# Generate SSH key (run on your LOCAL machine)
ssh-keygen -t ed25519 -C "your_email@example.com"
ssh-copy-id user@your-server-ip
# Disable password auth (ON THE SERVER)
sudo sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo sed -i 's/^#*PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config
# Move SSH to port 2222 for tarpit setup
sudo mkdir -p /etc/systemd/system/ssh.socket.d/
sudo tee /etc/systemd/system/ssh.socket.d/override.conf << 'EOF'
[Socket]
ListenStream=
ListenStream=2222
EOF
# Configure endlessh tarpit on port 22
sudo mkdir -p /etc/endlessh
sudo tee /etc/endlessh/config << 'EOF'
Port 22
Delay 10000
MaxLineLength 32
MaxClients 4096
LogLevel 1
EOF
# Fix endlessh systemd service
sudo mkdir -p /etc/systemd/system/endlessh.service.d/
sudo tee /etc/systemd/system/endlessh.service.d/override.conf << 'EOF'
[Service]
PrivateUsers=false
EOF
# Configure fail2ban
sudo tee /etc/fail2ban/jail.local << 'EOF'
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 2592000
findtime = 600
EOF
# Configure firewall
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 2222/tcp # New SSH port
sudo ufw allow 80/tcp # HTTP
sudo ufw allow 443/tcp # HTTPS
sudo ufw --force enable
# Start everything
sudo systemctl daemon-reload
sudo systemctl restart ssh.socket ssh
sudo systemctl enable --now fail2ban endlessh
# Fix Clawdbot permissions
chmod 700 ~/.clawdbot
chmod 600 ~/.clawdbot/clawdbot.json 2>/dev/null
# Run Clawdbot security audit
clawdbot security audit --fix
# Verify everything
echo "=== SSH on port 2222 ==="
ss -tlnp | grep :2222
echo "=== endlessh tarpit on port 22 ==="
ss -tlnp | grep :22
echo "=== fail2ban status ==="
sudo fail2ban-client status sshd
echo "=== ufw status ==="
sudo ufw status verbose
echo "=== Clawdbot security ==="
clawdbot security audit

Important: After running this, connect via SSH on the new port:

ssh user@your-server-ip -p 2222

The Complete Security Stack

After following this guide, your Clawdbot server has:

  • SSH key authentication โ€” No passwords to brute-force
  • Password auth disabled โ€” Even if they guess right, it won't work
  • endlessh tarpit โ€” Bots waste time on port 22 while real SSH hides on 2222
  • fail2ban โ€” 3 attempts โ†’ 30-day ban (backup layer)
  • ufw firewall โ€” Only necessary ports exposed
  • pass โ€” Secrets GPG-encrypted at rest
  • Clawdbot pairing โ€” Strangers can't message your bot
  • Proper permissions โ€” Config and credentials locked down
  • AbuseIPDB reporting โ€” Attackers get blacklisted globally

That's defense in depth. Multiple layers, each one making the next attack harder. The tarpit is the cherry on top โ€” instead of just blocking attackers, you're wasting their time and resources while keeping your real services hidden.

It's not paranoia when every server with a public IP gets attacked within hours. Five minutes of setup. Sleep better at night.


For more Clawdbot security details, check the official security docs.

Stay Updated

Get notified about new posts on automation, productivity tips, indie hacking, and web3.

No spam, ever. Unsubscribe anytime.

Comments

Related Posts