Ubuntu 22.04에 Fail2Ban으로 SSH 보호하는 방법

소개

SSH는 클라우드 서버에 연결하는 표준 방법입니다. 이는 내구성이 있으며 새로운 암호화 표준이 개발됨에 따라 새로운 SSH 키를 생성하는 데 사용될 수 있어 핵심 프로토콜이 안전하게 유지됩니다. 그러나 어떤 프로토콜이나 소프트웨어 스택도 완전히 방어할 수는 없으며, 인터넷 전역에 걸쳐 광범위하게 배포된 SSH는 악의적인 공격자들이 액세스를 시도할 수 있는 매우 예측 가능한 공격 대상 또는 공격 경로를 대표합니다.

네트워크에 노출된 모든 서비스는 이와 같은 잠재적인 대상입니다. 널리 사용되는 서버에서 실행 중인 SSH 서비스의 로그를 검토하면 사용자와 봇 모두에 의한 반복적이고 체계적인 로그인 시도가 자주 나타납니다. 이러한 공격이 거의 성공하지 않도록 SSH 서비스를 최적화할 수는 있지만(SSH 키 대신 암호 인증을 비활성화하는 것 등), 여전히 경미한 계속되는 취약점을 가질 수 있습니다.

대규모 제품 배포에 대해 완전히 받아들일 수 없는 책임을 가진 경우, 일반적으로 WireGuard와 같은 VPN을 SSH 서비스 앞에 구현하여 외부 인터넷에서 기본 SSH 포트 22에 직접 연결하는 것이 불가능하도록 합니다. 이러한 VPN 솔루션은 널리 신뢰받지만, 복잡성을 추가할 수 있으며 몇 가지 자동화나 기타 작은 소프트웨어 훅을 망가뜨릴 수 있습니다.

전체 VPN 설정을 하기 전이나 추가로, Fail2ban이라는 도구를 구현할 수 있습니다. Fail2ban은 일정 횟수의 로그인 시도 실패 후 특정 IP를 차단하는 방화벽 구성을 자동으로 변경하는 규칙을 생성하여 대규모 무차별 공격을 크게 완화할 수 있습니다. 이렇게 하면 서버가 개입 없이도 이러한 접근 시도에 대해 자체를 보호할 수 있습니다.

이 안내서에서는 Ubuntu 22.04 서버에 Fail2ban을 설치하고 사용하는 방법을 살펴보겠습니다.

전제 조건

이 가이드를 완료하려면 다음이 필요합니다:

  • Ubuntu 22.04 서버 및 sudo 권한이 있는 비 루트 사용자. 이러한 권한을 가진 사용자를 설정하는 방법에 대해 자세히 알아보려면 Ubuntu 22.04에서 초기 서버 설정 가이드를 참조하십시오.

  • 선택 사항으로, 명시적으로 금지되는 것을 테스트할 첫 번째 서버에 연결할 수 있는 두 번째 서버가 있습니다.

단계 1 — Fail2ban 설치

Fail2ban은 우분투 소프트웨어 저장소에서 사용할 수 있습니다. 패키지 목록을 업데이트하고 Fail2ban을 설치하려면 다음 명령을 비 루트 사용자로 실행하십시오:

  1. sudo apt update
  2. sudo apt install fail2ban

Fail2ban은 설치된 후 자동으로 백그라운드 서비스를 설정합니다. 그러나 일부 기본 설정이 원하지 않는 효과를 일으킬 수 있으므로 기본적으로 비활성화됩니다. 이를 systemctl 명령을 사용하여 확인할 수 있습니다:

  1. systemctl status fail2ban.service
