blog.stackframe.dev

Fail2ban으로 SSH 브루트포싱 차단하기

나는 보통 SSH를 VPN을 통해서만 접근할 수 있도록 구축하지만 어쩔 수 없이 인터넷에서 바로 접속 할 수 있도록 열어 둔 경우 엄청난 브루트포싱에 시달리게 된다.

다수의 IP에서 root 계정에 접속 시도

대부분의 시스템은 SSH에서 root로 접속하지 못하게 기본 설정이 되어있으므로 사용자의 계정명이 노출되었고 단순한 비밀번호를 사용하는게 아니라면 브루트포싱으로 해킹 당할 가능성은 높지 않다. 나도 처음 브루트포싱이 시작되었을 때 이렇게 생각하고 별다른 조치를 취하지 않고 방치했었다. 하지만 해킹이 아니라 엄청난 접속 실패 로그로 인해 용량이 갉아먹히는 문제로 브루트포싱을 막게 되었다.

btmp 파일과 시스템 저널 사용 용량. 참고로 동시기에 올린 VPN으로만 접속 가능한 서버는 현재 저널 용량이 46MB이다.

일정 수 이상 실패가 발생한다면 접속을 막기 위해 Fail2ban을 사용한다. 이 프로그램은 로그를 조회하여 일정 수 이상의 실패가 발견된다면 해당 IP를 방화벽에 등록하여 더 이상 접속하지 못하도록 한다. 각자 배포판에 맞게 설치하면 /etc/fail2ban/ 디렉토리에 설정 파일이 들어있다.

Fail2ban은 특이하게 설정 파일이 *.conf*.local로 구성된다. *.conf 파일은 기본 설정으로 fail2ban에서 제공하는 것이고 사용자가 직접 수정하는 것이 아니다. 대신 *.local 파일을 만들어서 거기에 사용자 환경에 맞게 값들을 덮어쓸 수 있다. 예를 들어 fail2ban 서버 설정인 fail2ban.conf는 해당 디렉토리에 fail2ban.local을 만들어 설정하고, fail2ban이 동작할 서비스들을 설정하는 jail.confjail.local 파일에서 설정할 수 있다.

이번에 설정하려는 것은 SSH에서 3번 이상 접속 실패가 발생할 경우 IP를 차단하는 것이다. 먼저 /etc/fail2ban/jail.local 파일을 생성하고 아래의 값을 추가한다:

[DEFAULT]
bantime = 1y
maxretry = 3

[sshd]
enabled = true

[DEFAULT] 섹션은 특수한 섹션으로 다른 모든 섹션에서 기본적으로 적용되는 옵션들을 설정할 수 있다. jail.conf 파일을 열어보면 bantimemaxretry 같은 값이 [DEFAULT] 섹션에 포함되어 있는 것을 확인할 수 있다. 이 기본 값들을 내가 원하는 값으로 변경하기 위해 jail.local 파일에 설정한 것이다. 나는 차단 시간을 1년, 실패 임계값을 3번으로 설정했다. 아래의 [sshd] 섹션의 설정은 SSH에 대해 동작할 수 있도록 활성화를 시킨다는 의미다. [sshd] 섹션의 기본 설정도 jail.conf에 포함되어 있으니 확인해보면 좋다. 나머지 세세한 [sshd] 설정은 따로 파일을 만들어서 진행할 것이다.

이제 /etc/fail2ban/jail.d/sshd.local 파일을 만들어 아래와 같이 설정한다:

[sshd]
port = 4421
banaction = nftables

port는 SSH 포트를 의미한다. SSH 포트를 22가 아닌 다른 값으로 변경하는 것이 일반적이니 여기서 현재 서버 설정과 동일하게 설정한다. 그리고 banaction은 어떤 방식으로 차단할 지 정한다. 기본 설정은 iptables-multiport이지만 나는 개인적으로 nftables를 좋아하기 때문에 이렇게 변경했다. 만약 SSH에서만 특별하게 차단 시간을 변경하고 싶다면 여기에 bantime을 설정하면 된다.

추가적으로 위에서 설정하지 않았지만 중요한 findtimeignoreip가 있다. findtime은 과거 언제까지의 기록을 확인하여 실패 횟수를 셀 지 설정한다. 포맷은 bantime과 동일하다. 기본 값은 10분으로 되어있다. 브루트포스 간격이 넓은 경우 이 값과 maxretry를 적절하게 설정해야 제대로 차단할 수 있을 것이다. ignoreip는 차단 대상에서 제외할 IP를 설정한다. 로컬 IP 같이 자신이 사용하는 IP를 여기에 입력해두면 내가 잘못 비밀번호를 입력해서 실패했을 때 차단되지 않도록 할 수 있다. IP 서브네팅 형태로 대역을 지정할 수 있고 공백으로 여러 대역을 입력할 수 있다.

설정의 기본 구조와 필수적으로 알아둬야 할 옵션들을 소개했다. 기본 구조만 제대로 이해하고 있다면 jail.conf(5) man 페이지를 참고하여 더 세부적으로 설정할 수 있을 것이다.

마지막으로 systemctl로 fail2ban 서버를 실행하면 된다. 서버가 재시작하더라도 자동으로 실행하고 싶다면 두 번째 명령도 실행한다:

# systemctl start fail2ban
# systemctl enable fail2ban

추가로 현재 차단된 상태가 어떤지 확인하려면 fail2ban-client를 사용하면 된다.

184개의 IP가 차단 당함

추가로 nftables의 테이블을 확인해보니 다음과 같이 나왔다:

# nft list table inet f2b-table
table inet f2b-table {
        set addr-set-sshd {
                type ipv4_addr
                elements = { 1.179.185.50, 2.40.59.98,
                             5.51.84.107, 5.183.8.231,
                             5.189.140.231, 5.195.235.226,
.......
                             221.165.227.155, 222.122.82.135,
                             223.26.28.178 }
        }

        chain f2b-chain {
                type filter hook input priority filter - 1; policy accept;
                tcp dport 4421 ip saddr @addr-set-sshd reject with icmp port-unreachable
        }
}

댓글