Linux

fail2ban 및 GeoIP 와 BlackIP를 이용한 IP 차단하기

respiro 2019. 1. 3. 14:41

IP 차단하기


작성일: 2019년 1월 04일

최종 수정: 2020년 4월 23일


레퍼런스들

0. 머리글

 

  외부 접근이 되지 않는 환경에서 테스트하던 PC 를 외부 접근이 되는 공간으로 이전한지 원격에서 로그인시 다음과 같은 메시지를 볼 수 있다.

마지막 로그인: 목  1월  3 13:23:59 KST 2019 일시 pts/0

마지막 로그인 실패: 목  1월  3 17:15:22 KST 2019 122.194.229.3에서 시작 일시 ssh:notty

마지막 로그인 후 1830 번의 로그인 시도가 실패하였습니다.


 아주 짧은 시간동안에도 수많은 불법 로그인이 시도되고 있다.



로그인관련 로그를 살펴보면, /var/log/secure

Dec 31 01:16:07 localhost sshd[80983]: Failed password for root from 122.194.229.41 port 54340 ssh2

...

Jan  3 17:16:49 localhost sshd[99212]: Failed password for root from 122.194.229.3 port 64254 ssh2


122.194.xxx.xxx 대역폭에서 IP 가 바꿔가며 계속 로그인을 시도하고 있다.


IP 하나를 보면, (google 에서 그냥 whois 122.194.229.3)

122.194.229.3 IP Address Information

ISPChina Unicom Jiangsu Province Network
Usage TypeUnknown
Domain Namechinaunicom.com
Country
CityLianyungang, Jiangsu


외부에 연결된 컴퓨터의 필수 프로그램인 fail2ban 을 설치해서 이러한 IP 들을 차단하도록 한다.



1. fail2ban 


*** 리눅스 설치시에 반드시 설치하라 ***


1) 소개

 fail2ban 은 로그 파일을 스캔해서 로그인 암호 실패를 한 IP 주소들을 방화벽 도구를 이용해 차단하는 프로그램이다. 스캔하는 로그파일은 sshd 및 아파치 웹 서버등의 로그 파일등으로 여러가지 서비스들의 로그 파일을 읽을 수 있다.

설치하면, 이러한 로그파일들을 읽고 차단하는 룰에 대한 기본 설정파일을 함께 설치한다.




2) 설치


 가) RPM 패키지 설치


 CentOS 7 기본 저장소에는 이 프로그램 패키지가 없으며, EPEL 저장소에서 제공하고 있다. 설치 전 먼저, EPEL 저장소를 yum 저장소 목록에 추가해야 한다.

# yum install epel-release


# yum search fail2ban

...

=============================================================== N/S matched: fail2ban ================================================================

fail2ban-all.noarch : Install all Fail2Ban packages and dependencies

fail2ban-firewalld.noarch : Firewalld support for Fail2Ban

fail2ban-hostsdeny.noarch : Hostsdeny (tcp_wrappers) support for Fail2Ban

fail2ban-mail.noarch : Mail actions for Fail2Ban

fail2ban-sendmail.noarch : Sendmail actions for Fail2Ban

fail2ban-server.noarch : Core server component for Fail2Ban

fail2ban-shorewall.noarch : Shorewall support for Fail2Ban

fail2ban-systemd.noarch : Systemd journal configuration for Fail2Ban

fail2ban-tests.noarch : Fail2Ban testcases

fail2ban.noarch : Daemon to ban hosts that cause multiple authentication errors


위와 같은 fail2ban 패키지들이 존재한다.

여기서는 fail2ban 과 fail2ban-systemd 패키지를 설치한다. (핵심 패키지는 fail2ban-server 패키지로 함께 설치된다.)

# yum install fail2ban fail2ban-systemd


나) 소스 컴파일 설치


fail2ban 의 최신 릴리스 소스를 내려받을 설치할 수 있다.


Python 으로 작성되었기에 Python 관련 도구들이 필요하다.

# yum install python-devel python-inotify


$ tar xvfj fail2ban-0.11.0.tar.bz2

$ cd fail2ban-0.11.0

$ sudo python setup.py install


