본문으로 건너뛰기
cccskills
무료GitHub에 공개

vps-security-hardening

Audit and harden VPS security — fail2ban, SSH hardening, firewall setup

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

설치 방법 보기

포함된 파일(2)

  • SKILL.md8.1 KB
  • references/ssh-key-vs-password.md3.6 KB

SKILL.md(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

VPS Security Hardening

Audit and harden VPS security with fail2ban (brute-force protection), SSH hardening, and optional firewall setup.

When to Use

  • New VPS setup (initial hardening)
  • Security audit requested
  • SSH brute-force attacks detected
  • User wants to "secure VPS" or "protect server"

Prerequisites: Establishing SSH Access

Before hardening, ensure you can SSH into the VPS.

If Password Auth is Disabled (PublicKey only)

VPS providers often disable password auth by default. You need to add your SSH key first.

Option 1: Via VPS Web Console (Recommended)

  1. Generate SSH key locally (if not exists):

    ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N '' -C "user@machine"
    cat ~/.ssh/id_ed25519.pub
    
  2. Login to VPS via web console (provider dashboard → Console/Terminal)

  3. Add public key to VPS:

    mkdir -p ~/.ssh
    echo "ssh-ed25519 AAAA... user@machine" >> ~/.ssh/authorized_keys
    chmod 700 ~/.ssh
    chmod 600 ~/.ssh/authorized_keys
    
  4. Test from local machine:

    ssh root@VPS_IP
    

Option 2: Via Provider Dashboard

Most providers (DigitalOcean, Vultr, Biznet, etc.) have "Add SSH Key" in dashboard:

  • Copy public key (cat ~/.ssh/id_ed25519.pub)
  • Paste into provider's SSH key management
  • Rebuild/restart VPS (some providers require this)

Option 3: Enable Password Auth Temporarily

Only if web console is unavailable:

  1. Login via web console
  2. Edit SSH config:
    echo "PasswordAuthentication yes" >> /etc/ssh/sshd_config.d/99-temp-password.conf
    systemctl reload sshd
    
  3. SSH in with password, add your key
  4. Remove temp config:
    rm /etc/ssh/sshd_config.d/99-temp-password.conf
    systemctl reload sshd
    

Common Pitfall: sshpass with PublicKey-Only VPS

Problem: sshpass -p 'password' ssh user@host fails with "Permission denied (publickey)" even with correct password.

Why: VPS has PasswordAuthentication no in sshd_config — password auth is disabled at server level.

Solution: Use web console to add SSH key first (see Option 1 above).

Workflow

Phase 1: Security Audit

  1. Check running processes

    ps aux --sort=-%mem | head -20
    systemctl list-units --type=service --state=running
    
  2. Check listening ports

    sudo ss -tulpn
    sudo netstat -tulpn
    
  3. Check for rootkits/malware

    # Hidden processes
    ps aux | wc -l
    ls /proc | grep -E '^[0-9]+$' | wc -l
    
    # Recent failed logins
    sudo grep "Failed password" /var/log/auth.log | tail -20
    
  4. Check user accounts

    cat /etc/passwd | grep -E '/bin/(bash|sh)$'
    sudo lastlog
    
  5. Resource usage

    free -h
    df -h
    uptime
    

Phase 2: Install fail2ban

# Install
sudo apt-get update
sudo apt-get install -y fail2ban

# Enable and start
sudo systemctl enable fail2ban
sudo systemctl start fail2ban

Phase 3: Configure fail2ban

Create /etc/fail2ban/jail.local:

[DEFAULT]
bantime  = 3600        # Ban for 1 hour
findtime = 600         # Count failures in last 10 minutes
maxretry = 5           # Ban after 5 failures

[sshd]
enabled = true
port    = 22
logpath = /var/log/auth.log
maxretry = 5

Restart:

sudo systemctl restart fail2ban
sudo fail2ban-client status sshd

Phase 4: SSH Hardening

Create /etc/ssh/sshd_config.d/99-hardening.conf:

# Disable root login
PermitRootLogin no

# Enable public key auth
PubkeyAuthentication yes

# Disable empty passwords
PermitEmptyPasswords no

# Limit auth attempts
MaxAuthTries 3

# Disable X11 forwarding
X11Forwarding no

# Disable TCP forwarding
AllowTcpForwarding no

# Disable agent forwarding
AllowAgentForwarding no

# Set login grace time
LoginGraceTime 30

# Limit sessions
MaxSessions 2

# Strong ciphers only
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com

# Strong MACs only
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com

# Strong key exchange
KexAlgorithms curve25519-sha256,diffie-hellman-group-exchange-sha256

Test and reload:

sudo sshd -t
sudo systemctl reload sshd

Phase 5: Verify

# fail2ban status
sudo fail2ban-client status sshd

# SSH config
sudo sshd -T | grep -E '(permitrootlogin|maxauthtries|x11forwarding)'

# Check banned IPs
sudo fail2ban-client get sshd banip

Important: Password vs SSH Key Decision

DO NOT automatically disable password authentication!

Check First

# Check if user has SSH keys
cat ~/.ssh/authorized_keys

# Check how user is currently connected
sudo grep "Accepted" /var/log/auth.log | tail -5

Decision Logic

If user logs in with PASSWORD:

  • ✅ Keep PasswordAuthentication yes
  • ✅ fail2ban provides brute-force protection
  • ⚠️ Disabling password = user gets locked out

If user logs in with SSH KEY:

  • ✅ Can disable PasswordAuthentication no
  • ✅ Maximum security (impossible to brute-force)

User Preference Handling

CRITICAL: If user says "keep password" or "tanpa ssh key" or similar:

  • ✅ Accept their decision
  • ✅ Explain security is already good with fail2ban
  • ❌ DO NOT keep suggesting SSH keys
  • ❌ DO NOT say "but SSH keys are better"
  • ❌ DO NOT make them feel their choice is wrong

User knows their use case better than you:

  • They might need portability (login from anywhere)
  • They might not want key file management
  • They might prefer convenience over maximum security
  • Respect their decision and move on

Pitfalls

1. Disabling Password Auth Too Early

Problem: User currently uses password, you disable it, user gets locked out.

Solution:

  • Always check current connection method first
  • If password login, keep it enabled
  • Only disable if user has working SSH keys AND explicitly requests it

2. Not Testing SSH Config

Problem: Invalid SSH config breaks SSH service, user locked out.

Solution:

  • Always run sudo sshd -t before reload
  • Use reload not restart (preserves current connections)

3. fail2ban Banning User's Own IP

Problem: User makes typo 5 times, gets banned.

Solution:

  • Explain how to unban via VPS console: sudo fail2ban-client unban --all
  • Consider whitelist for user's known IPs (optional)

4. Over-Suggesting Security Improvements

Problem: User made decision (e.g., keep password), you keep suggesting alternatives.

Solution:

  • Present options ONCE with pros/cons
  • User decides
  • Accept decision and move on
  • Don't revisit unless user asks

5. Cloud Provider Default Users

Problem: Deleting cloud provider system users (e.g., lighthouse on Tencent Cloud).

Solution:

  • Check if user has sudo privileges: sudo grep lighthouse /etc/sudoers.d/*
  • If yes, it's emergency access mechanism
  • DO NOT delete (user might need it for recovery)

Monitoring Commands

# Check fail2ban status
sudo fail2ban-client status sshd

# Check banned IPs
sudo fail2ban-client get sshd banip

# Unban IP
sudo fail2ban-client set sshd unbanip 1.2.3.4

# Watch SSH attacks live
sudo journalctl -u ssh -f

# Recent failed attempts
sudo grep "Failed password" /var/log/auth.log | tail -20

Optional: UFW Firewall

Only enable if user requests or if no cloud-level firewall exists.

# Allow SSH first (CRITICAL!)
sudo ufw allow 22/tcp

# Allow other services
sudo ufw allow 1430/tcp  # Example: API port

# Enable
sudo ufw enable

# Check status
sudo ufw status

Success Criteria

  • ✅ fail2ban running and banning attackers
  • ✅ SSH hardened (root disabled, limited attempts)
  • ✅ User can still login (not locked out)
  • ✅ Auto-updates enabled
  • ✅ User satisfied with security level

References

리뷰

아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.

댓글

로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

보내면 바로 공개됩니다. 이메일 주소나 전화번호 같은 개인 정보는 쓰지 마세요. URL은 2개까지입니다.

0 / 1,000자

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

같은 저장소의 스킬

Drives development with tests. Use when implementing any logic, fixing any bug, or changing any behavior. Use when you need to prove that code works, when a bug report arrives, or when you're about to modify existing functionality.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

kevinnft/ai-agent-skills142026년 8월 1일 업데이트

airtable

무료

Airtable REST API via curl. Records CRUD, filters, upserts.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

kevinnft/ai-agent-skills142026년 8월 1일 업데이트

Guides stable API and interface design. Use when designing APIs, module boundaries, or any public interface. Use when creating REST or GraphQL endpoints, defining type contracts between modules, or establishing boundaries between frontend and backend.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

kevinnft/ai-agent-skills142026년 8월 1일 업데이트

Build monitoring bots that poll APIs and send notifications on state changes (new listings, price alerts, status updates)

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

kevinnft/ai-agent-skills142026년 8월 1일 업데이트

REST/GraphQL API testing with automated validation — test endpoints, validate responses, check status codes, and ensure API contracts

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

kevinnft/ai-agent-skills142026년 8월 1일 업데이트

Manage Apple Notes via memo CLI: create, search, edit.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

kevinnft/ai-agent-skills142026년 8월 1일 업데이트

kevinnft의 스킬 모두 보기

이 스킬의 문제 신고