IT pass HikiWiki - [Memo2024][ITPASS]fail2ban のインストールと設定 Diff

  • Added parts are displayed like this.
  • Deleted parts are displayed like this.

{{toc}}

[((<[ITPASS2024]2024年度サーバ構築ログ>)) へ戻る]

= 概要

サーバへの不正アクセスを減らすため, fail2ban のインストールと設定を行う.

= fail2ban のインストール

  $ sudo -s
  # apt-get update
  # apt-get install fail2ban

iptables -L でインストールされたことを確認する.

  # iptables -L

以下のように fail2ban の記述が表示される.
  
Chain INPUT (policy ACCEPT)
target     prot opt source               destination        

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination        

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination    

= 設定ファイルの編集

fail2ban の設定ファイルは, /etc/fail2ban/jail.conf である.
以下の通り設定ファイルを編集する.

== ssh

ssh に関する設定を以下のように追記する.
enabled が true になっているとサービスが実行される. false は実行されない.

[ssh]
enabled = true
port    = ssh
filter  = sshd
logpath  = /var/log/auth.log
maxretry = 4

* ignoreip: 不正アクセスとして扱わないアクセス元を指定.
* bantime: 不正アクセスと認めたときに, アクセスを何秒遮断するか指定.
* findtime, maxretry: findtime 秒間のうちに maxretry 回失敗すると不正アクセスとみなされる.
* destemail: 不正アクセスが認められたときのメールの送り先.
* logpath: 監視をするログの場所を指定する.

== apache

apache に関する設定を以下のように書き換える.

  [apache-nohome]
  enabled  = true
  port     = http,https
  filter   = apache-nohome
  findtime = 60
  logpath  = /var/log/httpd-*error.log
  maxretry = 60
  bantime  = 1200

また以下を追記する.

  [apache]
  enabled = true
  port    = http,https
  filter  = apache-auth
  findtime= 60  
  logpath = /var/log/httpd-*error.log
  maxretry = 60
  bantime  = 1200  

  # default action is now multiport, so apache-multiport jail was left
  # for compatibility with previous (<0.7.6-2) releases

  [apache-multiport]
  enabled   = true
  port      = http,https
  filter    = apache-auth
  findtime  = 10  
  logpath = /var/log/httpd-*error.log
  maxretry  = 60
  bantime  = 1200


  [apache-ddos]
  enabled  = true
  port     = http,https
  filter   = apache-ddos
  findtime= 10
  logpath  = /var/log/httpd-*access.log
  maxretry = 60
  bantime  = 1200

apache ではエラーログを, apache-multiport ではアクセスログを監視する.
findtime, maxretry については, このぐらいが妥当と思われるが要請などがあれば適宜変えていくこと.

= failregex の追加

  * failregex を設定すると, その設定に対応したログのメッセージをカウントし, findtime 以内に maxretry 回, 同じ IP アドレスからのメッセージがカウントされるとその IP アドレスからのアクセスが ban される.
  * ignoreregex は failregex で設定したもののうち, カウントしたくないメッセージがある場合に設定する.
  * failregex の最後の行は access ログを監視するための構文である.
    * access ログは error ログとはメッセージの書式が異なるので, その上の 5 つとは書き方が異なる.
  * 1 つの html ページに画像がたくさん貼付けてあるとそれだけでカウントして ban してしまうことがある. そのため, png, jpg(jpeg), gif ファイルについては ignoreregex に追加している.


== apache-ddos の設定

* apache-ddos.conf のバックアップを行う.

   # cd /etc/fail2ban/filter.d
   # mv apache-ddos.conf apache-ddos.conf.bk

* 下の内容を持つ apache-ddos.conf を新たに作成する.

    # Fail2Ban apache-ddos filter
    #

    [Definition]

    failregex = ^<HOST> -.*GET.*
    ignoreregex = \.(?i)(jpe?g|gif|png|bmp|pdf|js|css|woff|eot|ttf|ico|txt|xml|swf|xlsx?|docx?|pptx?)

* この状態だと以下のエラーメッセージが表示され, fail2ban がアクティブにならなかった.

    global flags not at the start of the expression at position 2