릴리스 또는 최신 소스로부터 빌드할 때에는 몇 가지 옵션을 CentOS 에 맞도록 수정해야 한다.

특히,  jail.conf 파일의 INCLUDE 섹션을 수정한다.

[INCLUDES]


#before = paths-distro.conf

before = paths-fedora.conf


files/fail2ban.service.in 파일을 수정한다.

PartOf=iptables.service firewalld.service ip6tables.service ipset.service

PartOf=firewalld.service


고칠것이 이것저것 많다.


그냥, 시스템에 맞게 잘 수정된 패키지를 설치해서 잘 쓰도록 하자 !!!!


3) 설정

  설치하면 /etc/fail2ban 폴더에 설정파일 및 차단 룰이 있으며, 각 운영체제에서 스캔할 로그파일을 정의한 파일을 볼 수 있다.

 CentOS 의 경우 /etc/fail2ban/paths-fedora.conf 파일에 해당 로그파일들이 명시되어 있다.


  먼저, 다음과 같이 기본 설정파일을 복사한다.

# cd /etc/fail2ban

# cp jail.conf jail.local

모든 변경 사항을 jail.local 에 적용하게 될 것이다.


주요 공통 설정 옵션

[DEFAULT]


ignoreip = 127.0.0.1/8 192.168.0.0/24     # 자신이 주로 사용하는 IP 및 내부 네트워크를 추가해 둬서, 내 IP가 차단당하지 않도록 한다.

bantime = -1                                    # IP 차단 시간을 초로 정의한다. 기본값을 6000 초다. -1 은 영구 차단을 한다.

findtime = 600                                  # 600 초안에 maxretry(5) 시도  실패의 경우를 정의한다.

maxretry = 5



paths-common.conf 파일의 아래 설정을 반드시 변경한다.

(auto 로 사용할 경우, CPU 점유율이 100%를 차지하게 된다.)

[DEFAULT]


##default_backend = auto

default_backend = polling


Too many open file 에러 발생시를 위해 파일 Open 제한 설정

# mkdir -p /etc/systemd/system/fail2ban.service.d


# cat << EOF > /etc/systemd/system/fail2ban.service.d/limits.conf

[Service]

LimitNOFILE=2048

EOF


# systemctl daemon-reload


가) sshd 로그인 차단


가장 중요한 서비스인 SSHD 로그인에 대한 IP 차단을 설정한다. 

모든 설정 섹션을 동작시킬려면, enabled = true 옵션을 추가해 줘야 한다.


/etc/fail2ban/jail.local

[sshd]

enabled = true

port      = ssh

logpath  = %(sshd_log)s

backend = %(sshd_backend)s

maxretry = 3


[sshd-ddos]

enabled = true

port      = ssh

logpath  = %(sshd_log)s

backend = %(sshd_backend)s


나) 아파치 웹 서버 IP 차단


아파치 웹 서버의 경우, mod_security 등의 모듈과 함께 fail2ban 에서 차단할 수 있는 옵션들이 다음과 같이 있다.

웹 서버가 Apache Server 가 아닌 엔진 X (nginx) 인 경우에는 해당 섹션을 활성화시켜주고 옵션 상태를 수정하면 된다.


[apache-auth]

enabled = true

port     = http,https

logpath  = %(apache_error_log)s


[apache-badbots]
enabled = true
port     = http,https
logpath  = %(apache_access_log)s
bantime  = 172800
maxretry = 1

[apache-noscript]
enabled = true
port     = http,https
logpath  = %(apache_error_log)s

[apache-overflows]
enabled = true
port     = http,https
logpath  = %(apache_error_log)s
maxretry = 2

[apache-nohome]
enabled = true
port     = http,https
logpath  = %(apache_error_log)s
maxretry = 2

[apache-botsearch]
enabled = true
port     = http,https
logpath  = %(apache_error_log)s
maxretry = 2

[apache-fakegooglebot]
enabled = true
port     = http,https
logpath  = %(apache_access_log)s
maxretry = 1
ignorecommand = %(ignorecommands_dir)s/apache-fakegooglebot <ip>

[apache-modsecurity]
enabled = true
port     = http,https
logpath  = %(apache_error_log)s
maxretry = 2


