📑 이 챕터에서 다룰 내용
Public IP가 있는 서버는 곧 인터넷에 노출된다는 뜻이에요. 서버를 개설하는 순간부터 전 세계에서 SSH 포트를 자동으로 스캔하는 봇들이 접속을 시도합니다. 첫 1시간 안에 보안 셋업을 끝내는 것이 원칙입니다.
| 항목 | 내용 |
|---|---|
| 예상 시간 | 30~45분 |
| 핵심 | SSH 접속 강화 + 방화벽 + 자동 차단 |
| 전제 조건 | Contabo VPS SSH 접속 완료 (1편), 2편 토큰 발급 완료 |
- 시스템 업데이트 + 기본 도구 설치
- SSH 키 인증 강제 (비밀번호 로그인 차단)
- ufw 방화벽 설정
- fail2ban 자동 차단 (5회 실패 → 1시간 차단)
- unattended-upgrades 자동 보안 패치
- idle 회수 방지 cron
SSH로 서버에 처음 접속하면 제일 먼저 시스템을 최신 상태로 업데이트합니다. 첫 업데이트는 약 5~10분 걸려요.
# 첫 접속 직후 실행 sudo apt update sudo apt upgrade -y # 첫 업데이트 시 약 5~10분 소요 # 기본 도구 설치 sudo apt install -y curl wget git vim htop tmux build-essential # 시간대 설정 (한국 UTC+9) sudo timedatectl set-timezone Asia/Seoul date # Sun Mar 15 14:23:01 KST 2026
curl/wget: 파일 다운로드git: 코드 관리vim: 터미널 텍스트 편집기htop: CPU·메모리 사용량 모니터tmux: 터미널 세션 유지 (SSH 끊겨도 작업 유지)build-essential: C/C++ 빌드 도구 (Node.js·Python 패키지 컴파일에 필요)
비밀번호 로그인을 차단하고 SSH 키 인증만 허용합니다. 비밀번호는 무차별 대입(brute force)에 취약하지만, SSH 키는 사실상 뚫기 불가능해요.
# sshd_config 파일 열기 sudo vim /etc/ssh/sshd_config # ★ 변경할 항목들 # 1. PermitRootLogin no # root 직접 로그인 차단 # 2. PasswordAuthentication no # 비밀번호 로그인 차단 (SSH 키만) # 3. PubkeyAuthentication yes # SSH 키 인증 ON # 4. Port 22 # 기본 22 (또는 변경 검토) # 5. ClientAliveInterval 300 # 5분 idle 시 keepalive 전송 # 6. ClientAliveCountMax 2 # 2회 시도 후 disconnect # 저장 후 SSH 서비스 재시작 sudo systemctl restart ssh
- 변경 후 새 터미널 창에서 접속 테스트를 먼저 하세요 — 현재 세션은 절대 닫지 마세요.
- 새 터미널에서 접속이 안 되면, 현재 세션에서 설정을 복구합니다.
- 모든 접속이 막혔다면 Contabo 대시보드 → Console 메뉴 (웹 콘솔)로 접근하세요. SSH 없이도 서버를 제어할 수 있어요.
1편에서 SSH 키를 만들지 않았다면, PasswordAuthentication no로 변경하기 전에 꼭 먼저 키를 만들고 서버에 등록하세요.
# 로컬 터미널에서
ssh-keygen -t ed25519 -C "your_email@gmail.com"
ssh-copy-id -i ~/.ssh/id_ed25519.pub root@서버IP
ufw(Uncomplicated Firewall)는 Ubuntu의 간편 방화벽입니다. 기본적으로 모든 외부 접속을 차단하고, SSH와 HTTPS만 허용합니다.
# ufw 설치 sudo apt install -y ufw # 기본 정책 설정 sudo ufw default deny incoming # 외부 → 서버: 모두 차단 sudo ufw default allow outgoing # 서버 → 외부: 모두 허용 # SSH 허용 (★ enable 전에 반드시 먼저 추가하세요) sudo ufw allow 22/tcp # HTTPS 허용 (봇 운영 시 webhook 등) sudo ufw allow 443/tcp # 방화벽 활성화 sudo ufw enable # y 입력 # 상태 확인 sudo ufw status verbose
SSH 허용 없이 ufw enable을 실행하면 즉시 접속이 끊기고 SSH로 재접속이 불가능합니다. 이 경우 Contabo 대시보드의 웹 콘솔로만 복구할 수 있어요.
Contabo는 OS 방화벽(ufw) 하나만 설정합니다
AWS·Oracle Cloud 등은 클라우드 레벨 방화벽(Security Group·VCN)과 OS 레벨 방화벽(ufw) 두 단계를 모두 설정해야 합니다.
Contabo는 OS 레벨(ufw) 하나만 설정하면 됩니다. 클라우드 레벨 방화벽이 따로 없어요.
| 포트 | 용도 | 설정 |
|---|---|---|
| 22/tcp | SSH 접속 | 허용 (필수) |
| 443/tcp | HTTPS (webhook 등) | 허용 권장 |
| 80/tcp | HTTP | Cloudflare Tunnel 사용 시 불필요 |
fail2ban은 SSH 로그인 실패를 감지해 해당 IP를 자동으로 차단하는 도구예요. 무차별 대입 공격을 방어하는 1차 안전망입니다.
# 설치 sudo apt install -y fail2ban # 기본 설정 파일 복사 (원본 보존) sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local # jail.local 편집 sudo vim /etc/fail2ban/jail.local # ★ [DEFAULT] 섹션에서 변경할 항목 # bantime = 1h # 1시간 차단 # findtime = 10m # 10분 안에 # maxretry = 5 # 5회 실패 시 차단 # [sshd] 섹션 활성화 # enabled = true # port = 22 # 서비스 등록 + 재시작 sudo systemctl enable fail2ban sudo systemctl restart fail2ban # 상태 확인 sudo fail2ban-client status sudo fail2ban-client status sshd
| 설정 항목 | 값 | 의미 |
|---|---|---|
| bantime | 1h | 차단 지속 시간 (1시간) |
| findtime | 10m | 실패 횟수를 집계하는 시간 창 (10분) |
| maxretry | 5 | 이 횟수 이상 실패하면 차단 |
운영 중에 어떤 IP가 차단됐는지 확인하려면:
sudo fail2ban-client status sshd
특정 IP를 수동으로 차단 해제하려면:
sudo fail2ban-client set sshd unbanip 1.2.3.4
보안 패치는 시간이 지남에 따라 계속 나와요. 매번 수동으로 업데이트하기 어려우니, 보안 패치만 자동으로 적용되도록 설정합니다.
# unattended-upgrades 설치 sudo apt install -y unattended-upgrades # 자동 활성화 (대화형 설정) sudo dpkg-reconfigure --priority=low unattended-upgrades # "Yes" 선택 # 설정 완료 후 자동 생성되는 파일 # /etc/apt/apt.conf.d/20auto-upgrades # 매일 자동으로 보안 업데이트가 적용됩니다
unattended-upgrades는 보안 패치만 자동 적용해요. 일반 패키지 버전 업그레이드는 자동으로 하지 않아 시스템 안정성을 유지합니다.
Cloud VPS 10은 8GB RAM이라 swap을 거의 사용하지 않아요. 그래도 메모리가 부족해지는 OOM(Out Of Memory) 상황에 대비해 swap 파일을 추가해 두는 것이 좋습니다.
# 4GB swap 파일 생성 sudo fallocate -l 4G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile # 재부팅 후에도 유지되도록 fstab에 등록 echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab # swappiness 낮춤 (RAM을 우선 사용, swap은 최후 수단) echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.conf sudo sysctl -p # 확인 free -h swapon --show
vm.swappiness=10으로 설정하면 RAM이 90% 이상 찼을 때만 swap을 사용합니다. 기본값은 60인데, 10으로 낮추면 RAM을 최대한 활용해 봇 응답 속도가 빨라져요.
일부 클라우드 서비스는 CPU 사용량이 일정 기간 너무 낮으면 서버를 회수하는 정책을 운영해요. Contabo는 현재 이 정책을 적용하지 않지만, 대비 차원에서 가벼운 cron job을 설정해 두면 안전합니다.
Contabo는 현재 idle 회수 정책이 없어요. 다만 향후 변경 가능성에 대비하거나, Oracle Cloud Free Tier 등 다른 서비스와 함께 사용하는 경우에 이 설정이 유용합니다.
봇이 사용자 요청을 처리하면 자연스럽게 CPU를 사용하므로, 실제 봇 운영 중에는 이 cron이 없어도 되는 경우가 많아요.
# crontab 편집 sudo crontab -e # 매 6시간마다 1초간 CPU 가볍게 활성화 0 */6 * * * dd if=/dev/zero of=/dev/null bs=1M count=100 2>/dev/null # 저장 후 crontab 확인 sudo crontab -l
봇이 주기적으로 API를 호출하거나 로그를 기록하는 등 정기 작업을 하면, 자연스럽게 CPU를 사용하게 돼요. 이 경우 별도의 idle 방지 cron이 없어도 됩니다.
- 1️⃣ 시스템 업데이트:
apt update && apt upgrade -y+ 기본 도구 설치 + 시간대 설정 - 2️⃣ SSH 보안:
PasswordAuthentication no+PermitRootLogin no→ SSH 키 인증만 허용 - 3️⃣ 방화벽(ufw): 기본 deny + SSH(22) + HTTPS(443) 허용 →
ufw enable - 4️⃣ fail2ban: 10분 안에 5회 실패 → 1시간 차단 (SSH 무차별 대입 방어)
- 5️⃣ 자동 보안 패치:
unattended-upgrades로 매일 자동 적용 - 6️⃣ swap: 4GB swap 파일 +
swappiness=10(RAM 우선 사용) - 7️⃣ idle 방지: 6시간마다 가벼운 cron (대비용, 봇 운영 시 선택)
Ubuntu 24.04 보안 6단계: 시스템 업데이트 → SSH 키 인증 강제 → ufw 방화벽 → fail2ban 자동 차단 → 자동 보안 패치 → swap 추가
이 6단계를 마치면 서버가 안전한 상태로 봇을 운영할 준비가 완료됩니다. 다음은 4편 — Discord 봇 boilerplate예요.