SIP-Fail2banのソースを表示
←
SIP-Fail2ban
ナビゲーションに移動
検索に移動
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
登録利用者
、
管理者
。
このページのソースの閲覧やコピーができます。
IAXでのFail2banは'''[[IAX-Fail2ban]]'''を参照してください。 ==fail2ban== ログファイルとiptablesを利用したファイアウォールの一種。Brute Forceアタックの対策に使いやすい。<br> :http://www.fail2ban.org/ :http://sourceforge.net/projects/fail2ban/ ==CentOS== CentOSではeaplからyumでインストールすることが可能です。 yum install -y epel-release yum --enablerepo=epel -y install fail2ban yumでインストールした最新のFail2BanはAsteriskのログフォーマットを変更し、ローカル設定ファイルを作成するだけで使用することができます。<BR> まずAsteriskのlogger.confを修正し [general] ; Customize the display of debug message time stamps ; this example is the ISO 8601 date format (yyyy-mm-dd HH:MM:SS) ; see strftime(3) Linux manual for format specifiers dateformat=%F %T dateformatの箇所のコメント(;)を外して有効にし、Asteriskを再起動します。<br> /etc/fail2ban/に以下の内容のjail.localというファイルを作成します。ファイルがある場合には修正します。 [DEFAULT] ignoreip = backend = polling bantime = 3600 ; 1hour maxretry= 5 usedns = no [asterisk] enabled = true fail2banを起動すると監視が始まります。 ==動作条件== pythonとiptablesが必要。yum install python iptablesなどで入れておいて下さい。 ==インストール== まずSFからfail2banをダウンロードし、展開します。 tar jxvf fail2ban-0.8.4.tar.bz2 展開したディレクトリでインストールを実行します。 cd fail2ban-0.8.4 python ./setup.py install スタートアップ・スクリプトをコピーしておきます(CentOSなどRedHat系の場合の例)。 cp files/redhat-initd /etc/init.d/fail2ban ==設定== ===Asteriskのログフォーマットを変更する=== Fail2banはそのままではAsteriskのログの日付を認識できないため、Asteriskのログフォーマットを変更します。<br> /etc/asterisk/logger.confを編集し、日付のフォーマット変更を行います。<br> [general]セクションにある dateformat=%F %T のコメントを外すか、もしこのエントリがなければ記述します。設定を変更したら、Asteriskを再起動するか、loggerモジュールのリロードを行って、変更を有効にします。これによりAsteriskのログの日付形式が以下のように変わりますので、確認してください。 [2010-12-30 09:25:25] NOTICE[17537] chan_sip.c:..... ===Asterisk用の定義ファイルを作る=== /etc/fail2ban/filter.d ディレクトリに asterisk.conf という名前で以下のようなファイルを作ります。ここで指定したメッセージがBAN基準として使われるメッセージとなります。<br> <br> Asterisk 1.8系の場合 # Fail2Ban configuration file # # # $Revision: 250 $ # [INCLUDES] # Read common prefixes. If any customizations available -- read them from # common.local #before = common.conf [Definition] #_daemon = asterisk # Option: failregex # Notes.: regex to match the password failures messages in the logfile. The # host must be matched by a group named "host". The tag "<HOST>" can # be used for standard IP/hostname matching and is only an alias for # (?:::f{4,6}:)?(?P<host>\S+) # Values: TEXT # failregex = Registration from '.*' failed for '<HOST>(:[0-9]{1,5})?' - Wrong password Registration from '.*' failed for '<HOST>(:[0-9]{1,5})?' - No matching peer found Registration from '.*' failed for '<HOST>(:[0-9]{1,5})?' - Username/auth name mismatch Registration from '.*' failed for '<HOST>(:[0-9]{1,5})?' - Device does not match ACL Registration from '.*' failed for '<HOST>(:[0-9]{1,5})?' - Peer is not supposed to register Registration from '.*' failed for '<HOST>(:[0-9]{1,5})?' - Not a local domain # Option: ignoreregex # Notes.: regex to ignore. If this regex matches, the line is ignored. # Values: TEXT # ignoreregex = Asterisk 1.6とそれ以前の場合 # Fail2Ban configuration file # # # $Revision: 250 $ # [INCLUDES] # Read common prefixes. If any customizations available -- read them from # common.local #before = common.conf [Definition] #_daemon = asterisk # Option: failregex # Notes.: regex to match the password failures messages in the logfile. The # host must be matched by a group named "host". The tag "<HOST>" can # be used for standard IP/hostname matching and is only an alias for # (?:::f{4,6}:)?(?P<host>\S+) # Values: TEXT # failregex = Registration from '.*' failed for '<HOST>' - Wrong password Registration from '.*' failed for '<HOST>' - No matching peer found Registration from '.*' failed for '<HOST>' - Username/auth name mismatch Registration from '.*' failed for '<HOST>' - Device does not match ACL Registration from '.*' failed for '<HOST>' - Peer is not supposed to register Registration from '.*' failed for '<HOST>' - Not a local domain # Option: ignoreregex # Notes.: regex to ignore. If this regex matches, the line is ignored. # Values: TEXT # ignoreregex = Asterisk 1.8とそれ以前ではログのホスト部分にポート番号を含む、含まないの違いがあるためfailregexの記述を変える必要がありますので注意してください。この部分に合致するメッセージが、ログファイルに現れたならばBAN基準になりますので注意して記述します。これ意外にも、引っかけたいメッセージがある場合にはそれも記述するとよいでしょう。<br> ===BANのアクションを作成する=== ここではUDPの5060ポート、つまりSIPだけをBAN対象としたいためアクションをSIP用に作成します。 /etc/fail2ban/action.d で以下のようにしてアクションを作成します。<br> まず cp iptables-allports.conf iptables-sip.conf を行って、全ポート用のアクションをコピーします。次に iptables-sip.conf を編集し、以下のようにBANとUNBANのエントリを修正します。 # Option: actionban # Notes.: command executed when banning an IP. Take care that the # command is executed with Fail2Ban user rights. # Tags: <ip> IP address # <failures> number of failures # <time> unix timestamp of the ban time # Values: CMD # actionban = iptables -I fail2ban-<name> 1 -s <ip> -p udp --dport 5060 -j DROP # Option: actionunban # Notes.: command executed when unbanning an IP. Take care that the # command is executed with Fail2Ban user rights. # Tags: <ip> IP address # <failures> number of failures # <time> unix timestamp of the ban time # Values: CMD # actionunban = iptables -D fail2ban-<name> -s <ip> -p udp --dport 5060 -j DROP -p udp と --dport 5060 を actionban と actionunban に追記します。 ===fail2banの設定ファイルを修正=== /etc/fail2ban にある jail.conf ファイルの最後に以下を追加します。 [asterisk-iptables] enabled = true filter = asterisk action = iptables-sip[name=ASTERISK, protocol=all] sendmail-whois[name=ASTERISK, dest=root, sender=fail2ban@example.net] logpath = /var/log/asterisk/messages maxretry = 5 findtime = 600 bantime = 604800 *action BAN処理のアクションを定義します。この例ではiptables-sipを実行します。その後、sendmail-whois で BANしたIPアドレスのwhois情報を dest= で指定された宛先に送ります。このとき使用されるメールのFrom:はfail2ban@exampleになりますので、適切なものに書き換えます。<br> アクションの所で iptables-allports を指定するとSIPだけでなく、すべてのポートからの接続を蹴るように iptables に設定されます。『怪しい攻撃元』をブロックするという意味では、こちらのアクションの方がより安全と言えます。 *logpath Asteriskのログファイルへのパスを記述します。 *maxretry 何回以上失敗したらBANするかの指定です。 *findtime この時間内にmaxretryで指定した回数以上失敗するとBANします。上の例では600秒(10分)の間に、5回以上の失敗があった場合にはBANされます。 *bantime ここで指定された期間がBAN期間になります。指定は秒数です。上の例では 60x60x24x7=604800、つまり1週間になります。 ==fail2banを起動する== /etc/init.d/fail2ban start 起動したら期待の動作をするかどうかを、よく確認してください。試しに故意に間違えたパスワードで5回以上ログインをしてみるなどです。<br> 起動に問題がなければ、fail2banが自動起動されるように登録しておけば良いでしょう。 chkconfig --add fail2ban ===起動の確認=== iptables -L -v で確認すると 61638 8222K fail2ban-ASTERISK all -- any any anywhere anywhere や Chain fail2ban-ASTERISK (1 references) pkts bytes target prot opt in out source destination 61627 8216K RETURN all -- any any anywhere anywhere のようなエントリがあるはずです。<br> BANされるとメールが送られ 11 6424 DROP udp -- any any xxx.xxx.xxx.xx anywhere udp dpt:5060 のようなDROPのエントリが追加されているはずです。 ==INVITEによるBrute force攻撃への対策== REGISTERメッセージによる攻撃以外に、INVITEによるBrute force攻撃も確認されています。 この攻撃時に出力されるログメッセージは以下のようなものになります。 Failed to authenticate user "Anonymous" <sip:anonymous@192.168.1.2>;tag=as105e401c このログメッセージの攻撃元IPアドレスが、FROMヘッダに記載されているIPアドレスになっています。 このままでは、NAT配下のサーバーからの攻撃や、FROMヘッダが偽装された場合にfail2banで対応することができません。 そこで、Asteriskへパッチを当てて、実際の攻撃元IPアドレスを表示するように修正します。 ===Asteriskへパッチを当てる=== 次のようなパッチをAsteriskに適用します。 このパッチはAsterisk-1.4.40を対象にしていますが、1.6系、1.8系にも同様の修正で対応できます。 --- asterisk-1.4.40.orig/channels/chan_sip.c 2011-01-05 02:11:48.000000000 +0900 +++ asterisk-1.4.40/channels/chan_sip.c 2011-03-10 17:59:26.000000000 +0900 @@ -15456,7 +15456,7 @@ ast_log(LOG_NOTICE, "Sending fake auth rejection for user %s\n", get_header(req, "From")); transmit_fake_auth_response(p, SIP_INVITE, req, XMIT_RELIABLE); } else { - ast_log(LOG_NOTICE, "Failed to authenticate user %s\n", get_header(req, "From")); + ast_log(LOG_NOTICE, "Failed to authenticate user %s (%s:%d)\n", get_header(req, "From"), ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); transmit_response_reliable(p, "403 Forbidden", req); } p->invitestate = INV_COMPLETED; こちらは Asterisk-1.8.23.0 用です。Asterisk-11.5.1 でもほぼ同じコードが使えます。 --- asterisk-1.8.23.0/channels/chan_sip.c.orig 2013-08-02 11:41:03.233638321 +0900 +++ asterisk-1.8.23.0/channels/chan_sip.c 2013-12-06 14:51:08.698990909 +0900 @@ -22673,7 +22673,7 @@ return 0; } if (res < 0) { /* Something failed in authentication */ - ast_log(LOG_NOTICE, "Failed to authenticate device %s\n", get_header(req, "From")); + ast_log(LOG_NOTICE, "Failed to authenticate device %s (%s)\n", get_header(req, "From"), ast_sockaddr_stringify(addr)); transmit_response(p, "403 Forbidden", req); sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); return 0; @@ -23334,7 +23334,7 @@ goto request_invite_cleanup; } if (res < 0) { /* Something failed in authentication */ - ast_log(LOG_NOTICE, "Failed to authenticate device %s\n", get_header(req, "From")); + ast_log(LOG_NOTICE, "Failed to authenticate device %s (%s)\n", get_header(req, "From"), ast_sockaddr_stringify(addr)); transmit_response_reliable(p, "403 Forbidden", req); p->invitestate = INV_COMPLETED; sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); @@ -25164,7 +25164,7 @@ p->lastinvite = seqno; return 0; } else if (auth_result < 0) { - ast_log(LOG_NOTICE, "Failed to authenticate device %s\n", get_header(req, "From")); + ast_log(LOG_NOTICE, "Failed to authenticate device %s (%s)\n", get_header(req, "From"), ast_sockaddr_stringify(addr)); transmit_response(p, "403 Forbidden", req); sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); ast_string_field_set(p, theirtag, NULL); @@ -25384,7 +25384,7 @@ if (res == AUTH_CHALLENGE_SENT) /* authpeer = NULL here */ return 0; if (res != AUTH_SUCCESSFUL) { - ast_log(LOG_NOTICE, "Failed to authenticate device %s\n", get_header(req, "From")); + ast_log(LOG_NOTICE, "Failed to authenticate device %s (%s)\n", get_header(req, "From"), ast_sockaddr_stringify(addr)); transmit_response(p, "403 Forbidden", req); pvt_set_needdestroy(p, "authentication failed"); Asterisk 11.23.1用パッチです。 --- channels/chan_sip.c.orig 2016-09-09 01:28:35.000000000 +0900 +++ channels/chan_sip.c 2016-10-28 23:26:38.985774935 +0900 @@ -18751,7 +18751,7 @@ static void receive_message(struct sip_p return; } if (res < 0) { /* Something failed in authentication */ - ast_log(LOG_NOTICE, "Failed to authenticate device %s\n", sip_get_header(req, "From")); + ast_log(LOG_NOTICE, "Failed to authenticate device %s (%s)\n", sip_get_header(req, "From"), ast_sockaddr_stringify(addr)); transmit_response(p, "403 Forbidden", req); sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); return; @@ -24963,7 +24963,7 @@ static int handle_request_options(struct return 0; } if (res < 0) { /* Something failed in authentication */ - ast_log(LOG_NOTICE, "Failed to authenticate device %s\n", sip_get_header(req, "From")); + ast_log(LOG_NOTICE, "Failed to authenticate device %s (%s)\n", sip_get_header(req, "From"), ast_sockaddr_stringify(addr)); transmit_response(p, "403 Forbidden", req); sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); return 0; @@ -25798,7 +25798,7 @@ static int handle_request_invite(struct goto request_invite_cleanup; } if (res < 0) { /* Something failed in authentication */ - ast_log(LOG_NOTICE, "Failed to authenticate device %s\n", sip_get_header(req, "From")); + ast_log(LOG_NOTICE, "Failed to authenticate device %s (%s)\n", sip_get_header(req, "From"), ast_sockaddr_stringify(addr)); transmit_response_reliable(p, "403 Forbidden", req); p->invitestate = INV_COMPLETED; sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); @@ -27788,7 +27788,7 @@ static int handle_request_publish(struct p->lastinvite = seqno; return 0; } else if (auth_result < 0) { - ast_log(LOG_NOTICE, "Failed to authenticate device %s\n", sip_get_header(req, "From")); + ast_log(LOG_NOTICE, "Failed to authenticate device %s (%s)\n", sip_get_header(req, "From"), ast_sockaddr_stringify(addr)); transmit_response(p, "403 Forbidden", req); sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT); ast_string_field_set(p, theirtag, NULL); @@ -28003,7 +28003,7 @@ static int handle_request_subscribe(stru if (res == AUTH_CHALLENGE_SENT) /* authpeer = NULL here */ return 0; if (res != AUTH_SUCCESSFUL) { - ast_log(LOG_NOTICE, "Failed to authenticate device %s for SUBSCRIBE\n", sip_get_header(req, "From")); + ast_log(LOG_NOTICE, "Failed to authenticate device %s (%s) for SUBSCRIBE\n", sip_get_header(req, "From"), ast_sockaddr_stringify(addr)); transmit_response(p, "403 Forbidden", req); pvt_set_needdestroy(p, "authentication failed"); パッチを当てて、Asteriskをコンパイルし直し、再起動します。 すると、先ほどの攻撃時のログは以下のように出力されるようになります。 Failed to authenticate user "Anonymous" <sip:anonymous@192.168.1.2>;tag=as105e401c (123.45.67.89:5060) ログの( )内に攻撃元の実IPアドレスが表示されるようになり、これを元にfail2banで攻撃を検知することができます。 ===fail2banへ設定を追加=== 修正したログに合わせたフィルタ設定をfail2banに追加します。 /etc/fail2ban/filter.d/asterisk.conf の failregex の項目に以下を追加します。 NOTICE.* .*: Failed to authenticate user .* \(<HOST>:.*\) フィルタ追加後、fail2banを再起動し設定完了です。 [[Category:セキュリティ]]
SIP-Fail2ban
に戻る。
ナビゲーション メニュー
個人用ツール
ログイン
名前空間
ページ
議論
日本語
表示
閲覧
ソースを閲覧
履歴表示
その他
検索
案内
メインページ
最近の更新
おまかせ表示
ヘルプ
広告
サイトコンテンツ
コミュニティ
Asterisk
Asterisk 18
Asterisk 20
Asterisk 22
IP電話機
購入情報
導入事例
回線接続
ベンダー
ひかり電話
セキュリティ
イベント情報
スペシャル
Asterisk pjsip
ABS
黒電話 ハック
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報