서론: 왜 홈서버 보안이 중요한가

홈서버를 인터넷에 공개하는 순간, 전 세계의 봇과 해커들이 당신의 서버를 스캔하기 시작합니다. 과장이 아닙니다. 실제로 새로운 서버를 온라인에 올리면 몇 분 안에 SSH 무차별 대입 공격(brute force attack)이 시작되는 것을 로그에서 확인할 수 있습니다. 지난 편에서 네트워크와 DDNS 설정을 마쳤다면, 이제 서버를 안전하게 지키는 방법을 알아야 할 때입니다.

보안은 어렵고 복잡해 보이지만, 기본적인 원칙만 제대로 지켜도 대부분의 공격을 막을 수 있습니다. 이번 편에서는 홈서버 운영자라면 반드시 알아야 할 보안 설정들을 하나씩 살펴보겠습니다.

1. UFW 방화벽 설정

1.1 방화벽이란?

방화벽은 서버로 들어오고 나가는 네트워크 트래픽을 제어하는 보안 시스템입니다. 쉽게 말해서 "누가 어떤 문으로 들어올 수 있는지"를 정하는 것이죠. Ubuntu에서는 UFW(Uncomplicated Firewall)라는 도구를 사용하면 iptables보다 훨씬 쉽게 방화벽을 관리할 수 있습니다.

1.2 UFW 설치 및 기본 설정

대부분의 Ubuntu 버전에는 UFW가 기본 설치되어 있습니다. 설치 여부를 확인하고, 없다면 설치합니다.

# UFW 설치 확인 및 설치
sudo apt update
sudo apt install ufw

# UFW 상태 확인
sudo ufw status

처음에는 비활성화 상태일 것입니다. 활성화하기 전에 반드시 SSH 접속을 허용해야 합니다. 그렇지 않으면 방화벽이 활성화되는 순간 서버에서 쫓겨나게 됩니다.

# 기본 정책 설정: 모든 들어오는 연결 차단, 나가는 연결 허용
sudo ufw default deny incoming
sudo ufw default allow outgoing

# SSH 허용 (중요!)
sudo ufw allow ssh
# 또는 포트 번호로 지정
sudo ufw allow 22/tcp

# 웹 서버 포트 허용
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# UFW 활성화
sudo ufw enable

1.3 서비스별 포트 허용

운영하는 서비스에 따라 필요한 포트를 열어주어야 합니다.

# 특정 포트 허용
sudo ufw allow 8080/tcp    # 대체 웹 포트
sudo ufw allow 32400/tcp   # Plex 미디어 서버

# 포트 범위 허용
sudo ufw allow 6000:6010/tcp

# 특정 IP에서만 접근 허용
sudo ufw allow from 192.168.1.0/24 to any port 22

# 특정 IP 차단
sudo ufw deny from 123.45.67.89

# 규칙 확인
sudo ufw status numbered

# 특정 규칙 삭제 (번호로)
sudo ufw delete 3
주의: 원격으로 서버를 관리하고 있다면 SSH 포트를 차단하지 않도록 각별히 주의하세요. 실수로 차단하면 서버에 물리적으로 접근해야 합니다.

2. fail2ban으로 무차별 대입 공격 방어

2.1 fail2ban이란?

fail2ban은 로그 파일을 모니터링하다가 비정상적인 접근 시도(예: 반복되는 로그인 실패)를 감지하면 해당 IP를 자동으로 차단하는 도구입니다. SSH 무차별 대입 공격을 막는 데 매우 효과적입니다.

2.2 fail2ban 설치 및 설정

# fail2ban 설치
sudo apt install fail2ban

# 서비스 시작 및 자동 시작 설정
sudo systemctl start fail2ban
sudo systemctl enable fail2ban

fail2ban의 설정은 /etc/fail2ban/ 디렉토리에 있습니다. 기본 설정 파일을 직접 수정하지 말고, local 파일을 만들어서 사용하는 것이 권장됩니다.

# 로컬 설정 파일 생성
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.local

2.3 jail.local 상세 설정

주요 설정 옵션들을 살펴보겠습니다.

[DEFAULT]
# 차단 시간 (초 단위, -1은 영구 차단)
bantime = 3600

# 로그인 시도 감시 시간 범위
findtime = 600

# 허용되는 실패 횟수
maxretry = 5

# 차단에서 제외할 IP (자신의 IP 추가)
ignoreip = 127.0.0.1/8 ::1 192.168.1.0/24

# 차단 시 이메일 알림 (선택)
# action = %(action_mwl)s
# destemail = your@email.com
# sender = fail2ban@yourdomain.com

