Asterisk キューのログを MySql へ格納

Asterisk 呼情報をODBCでMySqlへ格納する方法を以前やりました。

Asterisk CDR(呼情報)をODBCでMySqlへ格納
Asterisk CDR(呼情報)をODBCでMySqlへ格納(後記)

今回はAsterisk のキュー(待ち呼)のログをODBCでMySqlへ格納する方法を紹介します。

1. キューログ用のテーブルを作成

まずは、キューログ用に queue_log テーブルを作成します。

CREATE TABLE `queue_log` (
    `id`              bigint(255) unsigned NOT NULL AUTO_INCREMENT,
    `time`            varchar(26) NOT NULL DEFAULT '',
    `callid`          varchar(40) NOT NULL DEFAULT '',
    `queuename`       varchar(20) NOT NULL DEFAULT '',
    `agent`           varchar(20) NOT NULL DEFAULT '',
    `event`           varchar(20) NOT NULL DEFAULT '',
    `data`            varchar(100) NOT NULL DEFAULT '',
    `data1`           varchar(40) NOT NULL DEFAULT '',
    `data2`           varchar(40) NOT NULL DEFAULT '',
    `data3`           varchar(40) NOT NULL DEFAULT '',
    `data4`           varchar(40) NOT NULL DEFAULT '',
    `data5`           varchar(40) NOT NULL DEFAULT '',
    `created`         timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (`id`),
    KEY `queue` (`queuename`),
    KEY `event` (`event`)
) DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;

2. extconfig.conf

/etc/asterisk/extconfig.conf にキューのログを格納する情報を記述します。

queue_log => odbc,asterisk,queue_log

第1パラメータ: ドライバ
第2パラメータ: res_odbc.conf のデータベースの設定情報 (DSN)
第3パラメータ: テーブル名

3. AsteriskとODBC接続の構成

AsteriskとODBC接続の構成は /etc/asterisk/res_odbc.conf で行います。

[asterisk]
enabled => yes
dsn => asterisk-connector
username => asterisk
password => asterpass
pre-connect => yes

4. ODBC設定の追加

Asteriskデータベースへの接続情報を /etc/odbc.ini へ追加します。

[asterisk-connector]
Description           = MySQL connection to 'asterisk' database
Driver                = MySQL
Database              = asterisk
Server                = localhost
UserName              = asterisk
Password              = asterpass
Port                  = 3306
Socket                = /var/lib/mysql/mysql.sock

5. 動作確認

Asterisk 再起動して動作確認します。

# service asterisk restart

キュー情報がMySqlへ格納されるか動作確認してみます。
ここでは、SIP #2501 がキューに入って #2502 が受けた結果を表示しています。

# mysql -u asterisk -p
Enter password: 

mysql> use asterisk;
mysql> select * from queue_log;

+----+----------------------------+--------------+------------+----------+----------------+------+-------+--------------+-------+-------+-------+---------------------+
| id | time                       | callid       | queuename  | agent    | event          | data | data1 | data2        | data3 | data4 | data5 | created             |
+----+----------------------------+--------------+------------+----------+----------------+------+-------+--------------+-------+-------+-------+---------------------+
| 18 | 2016-09-19 12:33:53.249160 | 1474256033.2 | queue_test | NONE     | ENTERQUEUE     |      |       | 2501         | 1     |       |       | 2016-09-19 12:33:53 |
| 19 | 2016-09-19 12:33:56.479286 | 1474256033.2 | queue_test | SIP/2502 | CONNECT        |      | 3     | 1474256033.3 | 3     |       |       | 2016-09-19 12:33:56 |
| 20 | 2016-09-19 12:34:06.721414 | 1474256033.2 | queue_test | SIP/2502 | COMPLETECALLER |      | 3     | 10           | 1     |       |       | 2016-09-19 12:34:06 |
+----+----------------------------+--------------+------------+----------+----------------+------+-------+--------------+-------+-------+-------+---------------------+
3 rows in set (0.01 sec)

