[태그:] 보안

  • HTTPS TLS, HSTS

    HTTP의 한계

    기본적으로 HTTP 프로토콜은 평문(plain text)으로 데이터를 주고 받고,

    이는 로그인 정보, 세션 쿠키, API 응답 등 모든 통신 내용이 노출될 수 있는 위험을 내포한다.

    이런 HTTP의 한계를 이용한 대표적인 공격으로는

    중간자 공격(MITM, Man-in-the-Middle)이 있으며, 공격자는 이 공격을 통해 사용자의 네트워크

    트래픽을 가로채고 내용을 열람하거나 수정할 수 있다. (e.g. 카페 와이파이에서 비밀번호 유출)

    이를 해결하기 위해, 평문의 데이터를 전송, 즉 주고 받을 때

    전송 구간을 암호화(Encryption) 하는 것을 도입하고자 했다.

    이 암호화를 수행하는 기술을 TLS(Transport Layer Security) 라 한다.

     

    TLS?

    웹 통신을 암호화하기 위한 표준 프로토콜,

    이전에는 SSL(Secure Sockets Layer)이라 불렸지만, 여러 보안 결함이 발견되었다.

    여러 보안 결함들을 해결하고 추가적인 보안 기능을 제공하도록 개선된 것이 TLS(버전 업그레이드).

    TLS는 통신 과정에서 다음 세 가지를 보장한다.

    • 기밀성(Confidentiality): 제3자가 데이터를 읽을 수 없음.
    • 무결성(Integrity): 데이터가 중간에서 변조되지 않음.
    • 인증(Authentication): 서버 또는 클라이언트가 신뢰할 수 있는 대상임을 검증.

     

    TLS 핸드셰이크 과정

    TLS는 실제 데이터 전송 전에 암호화된 연결을 수립(handshake)한다.

     

    Client Hello

    브라우저(클라이언트)가 서버에 TLS를 사용하고 싶은 의사와 가능한 암호화 알고리즘을 제안한다.

     

    Server Hello

    서버가 암호화 알고리즘을 선택, 공개키가 담긴 SSL 인증서를 전달한다.

     

    인증서 검증

    브라우저는 이 인증서가 신뢰할 수 있는 기관(CA, Certificate Authority)에서 발급된 것인지 검증,

    인증서에 포함된 도메인, 만료일, 서명 정보 등을 검사한다.

     

    비밀키 교환

    브라우저와 서버는 공개키 암호화를 통해 세션 키를 교환,

    이후 데이터는 이 세션 키로 대칭 암호화되어 통신한다.

     

     

    HTTPS는 TLS 위의 HTTP

    HTTPS = HTTP + TLS

    HTTP의 내용(요청 메서드, 헤더, 바디 등)은 그대로, ‘전송하는 과정’만 암호화한다.

    HTTPS의 효과

    • 통신 중 비밀번호, 쿠키, API 응답이 노출되지 않음.
    • 세션 하이재킹(Session Hijacking), 쿠키 탈취 등의 위험이 크게 줄어든다.
    • HTTP/2, HTTP/3 등 최신 프로토콜은 모두 HTTPS를 기반으로 동작.

     

    HSTS(HTTP Strict Transport Security)

    HTTPS를 적용했다고 완전히 안전한 것은 아니다.

    최초 접속이 HTTP로 이루어지는 상황을 생각해보자.

    e.g.

    사용자가 http://example.com 을 입력하여 접속 시도,

    브라우저에서는 먼저 HTTP로 요청 → 서버가 301 리다이렉트 → HTTP로 이동하게 된다.

    이때, 이 첫 요청 사이에 공격자가 개입하면 여전히 중간자 공격 가능성이 존재하게 된다.

    HSTS로 해결할 수 있다

    HSTS는 서버가 브라우저에 다음 헤더를 내려주는 방식이다.

    Strict-Transport-Security: max-age=3153600; includeSubDomains; preload

    이후 브라우저는 해당 도메인에 대해,

    • 무조건 HTTPS로만 접속하도록 강제.
    • HTTP 요청 시도하지 않음(리다이렉트 이전에 차단)
    • preload 옵션을 등록 시 주요 브라우저의 HSTS Preload List에 도메인이 포함되어, 첫 방문 전에 HTTPS만 사용 가능.

    즉, 사용자가 HTTP로 접속하도록 허용하지 않는다.

  • 프론트엔드 개발자를 위한 인증 메커니즘(쿠키와 세션, JWT, HttpOnly)

    인증과 상태 관리의 필요성

    웹은 본래 무상태(Stateless) 프로토콜인 HTTP 위에서 동작,

    즉 클라이언트가 요청을 보낼 때마다 서버는 이 요청이 누구로부터 왔는지를 기본적으로 알 수 없다.(검증 안됨)

    사용자가 로그인을 해도 다음 요청에서 서버는 그 사용자가 여전히 로그인 상태인지 알 수 없다.

    따라서, 인증 상태를 유지하기 위한 메커니즘을 필요로 한다.

    → 쿠키, 세션, JWT

    쿠키(Cookie)

    브라우저가 저장하는 작은 데이터. 상태 유지의 기본 단위,

    상태 유지를 위해 사용한다. (Session ID 보관, 로그인 상태 유지, 사용자 설정 값 저장 등)

    서버가 응답 시 Set-Cookie 헤더를 내려주면, 브라우저는 이후 해당 도메인 요청마다

    자동으로 Cookie 헤더를 붙인다.

    장점

    • 브라우저에 표준 기능으로 내장되어 있다. 즉, 별도의 구현이 필요없다.
    • 서버와 클라이언트 간 상태 공유가 간단함.

    단점

    • 용량 제한(4KB), 도메인별 개수 제한.
    • 민감한 정보 저장 시 보안 취약함.(XSS, 탈취)
    • 클라이언트에서 수정이 가능함

    세션(Session)

    서버에서 관리하는 사용자 상태.

    안정적이지만 확장성에는 한계가 존재한다.

    보통 서버는 사용자가 로그인하면 고유한 세션 ID를 발급,

    이 세션 ID는 클라이언트의 쿠키에 저장되고, 요청 시 함께 전송된다.

    서버는 이 세션 ID를 조회하여 해당 사용자의 로그인 상태나 데이터를 확인한다.

    장점

    • 실제 중요한 데이터를 서버에 저장하면 클라이언트 유출 위험이 낮다
    • 서버가 세션 만료, 강제 로그아웃 등을 제어할 수 있다.

    단점

    • 서버 메모리/스토리지를 점유 → 트래픽이 많으면 확장성 문제가 생김.
    • 서버 간 세션 공유가 필요 → Redis 같은 중앙 저장소 필요.
    • 서버리스, 무상태 아키텍처에서는 현실적으로 어렵다.

    JWT(JSON Web Token)

    세션을 서버에 저장하지 않고, 토큰 자체에 사용자 상태를 담는 방식.

    상태를 토큰 자체에 담기 때문에 서버 확장성에 유리하지만 탈취 시 위험할 수 있음.

    로그인 성공 시 서버가 서명된 JWT를 발급,

    클라이언트는 JWT를 로컬 스토리지, 세션 스토리지, 혹은 쿠키에 저장. 이후 API 요청시, 헤더에 포함

    서버는 서명만 검증하면 요청자 식별 가능.

    Authorization: Bearer <token>

    장점

    • 무상태(Stateless) → 서버 확장성에 유리.
    • 다양한 서비스/도메인 간 인증 공유(SSO)에 유용함
    • JSON 포맷 → 읽기/파싱 쉬움.

    단점

    • 토큰 자체가 길다. 즉, HTTP 헤더 부담.
    • 토큰이 탈취되면 만료될 때까지 악용이 가능함(서버에서 강제 폐기 어려움)
    • 로컬 스토리지/세션 스토리지 저장 시 XSS 공격에 취약.

    HttpOnly ?

    쿠키를 안전하게 지키는 최소한의 보안 옵션,

    쿠키를 사용할 때 보안을 강화하려면 HttpOnly 옵션을 반드시 고려해야 한다.

    HttpOnly 쿠키는 자바스크립트(document.cookie)로 접근할 수 없고,

    오직 HTTP 요청에만 자동으로 첨부된다.

    → 즉, XSS 공격자가 자바스크립트를 주입하더라도 쿠키 값을 읽어내기 어렵다.

    보통 세션 ID나 JWT Access Token을 쿠키에 저장할 때

    HttpOnly + Secure 옵션을 함께 설정한다.

    *Secure: HTTPS에서만 전송

    *SameSite: 크로스사이트 요청 시 쿠키 전송 제한(CSRF 방어)

    실무에서 사용할 때

    소규모 서비스에서 인증 메커니즘

    단순 로그인 유지에서는 다음과 같이 안전하고 간단하게 설계할 수 있다

    → 세션 기반 + HttpOnly 쿠키

    대규모/분산 아키텍처 서비스에서의 인증 메커니즘

    JWT 기반 토큰 인증으로 설계하면 서버 확장성에 유리.

    단, Refresh Token + 짧은 Access Token 주기로 보완해야 보안을 강화할 수 있음

    보안 강화에 있어서 필요한 부분

    • 민감한 데이터는 쿠키/스토리지에 직접 저장하지 않도록 할 것.
    • HttpOnly, Secure, SameSite 옵션을 적극 사용
    • JWT는 꼭 짧은 수명 + Refresh Token 구조로 운영하도록 한다.

  • 방화벽과 OpenSSH로 서버 보안 강화하기: 실무에서 바로 쓰는 완벽 가이드

    안녕하세요, 성장하는 개발자 여러분!

    “서버 보안”이라고 하면 뭔가 복잡하고 어려운 것처럼 느껴지시나요? 하지만 실제로는 몇 가지 핵심 원칙만 제대로 지키면 90%의 공격을 막을 수 있습니다. 오늘은 가장 기본이면서도 강력한 두 가지 보안 도구인 방화벽과 OpenSSH를 활용해 서버를 안전하게 지키는 방법을 알려드리겠습니다.

    실무에서 제가 직접 겪었던 보안 사고들과 그 해결 과정을 통해 배운 실전 노하우를 함께 공유하니, 끝까지 집중해서 읽어보시길 바랍니다! 🔒

    1. 서버 보안의 기본 원칙: 최소 권한과 다층 방어

    보안의 황금률

    1. 최소 권한 원칙: 꼭 필요한 것만 열어두기
    2. 다층 방어: 하나의 보안 장치에 의존하지 않기
    3. 지속적인 모니터링: 로그를 통한 이상 징후 감지
    4. 정기적인 업데이트: 보안 패치는 최우선

    실무에서 자주 발생하는 보안 위협들

    # 실제 공격 시도 로그 예시
    grep "Failed password" /var/log/secure | tail -5
    # Jan 15 14:32:11 server sshd[1234]: Failed password for root from 192.168.1.100 port 22
    # Jan 15 14:32:13 server sshd[1235]: Failed password for admin from 192.168.1.100 port 22
    # Jan 15 14:32:15 server sshd[1236]: Failed password for user from 192.168.1.100 port 22
    
    # 의심스러운 접속 시도 확인
    journalctl -u sshd | grep "authentication failure" | tail -10

    이런 로그들이 보이시나요? 이미 여러분의 서버가 공격받고 있을 수 있습니다!

    2. Firewalld: 현대적인 방화벽 관리의 핵심

    Firewalld vs iptables: 왜 Firewalld를 써야 할까?

    Firewalld의 장점:

    • 동적 설정 변경: 서비스 재시작 없이 즉시 적용
    • Zone 기반 관리: 네트워크 환경별 정책 분리
    • GUI 지원: 명령어뿐만 아니라 그래픽 도구도 제공
    • XML 설정: 사람이 읽기 쉬운 설정 파일

    기본 설정과 상태 확인

    # 1. Firewalld 상태 확인
    sudo systemctl status firewalld
    sudo firewall-cmd --state
    
    # 2. 현재 설정 확인
    sudo firewall-cmd --list-all
    
    # 3. 활성 영역(Zone) 확인
    sudo firewall-cmd --get-active-zones
    
    # 4. 기본 영역 확인
    sudo firewall-cmd --get-default-zone

    Zone 개념 이해하기

    Firewalld의 가장 강력한 기능 중 하나가 Zone입니다:

    # 사용 가능한 모든 Zone 확인
    sudo firewall-cmd --get-zones
    # block dmz drop external home internal public trusted work
    
    # 각 Zone의 특성
    # - drop: 모든 들어오는 패킷 차단 (가장 엄격)
    # - block: 들어오는 패킷 거부 응답
    # - public: 기본 Zone, SSH와 DHCP 클라이언트만 허용
    # - external: 외부 네트워크용, NAT 환경에서 사용
    # - internal: 내부 네트워크용, 더 많은 서비스 허용
    # - home: 홈 네트워크용, 파일 공유 등 허용
    # - work: 직장 네트워크용
    # - trusted: 모든 패킷 허용 (가장 관대)

    실무 시나리오별 방화벽 설정

    시나리오 1: 웹 서버 보안 설정

    # 기본 Zone을 public으로 설정 (이미 기본값)
    sudo firewall-cmd --set-default-zone=public
    
    # HTTP/HTTPS 서비스 영구 허용
    sudo firewall-cmd --permanent --add-service=http
    sudo firewall-cmd --permanent --add-service=https
    
    # 커스텀 포트 허용 (예: 8080)
    sudo firewall-cmd --permanent --add-port=8080/tcp
    
    # 설정 적용
    sudo firewall-cmd --reload
    
    # 확인
    sudo firewall-cmd --list-services
    sudo firewall-cmd --list-ports

    시나리오 2: 데이터베이스 서버 보안 강화

    # 특정 IP에서만 MySQL 접근 허용
    sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port protocol="tcp" port="3306" accept'
    
    # 특정 서버에서만 PostgreSQL 접근 허용
    sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.100" port protocol="tcp" port="5432" accept'
    
    # 모든 외부 접근 차단하고 내부 네트워크만 허용
    sudo firewall-cmd --permanent --zone=internal --add-source=192.168.1.0/24
    sudo firewall-cmd --permanent --zone=internal --add-service=mysql
    sudo firewall-cmd --permanent --zone=internal --add-service=postgresql
    
    sudo firewall-cmd --reload

    시나리오 3: 개발 서버 임시 포트 열기

    # 임시로 포트 열기 (재부팅 시 삭제됨)
    sudo firewall-cmd --add-port=3000/tcp
    sudo firewall-cmd --add-port=8080/tcp
    
    # 확인
    sudo firewall-cmd --list-ports
    
    # 영구 설정으로 변경 (필요한 경우)
    sudo firewall-cmd --runtime-to-permanent

    Rich Rules: 고급 방화벽 정책

    # 1. 특정 시간대에만 SSH 접근 허용 (고급 설정)
    # 평일 9시-18시에만 특정 IP에서 SSH 접근 허용
    sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.100" service name="ssh" log prefix="SSH Access: " level="info" limit value="3/m" accept'
    
    # 2. 무차별 대입 공격 방지
    # 동일 IP에서 5번 이상 실패 시 10분간 차단
    sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" service name="ssh" log prefix="SSH Brute Force: " level="warning" limit value="5/m" drop'
    
    # 3. 포트 스캔 감지 및 차단
    sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" port port="22" protocol="tcp" log prefix="SSH Scan: " level="warning" limit value="1/m" accept'

    방화벽 로그 모니터링

    # 방화벽 로그 실시간 모니터링
    sudo journalctl -u firewalld -f
    
    # 특정 키워드로 로그 필터링
    sudo journalctl -u firewalld | grep "SSH"
    sudo journalctl -u firewalld | grep "DROP"
    
    # 로그 분석 스크립트
    #!/bin/bash
    echo "=== 오늘의 방화벽 로그 요약 ==="
    echo "총 차단된 연결 수:"
    sudo journalctl -u firewalld --since today | grep -c "DROP"
    echo "SSH 접근 시도:"
    sudo journalctl -u firewalld --since today | grep -c "SSH"
    echo "가장 많이 시도한 IP:"
    sudo journalctl -u firewalld --since today | grep -oP 'from K[0-9.]+' | sort | uniq -c | sort -nr | head -5

    3. OpenSSH: 안전한 원격 접속의 모든 것

    SSH 기본 보안 강화

    1. SSH 설정 파일 최적화

    # SSH 설정 파일 백업
    sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup
    
    # 주요 보안 설정
    sudo nano /etc/ssh/sshd_config

    필수 보안 설정들:

    # /etc/ssh/sshd_config 권장 설정
    
    # 1. 기본 포트 변경 (선택사항)
    Port 2222
    
    # 2. Root 로그인 완전 차단
    PermitRootLogin no
    
    # 3. 패스워드 로그인 비활성화 (키 인증만 허용)
    PasswordAuthentication no
    ChallengeResponseAuthentication no
    UsePAM no
    
    # 4. 빈 패스워드 금지
    PermitEmptyPasswords no
    
    # 5. X11 포워딩 비활성화 (필요없는 경우)
    X11Forwarding no
    
    # 6. 로그인 시간 제한
    LoginGraceTime 30
    
    # 7. 최대 동시 세션 제한
    MaxSessions 3
    
    # 8. 특정 사용자만 SSH 접근 허용
    AllowUsers developer admin
    
    # 9. 특정 그룹만 SSH 접근 허용
    AllowGroups ssh-users
    
    # 10. 연결 유지 설정
    ClientAliveInterval 300
    ClientAliveCountMax 2

    설정 후 서비스 재시작:

    # 설정 파일 문법 검사
    sudo sshd -t
    
    # SSH 서비스 재시작
    sudo systemctl restart sshd
    
    # 상태 확인
    sudo systemctl status sshd

    SSH 키 기반 인증: 패스워드보다 1000배 안전한 방법

    1. SSH 키 쌍 생성

    # RSA 키 생성 (4096비트, 더 안전)
    ssh-keygen -t rsa -b 4096 -C "your-email@domain.com"
    
    # 또는 더 최신의 Ed25519 키 (권장)
    ssh-keygen -t ed25519 -C "your-email@domain.com"
    
    # 키 생성 시 옵션들
    # -t: 키 타입 (rsa, ed25519)
    # -b: 키 비트 수
    # -C: 코멘트 (보통 이메일)
    # -f: 키 파일 이름 지정

    2. 공개키 서버에 복사

    # 자동으로 공개키 복사
    ssh-copy-id username@server-ip
    
    # 커스텀 포트 사용 시
    ssh-copy-id -p 2222 username@server-ip
    
    # 특정 키 파일 지정
    ssh-copy-id -i ~/.ssh/custom_key.pub username@server-ip
    
    # 수동으로 복사 (ssh-copy-id 사용 불가 시)
    cat ~/.ssh/id_rsa.pub | ssh username@server-ip "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

    3. SSH 키 관리 및 보안

    # 키 권한 설정 (매우 중요!)
    chmod 700 ~/.ssh
    chmod 600 ~/.ssh/id_rsa
    chmod 644 ~/.ssh/id_rsa.pub
    chmod 600 ~/.ssh/authorized_keys
    
    # 여러 키 관리를 위한 SSH config 설정
    nano ~/.ssh/config

    SSH Config 예시:

    # ~/.ssh/config
    Host prod-server
        HostName 192.168.1.100
        Port 2222
        User developer
        IdentityFile ~/.ssh/prod_server_key
    
    Host dev-server
        HostName 192.168.1.200
        Port 22
        User admin
        IdentityFile ~/.ssh/dev_server_key
    
    Host git-server
        HostName github.com
        User git
        IdentityFile ~/.ssh/github_key
    
    # 모든 서버에 대한 기본 설정
    Host *
        ServerAliveInterval 60
        ServerAliveCountMax 3
        StrictHostKeyChecking ask
        UserKnownHostsFile ~/.ssh/known_hosts

    사용법:

    # 간단하게 접속
    ssh prod-server
    ssh dev-server
    
    # 파일 복사도 편리하게
    scp myfile.txt prod-server:~/

    SSH 터널링: 안전한 포트 포워딩

    로컬 포트 포워딩

    # 원격 서버의 MySQL을 로컬에서 접근
    ssh -L 3306:localhost:3306 username@server-ip
    
    # 원격 서버의 웹 애플리케이션을 로컬에서 접근
    ssh -L 8080:localhost:80 username@server-ip
    
    # 백그라운드 실행
    ssh -f -N -L 3306:localhost:3306 username@server-ip

    리모트 포트 포워딩

    # 로컬의 서비스를 원격에서 접근 가능하게 (주의 필요)
    ssh -R 8080:localhost:3000 username@server-ip
    
    # 백그라운드 실행
    ssh -f -N -R 8080:localhost:3000 username@server-ip

    SOCKS 프록시

    # SOCKS 프록시 생성
    ssh -D 1080 username@server-ip
    
    # 브라우저에서 localhost:1080을 SOCKS 프록시로 설정하면
    # 모든 트래픽이 서버를 통해 전송됨

    4. 실전 보안 모니터링과 자동화

    SSH 접속 로그 분석

    # 성공한 SSH 로그인 확인
    sudo grep "Accepted" /var/log/secure
    
    # 실패한 SSH 로그인 확인
    sudo grep "Failed password" /var/log/secure
    
    # 특정 IP의 접속 시도 분석
    sudo grep "192.168.1.100" /var/log/secure
    
    # 오늘의 SSH 활동 요약
    sudo journalctl -u sshd --since today | grep -E "(Accepted|Failed)"

    자동 보안 모니터링 스크립트

    #!/bin/bash
    # ssh_monitor.sh - SSH 보안 모니터링 스크립트
    
    LOG_FILE="/var/log/ssh_monitor.log"
    SECURE_LOG="/var/log/secure"
    ALERT_THRESHOLD=5
    
    echo "=== SSH 보안 모니터링 시작: $(date) ===" >> $LOG_FILE
    
    # 1. 실패한 로그인 시도 카운트
    FAILED_ATTEMPTS=$(grep "Failed password" $SECURE_LOG | grep "$(date +%b %d)" | wc -l)
    
    if [ $FAILED_ATTEMPTS -gt $ALERT_THRESHOLD ]; then
        echo "⚠️  경고: 오늘 $FAILED_ATTEMPTS 번의 로그인 실패가 발생했습니다!" >> $LOG_FILE
    
        # 가장 많이 시도한 IP 찾기
        TOP_ATTACKERS=$(grep "Failed password" $SECURE_LOG | grep "$(date +%b %d)" | 
                       grep -oP 'from K[0-9.]+' | sort | uniq -c | sort -nr | head -3)
    
        echo "주요 공격 IP들:" >> $LOG_FILE
        echo "$TOP_ATTACKERS" >> $LOG_FILE
    
        # 자동 차단 (선택사항)
        echo "$TOP_ATTACKERS" | while read count ip; do
            if [ $count -gt 10 ]; then
                echo "IP $ip 자동 차단 (시도 횟수: $count)" >> $LOG_FILE
                sudo firewall-cmd --add-rich-rule="rule family='ipv4' source address='$ip' drop"
            fi
        done
    fi
    
    # 2. 새로운 SSH 키 추가 감지
    AUTHORIZED_KEYS="/home/*/.ssh/authorized_keys"
    for auth_file in $AUTHORIZED_KEYS; do
        if [ -f "$auth_file" ]; then
            KEY_COUNT=$(wc -l < "$auth_file")
            echo "$(dirname $auth_file): $KEY_COUNT 개의 SSH 키" >> $LOG_FILE
        fi
    done
    
    # 3. Root 로그인 시도 감지
    ROOT_ATTEMPTS=$(grep "Failed password for root" $SECURE_LOG | grep "$(date +%b %d)" | wc -l)
    if [ $ROOT_ATTEMPTS -gt 0 ]; then
        echo "🚨 위험: Root 계정으로 $ROOT_ATTEMPTS 번의 로그인 시도가 있었습니다!" >> $LOG_FILE
    fi
    
    echo "=== 모니터링 완료: $(date) ===" >> $LOG_FILE
    echo "" >> $LOG_FILE

    Fail2Ban: 자동 침입 차단 시스템

    # Fail2Ban 설치
    sudo dnf install fail2ban -y
    sudo systemctl enable fail2ban
    sudo systemctl start fail2ban
    
    # SSH 보호 설정
    sudo nano /etc/fail2ban/jail.local
    [DEFAULT]
    # 차단 시간 (초)
    bantime = 3600
    # 관찰 시간 (초)
    findtime = 600
    # 최대 시도 횟수
    maxretry = 5

    [sshd]

    enabled = true port = ssh logpath = /var/log/secure maxretry = 3 bantime = 7200

    # Fail2Ban 재시작
    sudo systemctl restart fail2ban
    
    # 상태 확인
    sudo fail2ban-client status
    sudo fail2ban-client status sshd
    
    # 차단된 IP 확인
    sudo fail2ban-client get sshd banned
    
    # 수동으로 IP 차단/해제
    sudo fail2ban-client set sshd banip 192.168.1.100
    sudo fail2ban-client set sshd unbanip 192.168.1.100

    5. 보안 점검 체크리스트와 베스트 프랙티스

    일일 보안 점검 체크리스트

    #!/bin/bash
    # daily_security_check.sh
    
    echo "=== 일일 보안 점검 $(date) ==="
    
    # 1. 시스템 업데이트 확인
    echo "1. 시스템 업데이트 상태:"
    dnf check-update | wc -l
    
    # 2. 방화벽 상태 확인
    echo "2. 방화벽 상태:"
    sudo systemctl is-active firewalld
    
    # 3. SSH 서비스 상태 확인
    echo "3. SSH 서비스 상태:"
    sudo systemctl is-active sshd
    
    # 4. 활성 네트워크 연결 확인
    echo "4. 현재 활성 연결 (상위 10개):"
    sudo ss -tuln | head -10
    
    # 5. 마지막 로그인 확인
    echo "5. 최근 로그인 기록:"
    last -n 5
    
    # 6. 수상한 프로세스 확인
    echo "6. 높은 CPU 사용 프로세스:"
    ps aux --sort=-%cpu | head -5
    
    # 7. 디스크 사용량 확인
    echo "7. 디스크 사용량:"
    df -h | grep -v tmpfs
    
    # 8. 실패한 로그인 시도
    echo "8. 오늘의 실패한 로그인 시도:"
    sudo grep "Failed password" /var/log/secure | grep "$(date +%b %d)" | wc -l
    
    echo "=== 점검 완료 ==="

    월간 보안 리뷰 체크리스트

    • [ ] 사용자 계정 검토: 불필요한 계정 제거
    • [ ] SSH 키 정리: 사용하지 않는 키 제거
    • [ ] 방화벽 규칙 점검: 불필요한 규칙 정리
    • [ ] 로그 분석: 수상한 활동 패턴 확인
    • [ ] 보안 패치 적용: 최신 보안 업데이트
    • [ ] 백업 확인: 설정 파일 백업 상태 점검

    보안 사고 대응 절차

    1. 즉시 대응 (5분 이내)

    # 의심스러운 IP 즉시 차단
    sudo firewall-cmd --add-rich-rule="rule family='ipv4' source address='SUSPICIOUS_IP' drop"
    
    # 모든 SSH 연결 확인
    who
    w
    
    # 의심스러운 세션 강제 종료
    sudo pkill -u suspicious_user
    
    # 긴급 상황 시 SSH 포트 임시 변경
    sudo sed -i 's/Port 22/Port 2222/' /etc/ssh/sshd_config
    sudo systemctl restart sshd

    2. 조사 및 분석 (30분 이내)

    # 상세 로그 분석
    sudo grep -E "($(date +%b %d)|$(date -d yesterday +%b %d))" /var/log/secure > security_incident_$(date +%Y%m%d).log
    
    # 네트워크 연결 상태 저장
    sudo ss -tuln > network_status_$(date +%Y%m%d).log
    
    # 프로세스 상태 저장
    ps aux > process_status_$(date +%Y%m%d).log

    3. 복구 및 강화 (1시간 이내)

    # 패스워드 강제 변경
    sudo passwd username
    
    # SSH 키 교체
    ssh-keygen -t ed25519 -C "incident-response-$(date +%Y%m%d)"
    
    # 방화벽 규칙 강화
    sudo firewall-cmd --set-default-zone=drop
    sudo firewall-cmd --zone=trusted --add-source=ADMIN_IP

    마치며: 보안은 여정이지 목적지가 아닙니다

    핵심 원칙 재정리

    1. 기본을 충실히: 방화벽 + SSH 키 인증만으로도 90% 보안 확보
    2. 지속적인 모니터링: 로그 분석과 이상 징후 감지
    3. 정기적인 점검: 보안 설정과 계정 관리
    4. 빠른 대응: 사고 발생 시 신속한 차단과 분석

    실무에서 기억할 점

    • 편의성 vs 보안: 항상 트레이드오프 관계임을 인식
    • 문서화: 모든 보안 설정과 대응 절차를 문서로 남기기
    • 팀 공유: 보안 지식과 절차를 팀원들과 공유
    • 지속적인 학습: 새로운 공격 기법과 방어 방법 학습

    다음 단계

    오늘 배운 내용을 바탕으로:

    1. 테스트 서버에서 연습: 실제 운영 서버에 적용하기 전에 충분히 연습
    2. 모니터링 시스템 구축: 자동화된 보안 모니터링 환경 구성
    3. 백업 계획 수립: 보안 사고 시 빠른 복구를 위한 백업 전략
    4. 팀 내 보안 문화 조성: 개발팀 전체가 보안을 의식하는 문화 만들기

    기억하세요: 완벽한 보안은 존재하지 않습니다. 하지만 기본적인 보안 수칙을 지키는 것만으로도 대부분의 공격으로부터 서버를 안전하게 지킬 수 있습니다.

    보안은 한 번 설정하고 끝나는 것이 아니라 지속적으로 관리하고 개선해야 하는 여정입니다. 오늘부터 여러분도 이 여정에 함께해주세요! 🛡️


    다음 포스트에서는 “로그 관리와 모니터링 실전 가이드”에서 더 고급 모니터링 기법들을 다뤄보겠습니다. 기대해 주세요!