[apache-shellshock]
enabled = true
port    = http,https
logpath = %(apache_error_log)s
maxretry = 1


다) PHP 


php 로 url 파일 열기를 시도하는 IP 를 차단한다.

[php-url-fopen]

enabled = true

port    = http,https

logpath = %(nginx_access_log)s

          %(apache_access_log)s



라) 메일 서버 (sendmail, qmail, postfix 등)


메일 서버를 사용하는 경우 해당 메일 서버 옵션을 활성화시킨다.

[sendmail-auth]

enabled = true

port    = submission,465,smtp

logpath = %(syslog_mail)s

backend = %(syslog_backend)s



[sendmail-reject]

enabled = true

port     = smtp,465,submission

logpath  = %(syslog_mail)s

backend  = %(syslog_backend)s


마) Oracle 차단


예정


바) Postgresql DB 접속 차단


먼저, 필터를 생성한다.

/etc/fail2ban/filter.d/postgresql.conf


[Definition]


failregex = <HOST>\(\d+\) FATAL:  password authentication failed for .+$

            <HOST>\(\d+\) FATAL:  no pg_hba.conf entry for host .+$


ignoreregex = duration:

필터의 regex 내용은 로그 환경에 따라 맞게 수정되어야 한다.


Action 파일을 생성한다.

/etc/fail2ban/action.d/postgresql.conf

[postgresql]

enabled  = true

filter   = postgresql

action   = iptables[name=PostgreSQL, port=5432, protocol=tcp]

           sendmail-whois[name=PostgreSQL, dest=root@localhost]

logpath  = /var/log/postgresql/postgresql-9.log

maxretry = 3


필터 테스트

# fail2ban-regex /var/log/postgresql/postgresql-9.log /etc/fail2ban/filter.d/postgresql.conf


Results

=======


Failregex: 0 total


Ignoreregex: 0 total



위와 같이 새로 만든 필터가 로그파일에 대해 제대로 동작하는지 확인 후 사용해야 한다.

Failregex 에 검출되어야 한다.



PostgreSQL 로그 관련 참조


사) Jenkins 차단


예정


아) Wordpress 차단




4) 상태


fail2ban 이 감시하는 서비스 상태를 볼려면 다음과 같이 한다.

# fail2ban-client  status

Status

|- Number of jail:      13

`- Jail list:   apache-auth, apache-badbots, apache-botsearch, apache-fakegooglebot, apache-nohome, apache-noscript, apache-overflows, apache-shellshock, php-url-fopen, sendmail-auth, sendmail-reject, sshd, sshd-ddos


특정 서비스의 Jail 상태를 보기 위해서는 다음과 같이 한다.

# fail2ban-client status sshd

Status for the jail: sshd

|- Filter

|  |- Currently failed: 2

|  |- Total failed:     180773

|  `- Journal matches:  _SYSTEMD_UNIT=sshd.service + _COMM=sshd

`- Actions

   |- Currently banned: 1867

   |- Total banned:     1867

   `- Banned IP list:   1.237.178.27 1.238.85.187 100.14.70.124 101.0.78.66 101.206.156.122 101.235.114.131 101.88.90.168 101.91.125.57 103.11.74.107



방화벽 차단된 상태 보기

# iptables -L

...

...


Chain f2b-apache-shellshock (1 references)

target     prot opt source               destination

RETURN     all  --  anywhere             anywhere


Chain f2b-php-url-fopen (1 references)

target     prot opt source               destination

RETURN     all  --  anywhere             anywhere


Chain f2b-sendmail-auth (1 references)

target     prot opt source               destination

RETURN     all  --  anywhere             anywhere


Chain f2b-sendmail-reject (1 references)

target     prot opt source               destination

RETURN     all  --  anywhere             anywhere


Chain f2b-sshd-ddos (1 references)

target     prot opt source               destination

RETURN     all  --  anywhere             anywhere


Chain f2b-sshd (1 references)

target     prot opt source               destination

REJECT     all  --  056-153-158-163.dynamic.caiway.nl  anywhere             reject-with icmp-port-unreachable

REJECT     all  --  85.1222offices.com   anywhere             reject-with icmp-port-unreachable