参考:
http://stackoverflow.com/questions/30161384/asterisk-11-queue-log-to-mysql
http://work.mikeboylan.com/posts/2012/03/asterisk-queuelog-to-mysql.html
http://lists.digium.com/pipermail/asterisk-users/2009-September/237448.html

以上です。

Asterisk TLSとSRTPでより安全なコール (パート2: SRTP編)

前回はTLS設定で呼制御の暗号化を試みました。今回は通話の暗号化を試みます。

1. sip.conf の変更
/etc/asterisk/sip.conf のSIPクライアント(例 2001 )の定義に “encryption=yes” を追加します。

[2001]
type=peer
secret=password    ; this is NOT a secure password
host=dynamic
...(省略)...
transport=tls
encryption=yes

2. クライアントの設定
Zoiper で 暗号化 を有効にして確認します。

Preferences -> Accounts -> Advanced -> Use rport media をチェック
Preferences -> Accounts -> Advanced -> Use TLS with SDES SRTP を選択

以上です。

通話を開始すると Zoiper 上にカギのアイコンが表示されます。

また、今回の設定は Zoiper 以外にも AGEphone Business の評価版での試用をしました。
サポートの方に教えて頂きました AGEphone Business の設定方法は下記のとおりです。

Windows - AGEphone Biz3
TLS
- アカウント設定 > 接続種別 = TLS
- アカウント設定 > 全般の設定 > トランスポートにTLSを使う = ON
SRTP
- アカウント設定 > 全般の設定 > メディア暗号化(SRTP) = ON

Asterisk TLSとSRTPでより安全なコール (パート1: TLS編)

Asterisk には TLS(Transport Layer Security)SRTP(Secure Real-time Transport Protocol) により通信を安全に行う方法があります。

TLS は Asterisk と SIPクライアントの SIP によるやりとりを暗号化し、SRTP は電話の音声ストリームを暗号化します。
ここでは CentOS6.x 上で Asterisk 13 をソースをビルドしてインストール方法は省略します。ただし、Asterisk 13 のビルドは下記の必要なパッケージをインストールしてから行ってください。

1. 必要なパッケージのインストール
まず、暗号化にに必要な OpenSSL と LibSRTP をインストールします。

# yum install openssl openssl-devel
# yum install libsrtp libsrtp-devel

2. 自己署名証明書の作成
Asterisk で利用する自己署名証明書を生成するために Asterisk のソースディレクトリ下の contrib/scripts/に ast_tls_cert という便利なツールが付属しています。これで サーバー証明書とクライアント証明書を生成します。

# mkdir /etc/asterisk/keys
# ./ast_tls_cert -C foo.com -O "Foo Company" -d /etc/asterisk/keys
# ./ast_tls_cert -m client -c /etc/asterisk/keys/ca.crt -k /etc/asterisk/keys/ca.key -C foo.com -O "Foo Company" -d /etc/asterisk/keys -o sipclient

※ foo.com や "Foo Company" は実際のサーバーのFQDN またはIPアドレス、社名に置き換えてください。また、コマンドの途中でパスフレーズを数回入力するように促されますので適切なものを入力します。

コマンドを実行すると以下のファイルが /etc/asterisk/keys ディレクトリに生成されます。

# ll /etc/asterisk/keys 

asterisk.crt
asterisk.csr
asterisk.key
asterisk.pem
sipclient.crt
sipclient.csr
sipclient.key
sipclient.pem
ca.cfg
ca.crt
ca.key
tmp.cfg

3. sip.conf の変更
/etc/asterisk/sip.conf に以下を追加します。

tlsenable=yes
tlsbindaddr=0.0.0.0:5061
tlscertfile=/etc/asterisk/keys/asterisk.pem
tlscafile=/etc/asterisk/keys/ca.crt
tlscipher=ALL
tlsclientmethod=tlsv1

続けて、SIPクライアント(例 2001 )の定義に “transport=tls” を追加します。

[2001]
type=peer
secret=password    ; this is NOT a secure password
host=dynamic
...(省略)...
transport=tls

4. クライアントの設定
Zoiper で TLS を有効にして確認します。