* 調べた結果 apache-ddos.conf の一部を以下のように書き換えると無事起動できた. (厳密に同じエラーではないが参考 : ((<Python3.11における正規表現の書き方について|URL:https://teratail.com/questions/u5fnmft7dm4c4v>)) )

    ignoreregex = \.(?i:jpe?g|gif|png|bmp|pdf|js|css|woff|eot|ttf|ico|txt|xml|swf|xlsx?|docx?|pptx?)

== apache-auth の設定

* apache-auth.conf のバックアップを行う.

   # cd /etc/fail2ban/filter.d
   # mv apache-auth.conf apache-auth.conf.bk

* 下の内容を持つ apache-auth.conf を新たに作成する.

   # Fail2Ban apache-auth filter
   #

   [INCLUDES]

   # Read common prefixes. If any customizations available -- read them from
   # apache-common.local
   before = apache-common.conf

   [Definition]

   # Mode for filter: normal (default) and aggressive (allows DDoS & brute force detection of mod_evasive)
   mode = normal

   # ignore messages of mod_evasive module:
   apache-pref-ign-normal = (?!evasive)
   # allow "denied by server configuration" from all modules:
   apache-pref-ign-aggressive =
   # mode related ignore prefix for common _apache_error_client substitution:
   apache-pref-ignore = <apache-pref-ign-<mode>>

   #prefregex = ^%(_apache_error_client)s (?:AH\d+: )?<F-CONTENT>.+</F-CONTENT>$
   prefregex =

   failregex = ^.* \[client <HOST>:[0-9]+\] AH01618: user .*? not found:
               ^.* \[client <HOST>:[0-9]+\] AH01617: user .*?: authentication failure .* Password Mismatch, referer:

   ignoreregex = ^<HOST> -.*GET.*(jpg|jpeg|gif|png).*  

== apache-common, apache-nohome, apache-noscript, apache-overflows の設定

次に, apache-common.conf, apache-nohome.conf, apache-noscript.conf, apache-overflows.conf の中身を変更, 確認する.

* /etc/fail2ban/filter.d/apache-common.conf

  * 以下のように変更する.

_apache_error_client = \[[^]]*\] \[(:?error|\S+:\S+)\]( \[pid \d+(:\S+\d+)?\])? \[client <HOST>(:\d{1,5})?\]


* /etc/fail2ban/filter.d/apache-nohome.conf

以下のように記述されているかを確認する.

failregex = ^%(_apache_error_client)s (AH00128: )?File does not exist: .*/~.*

* /etc/fail2ban/filter.d/apache-noscript.conf

  * 以下のように記述する.

failregex = ^%(_apache_error_client)s ((AH001(28|30): )?File does not exist|(AH01264: )?script not found or unable to stat):/\S*(php([45]|[.-]cgi)?|\.asp|\.exe|\.pl)(, referer: \S+)?\s*$
             ^%(_apache_error_client)s script'/\S*(php([45]|[.-]cgi)?|\.asp|\.exe|\.pl)\S*' not found or unable to stat(, referer: \S+)?\s*$


* /etc/fail2ban/filter.d/apache-overflows.conf

  * 以下のように記述する.

failregex = ^%(_apache_error_client)s ((AH0013[456]: )?Invalid
             (method|URI) in request .*( - possible attempt to establish SSL
             connection on non-SSL port)?|(AH00565: )?request failed: URI too long
             \(longer than \d+\)|request failed: erroneous characters after protocol
             string: .*|AH00566: request failed: invalid characters in URI)(,referer: \S+)?$


== ssh

* /etc/fail2ban/filter.d/sshd.conf の failregex を編集する.

  * 以下の 1 行を追記する.

^%(__prefix_line)s[iI] .* [[]<HOST>[]] .* POSSIBLE BREAK-IN ATTEMPT\s*S

= ログレベルの確認

* /etc/fail2ban/fail2ban.conf の中のログレベルを確認する.
(デフォルトになっているはずなので, 作業する必要はないが, 確認しておくこと)

  * ban, unban の記録がログに出力されるレベル

  # Option: loglevel
  # Notes.: Set the log level output.
  #         CRITICAL
  #         ERROR
  #         WARNING
  #         NOTICE
  #         INFO
  #         DEBUG
  # Values: [ LEVEL ]  Default: ERROR
  #
  loglevel = INFO

= fail2ban の起動

以下のコマンドで fail2ban を起動する.

  # systemctl start fail2ban

fail2ban が動いているか確認する.

# systemctl status fail2ban

* サービスの停止・開始・再起動は ((<[ITPASS2011a]サービスの開始・停止>)) を参照のこと.

= 動作テスト

== ssh

joho07 から, 存在しないユーザ名で tako に ssh を行い, 動作をチェックを行う.

$ ssh hoge@10.35.19.XXX            <-- tako のプライベート IP アドレス
Permission denied (Publickey).
(これを繰り返す)


maxretry 回目には接続が切られ,

hoge@joho07-itpass:~$ ssh hoge@10.35.19.XXX
ssh: connect to host 10.35.19.XXX port 22: Connection refused


とメッセージが届いた.

tako で iptables -L をして, リストに加えられているかを確認する.  

  Chain INPUT (policy ACCEPT)
  target     prot opt source               destination
  f2b-sshd   tcp  --  anywhere             anywhere             multiport
  dports ssh

  Chain FORWARD (policy ACCEPT)
  target     prot opt source               destination

  Chain OUTPUT (policy ACCEPT)
  target     prot opt source               destination

  Chain f2b-sshd (1 references)
  target     prot opt source               destination
  REJECT     all  --  ip188-42.pnet.kobe-u.ac.jp  anywhere            
  reject-with icmp-port-unreachable
  RETURN     all  --  anywhere             anywhere  

fail2ban のログに記録されているか確認する. 以下のような警告がログ /var/log/fail2ban.log に記載される.
2024-11-09 15:43:20,505 fail2ban.actions        [926]: NOTICE  [sshd] Ban 10.35.19.XXX

=== error のテスト

* fail2ban を再起動する.

# /etc/init.d/fail2ban restart

* ブラウザを立ち上げ, johoXX から
10.35.19.XXX/hoge
を入力して, findtime 以内に maxretry 回以上アクセスする.
今回は
  $ wget http://10.35.19.XXX/hoge
と打ち込んだ.

ここで, テストのために一時的に jail.conf を書き換えると, fail2ban が停止してしまった.
原因は究明中.
* fail2ban 再起動の際に上記 restart でなく satrt することで解決したapache-ddos.conf の項に記述した方法を用いて対処した.

* iptables -L を見て, アクセスした IP アドレスが ban されていることを確認する.

   Chain f2b-apache-ddos (1 references)
   target     prot opt source               destination        
   REJECT     all  --  10.35.19.XXX        anywhere             reject-with icmp-port-unreachable
   RETURN     all  --  anywhere             anywhere          

* /var/log/fail2ban.log についても確認する.

   2018-11-14 14:59:52,066 fail2ban.actions        [4034]: NOTICE  [apache-ddos] Ban 10.35.19.XXX


=== access のテスト

* ブラウザから tako-itpass.scitec.kobe-u.ac.jp 以下のファイルに findtime 以内に maxretry 回更新する.

10.35.19.XXX/test

* iptables -L を見て, アクセスした IP アドレスが ban されていることを確認する.

   Chain f2b-apache-ddos (1 references)
   target     prot opt source               destination        
   REJECT     all  --  10.35.19.XXX        anywhere             reject-with icmp-port-unreachable
   RETURN     all  --  anywhere             anywhere            
          
* /var/log/fail2ban.log についても確認する.

   2018-11-14 15:06:52,767 fail2ban.actions        [4034]: NOTICE  [apache-ddos] Ban 10.35.19.XXX


= 挙動がシステムログメールに記載されるように設定

== スクリプトの設置

* ika の ~itpass/ftp/server/2011/system_report/loginfail が tako の /etc/cron.local/daily/800_loginfail にコピーされていることを確認する.


== テスト

* 情報実験機など (固定IPが望ましい) から maxretry 回, 存在しない名前でログインして ban されたことを確認する (同じ日に ssh でテストしているならこの作業はしなくてよい).
* 次の日のメールのシステムログに出力されていることを確認する.
* 確認することができなかった. 原因を検討する.

システムログの日付のフォーマットが

Nov 12 23:50:02 tako-itpass sshd[2570306]: Connection closed by invalid user itbase 130.54.59.159 port 37656 [preauth] 

の形式で書かれることが期待されていたのに, 実際は

2024-11-13T15:59:30.723436+09:00 tako-itpass sshd[2570306]: Connection closed by invalid user itbase 130.54.59.159 port 37656 [preauth] 

といった形式で書かれていた. fail2ban のシステムログメールは /var/log/auth.log を参照しており, これは /etc/rsyslog.conf によって設定されている. rsyslog.conf に

$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat

と追記し,

systemctl restart rsyslog.service

でシステムログの再起動を行う.
すると, 求められていた形式でログが記述され, 無事システムログがメールに出力されるようになった.

== fail2ban の動作確認

*  fail2ban のフィルターの動作確認を行う.

  # fail2ban-regex --print-all-missed /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf

* 表示内容を確認し, フィルターにかかっていることを確認する.