- Posted on
- • Artificial Intelligence
Artificial Intelligence SSH Troubleshooting
- Author
-
-
- User
- linuxbash
- Posts by this author
- Posts by this author
-
AI-Assisted SSH Troubleshooting: Turn Noisy Logs Into Clear Fixes
Ever stared at 500 lines of ssh -vvv output at 2 a.m. and thought, “There must be a faster way”? Good news: artificial intelligence can help you make sense of SSH logs, pinpoint likely causes, and suggest concrete fixes—if you feed it the right evidence.
In this guide, you’ll learn a practical, reproducible workflow to:
Capture the right data from both client and server
Sanitize it safely
Ask an AI the right questions
Validate and implement fixes quickly
We’ll also cover real-world SSH failures and their reliable command-line remedies.
Why use AI for SSH troubleshooting?
SSH errors are terse and context-sensitive. The fix often depends on a small detail buried in verbose logs.
AI excels at pattern-matching across long logs, comparing error patterns against known failure modes.
The bottleneck isn’t “answers,” it’s input quality. Structured, sanitized evidence gets you useful responses.
Security note: Never paste secrets or private keys into any AI tool. Sanitize thoroughly and keep sensitive data local whenever possible.
Prerequisites: Install the core tools
You likely have some of these already. Install what’s missing using your package manager.
OpenSSH client and server
- apt:
sudo apt update sudo apt install -y openssh-client openssh-server- dnf:
sudo dnf install -y openssh-clients openssh-server- zypper:
sudo zypper install -y openssh- Start/enable server (if needed):
# Debian/Ubuntu sudo systemctl enable --now ssh # RHEL/Fedora/SUSE sudo systemctl enable --now sshdNetwork reachability tools (netcat + nmap)
- apt:
sudo apt install -y netcat-openbsd nmap- dnf:
sudo dnf install -y nmap-ncat nmap- zypper:
sudo zypper install -y netcat-openbsd nmapPacket capture (optional but useful)
- apt:
sudo apt install -y tcpdump- dnf:
sudo dnf install -y tcpdump- zypper:
sudo zypper install -y tcpdumpSELinux tools (for SELinux-enabled servers)
- apt:
sudo apt install -y policycoreutils selinux-utils- dnf:
sudo dnf install -y policycoreutils policycoreutils-python-utils- zypper:
sudo zypper install -y policycoreutilsFirewall frontends (server-side; install what matches your distro)
- apt (UFW):
sudo apt install -y ufw- dnf (Firewalld):
sudo dnf install -y firewalld sudo systemctl enable --now firewalld- zypper (Firewalld):
sudo zypper install -y firewalld sudo systemctl enable --now firewalld
The AI-friendly troubleshooting workflow
1) Capture a clean, reproducible SSH attempt
From the client:
ssh -vvv -o ConnectTimeout=10 -o StrictHostKeyChecking=yes -o BatchMode=yes user@example.com -p 22 2>&1 | tee ssh_client_vvv.log
If you can access the server (console, IPMI, or alternative account), collect server-side logs:
Systemd-based:
# Debian/Ubuntu typically uses 'ssh', RHEL/Fedora 'sshd' (try both)
sudo journalctl -u ssh -n 300 --no-pager > sshd_journal.log || true
sudo journalctl -u sshd -n 300 --no-pager >> sshd_journal.log || true
Non-systemd or extra context:
# Debian/Ubuntu auth log
sudo tail -n 300 /var/log/auth.log > sshd_authlog.log 2>/dev/null || true
# RHEL/Fedora/CentOS auth log
sudo tail -n 300 /var/log/secure > sshd_secure.log 2>/dev/null || true
Network reachability checks (client-side):
nc -vz example.com 22
nmap -Pn -p 22 example.com
Service/listening socket (server-side):
sudo ss -tlnp | grep -E ':(22|2222)\s'
sudo grep -nE '^(Port|ListenAddress|PermitRootLogin|PasswordAuthentication|PubkeyAuthentication|KexAlgorithms|HostKeyAlgorithms|PubkeyAcceptedKeyTypes|Match)\b' /etc/ssh/sshd_config
2) Sanitize before sharing with any AI
Remove secrets, private keys, tokens, and internal-only details. Examples:
# Strip likely base64-like blobs (public keys, tokens)
sed -i -E 's/[A-Za-z0-9+\/=]{24,}/[REDACTED]/g' ssh_client_vvv.log
# Mask IPs/hostnames (customize your patterns)
sed -i -E 's/([0-9]{1,3}\.){3}[0-9]{1,3}/[IP]/g' ssh_client_vvv.log
sed -i -E 's/\b([a-zA-Z0-9._-]+\.)+[a-zA-Z]{2,}\b/[HOST]/g' ssh_client_vvv.log
# Mask usernames
sed -i -E 's/\buser@example.com\b/user@[HOST]/g' ssh_client_vvv.log
sed -i -E 's/\buser\b/[USER]/g' ssh_client_vvv.log
Do not ever paste from ~/.ssh/id_* private keys. Public keys are usually fine but still consider redaction.
3) Ask the AI precise, testable questions
Give it structure:
Context:
- Client OS/SSH: Ubuntu 22.04, OpenSSH_8.9p1
- Server OS/SSH: RHEL 9, OpenSSH_8.7p1
- Network: Port 22, public IP, corporate firewall present
- What changed: Upgraded client yesterday, same server
Goal:
- Explain why auth fails and list the top 3 likely causes with commands to confirm/refute each.
Artifacts:
- Key client log lines:
<paste a few lines around the actual error from ssh_client_vvv.log>
- Key server log lines (if any):
<paste from sshd_journal.log or /var/log/auth.log>
- Reachability:
nc/nmap results summarized
This structure nudges the AI to give you hypotheses plus concrete commands to validate them.
4) Validate AI suggestions deterministically
Whatever the AI proposes, run the simplest commands to confirm or deny. Examples:
# Check file permissions (client and server user)
ls -ld ~/.ssh && ls -l ~/.ssh
# Should be:
# ~/.ssh -> 700
# private keys -> 600
# authorized_keys -> 600
# *.pub -> 644
# Server is listening on expected port(s)
sudo ss -tlnp | grep sshd
# Firewall status
sudo ufw status verbose 2>/dev/null || true
sudo firewall-cmd --state 2>/dev/null || true
# Algorithm availability
ssh -Q key | head
ssh -Q kex | head
5) Automate your triage (script you can paste into a ticket)
Save this as ssh-triage.sh on the client:
#!/usr/bin/env bash
set -euo pipefail
HOST="${1:-}"
PORT="${2:-22}"
USER="${3:-$USER}"
if [[ -z "$HOST" ]]; then
echo "Usage: $0 <host> [port] [user]" >&2
exit 1
fi
STAMP="$(date +%Y%m%d_%H%M%S)"
OUTDIR="ssh_triage_${HOST}_${STAMP}"
mkdir -p "$OUTDIR"
# Client-side attempt
ssh -vvv -o ConnectTimeout=10 -o BatchMode=yes -p "$PORT" "${USER}@${HOST}" 2>&1 | tee "$OUTDIR/client_ssh_vvv.log" || true
# Reachability
{
echo "=== nc -vz ${HOST} ${PORT} ==="
nc -vz "$HOST" "$PORT" 2>&1 || true
echo
echo "=== nmap -Pn -p ${PORT} ${HOST} ==="
nmap -Pn -p "$PORT" "$HOST" 2>&1 || true
} | tee "$OUTDIR/reachability.log"
# Basic env
{
echo "=== ssh -V ==="
ssh -V 2>&1
echo
echo "=== uname -a ==="
uname -a
} | tee "$OUTDIR/client_env.log"
# Redact likely secrets
for f in "$OUTDIR"/*.log; do
sed -i -E 's/[A-Za-z0-9+\/=]{24,}/[REDACTED]/g' "$f"
sed -i -E 's/([0-9]{1,3}\.){3}[0-9]{1,3}/[IP]/g' "$f"
done
echo "Triage bundle ready in: $OUTDIR"
echo "Next: Copy only the relevant error lines into your AI prompt (avoid sensitive data)."
Make it executable:
chmod +x ssh-triage.sh
Real-world examples (and solid fixes)
1) Connection timed out / refused
Symptoms:
nc -vz example.com 22times out or refusesnmap -Pn -p 22 example.comshows filtered/closed
Checks and fixes:
# On the server, ensure sshd is running
sudo systemctl status sshd || sudo systemctl status ssh
# Open the firewall
# UFW (Debian/Ubuntu)
sudo ufw allow 22/tcp
sudo ufw reload
# firewalld (RHEL/Fedora/SUSE)
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --reload
# Confirm listening
sudo ss -tlnp | grep ':22'
If using a non-standard port (e.g., 2222), update the firewall accordingly and ensure your SSH command uses -p 2222.
2) WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!
Cause: The server’s host key changed (legit reimage) or a possible MITM attack.
Safe resolution steps:
Out-of-band verify the server rebuild/change with your team.
If verified legit:
ssh-keygen -R example.com ssh-keyscan -H example.com >> ~/.ssh/known_hostsIf unverified: stop and investigate.
3) Permission denied (publickey)
Likely causes:
Wrong key used, ssh-agent offering too many keys, or wrong file permissions
Server-side
authorized_keysmissing/wrong ownershipSELinux context on
~/.sshincorrect (on SELinux systems)
Fix checklist:
# Client: force a specific key and prevent agent spam
ssh -i ~/.ssh/id_ed25519 -o IdentitiesOnly=yes user@example.com
# Client: fix perms
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_* ~/.ssh/authorized_keys 2>/dev/null || true
chmod 644 ~/.ssh/*.pub 2>/dev/null || true
# Server: correct ownership and perms
sudo chown -R user:user ~user/.ssh
sudo chmod 700 ~user/.ssh
sudo chmod 600 ~user/.ssh/authorized_keys
# Server: restore SELinux context (if enabled)
sudo restorecon -Rv ~user/.ssh
Also confirm:
# Server sshd_config critical lines
sudo grep -E '^(PubkeyAuthentication|PasswordAuthentication|AuthorizedKeysFile|Match)\b' /etc/ssh/sshd_config
# Restart sshd after changes
sudo systemctl restart sshd || sudo systemctl restart ssh
4) No matching host key type / No matching key exchange method
Cause: Algorithm mismatch, often after OpenSSH deprecations (e.g., ssh-rsa SHA-1 signatures disabled in newer clients).
Quick workaround for a known legacy target:
# ~/.ssh/config
Host legacy-host
HostName example.com
User root
HostKeyAlgorithms +ssh-rsa
PubkeyAcceptedKeyTypes +ssh-rsa
Long-term fix: upgrade the legacy server/client to support modern algorithms. At minimum, prefer ed25519 keys:
ssh-keygen -t ed25519 -a 100 -f ~/.ssh/id_ed25519
5) Too many authentication failures
Cause: ssh-agent offering many keys; server rejects before trying the right one.
Fix:
ssh-add -l # See loaded keys
ssh-add -D # Remove all keys
ssh -i ~/.ssh/id_ed25519 -o IdentitiesOnly=yes user@example.com
Or limit keys per host in ~/.ssh/config:
Host myhost
HostName example.com
User user
IdentitiesOnly yes
IdentityFile ~/.ssh/id_ed25519
Pro tips for using AI effectively (and safely)
Minimize and focus: paste only the error lines around the failure, plus a short environment summary.
Keep sensitive data out: redact usernames, IPs, domains, and any token-looking strings.
Ask for hypotheses and verification commands; then run them yourself.
Convert a validated fix into a script or Ansible task so you never repeat the same manual steps.
Conclusion and next steps
AI won’t replace your Bash skills—but it will save you time by turning messy SSH logs into targeted, testable leads. Adopt the triage workflow above, keep a sanitized evidence bundle ready, and make AI your log-reading assistant while you stay in control of the commands and changes.
Call to action:
Drop the
ssh-triage.shscript into your toolbox and use it on your next SSH issue.Build a team runbook with the real-world checks above.
Iterate: each solved case becomes a faster fix next time.
Got a tricky SSH failure pattern? Feed it through this workflow and watch your mean-time-to-fix shrink.