Preferences -> Accounts -> Advanced -> Use rport をチェック
Preferences -> Accounts -> Advanced -> Use TLS transport を選択
Preferences -> Advanced -> Security -> Extra CA certificate に sipclient.pem ファイルを選択
Preferences -> Advanced -> Security -> Protocol suite: から TLS v1 を選択
Preferences -> Advanced -> Security -> Disable certificate verification をチェック ※1

※1 このチェックボックスは DANGEROUS DO NOT USE! と表記されていますが、これをチェックしないと
Certificatge: Issuer untrusted/not found/not valid/wrong purpose というエラーになります。
自己署名の証明書のためと思われます。また、再起動するとチェックが解除されていますので、起動のたびにチェックをする必要があります。
これが、フリー版の制限なのか、自己署名証明書のせいなのかはわかりません。;)

Fail2ban で不正アクセス防止 (asterisk 編パート2)

前回の投稿でfai2banで不正アクセス対策をした後にも、しつこくアクセス元を変えたり、以下のように fail2ban のフィルターに検出されないような手段でアクセスを試みている様子。

Failed to authenticate device 111<sip:111@NNN.NN.NNN.NNN>;tag=649747a9

voip-info.jpSIP-Fail2ban の投稿記事を参考に SIP のブルートフォース攻撃を抑止するパッチを Asterisk 13.8.2 用に作成し、適用しました。

chan_sip.c の修正パッチ:

--- chan_sip.c.20160512 2016-05-12 10:55:25.221687414 +0900
+++ chan_sip.c  2016-05-12 11:09:13.753796299 +0900
@@ -19347,7 +19347,7 @@
                        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;
@@ -25340,7 +25340,7 @@
                        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;
@@ -26122,7 +26122,7 @@
                        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);
@@ -27842,7 +27842,7 @@
                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);

上記の変更を行い再ビルドした Asterisk を再起動してログを確認。パッチ適用後のログのように行末へ不正アクセス元のIPアドレスが表示されるようになりました。
※NNN.NN.NNN.NNN はサーバーのIPアドレス

パッチ適用前:

[2016-05-12 11:13:24] NOTICE[30781][C-0000002a]: chan_sip.c:26125 handle_request_invite: Failed to authenticate device 111<sip:111@NNN.NN.NNN.NNN>;tag=649747a9
[2016-05-12 11:13:26] NOTICE[30781][C-0000002b]: chan_sip.c:26125 handle_request_invite: Failed to authenticate device 111<sip:111@NNN.NN.NNN.NNN>;tag=f39f5f63
[2016-05-12 11:13:27] NOTICE[30781][C-0000002c]: chan_sip.c:26125 handle_request_invite: Failed to authenticate device 111<sip:111@NNN.NN.NNN.NNN>;tag=8e066fe2
[2016-05-12 11:13:28] NOTICE[30781][C-0000002d]: chan_sip.c:26125 handle_request_invite: Failed to authenticate device 111<sip:111@NNN.NN.NNN.NNN>;tag=6af3aa52

パッチ適用後:

[2016-05-12 11:21:07] NOTICE[8958][C-00000000]: chan_sip.c:26125 handle_request_invite: Failed to authenticate device 333<sip:333@NNN.NN.NNN.NNN>;tag=1b248211 (xxx.42.218.186:5076)                               
[2016-05-12 11:21:08] NOTICE[8958][C-00000001]: chan_sip.c:26125 handle_request_invite: Failed to authenticate device 333<sip:333@NNN.NN.NNN.NNN>;tag=4323ab38 (xxx.42.218.186:5074)                               
[2016-05-12 11:21:09] NOTICE[8958][C-00000002]: chan_sip.c:26125 handle_request_invite: Failed to authenticate device 333<sip:333@NNN.NN.NNN.NNN>;tag=ba356309 (xxx.42.218.186:5082)                               
[2016-05-12 11:21:11] NOTICE[8958][C-00000003]: chan_sip.c:26125 handle_request_invite: Failed to authenticate device 333<sip:333@NNN.NN.NNN.NNN>;tag=7e32110c (xxx.42.218.186:5076)    