REJECT     all  --  162.243.165.39       anywhere             reject-with icmp-port-unreachable

REJECT     all  --  162.243.158.198      anywhere             reject-with icmp-port-unreachable

REJECT     all  --  162.243.158.185      anywhere             reject-with icmp-port-unreachable

REJECT     all  --  162.243.10.64        anywhere             reject-with icmp-port-unreachable

REJECT     all  --  162-12-217-156.ip.weelax.fr  anywhere             reject-with icmp-port-unreachable

REJECT     all  --  161.132.195.76       anywhere             reject-with icmp-port-unreachable

REJECT     all  --  161.10.238.226       anywhere             reject-with icmp-port-unreachable

REJECT     all  --  160.20.53.2          anywhere             reject-with icmp-port-unreachable

REJECT     all  --  baikalweb.jinr.ru    anywhere             reject-with icmp-port-unreachable



SSHD 서버의 암호오류로 차단된 IP 목록을 볼 수 있다.


fail2ban 로그 보기

# cat /var/log/fail2ban.log | grep "] Ban" | awk '{print $NF}' | sort | uniq -c | sort -n

...

      3 145.239.82.192

      3 146.0.128.157

      3 146.148.22.11

      3 146.185.148.67

      3 218.92.1.166



5) 차단된 IP 복구하기


가끔 암호가 생각나지 않아서, 내가 사용하는 IP 가 차단되는 경우가 있다. 이럴 경우, 다음과 같이 사용 IP 차단을 해제한다.

# fail2ban-client set sshd unbanip IP주소


fail2ban 은 차단된 IP 목록을 sqlite3 DB 파일로 저장한다.

# fail2ban-client get dbfile

Current database file is:

