Files
agent-skills/devops/ssh-server-setup/SKILL.md
Hermes Agent ccc63d1e70 first commit
2026-05-10 13:52:46 +08:00

186 lines
5.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: ssh-server-setup
description: "Set up SSH key authentication, configure firewalls, harden SSH, and audit server security. Use when: (1) user needs SSH access to a server, (2) SSH connection fails with permission errors, (3) setting up key-based auth for new users, (4) enabling/configuring UFW firewall, (5) analyzing SSH attacks, (6) hardening SSH config."
---
# SSH Server Setup & Troubleshooting
## Quick Setup (New Key Pair)
### 1. Generate Key Pair
```bash
# On client machine (or use Xshell's key generator)
ssh-keygen -t rsa -b 2048 -f ~/.ssh/id_rsa -C "user@host"
```
### 2. Install Public Key on Server
```bash
# On server
mkdir -p /home/<user>/.ssh
echo '<public-key-content>' >> /home/<user>/.ssh/authorized_keys
chmod 700 /home/<user>/.ssh
chmod 600 /home/<user>/.ssh/authorized_keys
chmod 755 /home/<user> # CRITICAL: must NOT be 777 or group-writable
chown -R <user>:<user> /home/<user>/.ssh
```
### 3. Verify SSH Config Allows Key Auth
```bash
grep -E "^(PubkeyAuthentication|AuthorizedKeysFile)" /etc/ssh/sshd_config
# Should show:
# PubkeyAuthentication yes
# AuthorizedKeysFile .ssh/authorized_keys
```
## ⚠️ Critical Pitfall: Home Directory Permissions
**Symptom**: SSH logs show `Authentication refused: bad ownership or modes for directory /home/<user>`
**Root cause**: SSH (OpenSSH) refuses public key authentication if the user's home directory has group or other write permissions (e.g., 777, 775).
**Fix**:
```bash
chmod 755 /home/<user>
```
**Why**: OpenSSH considers a writable home directory a security risk — other users could manipulate `~/.ssh/authorized_keys`. The directory must be owned by the user and not writable by group/others.
**Debugging**:
```bash
# Check current permissions
ls -la /home/ | grep <user>
# Should show drwxr-xr-x (755), NOT drwxrwxrwx (777) or drwxrwxr-x (775)
# Check SSH logs for the exact error
tail -20 /var/log/auth.log | grep -i "ssh\|publickey"
# Or on systemd systems:
journalctl -u ssh --no-pager -n 20
```
## Permission Checklist
| Path | Owner | Permissions | Why |
|------|-------|-------------|-----|
| `/home/<user>` | `<user>` | `755` | SSH refuses auth if group/other writable |
| `~/.ssh/` | `<user>` | `700` | Only owner should access SSH config |
| `~/.ssh/authorized_keys` | `<user>` | `600` | Only owner should read/write keys |
| `~/.ssh/id_rsa` (private) | `<user>` | `600` | Private key must be restricted |
## Xshell-Specific Notes
1. **Generate key**: 工具 → 用户密钥管理器 → 新建 → RSA 2048
2. **Import key**: 工具 → 用户密钥管理器 → 导入
3. **Connection settings**:
- 协议: SSH
- 用户身份验证: 方法选 **Public Key**(不是 Password
- 用户名: `ubuntu` (or whatever the server user is)
- 用户密钥: select the imported key
## Common Errors
| Error | Cause | Fix |
|-------|-------|-----|
| `bad ownership or modes for directory` | Home dir writable by group/others | `chmod 755 /home/<user>` |
| `bad ownership or modes for file` | authorized_keys wrong perms | `chmod 600 ~/.ssh/authorized_keys` |
| `Permission denied (publickey)` | Key not in authorized_keys | Add public key to file |
| `Connection closed by foreign host` | Auth failed, server disconnects | Check logs for specific reason |
| `所选的用户密钥未在远程主机上注册` | Public key not installed on server | Add public key to authorized_keys |
---
## UFW Firewall Setup
When enabling SSH access, always set up UFW in this order to avoid lockout:
```bash
# 1. Allow SSH FIRST (before enabling firewall)
sudo ufw allow 22/tcp comment "SSH"
# 2. Set default policies
sudo ufw default deny incoming
sudo ufw default allow outgoing
# 3. Enable (use --force for non-interactive)
sudo ufw --force enable
# 4. Verify
sudo ufw status verbose
```
**Opening additional ports later:**
```bash
sudo ufw allow 80/tcp comment "HTTP"
sudo ufw allow 443/tcp comment "HTTPS"
sudo ufw allow from <specific-ip> to any port 22 # Restrict SSH to specific IP
```
---
## SSH Attack Analysis
**Check attack patterns:**
```bash
# Failed/disconnected attempts with IP counts
journalctl -u ssh --no-pager --since "2026-05-01" | \
grep -i "failed\|invalid\|refused\|disconnected.*preauth" | \
grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | sort | uniq -c | sort -rn | head -15
# Successful logins only
journalctl -u ssh --no-pager --since "2026-05-01" | grep "Accepted" | \
grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | sort | uniq -c | sort -rn
```
**IP geolocation lookup:**
```bash
# ip-api.com (free, no key needed, rate limited 45/min)
curl -s "http://ip-api.com/json/<IP>?fields=country,regionName,isp,org"
```
**Typical attack sources:** Cloud provider IPs (Tencent Cloud, Alibaba Cloud, OVH, Hetzner) — these are botnet/scanner nodes, not targeted attacks.
---
## SSH Hardening (sshd_config)
Add to `/etc/ssh/sshd_config`:
```bash
MaxAuthTries 3 # Limit auth attempts per connection
LoginGraceTime 30 # Timeout for auth (seconds)
ClientAliveInterval 300 # Send keepalive every 5 min
ClientAliveCountMax 2 # Disconnect after 2 missed keepalives
MaxSessions 3 # Limit concurrent sessions per connection
AllowAgentForwarding no # Disable unless needed
AllowTcpForwarding no # Disable unless needed
```
Apply: `sudo systemctl restart sshd`
---
## Server Security Audit Checklist
```bash
# 1. SSH config
cat /etc/ssh/sshd_config | grep -v "^#" | grep -v "^$"
# 2. Firewall status
sudo ufw status verbose
# 3. fail2ban status (if installed)
sudo fail2ban-client status sshd
# 4. Auto-updates
cat /etc/apt/apt.conf.d/20auto-upgrades
# 5. Listening ports
ss -tlnp | grep -v "127.0.0.1" | grep -v "::1"
# 6. System resources
free -h && df -h / && uptime
# 7. Swap config
swapon --show
cat /proc/sys/vm/swappiness
```