voip-info.jp の投稿記事にありますように、Fail2ban のフィルターに以下のルールを適用すればこの手の不正アクセスを抑止することができるようになります。

NOTICE.* .*: Failed to authenticate user .* \(<HOST>:.*\)

Fail2ban で不正アクセス防止 (asterisk 編)

オープンソースIP-PBX Asterisk サーバーを外部公開サーバーへ入れてデモ環境を整えました。外部からの攻撃を抑止するために Fail2ban で対策をしました。

参考サイト:
http://www.voip-info.org/wiki/view/Fail2Ban+%28with+iptables%29+And+Asterisk
http://www.fail2ban.org/wiki/index.php/Asterisk

Fail2ban はCentOS 6.7 + EPEL リポジトリから yum でインストールします。

1. Fail2ban のインストール

# yum install fail2ban

2. jail.conf の変更

jail.conf をエディターで開いて、以下の設定を追加します。

# cd /etc/fail2ban
# vi jail.conf

-- ここから --
[asterisk-iptables]

enabled  = true
filter   = asterisk
action   = iptables-allports[name=ASTERISK, protocol=all]
           sendmail-whois[name=asterisk, dest=root, sender=fail2ban]
logpath  = /var/log/asterisk/messages
maxretry = 4
findtime = 21600
bantime = 86400
-- ここまで --

3. asterisk.conf (フィルター) の変更

fail2ban をインストールすると、/etc/fail2ban/filter.d/ の下にフィルターが用意されています。 asterisk.conf もありますので、これをバックアップしておいて、あらたにフィルターを作成します。

# cd /etc/fail2ban/filter.d/
# mv asterisk.conf asterisk.conf.bak

エディターで asterisk.conf を開いて以下の内容を入力します。

# vi asterisk.conf

-- ここから --
# Fail2Ban configuration file

[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 '' can
#          be used for standard IP/hostname matching and is only an alias for
#          (?:::f{4,6}:)?(?P\S+)
# Values:  TEXT
#
failregex = NOTICE.* .*: Registration from '.*' failed for ':.*' - Wrong password
            NOTICE.* .*: Registration from '.*' failed for ':.*' - No matching peer found
            NOTICE.* .*: Registration from '.*' failed for ':.*' - No matching peer found
            NOTICE.* .*: Registration from '.*' failed for ':.*' - Username/auth name mismatch
            NOTICE.* .*: Registration from '.*' failed for ':.*' - Device does not match ACL
            NOTICE.* .*: Registration from '.*' failed for ':.*' - Peer is not supposed to register
            NOTICE.* .*: Registration from '.*' failed for ':.*' - ACL error (permit/deny)
            NOTICE.* .*: Registration from '.*' failed for ':.*' - Device does not match ACL
            NOTICE.* .*: Registration from '\".*\".*' failed for ':.*' - No matching peer found
            NOTICE.* .*: Registration from '\".*\".*' failed for ':.*' - Wrong password
            NOTICE.*  failed to authenticate as '.*'$
            NOTICE.* .*: No registration for peer '.*' \(from \)
            NOTICE.* .*: Host  failed MD5 authentication for '.*' (.*)
            NOTICE.* .*: Failed to authenticate user .*@.*
            NOTICE.* .*:  failed to authenticate as '.*'
            NOTICE.* .*:  tried  to authenticate with nonexistent user '.*'
            VERBOSE.*SIP/-.*Received incoming SIP connection from unknown peer

# Option:  ignoreregex
# Notes.:  regex to ignore. If this regex matches, the line is ignored.
# Values:  TEXT
ignoreregex=
-- ここまで --

入力ができたら保存します。

4. Fail2ban 起動

# service fail2ban start
# chkconfig fail2ban on

5. 確認

iptables で確認すると以下のように Ban 状況がわかります。

# iptables -L -v
...
-- 省略 --
Chain f2b-ASTERISK (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 REJECT     all  --  any    any     xxx.75-143-13.dyn.dsl.cantv.net  anywhere            reject-with icmp-port-unreachable 

以上です。