[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 86400

# Nginx 관련 jail
[nginx-http-auth]
enabled = true
port = http,https
filter = nginx-http-auth
logpath = /var/log/nginx/error.log
maxretry = 5

[nginx-botsearch]
enabled = true
port = http,https
filter = nginx-botsearch
logpath = /var/log/nginx/access.log
maxretry = 2

설정을 변경한 후에는 fail2ban을 재시작해야 합니다.

# 설정 적용
sudo systemctl restart fail2ban

# 현재 차단 상태 확인
sudo fail2ban-client status
sudo fail2ban-client status sshd

# 특정 IP 수동 차단 해제
sudo fail2ban-client set sshd unbanip 123.45.67.89

3. SSH 보안 강화

3.1 SSH 포트 변경

기본 SSH 포트(22)를 변경하면 자동화된 봇 공격의 상당 부분을 피할 수 있습니다. 완벽한 보안책은 아니지만, 공격 로그가 확연히 줄어드는 것을 체감할 수 있습니다.

# SSH 설정 파일 편집
sudo nano /etc/ssh/sshd_config

# 다음 줄을 찾아서 수정 (주석 해제 및 포트 번호 변경)
Port 2222

포트를 변경하기 전에 반드시 UFW에서 새 포트를 허용하세요.

# 새 SSH 포트 허용
sudo ufw allow 2222/tcp

# SSH 서비스 재시작
sudo systemctl restart sshd

# 이제 새 포트로 접속
ssh -p 2222 username@server_ip

3.2 SSH 키 인증만 허용

비밀번호 인증보다 SSH 키 인증이 훨씬 안전합니다. 키 인증을 설정하고 비밀번호 로그인을 비활성화하는 것을 강력히 권장합니다.

# 클라이언트(본인 PC)에서 SSH 키 생성
ssh-keygen -t ed25519 -C "your_email@example.com"

# 생성된 공개키를 서버에 복사
ssh-copy-id -p 2222 username@server_ip

# 또는 수동으로 복사
cat ~/.ssh/id_ed25519.pub | ssh -p 2222 username@server_ip "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

키 인증이 정상 작동하는지 확인한 후, 비밀번호 인증을 비활성화합니다.

# SSH 설정 파일 편집
sudo nano /etc/ssh/sshd_config

# 다음 설정들을 찾아서 수정
PasswordAuthentication no
PubkeyAuthentication yes
PermitRootLogin no
PermitEmptyPasswords no
ChallengeResponseAuthentication no

# SSH 재시작
sudo systemctl restart sshd
중요: 비밀번호 인증을 비활성화하기 전에 반드시 SSH 키로 접속이 되는지 확인하세요. 그렇지 않으면 서버에서 완전히 잠길 수 있습니다.

3.3 추가 SSH 보안 설정

# /etc/ssh/sshd_config에 추가 설정
# 특정 사용자만 SSH 접속 허용
AllowUsers username1 username2

# 접속 대기 시간 제한
LoginGraceTime 30

# 최대 인증 시도 횟수
MaxAuthTries 3

# 동시 미인증 연결 수 제한
MaxStartups 10:30:60

# X11 포워딩 비활성화 (필요 없다면)
X11Forwarding no

4. SSL/TLS 인증서 (Let's Encrypt)

4.1 HTTPS가 필요한 이유

HTTP 통신은 암호화되지 않아 중간에서 데이터를 엿볼 수 있습니다. HTTPS는 SSL/TLS 인증서를 사용하여 통신을 암호화하고, 서버의 신원을 보장합니다. Let's Encrypt를 사용하면 무료로 신뢰할 수 있는 인증서를 발급받을 수 있습니다.

4.2 Certbot 설치 및 인증서 발급

# Certbot 설치
sudo apt install certbot python3-certbot-nginx

# Nginx를 사용하는 경우 (자동 설정)
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com

# 인증서만 발급 (수동 설정)
sudo certbot certonly --standalone -d yourdomain.com

# 인증서 발급 확인
sudo certbot certificates

4.3 인증서 자동 갱신

Let's Encrypt 인증서는 90일마다 갱신해야 합니다. Certbot은 자동 갱신을 위한 타이머를 설정합니다.

# 자동 갱신 타이머 확인
sudo systemctl status certbot.timer

# 수동 갱신 테스트
sudo certbot renew --dry-run

# cron으로 직접 자동 갱신 설정 (선택)
sudo crontab -e
# 다음 줄 추가 (매일 새벽 3시에 갱신 시도)
0 3 * * * /usr/bin/certbot renew --quiet

5. 리버스 프록시와 HTTPS

5.1 Nginx 리버스 프록시 설정

리버스 프록시를 사용하면 하나의 서버에서 여러 서비스를 도메인이나 경로로 분기할 수 있습니다. 또한 SSL 인증서를 한 곳에서 관리할 수 있어 편리합니다.

# /etc/nginx/sites-available/reverse-proxy
server {
    listen 80;
    server_name yourdomain.com;

    # HTTP를 HTTPS로 리다이렉트
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name yourdomain.com;

    # SSL 인증서 설정
    ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;

    # SSL 보안 설정
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
    ssl_prefer_server_ciphers off;

    # HSTS 헤더
    add_header Strict-Transport-Security "max-age=63072000" always;

    # 메인 애플리케이션으로 프록시
    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;
    }

    # API 서버로 프록시
    location /api/ {
        proxy_pass http://localhost:8080/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}
# 설정 활성화
sudo ln -s /etc/nginx/sites-available/reverse-proxy /etc/nginx/sites-enabled/

# 설정 테스트 및 적용
sudo nginx -t
sudo systemctl reload nginx

6. 보안 업데이트 자동화

6.1 unattended-upgrades 설정

보안 업데이트를 놓치면 알려진 취약점에 노출될 수 있습니다. Ubuntu의 unattended-upgrades를 사용하면 보안 업데이트를 자동으로 적용할 수 있습니다.

# 패키지 설치
sudo apt install unattended-upgrades apt-listchanges

# 자동 업데이트 설정
sudo dpkg-reconfigure -plow unattended-upgrades

6.2 상세 설정

# 설정 파일 편집
sudo nano /etc/apt/apt.conf.d/50unattended-upgrades

주요 설정 옵션:

// 자동 업데이트할 패키지 소스
Unattended-Upgrade::Allowed-Origins {
    "${distro_id}:${distro_codename}";
    "${distro_id}:${distro_codename}-security";
    "${distro_id}ESMApps:${distro_codename}-apps-security";
    "${distro_id}ESM:${distro_codename}-infra-security";
};

// 자동 제거할 미사용 커널 패키지
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";

// 자동 재부팅 (필요시)
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "03:00";

// 이메일 알림
Unattended-Upgrade::Mail "your@email.com";
Unattended-Upgrade::MailReport "on-change";

7. 침입 탐지 기초

7.1 로그 모니터링

서버 로그를 정기적으로 확인하면 이상 징후를 조기에 발견할 수 있습니다.

# 인증 로그 확인 (SSH 접속 시도)
sudo tail -f /var/log/auth.log

# 실패한 로그인 시도 확인
sudo grep "Failed password" /var/log/auth.log | tail -20

# 성공한 로그인 확인
sudo grep "Accepted" /var/log/auth.log | tail -20

# 시스템 로그 확인
sudo journalctl -xe

# 최근 로그인 기록
last
lastb  # 실패한 로그인

7.2 AIDE를 이용한 파일 무결성 검사

AIDE(Advanced Intrusion Detection Environment)는 파일 시스템의 변경을 감지하는 도구입니다.

# AIDE 설치
sudo apt install aide

# 초기 데이터베이스 생성
sudo aideinit

# 데이터베이스 적용
sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db

# 무결성 검사 실행
sudo aide --check

# cron으로 정기 검사 설정
sudo crontab -e
# 매일 새벽 4시에 검사
0 4 * * * /usr/bin/aide --check | mail -s "AIDE Report" your@email.com

7.3 rkhunter로 루트킷 검사

# rkhunter 설치
sudo apt install rkhunter

# 데이터베이스 업데이트
sudo rkhunter --update

# 속성 업데이트
sudo rkhunter --propupd

# 루트킷 검사 실행
sudo rkhunter --check

# 자동 검사 설정 (cron)
sudo crontab -e
0 5 * * * /usr/bin/rkhunter --check --skip-keypress 2>&1 | mail -s "rkhunter Report" your@email.com

8. 보안 체크리스트

홈서버 보안을 위한 체크리스트를 정리해 보았습니다.

항목 설정 여부 중요도
UFW 방화벽 활성화 필수 높음
SSH 키 인증 설정 필수 높음
SSH 비밀번호 인증 비활성화 권장 높음
fail2ban 설치 및 설정 권장 높음
SSH 포트 변경 선택 중간
root 로그인 비활성화 권장 높음
SSL/TLS 인증서 적용 필수 (웹 서비스) 높음
자동 보안 업데이트 권장 높음
정기적인 로그 확인 권장 중간

마치며

보안은 한 번 설정하고 끝나는 것이 아니라 지속적으로 관리해야 하는 영역입니다. 이번 편에서 다룬 기본적인 보안 설정만 제대로 해두어도 대부분의 자동화된 공격으로부터 서버를 보호할 수 있습니다.

다음 편에서는 서버 운영에서 빠질 수 없는 백업 전략과 모니터링에 대해 알아보겠습니다. 아무리 보안을 철저히 해도 예상치 못한 상황은 발생할 수 있으니, 백업과 모니터링으로 만일의 사태에 대비하는 것이 현명합니다.

질문이나 문제가 있다면 댓글로 남겨주세요. 함께 해결해 나가겠습니다.