AsteriskのチャンネルドライバをPJSIPにした

いつものようにFreeBSDのportsでAsteriskをver.13.16.0に更新したら突然動かなくなった。起動させてもログを出さないで一瞬で終了するので原因は不明。いろいろ試したらSIPチャンネルドライバのchan_sip.soを読み込むところで突然死しているみたい。(他に保留音などのmp3形式のファイルの再生などの機能が全く機能しないことも判明。slnとかは大丈夫)
何か変だが、Asteriskの13.16.0が悪いのかportsが悪いのかうちの環境固有の問題なのか・・・たぶん最後だろうけど

SIPが動かないとうちではIP電話のPBXとしてどうしようもない。(SIP用のCISCO 7961Gが居るので)
そこで標準のSIPチャンネルドライバではなくPJSIPチャンネルドライバを使用することに。これも動かないとかなり困ることに・・

とりあえずAsteriskをPJSIPでFUSION IP-Phone SMARTに接続する設定を書いた。(ただし以下は記事用の簡易版)

/usr/local/etc/asterisk/pjsip.conf
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
[transport-udp4]
type = transport
protocol = udp
bind = 0.0.0.0

;[transport-tcp4]
;type = transport
;protocol = tcp
;bind = 0.0.0.0

;[transport-udp6]
;type=transport
;protocol=udp
;bind=::
  
;[transport-tcp6]
;type=transport
;protocol=tcp
;bind=::

;---
[fusion]
type=registration
transport=transport-udp4
outbound_auth=fusion
server_uri=sip:smart.0038.net:5060
client_uri=sip:5???????@smart.0038.net:5060
retry_interval=60

[fusion]
type = auth
auth_type=userpass
username=5???????
password=secretpassword

[fusion]
type=endpoint
transport = transport-udp4
context=default
outbound_auth=fusion
;force_rport=yes
allow = !all,g722,ulaw
aors=fusion

[fusion]
type=identify
match=61.213.230.153
endpoint=fusion
 
[fusion]
type=aor
contact=sip:5???????@smart.0038.net

;---
;クライアント用のテンプレ設定 読み込むので消したらダメ
[endpoint-default](!)
type = endpoint
context = default
allow = !all,g722,ulaw
;direct_media = no
device_state_busy_at = 1
dtmf_mode = rfc4733
force_rport=no

[auth-default](!)
type=auth
auth_type=userpass

[aor-default](!)
type=aor
max_contacts=1

;---
; 内線 5000
[5000](endpoint-default)
type=endpoint
transport=transport-udp4
aors=5000
auth=5000auth

[5000](aor-default)

[5000auth](auth-default)
username=5000
password=himitsupassword

;---
; 内線 5100
[5100](endpoint-default)
type=endpoint
transport=transport-udp4
aors=5100 
auth=5100auth

[5100](aor-default)

[5100auth](auth-default)
username=5100
password=himitsupassword

5???????がFusionのSIP用ID、secretpasswordがそのパスワード。
sip.confと比べるとちょっと面倒な書き方。同じ[hoge]が続くと一瞬混乱するけどtypeで見て判断。[hoge]を[hage-hoge]にして識別するのもアリ(上の例だと5000authみたいなの)だけど解りやすそうで逆に迷う元になる(気がする)。

/usr/local/etc/asterisk/extensions.conf
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
[general]
writeprotect=no
priorityjumping=no

[globals]
SPEAKINGCLOCK=117
MORNINGCALL=0840
CLOCONUMNER=03????????
FUSIONNUMBER=5??????? 

[default]
;=== 時報 ===
exten => ${SPEAKINGCLOCK},1,Goto(speakclock,s,1)

;=== モーニングコール ===
exten => ${MORNINGCALL},1,Goto(morningcall,s,1)

;=== Cloco クラウドPBXで外線着信 ===
exten => ${CLOCONUMBER},1, Goto(chakushin,s,1)

;=== Fusionで外線着信 ===
exten => ${FUSIONNUMBER},1, Goto(chakushin,s,1)

;=== Cloco クラウドPBXで外線発信 (通常)===
;exten => _0.,1,Dial(PJSIP/${EXTEN}@cloco,120,T) ;普通に0から始まる電話番号だけで発信 この場合はCloco
;exten => _0.,n,Hangup()

;=== Cloco クラウドPBXで外線発信 (965付き)===
exten => _965.,1,NoOp  ;番号最初の965は処理しない
exten => _965.,n,Dial(PJSIP/${EXTEN}@cloco,120,T) ;965+電話番号でCloco使用を明確にして発信
exten => _965.,n,Hangup()