`- /var/lib/fail2ban/fail2ban.sqlite3


sqlite 로 DB 파일의 내용을 볼 수 있다.

# sqlite3 /var/lib/fail2ban/fail2ban.sqlite3 .table

bans        fail2banDb  jails       logs


# sqlite3 /var/lib/fail2ban/fail2ban.sqlite3 .schema

CREATE TABLE fail2banDb(version INTEGER);

CREATE TABLE jails(name TEXT NOT NULL UNIQUE, enabled INTEGER NOT NULL DEFAULT 1);

CREATE INDEX jails_name ON jails(name);

CREATE TABLE logs(jail TEXT NOT NULL, path TEXT, firstlinemd5 TEXT, lastfilepos INTEGER DEFAULT 0, FOREIGN KEY(jail) REFERENCES jails(name) ON DELETE CASCADE, UNIQUE(jail, path),UNIQUE(jail, path, firstlinemd5));

CREATE INDEX logs_path ON logs(path);

CREATE INDEX logs_jail_path ON logs(jail, path);

CREATE TABLE bans(jail TEXT NOT NULL, ip TEXT, timeofban INTEGER NOT NULL, data JSON, FOREIGN KEY(jail) REFERENCES jails(name) );

CREATE INDEX bans_jail_timeofban_ip ON bans(jail, timeofban);

CREATE INDEX bans_jail_ip ON bans(jail, ip);

CREATE INDEX bans_ip ON bans(ip);


Bans 테이블의 차단된 IP 를 직접 볼 수 있다.

# sqlite3 /var/lib/fail2ban/fail2ban.sqlite3 "select distinct ip from bans;"

1.160.8.216

1.179.175.58

1.237.178.27

1.238.85.187

1.246.10.93

100.14.70.124

...


이 테이블에 직접 IP 를 추가해서 사용할 수도 있다.



6) 서비스 사용하기


fail2ban 서비스를 시작하기전 방화벽 서비스를 시작한다. (당연히 사용하고 있을 것이다.)

# systemctl enable firewalld

# systemctl start firewalld


같은 방식으로 fail2ban 을 시작한다.

# systemctl enable fail2ban

# systemctl start fail2ban 


7) Log 파일 설정 수정하기


fail2ban 은 cron 을 사용하는 logrotate 를 이용해서 로그 파일을 관리한다.

기본 설정은 1주일 단위로 로그파일을 갱신한다.

로그 파일이 커지면, fail2ban 서버의 성능이 떨어지므로, 이 파일크기가 과도하게 커지는 경우, 로그 파일 갱신 단위를 daily 등으로 수정해서 관리한다.

/etc/logrotate.d/fail2ban

/var/log/fail2ban.log {

    daily

    rotate 7

    missingok

    compress

    notifempty

    postrotate

      /usr/bin/fail2ban-client flushlogs >/dev/null || true

    endscript

}



2. GeoIP


1) 소개

 GeoIP 는 IP 의 지리적 위치, 즉 국가가 어디인가를 알려주는 것이다. 이미 웹 서버에서는 GeoIP 를 사용해서 특정 국가를 차단하는 방법이 있다.



2) 설치하기


가) GeoIP 관련 패키지 설치하기

# yum search GeoIP

...

========================================== N/S matched: GeoIP ==========================================

GeoIP-data.noarch : Static snapshot of GeoIP databases

GeoIP-devel.i686 : Development headers and libraries for GeoIP

GeoIP-devel.x86_64 : Development headers and libraries for GeoIP

lighttpd-mod_geoip.x86_64 : GeoIP module for lighttpd to use for location lookups

mod_geoip.x86_64 : GeoIP module for the Apache HTTP Server

nginx-mod-http-geoip.x86_64 : Nginx HTTP geoip module

opensips-mmgeoip.x86_64 : Wrapper for the MaxMind GeoIP API

pdns-backend-geoip.x86_64 : GeoIP backend for pdns

python-GeoIP.x86_64 : Python bindings for the GeoIP geographical lookup libraries

python-geoip2-doc.noarch : Documentation for python-geoip2

python-pygeoip.noarch : Pure Python GeoIP API

python2-geoip2.noarch : Documentation for python-geoip2

syslog-ng-geoip.x86_64 : geoip support for syslog-ng

uwsgi-plugin-geoip.x86_64 : uWSGI - Plugin for GeoIP support

GeoIP.i686 : Library for country/city/organization to IP address or hostname mapping

GeoIP.x86_64 : Library for country/city/organization to IP address or hostname mapping

GeoIP-update.noarch : Crontab entry to facilitate automatic updates of databases

perl-Geo-IP.x86_64 : Efficient Perl bindings for the GeoIP location database

php-pecl-geoip.x86_64 : Extension to map IP addresses to geographic places


나) 아파치 웹서버에 GeoIP 사용하기



다) GeoIP CSV 파일 내려받기


CSV 로 국가별 IP 대역폭이 정리된 파일을 내려받을 수 있다.

# wget http://geolite.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip

# unzip GeoIPCountryCSV.zip


3) 특정 국가 IP 차단하기


CSV 파일은 다음과 같이 구성되어 있다.

"1.0.0.0","1.0.0.255","16777216","16777471","AU","Australia"

"1.0.1.0","1.0.3.255","16777472","16778239","CN","China"

"1.0.4.0","1.0.7.255","16778240","16779263","AU","Australia"


모두들 아는 그 국가를 차단해보자.


가) iptable 의 xtable 모듈을 이용하는 방법


귀챦다. (https://root.so/26)


나) CSV 로부터 직접 iptable 로 추가하는 방법


그냥 BASH 셀 스크립트로 처리하자.

block_china.sh

#!/bin/sh


DATA=/root/GeoIPCountryWhois.csv


iptables -N GeoIP-China

iptables -A GeoIP-China -j DROP


for IPRANGE in `egrep "China" $DATA | cut -d, -f1,2 | sed -e 's/"//g' | sed -e 's/,/-/g'`

do

        iptables -I INPUT -p all -m iprange --src-range $IPRANGE -j GeoIP-China

done


GeoIP-China 라는 체인 룰을 새로 생성하고, DROP 으로 처리한다.

CSV 파일의 특정 국가를 읽어서 새로 생성한 룰로 Jump 하도록 한다.


다음과 같이 실행한다.

# ./block_china.sh


..


# iptables -L | grep China

...

GeoIP-China  all  --  anywhere             anywhere             source IP range 1.1.0.0-1.1.0.255

GeoIP-China  all  --  anywhere             anywhere             source IP range 1.0.32.0-1.0.63.255

GeoIP-China  all  --  anywhere             anywhere             source IP range 1.0.8.0-1.0.15.255

GeoIP-China  all  --  anywhere             anywhere             source IP range 1.0.1.0-1.0.3.255

Chain GeoIP-China (4539 references)


이 IP 차단을 시스템 시작시 적용하려면, 

/etc/rc.d/rc.local 에 실행 스크립트를 추가해 둔다. 

# chmod +x /etc/rc.d/rc.local


같은 방식으로 특정 국가 목록을 더 추가해서 만들어 적용할 수 있다.(예, 남미 국가들...)



3. BlackIP


1) 소개


BlackIP 는 프로젝트 Honeypot 과 같이 Black IP 로 신고된 IP 들의 목록을 제공하는 Public 서비스들의 목록을 말한다.

이 BlackIP 들을 모아둔 정보가 다음 깃허브에 있다.



2) IP 제공 소스들 


가) Public 블랙 IP 리스트

나) TOR


다) 압축

라) 중단된 사이트



3) 소스 및 데이터 내려받기


git 으로 해당 저장소를 내려받는다.


# git clone --depth=1 https://github.com/maravento/blackip.git

# cd blackip

# tar xvfz blackip.tar.gz

blackip.txt


blackip.txt 파일에는 순수하지 않은 IP 들만 순수하게 들어 있다.

...

36.81.144.179

36.81.148.211

36.81.148.223

36.81.151.140

36.81.154.13

36.81.154.29

36.81.157.193

36.81.160.2

36.81.161.230

36.81.170.3

36.81.175.248

36.81.177.157

...



4) 차단하기

GeoIP 처럼 iptable 을 이용해서 직접추가해준다.

ipset 으로 Blacklist 를 만들어 사용하는 방법은 다음을 참조한다.


block_blackip.sh

#!/bin/sh


DATA=./blackip.txt


iptables -N BlackIP

iptables -A BlackIP -j DROP


for IP in `cat $DATA`

do

        iptables -I INPUT -p all -s $IP -j BlackIP

done




5) fail2ban 에 추가하기


위 방식과 달리 fail2ban 에 IP 를 직접 추가해주는 방식도 가능하다.

#!/bin/sh


DATA=./blackip.txt


for IP in `cat $DATA`

do

        fail2ban-client set sshd banip $IP

done



설정 보기

# iptables -L | grep Black

...


BlackIP    all  --  1.207.37.118         anywhere

BlackIP    all  --  1.207.37.28          anywhere

BlackIP    all  --  1.207.37.8           anywhere

BlackIP    all  --  1.207.36.125         anywhere

BlackIP    all  --  1.207.36.9           anywhere

...



4. 마무리


줄었을까...

암호:

마지막 로그인:        금  1월  4 12:34:08 KST 2019 일시 pts/0

마지막 로그인 실패: 금  1월  4 14:19:45 KST 2019 host-212-159-148-72.static.as13285.net에서 시작 일시 ssh:notty

마지막 로그인 후 3385 번의 로그인 시도가 실패하였습니다.


2 시간 동안 3385번의 로그인 시도가 있었다.


IP 차단을 하고 나서, 2시간이 지났을 때는 어떻게 되었을 까?

마지막 로그인:        금  1월  4 15:07:33 KST 2019 일시 pts/1

마지막 로그인 실패: 금  1월  4 15:54:16 KST 2019 ip64.ip-54-36-151.eu에서 시작 일시 ssh:notty

마지막 로그인 후 6 번의 로그인 시도가 실패하였습니다.


현저하게 줄어든 것을 볼 수 있다.



5. CentOS 8 을 위한 jail.local 수정

CentOS 8 의 방화벽 백엔드는 iptable 이 아니라, nftable 이다.

따라서, jail.local 의 벡엔드도 다음과 같이 수정해준다.

# banaction = iptables-multiport

# banaction_allports = iptables-allports

banaction = nftables-multiport

banaction_allports = nftables-allports


혹시라도 iptable 을 사용한 커스텀 액션이 있다면,, 모두 nftable 로 변경해준다.

며칠 사용해 본 느낌상 nftable 이 훨씬 안정적이다.