Rocky Linux 8에 Fail2Ban으로 SSH 보호하는 방법

소개

SSH는 클라우드 서버에 연결하는 기본적인 방법입니다. 이는 내구성이 있으며, 새로운 암호화 표준이 개발될 때마다 이를 사용하여 새로운 SSH 키를 생성할 수 있어 핵심 프로토콜이 안전하게 유지됩니다. 그러나 어떤 프로토콜이나 소프트웨어 스택도 완전히 방어할 수 없으며, SSH가 인터넷 전체에 널리 배포되어 있기 때문에 많은 사람들이 액세스를 시도할 수 있는 매우 예측 가능한 공격 대상 또는 공격 벡터로 인식됩니다.

네트워크에 노출된 모든 서비스는 이와 같은 잠재적인 대상이 될 수 있습니다. 널리 알려진 서버에서 실행 중인 SSH 서비스의 로그를 검토하면 사용자 및 봇에 의한 반복적이고 계획적인 로그인 시도가 자주 보입니다. 이러한 공격이 거의 성공하지 못하도록 SSH 키를 사용하여 암호 인증을 비활성화하는 등 SSH 서비스를 최적화할 수 있지만, 그래도 경미한 계속적인 취약점을 가지고 있을 수 있습니다.

대규모 프로덕션 배포에서 이 책임을 완전히 받아들일 수 없는 경우에는 일반적으로 외부 인터넷에서 기본 SSH 포트 22에 직접 연결하는 것이 불가능하도록 VPN(가령 WireGuard와 같은)을 구현하여 SSH 서비스 앞에 배치합니다. 이 VPN 솔루션은 일반적으로 신뢰되지만 복잡성이 추가되며 일부 자동화나 다른 소프트웨어 훅을 중단할 수 있습니다.

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

이 가이드에서는 Rocky Linux 8 서버에 Fail2ban을 설치하고 사용하는 방법을 살펴보겠습니다.

필수 준비 사항

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

  • 루트 권한이 아닌 사용자와 sudo 권한을 가진 Rocky Linux 8 서버가 있습니다. 이러한 권한을 가진 사용자를 설정하는 방법은 Rocky Linux 8 초기 서버 설정 가이드에서 자세히 알아볼 수 있습니다. 또한 서버에는 firewalld가 실행되어 있어야 합니다. 이는 초기 서버 설정 가이드에서 다루고 있습니다.

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

단계 1 — Fail2ban 설치

Fail2ban은 Rocky의 기본 소프트웨어 저장소에 포함되어 있지 않습니다. 그러나 Red Hat 및 Rocky Linux에서 일반적으로 사용되는 서드파티 패키지를 위한 EPEL 또는 Enterprise Linux용 향상된 패키지 저장소에서 사용할 수 있습니다. 시스템 패키지 소스에 EPEL을 추가하지 않았다면 다음과 같이 dnf를 사용하여 저장소를 추가할 수 있습니다:

  1. sudo dnf install epel-release -y

dnf 패키지 관리자는 이제 새로운 소프트웨어를 설치할 때 기본 패키지 소스에 추가로 EPEL을 확인합니다. 이제 Fail2ban을 설치합니다:

  1. sudo dnf install fail2ban -y

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

  1. systemctl status fail2ban.service
Output
○ fail2ban.service - Fail2Ban Service Loaded: loaded (/lib/systemd/system/fail2ban.service; disabled; vendor preset: disabled 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 파일을 제공하세요. 예: # # JAIL 활성화 방법: # # 이 파일을 직접 수정하지 않아야 합니다. # # 배포 업데이트에서 덮어쓰기나 개선될 가능성이 있습니다. # # jail.local 파일이나 jail.d/customisation.local 파일에 사용자 정의를 제공하세요. # 예를 들어, 모든 jail의 기본 차단 시간을 변경하고 # 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

이제 구성 변경을 시작할 수 있습니다. vi 또는 좋아하는 텍스트 편집기에서 파일을 엽니다:

  1. sudo vi 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의 중요한 참고 사항을 참조하십시오
#
# IP 주소의 오용 연락처로 xarf 이메일을 보내고 관련 로그 라인을 포함하여 금지

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에 업데이트를 보내어 가해자를 거기서도 차단합니다.

개별 감옥 설정

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

이 섹션 각각은 헤더 아래에 enabled = true 라인을 추가하여 개별적으로 활성화해야 합니다. 다른 설정과 함께.

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

이 튜토리얼에서는 SSH 감옥을 활성화합니다. 개별 감옥 설정의 맨 위에 있어야 합니다. 그렇지 않으면 기본 매개변수가 작동하지만, [sshd] 헤더 아래에 enabled = true 라는 구성 라인을 추가해야 합니다.

/etc/fail2ban/jail.local
#
# JAILS
#

#
# SSH 서버
#

[sshd]

# 더 공격적인 sshd 모드를 사용하려면 jail.local에서 filter 매개변수 "mode"를 설정하십시오:
# normal (기본값), ddos, extra 또는 aggressive (모두 결합).
# 사용 예 및 자세한 내용은 "tests/files/logs/sshd" 또는 "filter.d/sshd.conf"를 참조하십시오.
#mode   = normal
enabled = true
port    = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s

여기에서 설정된 다른 설정은 로그의 한 줄이 인증 실패를 나타내는지를 결정할 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
. . .

편집을 완료한 후 파일을 저장하고 닫으십시오. 만약 vi를 사용하는 경우 :x를 사용하여 저장하고 종료하십시오. 이 시점에서 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: disabled 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.6 -s /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 서버에서는 fail2ban-client의 출력을 확인하여 새로운 규칙을 볼 수 있습니다. fail2ban-client는 실행 중인 구성을 확인하기 위해 Fail2ban에서 제공하는 추가 명령입니다.

  1. sudo fail2ban-client status
Output
Status |- Number of jail: 1 `- Jail list: sshd

fail2ban-client status sshd를 실행하면 SSH에서 금지된 IP 주소 목록을 볼 수 있습니다:

  1. sudo fail2ban-client status sshd
Output
Status for the jail: sshd |- Filter | |- Currently failed: 2 | |- Total failed: 7 | `- Journal matches: _SYSTEMD_UNIT=sshd.service + _COMM=sshd `- Actions |- Currently banned: 1 |- Total banned: 1 `- Banned IP list: 134.209.165.184

Banned IP list 내용은 두 번째 서버의 IP 주소를 반영해야 합니다.

결론

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

다른 서비스를 보호하기 위해 fail2ban을 사용하는 방법에 대한 정보는 Fail2Ban을 사용하여 Nginx 서버 보호하는 방법Fail2Ban을 사용하여 Apache 서버 보호하는 방법을 읽어보세요.

Source:
https://www.digitalocean.com/community/tutorials/how-to-protect-ssh-with-fail2ban-on-rocky-linux-8