;=== Fusionで外線発信 (38付き)===
exten => _38.,1,NoOp  ;番号最初の38は処理しない
exten => _38.,n,Dial(PJSIP/${EXTEN}@fusion,120,T) ;38+電話番号でFusion使用による発信
exten => _38.,n,Hangup()

;=== 内線 ===
exten => 5000,1,Dial(PJSIP/5000,30)
exten => 5000,2,Congestion
exten => 5000,102,Busy

exten => 5100,1,Dial(PJSIP/5100,30)
exten => 5100,2,Congestion
exten => 5100,102,Busy

;===========

[speakclock]
; 時報
exten => s,1,Answer()
exten => s,n,Wait(1)
exten => s,n,AGI(speaktime.agi)
exten => s,n,Wait(1)
exten => s,n,Hangup()

[morningcall]
; モーニングコール
exten => s,1,Answer()
exten => s,n,Wait(1)
exten => s,n,AGI(wakeup.agi)
exten => s,n,Wait(1)
exten => s,n,Hangup()

[chakushin]
; 着信
exten => s,1,Set(FROMNUM=${CALLERID(number)})
exten => s,n,Set(CALLERID(name)=${FROMNUM})
exten => s,n,Goto(default,5000,1)

上のはサンプルなので実際に使ってるのとは全然違うけど、こんな感じよってことで関係ないのも少しだけ混ぜてみた。モーニングコールとか時報のAGIスクリプトはこの記事では書かない。
外線から着信したら内線5000だけを鳴らす。(最後の行で内線5000に行く)。複数の電話を鳴らしたいならGotoの替わりにDial(PJSIP/5000&PJSIP/5100,30)みたいにするか、電話番号+内線番号で着信したら電話番号を除いてその番号(内線)に飛ばすなど。

でたらめに拡張しまくってたので巨大な設定ファイルになってたけど1から設定し直したら1/3くらいになった。たまには見直すのもいいね。

で、PJSIPにした結果だけど無事動いた。mp3ファイルが再生されないのは直ってないけどslnなどに変換すりゃ済むし・・

関連記事:

Rspamdで迷惑メールを判定 (続き)

Rspamd

前回の続き。
前回はかろうじて動く程度にしただけなのでもう少し実用になるよう設定した。

上書き系の設定

/usr/local/etc/rspamd/override.d/metrics.conf (v1.7系では使用しないこと)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
actions {
  reject = 10;
}

symbol "PHISHING" {
  score = 15.0;
}

symbol "HAS_ATTACHMENT" {
  score = 1.5;
}

迷惑メールの判断しきい値は前回書いたように少し下げているが、これはrmilterの設定で「迷惑メールと判断されたメールを削除しない」場合に限る。
あとの2つは既存のルールのスコアを変更。

この部分は設定がガラっと変わったのでRspamd 1.7系のアクション設定の変更を参照下さい。

/usr/local/etc/rspamd/override.d/multimap.conf
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
freemail_envfrom {
  map = "/usr/local/etc/rspamd/map/free.txt.zst";
}

freemail_envrcpt {
  map = "/usr/local/etc/rspamd/map/free.txt.zst";
}

freemail_to {
  map = "/usr/local/etc/rspamd/map/free.txt.zst";
}

freemail_cc {
  map = "/usr/local/etc/rspamd/map/free.txt.zst";
}

disposable_envfrom {
  map = "/usr/local/etc/rspamd/map/disposable.txt.zst";
}

disposable_envrcpt {
  map = "/usr/local/etc/rspamd/map/disposable.txt.zst";
}

disposable_from {
  map = "/usr/local/etc/rspamd/map/disposable.txt.zst";
}

disposable_to {
  map = "/usr/local/etc/rspamd/map/disposable.txt.zst";
}

disposable_cc {
  map = "/usr/local/etc/rspamd/map/disposable.txt.zst";
}

disposable_replyto {
  map = "/usr/local/etc/rspamd/map/disposable.txt.zst";
}

これらは設定の初期値ではhttps://rspamd.com/に置かれたファイルが指定されているが、ローカルに置くことにした。
なお、ファイルサイズがそれほど大きいものでもないので変更無しでも構わないとは思う。

/usr/local/etc/rspamd/override.d/
1
2
3
4
openphish_enabled = true;
phishtank_enabled = true;
openphish_map = "/usr/local/etc/rspamd/multimap/feed.txt";
phishtank_map = "/usr/local/etc/rspamd/multimap/online-valid.json.zst";

前回も書いたがonline-valid.json.zstはダウンロードに時間がかかるので定期的にダウンロードしてローカルに置く方が良さげ。
前回は自前のウェブサーバに置いたが今回は完全ローカル。