Output
○ fail2ban.service - Fail2Ban Service Loaded: loaded (/lib/systemd/system/fail2ban.service; disabled; vendor preset: enabled Active: inactive (dead) Docs: man:fail2ban(1)

Fail2ban을 즉시 활성화할 수 있지만 먼저 몇 가지 기능을 검토하겠습니다.

단계 2 — Fail2ban 구성

fail2ban 서비스는 /etc/fail2ban 디렉토리에 설정 파일을 유지합니다. jail.conf라는 기본 파일이 있습니다. 해당 디렉토리로 이동하고 head -20을 사용하여 해당 파일의 처음 20 줄을 출력하십시오:

  1. cd /etc/fail2ban
  2. head -20 jail.conf
Output
# # 경고: 0.9.0 릴리스에서 심층적으로 리팩토링되었습니다. 설정을 검토하고 # 시스템에 맞게 설정하십시오. # # 변경 사항: 대부분의 경우 이 파일을 수정하지 않아야하지만 # jail.local 파일에서 사용자 정의를 제공하거나, # jail.d/ 디렉토리 아래의 별도의 .conf 파일을 제공하십시오. 예: # # JAILS를 활성화하는 방법: # # 이 파일을 수정해서는 안 됩니다. # # 배포 업데이트에서 덮어쓰기 또는 개선 될 수 있습니다. # # jail.local 파일이나 jail.d/customisation.local 파일에서 사용자 정의를 제공하십시오. # 예를 들어 모든 jails의 기본 차단 시간을 변경하고 # ssh-iptables jail을 활성화하려면 다음 (주석 처리되지 않은) 내용이 .local 파일에 나타납니다. # 세부 정보는 man 5 jail.conf를 참조하십시오. # # [DEFAULT]

다음과 같이 볼 수 있듯이 파일의 처음 여러 줄은 주석 처리되어 있습니다 – 이것들은 문서로 읽히도록 설정된 # 문자로 시작합니다. 또한, 이러한 주석은이 파일을 직접 수정하지 말라는 지침을 제공합니다. 대신, 두 가지 옵션이 있습니다. 여러 파일에서 Fail2ban에 대한 개별 프로필을 생성하거나 jail.d/ 디렉토리 내에서 생성하고 수집합니다. 또는 모든 로컬 설정을 jail.local 파일에 만들 수 있습니다. jail.conf 파일은 주기적으로 Fail2ban 자체가 업데이트됨에 따라 업데이트되며, 생성하지 않은 기본 설정의 소스로 사용됩니다.

이 자습서에서는 jail.local을 만듭니다. jail.conf을 복사하여 수행할 수 있습니다:

  1. sudo cp jail.conf jail.local

이제 구성 변경을 시작할 수 있습니다. 파일을 nano 또는 즐겨 사용하는 텍스트 편집기로 엽니다:

  1. sudo nano jail.local

파일을 스크롤하는 동안이 자습서는 업데이트하려는 일부 옵션을 검토합니다. 파일 상단 근처에 있는 [DEFAULT] 섹션 아래에있는 설정은 Fail2ban이 지원하는 모든 서비스에 적용됩니다. 파일의 다른 위치에는 [sshd]와 같은 다른 서비스에 대한 헤더가 있습니다. 이 헤더에는 기본 설정 위에 적용되는 서비스별 설정이 포함됩니다.

/etc/fail2ban/jail.local
[DEFAULT]
. . .
bantime = 10m
. . .

bantime 매개변수는 클라이언트가 올바르게 인증하지 못했을 때 클라이언트가 금지될 시간을 설정합니다. 이것은 초로 측정됩니다. 기본적으로 10분으로 설정됩니다.

/etc/fail2ban/jail.local
[DEFAULT]
. . .
findtime = 10m
maxretry = 5
. . .

다음 두 매개변수는 findtimemaxretry입니다. 이들은 클라이언트가 금지되어야 하는 부정 사용자로 판명되는 조건을 설정하는 데 함께 작동합니다.

변수 maxretry는 클라이언트가 금지되기 전에 findtime으로 정의된 시간 창 내에서 인증을 시도할 수 있는 횟수를 설정합니다. 기본 설정에서 fail2ban 서비스는 10분의 시간 창 내에서 5회 로그인 시도에 실패한 클라이언트를 금지합니다.

/etc/fail2ban/jail.local
[DEFAULT]
. . .
destemail = root@localhost
sender = root@<fq-hostname>
mta = sendmail
. . .

Fail2ban이 조치를 취할 때 이메일 알림을 받아야하는 경우 destemail, sendernamemta 설정을 평가해야 합니다. destemail 매개변수는 금지 메시지를 받을 이메일 주소를 설정합니다. sendername은 이메일의 “보낸 사람” 필드의 값을 설정합니다. mta 매개변수는 이메일을 보내기 위해 사용될 메일 서비스를 구성합니다. 기본적으로 이것은 sendmail이지만 Postfix나 다른 메일 솔루션을 사용할 수 있습니다.

/etc/fail2ban/jail.local
[DEFAULT]
. . .
action = $(action_)s
. . .

이 매개변수는 Fail2ban이 금지를 시도할 때 취하는 조치를 구성합니다. 값 action_은 이 매개변수 직전에 파일에 정의됩니다. 기본 조치는 금지 시간이 경과할 때까지 공격 호스트로부터의 트래픽을 거부하는 방화벽 구성을 업데이트하는 것입니다.

위의 $(action_)을 대체할 수 있는 기본 제공 action_ 스크립트가 있습니다:

/etc/fail2ban/jail.local
…
# 금지 및 whois 보고서를 destemail로 이메일 전송합니다.
action_mw = %(action_)s
            %(mta)s-whois[sender="%(sender)s", dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s"]

# 금지하고 whois 보고서와 관련 로그 라인을 포함하여 이메일을 보냅니다
# 를 destemail로
action_mwl = %(action_)s
             %(mta)s-whois-lines[sender="%(sender)s", dest="%(destemail)s", logpath="%(logpath)s", chain="%(chain)s"]

# 사용시 이 주의사항을 action.d/xarf-login-attack에서 확인하세요
#
# xarf 이메일을 사용하여 IP 주소의 남용 연락처에 이메일을 보내고 관련 로그 라인을 포함합니다
# 를 destemail로
action_xarf = %(action_)s
             xarf-login-attack[service=%(__name__)s, sender="%(sender)s", logpath="%(logpath)s", port="%(port)s"]

# CloudFlare에서 IP를 금지하고 whois 보고서와 관련 로그 라인을 포함하여 이메일을 보냅니다
# 를 destemail로
action_cf_mwl = cloudflare[cfuser="%(cfemail)s", cftoken="%(cfapikey)s"]
                %(mta)s-whois-lines[sender="%(sender)s", dest="%(destemail)s", logpath="%(logpath)s", chain="%(chain)s"]
…

예를 들어, action_mw는 조치를 취하고 이메일을 보내고, action_mwl는 조치를 취하고 이메일을 보내며 로깅을 포함하며, action_cf_mwl은 이 모든 것을 수행하는 동시에 귀하의 계정과 관련된 Cloudflare API로 가해자를 금지합니다.

개별 Jail 설정

다음은 개별 서비스를 다루는 구성 파일 부분입니다. 이들은 [sshd]와 같은 섹션 헤더로 지정됩니다.

이 섹션 각각은 헤더 아래에 enabled = true 줄을 추가하여 개별적으로 활성화되어야 합니다. 그리고 그들의 다른 설정도 포함되어야 합니다.

/etc/fail2ban/jail.local
[jail_to_enable]
. . .
enabled = true
. . .

기본적으로 SSH 서비스가 활성화되어 있고 다른 서비스는 모두 비활성화되어 있습니다.
.
여기에서 설정된 다른 몇 가지 설정은 로그의 특정 서비스에 대한 로그의 특정 줄이 인증 실패를 나타내는지를 결정하는 filter와 해당 서비스의 로그가 위치한 위치를 fail2ban에 알려주는 logpath입니다.

filter 값은 실제로 /etc/fail2ban/filter.d 디렉토리에 위치한 파일을 가리키며 확장자 .conf가 제거됩니다. 이러한 파일에는 로그의 특정 줄이 실패한 인증 시도인지 여부를 결정하는 정규 표현식(텍스트 구문 분석의 일반적인 줄임말)이 포함되어 있습니다. 이 가이드에서는 이러한 파일을 깊게 다루지 않을 것입니다. 왜냐하면 이러한 파일은 상당히 복잡하며 미리 정의된 설정이 적절한 줄과 일치합니다.

그러나 해당 디렉토리를 살펴보면 어떤 종류의 필터가 사용 가능한지 확인할 수 있습니다.

  1. ls /etc/fail2ban/filter.d

사용 중인 서비스와 관련된 것으로 보이는 파일을 볼 경우 텍스트 편집기로 열어야 합니다. 대부분의 파일은 상당히 잘 주석 처리되어 있으며 스크립트가 어떤 유형의 조건을 보호하도록 설계되었는지 적어도 확인할 수 있어야 합니다. 이러한 필터 대부분은 원하는 경우 jail.local 파일에서 활성화할 수 있는 jail.conf 파일의 적절한 (비활성화된) 섹션을 갖고 있습니다.

예를 들어, Nginx를 사용하여 웹사이트를 제공하고 있으며 사이트의 비밀번호로 보호된 부분이 로그인 시도로 인해 공격당하는 것을 알게 되었다고 상상해보십시오. 이 경우 fail2ban에게 /var/log/nginx/error.log 파일 내에서 이 조건을 확인하도록 nginx-http-auth.conf 파일을 사용하도록 지시할 수 있습니다.

실제로 이는 이미 /etc/fail2ban/jail.conf 파일의 [nginx-http-auth] 섹션에 설정되어 있습니다. 단순히 enabled 매개변수를 추가하면 됩니다:

/etc/fail2ban/jail.local
. . .
[nginx-http-auth]

enabled = true
. . .

편집을 완료하면 파일을 저장하고 닫으십시오. 이 시점에서 Fail2ban 서비스를 활성화하여 앞으로 자동으로 실행되도록 설정할 수 있습니다. 먼저 다음을 실행하십시오: systemctl enable:

  1. sudo systemctl enable fail2ban

그런 다음 첫 번째로 수동으로 시작하십시오: systemctl start:

  1. sudo systemctl start fail2ban

다음 명령을 사용하여 실행 여부를 확인할 수 있습니다: systemctl status:

  1. sudo systemctl status fail2ban
Output
● fail2ban.service - Fail2Ban Service Loaded: loaded (/lib/systemd/system/fail2ban.service; enabled; vendor preset: enab> Active: active (running) since Mon 2022-06-27 19:25:15 UTC; 3s ago Docs: man:fail2ban(1) Main PID: 39396 (fail2ban-server) Tasks: 5 (limit: 1119) Memory: 12.9M CPU: 278ms CGroup: /system.slice/fail2ban.service └─39396 /usr/bin/python3 /usr/bin/fail2ban-server -xf start Jun 27 19:25:15 fail2ban22 systemd[1]: Started Fail2Ban Service. Jun 27 19:25:15 fail2ban22 fail2ban-server[39396]: Server ready

다음 단계에서는 Fail2ban이 작동하는 것을 보여줄 것입니다.

단계 3 — 차단 정책 테스트 (선택 사항)

다른 서버에서, 앞으로 Fail2ban 서버에 로그인할 필요가 없는 서버에서, 해당 두 번째 서버가 차단되도록 규칙을 테스트할 수 있습니다. 두 번째 서버에 로그인한 후 Fail2ban 서버로 SSH를 시도해 보십시오. 존재하지 않는 이름을 사용하여 연결을 시도할 수 있습니다:

  1. ssh blah@your_server

비밀번호 프롬프트에 무작위 문자를 입력하십시오. 이를 몇 번 반복하십시오. 어느 시점에서는 Permission denied 오류 대신 Connection refused 오류를 받게 될 것입니다. 이는 두 번째 서버가 Fail2ban 서버에서 금지되었음을 나타냅니다.

Fail2ban 서버에서는 iptables 출력을 확인하여 새로운 규칙을 볼 수 있습니다. iptables는 서버의 저수준 포트 및 방화벽 규칙과 상호 작용하기 위한 명령입니다. DigitalOcean의 초기 서버 설정 가이드에 따라 왔다면, 더 높은 수준에서 방화벽 규칙을 관리하기 위해 ufw를 사용할 것입니다. iptables -S를 실행하면 ufw가 이미 생성한 모든 방화벽 규칙을 표시합니다:

  1. sudo iptables -S
Output
-P INPUT DROP -P FORWARD DROP -P OUTPUT ACCEPT -N f2b-sshd -N ufw-after-forward -N ufw-after-input -N ufw-after-logging-forward -N ufw-after-logging-input -N ufw-after-logging-output -N ufw-after-output -N ufw-before-forward -N ufw-before-input -N ufw-before-logging-forward -N ufw-before-logging-input -N ufw-before-logging-output …

iptables -S의 출력을 grep에 파이프하여 해당 규칙에서 f2b 문자열을 검색하면 fail2ban에 의해 추가된 규칙을 볼 수 있습니다:

  1. sudo iptables -S | grep f2b
Output
-N f2b-sshd -A INPUT -p tcp -m multiport --dports 22 -j f2b-sshd -A f2b-sshd -s 134.209.165.184/32 -j REJECT --reject-with icmp-port-unreachable -A f2b-sshd -j RETURN

Fail2ban에 의해 추가된 REJECT --reject-with icmp-port-unreachable를 포함하는 줄에는 두 번째 서버의 IP 주소가 반영될 것입니다.

결론

지금은 서비스에 대한 일부 차단 정책을 구성할 수 있어야 합니다. Fail2ban은 인증을 사용하는 모든 종류의 서비스를 보호하는 유용한 방법입니다. Fail2ban 규칙 및 파일이 작동하는 방법에 대해 자세히 알고 싶다면 fail2ban 규칙 및 파일이 작동하는 방법에 대한 튜토리얼을 확인할 수 있습니다.

다른 서비스를 보호하기 위해 fail2ban을 사용하는 방법에 대한 정보는 Ubuntu 14.04에서 Fail2Ban으로 Nginx 서버 보호하는 방법Ubuntu 14.04에서 Fail2Ban으로 Apache 서버 보호하는 방법을 읽어보실 수 있습니다.

Source:
https://www.digitalocean.com/community/tutorials/how-to-protect-ssh-with-fail2ban-on-ubuntu-22-04