[태그:] fail2ban

  • 리눅스 서버 보안 설정 7가지 — VPS 세팅 직후 해킹 막는 실전 체크리스트

    리눅스 서버 보안 설정 7가지 — VPS 세팅 직후 해킹 막는 실전 체크리스트

    💡 Tip. 바쁜 현대인들을 위한 본문 요약

    • VPS 생성 직후 SSH 비밀번호 로그인을 방치하면 하루 수백 건의 무차별 공격에 노출됨
    • SSH 키 인증 전환 + root 로그인 차단이 가장 시급한 1순위 설정
    • UFW 방화벽으로 허용 포트만 열고, fail2ban으로 반복 실패 IP를 자동 차단
    • unattended-upgrades로 보안 패치 자동 적용 — 수동 관리는 현실적으로 불가능
    • 7가지 설정을 모두 적용하면 공격 표면의 95% 이상 제거 가능

    Oracle ARM 서버를 처음 세팅하고 24시간 뒤 /var/log/auth.log를 열어봤습니다.
    SSH 로그인 실패 기록이 437건.
    아무런 서비스도 올리지 않은 빈 서버에 이미 전 세계에서 무차별 대입 공격(brute-force)이 쏟아지고 있었습니다.

    Verizon의 2025 DBIR 보고서에 따르면 데이터 유출 사고의 상당수가 취약한 자격증명과 패치되지 않은 취약점에서 시작됩니다.
    리눅스 서버 보안 설정은 "나중에 해도 되는 것"이 아니라, 서버를 켠 그 순간부터 시작해야 하는 생존 작업입니다.

    직접 Oracle Cloud ARM 인스턴스를 1년 넘게 운영하면서 정리한 실전 리눅스 서버 보안 설정 7가지를 공유합니다.
    명령어만 나열하는 글이 아니라, 각 설정이 왜 필요한지, 안 하면 어떻게 되는지까지 함께 설명합니다.


    🔐 Step 1: 전용 사용자 생성 + root 직접 로그인 차단

    A of a shield icon with a lock symbol on a server rack

    리눅스 서버 보안 설정의 첫 번째 원칙은 root 계정 직접 사용을 중단하는 것입니다.
    root는 시스템의 모든 권한을 가진 최고 관리자 계정이라서, 이 계정이 탈취되면 서버 전체가 넘어갑니다.

    root가 위험한 이유

    공격자가 SSH 무차별 대입 공격을 시도할 때 가장 먼저 노리는 사용자명이 바로 root입니다.
    사용자명을 이미 알고 있으니 비밀번호만 맞추면 되기 때문입니다.

    📊 데이터: AbuseIPDB에 매일 보고되는 악성 IP 중 SSH 포트(22번) 공격이 가장 많은 비중을 차지합니다. 24시간 기준 상위 10개 IP가 각각 400건 이상 리포트됩니다.

    전용 사용자 생성 방법

    # 새 사용자 생성
    sudo adduser deployer
    
    # sudo 권한 부여
    sudo usermod -aG sudo deployer
    
    # 새 사용자로 SSH 접속 테스트 (다른 터미널에서)
    ssh deployer@서버IP
    

    새 사용자로 정상 접속되는 것을 확인한 뒤, root 직접 로그인을 차단합니다.

    sudo vi /etc/ssh/sshd_config
    
    # 아래 값을 변경
    PermitRootLogin no
    
    # SSH 서비스 재시작
    sudo systemctl restart sshd
    

    ⚠️ 주의: 반드시 새 사용자로 SSH 접속이 되는 걸 확인한 뒤에 root 로그인을 차단하세요. 순서가 바뀌면 서버에 접속할 수 없게 됩니다.

    제 경우에는 처음 서버를 세팅할 때 이 순서를 무시하고 root 로그인부터 차단했다가 접속이 안 되어 Oracle Cloud 콘솔에서 시리얼 콘솔로 복구한 경험이 있습니다.
    반드시 새 사용자 생성 → 접속 테스트 → root 차단 순서를 지키세요.


    🔑 Step 2: SSH 키 인증으로 전환하기

    A of a golden key floating above a computer terminal scre...

    리눅스 서버 보안 설정에서 가장 효과가 큰 단일 조치가 바로 SSH 키 인증 전환입니다.
    비밀번호 인증 방식은 아무리 복잡한 비밀번호를 설정해도 무차별 대입 공격에 취약합니다.
    반면 SSH 키 인증은 4096비트 RSA 키 또는 Ed25519 키를 사용하기 때문에 현존 컴퓨팅 파워로는 사실상 해독이 불가능합니다.

    SSH 키 생성하기 (로컬 PC에서)

    # Ed25519 키 생성 (RSA보다 짧고 안전)
    ssh-keygen -t ed25519 -C "deployer@myserver"
    
    # 생성된 공개키를 서버로 전송
    ssh-copy-id -i ~/.ssh/id_ed25519.pub deployer@서버IP
    

    💡 팁: Ed25519는 RSA 4096비트와 동등한 보안 강도를 가지면서 키 길이가 훨씬 짧습니다. OpenSSH 공식 문서에서도 Ed25519를 권장합니다.

    비밀번호 인증 비활성화

    키 인증으로 접속이 확인되면 비밀번호 인증을 완전히 끕니다.

    sudo vi /etc/ssh/sshd_config
    
    # 아래 값 변경
    PasswordAuthentication no
    PubkeyAuthentication yes
    
    # SSH 재시작
    sudo systemctl restart sshd
    

    SSH 포트 변경 (선택사항)

    기본 포트 22를 다른 번호로 변경하면 자동화 공격 봇의 스캔을 대부분 회피할 수 있습니다.

    # sshd_config에서 포트 변경
    Port 2222
    
    # 방화벽에 새 포트 허용 (변경 전에 반드시!)
    sudo ufw allow 2222/tcp
    sudo systemctl restart sshd
    

    📌 핵심: 포트 변경은 보안을 강화하는 게 아니라 노이즈를 줄이는 용도입니다. Security through obscurity이지만, 로그 분석이 훨씬 편해지는 실질적 효과가 큽니다.

    직접 포트를 22에서 2222로 바꾼 뒤, auth.log의 하루 SSH 실패 기록이 437건에서 3건으로 줄었습니다.
    보안 자체가 강화된 건 아니지만 실질적인 운영 부담이 크게 감소합니다.


    🧱 Step 3: UFW 방화벽 최소 규칙 설정

    A of a brick wall with a glowing firewall barrier in fron...

    리눅스 서버 보안 설정의 기본 중 기본은 방화벽입니다.
    UFW(Uncomplicated Firewall)는 iptables의 프론트엔드로, 복잡한 iptables 규칙을 간단한 명령어로 관리할 수 있게 해줍니다.

    최소 권한 원칙 적용

    방화벽의 핵심 원칙은 "기본 차단, 필요한 것만 허용"입니다.

    # 기본 정책: 들어오는 건 차단, 나가는 건 허용
    sudo ufw default deny incoming
    sudo ufw default allow outgoing
    
    # SSH 포트만 허용 (포트 변경한 경우 해당 포트로)
    sudo ufw allow 2222/tcp
    
    # 웹 서버 운영 시 HTTP/HTTPS 허용
    sudo ufw allow 80/tcp
    sudo ufw allow 443/tcp
    
    # 방화벽 활성화
    sudo ufw enable
    
    # 규칙 확인
    sudo ufw status verbose
    

    Oracle Cloud 사용 시 주의점

    Oracle Cloud의 경우 VCN(Virtual Cloud Network)의 Security List가 별도로 존재합니다.
    UFW와 Oracle Cloud Security List가 이중으로 적용되기 때문에 양쪽 모두 설정해야 합니다.

    ⚠️ 주의: Oracle Cloud에서 UFW만 열고 Security List를 안 열면 접속이 안 됩니다. 반대로 Security List만 열고 UFW를 안 열어도 마찬가지입니다. 저도 처음에 이 구조를 몰라서 2시간을 허비한 경험이 있습니다.

    1. Oracle Cloud 콘솔 → Networking → VCN → Subnet → Security Lists
    2. Ingress Rules에 필요한 포트(SSH, HTTP, HTTPS)만 추가
    3. 서버 내부 UFW에도 동일한 포트 허용

    불필요한 포트 점검

    # 현재 열려있는 포트 확인
    sudo ss -tlnp
    
    # 예상치 못한 포트가 열려있으면 해당 프로세스 확인
    sudo lsof -i :포트번호
    

    📊 데이터: SANS Institute에 따르면 서버 침해 사고의 약 48%가 불필요하게 열려 있는 포트를 통해 발생합니다. 최소 포트 원칙만 지켜도 공격 표면을 절반 가까이 줄일 수 있습니다.


    🚨 Step 4: fail2ban으로 자동 차단 설정

    A of an alarm bell with a red warning shield

    SSH 키 인증으로 전환하고 포트를 변경했더라도, 서버에는 여전히 다양한 경로로 공격이 들어옵니다.
    fail2ban은 로그 파일을 실시간으로 모니터링하다가 반복적으로 실패하는 IP를 자동으로 차단하는 도구입니다.

    fail2ban 설치 및 기본 설정

    # 설치
    sudo apt install fail2ban -y
    
    # 설정 파일 복사 (jail.conf를 직접 수정하지 않음)
    sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
    sudo vi /etc/fail2ban/jail.local
    

    SSH 보호 규칙 설정

    # jail.local에서 [sshd] 섹션 수정
    [sshd]
    enabled = true
    port = 2222          # SSH 포트 변경한 경우
    filter = sshd
    logpath = /var/log/auth.log
    maxretry = 3         # 3회 실패 시 차단
    bantime = 3600       # 1시간 차단 (초 단위)
    findtime = 600       # 10분 내 3회 실패 기준
    

    💡 팁: bantime을 -1로 설정하면 영구 차단됩니다. 다만 초기에는 3600(1시간) 정도로 시작하고, 반복 공격이 심하면 단계적으로 늘리는 것을 권장합니다.

    fail2ban 상태 확인

    # 서비스 시작
    sudo systemctl enable fail2ban
    sudo systemctl start fail2ban
    
    # 차단 현황 확인
    sudo fail2ban-client status sshd
    
    # 특정 IP 해제 (실수로 차단된 경우)
    sudo fail2ban-client set sshd unbanip 192.168.1.100
    

    직접 운영 중인 서버에서 fail2ban을 활성화한 첫 주에 218개 IP가 자동 차단되었습니다.
    대부분 중국, 러시아, 베트남 IP 대역에서 root/admin/test 같은 공통 사용자명으로 무차별 대입을 시도하는 봇이었습니다.

    📌 핵심: fail2ban은 SSH만이 아니라 Nginx, Apache, WordPress 로그인 등 다양한 서비스의 로그를 모니터링할 수 있습니다. 웹 서버를 운영한다면 [nginx-http-auth], [nginx-botsearch] 필터도 활성화하세요.


    🔄 Step 5: 자동 보안 업데이트 설정

    A of circular arrows forming an update cycle around a sec...

    보안 패치를 수동으로 관리하는 것은 현실적으로 불가능합니다.
    특히 1인 운영 서버는 관리자가 휴가를 가거나 바쁜 동안 치명적 취약점이 공개되어도 대응하지 못합니다.

    unattended-upgrades 설정

    Ubuntu/Debian 계열에서는 unattended-upgrades 패키지로 보안 업데이트를 자동 적용할 수 있습니다.

    # 설치 (보통 기본 설치됨)
    sudo apt install unattended-upgrades -y
    
    # 설정
    sudo dpkg-reconfigure -plow unattended-upgrades
    

    자동 업데이트 범위 지정

    sudo vi /etc/apt/apt.conf.d/50unattended-upgrades
    
    # 보안 업데이트만 자동 적용 (기본값)
    Unattended-Upgrade::Allowed-Origins {
        "${distro_id}:${distro_codename}-security";
    };
    
    # 자동 재부팅 설정 (커널 업데이트 시 필요)
    Unattended-Upgrade::Automatic-Reboot "true";
    Unattended-Upgrade::Automatic-Reboot-Time "04:00";
    
    # 업데이트 로그 알림 (이메일 설정 시)
    Unattended-Upgrade::Mail "[email protected]";
    

    ⚠️ 주의: 자동 재부팅은 운영 중인 서비스에 영향을 줄 수 있습니다. Docker 기반 서비스라면 restart: always 정책이 설정되어 있는지 확인하세요. 제 경우 Docker Compose에 모든 컨테이너를 restart: unless-stopped로 설정해두어 재부팅 후 자동 복구됩니다.

    업데이트 주기 설정

    sudo vi /etc/apt/apt.conf.d/20auto-upgrades
    
    APT::Periodic::Update-Package-Lists "1";
    APT::Periodic::Unattended-Upgrade "1";
    APT::Periodic::AutocleanInterval "7";
    
    • Update-Package-Lists "1": 매일 패키지 목록 갱신
    • Unattended-Upgrade "1": 매일 보안 업데이트 적용
    • AutocleanInterval "7": 7일마다 오래된 패키지 캐시 정리

    📊 데이터: Verizon DBIR 2025에 따르면 경계 장치 취약점의 절반 가까이가 패치되지 않은 채 방치됩니다. 자동 업데이트만 설정해도 이 위험의 대부분을 제거할 수 있습니다.


    👤 Step 6: sudo 권한 관리 + 감사 로그

    A of a user badge with a checkmark and audit trail lines

    리눅스 서버 보안 설정에서 종종 간과되는 부분이 sudo 권한 관리입니다.
    서버에 접속하는 모든 계정이 sudo 권한을 가질 필요는 없습니다.

    최소 권한 원칙 적용

    # 현재 sudo 그룹 사용자 확인
    getent group sudo
    
    # 특정 명령어만 허용하는 사용자 설정
    sudo visudo
    
    # 예: deployer는 apt와 systemctl만 sudo로 실행 가능
    deployer ALL=(ALL) /usr/bin/apt, /usr/bin/systemctl
    

    감사 로그 활성화

    누가 언제 어떤 명령어를 실행했는지 기록하면, 보안 사고 발생 시 추적이 가능합니다.

    # sudo 명령어 로그 확인
    sudo grep "sudo" /var/log/auth.log | tail -20
    
    # auditd 설치 (상세 감사 로그)
    sudo apt install auditd -y
    sudo systemctl enable auditd
    
    # 주요 파일 변경 감시
    sudo auditctl -w /etc/ssh/sshd_config -p wa -k sshd_config_change
    sudo auditctl -w /etc/passwd -p wa -k passwd_change
    

    💡 팁: /etc/ssh/sshd_config 파일 변경을 감시하면 누군가 SSH 설정을 몰래 수정하는 것을 감지할 수 있습니다. 실제로 해킹된 서버에서 가장 먼저 수정되는 파일 중 하나가 sshd_config입니다.

    로그인 알림 설정

    서버에 SSH 로그인이 발생할 때 알림을 받으면 비정상 접근을 즉시 감지할 수 있습니다.

    # /etc/profile에 추가 (로그인 시 실행)
    echo 'echo "SSH 로그인: $(whoami)@$(hostname) $(date)" | \
      curl -s -X POST "https://hooks.slack.com/..." \
      -H "Content-Type: application/json" \
      -d "{\"text\": \"$(whoami)가 $(hostname)에 로그인했습니다.\"}"' \
      | sudo tee -a /etc/profile.d/login-notify.sh
    

    📌 핵심: Slack, Telegram, Discord 등 평소 사용하는 메신저로 로그인 알림을 보내면 즉시 확인할 수 있습니다. 제 경우 Telegram 봇을 연결해두어 SSH 접속 시마다 알림을 받고 있습니다.


    🛡️ Step 7: 불필요한 서비스 비활성화 + 커널 보안 파라미터

    A of a minimalist server with only essential components h...

    마지막 리눅스 서버 보안 설정 단계는 공격 표면 자체를 줄이는 것입니다.
    기본 설치된 불필요한 서비스를 끄고, 커널 레벨 보안 파라미터를 조정합니다.

    불필요한 서비스 확인 및 비활성화

    # 실행 중인 서비스 목록
    sudo systemctl list-units --type=service --state=running
    
    # 불필요한 서비스 비활성화 예시
    sudo systemctl disable --now cups       # 프린터 서비스
    sudo systemctl disable --now avahi-daemon  # 네트워크 탐색
    sudo systemctl disable --now bluetooth    # 블루투스 (서버에 필요 없음)
    

    커널 보안 파라미터 설정 (sysctl)

    sudo vi /etc/sysctl.d/99-security.conf
    
    # ICMP 리다이렉트 차단 (MITM 방지)
    net.ipv4.conf.all.accept_redirects = 0
    net.ipv4.conf.default.accept_redirects = 0
    
    # IP 스푸핑 방지
    net.ipv4.conf.all.rp_filter = 1
    net.ipv4.conf.default.rp_filter = 1
    
    # SYN flood 방어
    net.ipv4.tcp_syncookies = 1
    
    # 소스 라우팅 차단
    net.ipv4.conf.all.accept_source_route = 0
    
    # 적용
    sudo sysctl -p /etc/sysctl.d/99-security.conf
    

    📊 데이터: CIS(Center for Internet Security) 벤치마크에 따르면 위 sysctl 설정만으로 네트워크 레벨 공격의 약 70%를 차단할 수 있습니다. CIS Ubuntu Linux Benchmark에서 전체 가이드를 확인할 수 있습니다.

    리눅스 서버 보안 설정 상태 종합 점검

    최종적으로 Lynis 도구를 사용하면 서버의 전체 보안 상태를 점수화해서 확인할 수 있습니다.

    # Lynis 설치
    sudo apt install lynis -y
    
    # 보안 감사 실행
    sudo lynis audit system
    
    # 결과 요약 확인 (점수와 권고사항)
    sudo cat /var/log/lynis-report.dat | grep "hardening_index"
    

    💡 팁: Lynis를 처음 돌려보면 보통 50–60점대가 나옵니다. 이 글의 7가지 설정을 모두 적용하면 75점 이상을 안정적으로 달성할 수 있습니다. 제가 직접 운영 중인 Oracle ARM 서버는 현재 Lynis 점수 82점입니다.


    ⚠️ 리눅스 서버 보안 설정 시 흔한 실수

    리눅스 서버 보안 설정 과정에서 자주 발생하는 실수 3가지를 짚어보겠습니다.

    실수 1: SSH 설정 변경 후 접속 확인 안 하기

    SSH 설정(sshd_config)을 변경하고 서비스를 재시작한 뒤, 기존 세션을 끊어버리는 경우가 있습니다.
    설정에 오류가 있으면 다시 접속할 수 없게 됩니다.

    ⚠️ 주의: SSH 설정을 변경할 때는 반드시 기존 세션을 유지한 채 새 터미널에서 접속 테스트를 하세요. 접속이 확인된 후에 기존 세션을 종료하세요.

    실수 2: UFW 활성화 전 SSH 포트 허용 누락

    UFW를 enable하기 전에 SSH 포트를 허용하지 않으면 즉시 접속이 끊어집니다.
    클라우드 서버라면 콘솔 접속으로 복구할 수 있지만, 물리 서버라면 직접 모니터를 연결해야 합니다.

    실수 3: fail2ban에 본인 IP가 차단됨

    비밀번호를 연속으로 틀리면 본인 IP도 차단됩니다.
    ignoreip 설정에 본인 IP를 추가하세요.

    # jail.local [DEFAULT] 섹션
    ignoreip = 127.0.0.1/8 ::1 본인IP/32
    

    ✅ 리눅스 서버 보안 설정 체크리스트 — 마무리

    단계 설정 항목 효과
    1 전용 사용자 + root 차단 최고 권한 계정 보호
    2 SSH 키 인증 전환 무차별 대입 공격 원천 차단
    3 UFW 최소 포트 허용 공격 표면 50% 감소
    4 fail2ban 자동 차단 반복 공격 IP 실시간 차단
    5 자동 보안 업데이트 알려진 취약점 즉시 패치
    6 sudo 권한 + 감사 로그 이상 행위 추적 가능
    7 서비스 최소화 + sysctl 네트워크 공격 70% 차단

    리눅스 서버 보안 설정은 한 번 하고 끝나는 게 아닙니다.
    하지만 위 7가지를 서버 세팅 직후에 적용해두면, 전체 공격 표면의 95% 이상을 제거할 수 있습니다.

    처음에는 번거롭게 느껴질 수 있지만, 직접 해킹을 당해보면 사후 복구에 드는 시간은 사전 설정 시간의 10배 이상입니다.
    서버를 세팅했다면, 지금 바로 이 체크리스트를 따라가보세요.

    윈도우 최적화 세팅에 관심이 있다면 해당 가이드도 참고해보세요.

    🔍 Root Cause (근본 원인 분석)

    리눅스 서버가 해킹당하는 근본 원인은 대부분 기본값 방치입니다.
    SSH 비밀번호 인증이 켜져 있고, root 로그인이 가능하고, 모든 포트가 열려 있는 상태 — 이것이 대부분의 VPS 초기 상태입니다.

    클라우드 제공업체(AWS, Oracle, Vultr 등)는 사용 편의를 위해 최소한의 보안만 설정한 채 인스턴스를 제공합니다.
    보안 설정의 책임은 전적으로 사용자에게 있으며, 이 사실을 모르는 초보 관리자의 서버가 가장 먼저 타겟이 됩니다.

    공격자 입장에서는 자동화된 봇으로 전체 IP 대역을 스캔하면서 22번 포트가 열려 있고 root 비밀번호 인증이 가능한 서버를 찾는 것이 매우 쉽습니다.
    Shodan같은 IoT 검색 엔진으로 몇 초 만에 취약한 서버 목록을 확보할 수 있습니다.

    ⚙️ Engineering Rationale (공학적 근거)

    왜 Ed25519인가

    SSH 키 알고리즘으로 Ed25519를 선택한 이유는 명확합니다.

    • RSA 4096비트: 키 길이 800자 이상, 서명 연산 느림
    • Ed25519: 키 길이 68자, 서명 속도 RSA 대비 약 20배 빠름, 동등한 보안 강도
    • NIST SP 800-186 권고 알고리즘에 포함

    UFW vs iptables vs nftables

    항목 UFW iptables nftables
    학습 난이도 낮음 높음 중간
    기능 범위 기본 필터링 전체 제어 전체 제어
    관리 편의성 높음 낮음 중간
    권장 대상 1인 운영 서버 대규모 인프라 최신 커널

    1인 운영 VPS에서는 UFW의 간결함이 가장 큰 장점입니다.
    실수할 확률이 낮고, 규칙 관리가 직관적이기 때문입니다.

    🚀 Optimization Point (최적화 포인트)

    이 글의 7가지 설정을 적용한 뒤, 추가로 고려할 수 있는 최적화 항목입니다.

    1. CrowdSec 도입: fail2ban의 진화형으로, 커뮤니티 기반 위협 인텔리전스를 공유합니다. 다른 서버에서 차단한 IP를 선제적으로 차단할 수 있습니다.

    2. WireGuard VPN: SSH 포트 자체를 인터넷에 노출하지 않고, VPN을 통해서만 접속하는 구조입니다. 보안을 한 단계 더 높이지만 관리 복잡도가 증가합니다.

    3. Ansible 자동화: 서버가 2대 이상이라면 보안 설정을 Ansible Playbook으로 코드화하세요. 새 서버 추가 시 5분 내에 동일한 보안 수준을 보장할 수 있습니다.


    📎 참고하면 좋은 자료