2017年8月5日追記:
phishtank_enabledをtrue指定するのはrspamdが利用できるメモリが最低で8GB(サーバーのメモリ搭載量じゃない)、安心して使うには16GB以上ある場合だけにしておいた方が良いので要注意。rspamdがメモリをバカ食いするので悩んでいたが、これが原因だったっぽい。

追加系の設定

2018年4月28日削除:
Rspamd 1.7.3で使用するには不適切だと思われる内容を削除した。

/usr/local/etc/rspamd/local.d/multimap.conf
1
2
3
freemail_replyto {
  map = "/usr/local/etc/rspamd/multimap/free.txt.zst";
}

これだけはオーバーライドしようとしたら怒られたのでlocal.dに書いた。

/usr/local/etc/rspamd/local.d/redis.conf (1行)
servers = "127.0.0.1";

これは前回書いたのと同じ。

/usr/local/etc/rspamd/local.d/worker-controller.inc (1行)
enable_password = "$2$????(中略)????";

これは前回書いたウェブ管理画面へのアクセス用パスワードの登録。
閲覧用のpasswordを使うか閲覧&登録用のenable_passwordを使うか決めてrspamadmコマンドでパスワードを作成して記入。
両方使えるようにするのもアリなんだろうけどenable_passwordだけでいいんじゃないかと。

ホワイトリストの例 (from addressで)
/usr/local/etc/rspamd/override.d/multimap.conf (新規 or 追記)
1
2
3
4
5
6
7
sender_from_whitelist_user {                     
        type = "from";                           
        filter = "email";                   
        map = "/usr/local/etc/rspamd/multimap/whitelist_from_user.map";
        symbol = "SENDER_FROM_WHITELIST_USER";
        action = "accept"; # Prefilter mode
}

/usr/local/etc/rspam/module.d/multimap.confの例からfilter, mapの2行を変更したもの。

メールアドレスのホワイトリスト
/usr/local/etc/rspamd/multimap/whitelist_from_user.map (新規)
1
2
foobar@example.com
hoge@example.net

X-Spamd-Result: default: False [0.00 / 10.00]
 SENDER_FROM_WHITELIST_USER(0.00)[foobar@example.com]

ホワイトリストに登録したアドレスからのメールのヘッダには上のような記録がある筈。

設定の確認

$ /usr/local/bin/rspamadm configtest
syntax OK

上のようにsyntax OKが出れば文法的には問題ない。

$ /usr/local/bin/rspamadm configdump

全設定・ルール表示。これでしっかり確認した方が良さげ。
これで表示される設定/ルールを変更するなら上書きなのでoverride.dに書く。存在しないのを追加するならlocal.dに書くという感じ。

rspamadmは他に幾つか役割があるのでRspamd導入直後は頻繁に使うことになると思われる。

学習

ベイジアンフィルタに迷惑メールと正常なメールをそれぞれ200以上学習させてやる。迷惑メールだけ学習させれば良いというものではないらしい。(Rspamdのログのメッセージより)

初期学習必要数の200があまりにも多いということであれば /usr/local/etc/rspamd/local.d/classifier-bayes.conf に min_learns = 30; などと学習数を指定するようだが効果は未確認。

迷惑メールを1ファイルだけ学習させる。
$ /usr/local/bin/rspamc -c bayes learn_spam /hoge-path/spam-mail.eml
/hoge-path/というディレクトリ(フォルダ)に溜めているメールファイル(複数)を学習させる。
$ /usr/local/bin/rspamc -c bayes learn_spam /hoge-path/
非迷惑メールを1ファイルだけ学習させる。
$ /usr/local/bin/rspamc -c bayes learn_ham /hoge-path/ham-mail.eml
/hoge-path/というディレクトリ(フォルダ)に溜めているメールファイル(複数)を学習させる。
$ /usr/local/bin/rspamc -c bayes learn_ham  /hoge-path/

迷惑メールは消しちゃってるから学習させる検体持ってないよという場合はSPAM Archiveさんあたりから貰ってくる。ここは古いのから新しいのまで膨大にある(数十万通/月)ので量的には困らない筈。直近3,4ヶ月分程度を学習させれば十分すぎるかと。凄い時間かかるけど。
非迷惑メールは過去に受信して保存している自分のメールを全部学習させれば良い筈。
ちなみに150万通ほど学習させてbayes.spam.sqliteとlearn_cache.sqliteのファイルサイズの合計は400MB程度と以外と小さい。

この記事はRspamd 1.6.1でやってるので違うバージョンで正常に動くとは限らない。
Rspamdは発展途上ということもあってかバージョンによって設定がコロコロ変わるので念の為。

関連記事:
Up