Origami Devices

たまに変なもの作ります。あと、Raspberry Pi を長期運用したいと思います。

Raspberry Pi と Asterisk + iaxmodem + hylafax と Fusion IP-Phone Smart で作る FAX サーバ(1)

おことわり

本項は適宜修正しております。修正箇所には出来る限り脚注等を入れております。

はじめに

Raspbian(というか Debian)って、 aptitude install asterisk iaxmodem hylafax-server hylafax-client で全部インストールできちゃうんですね。というわけでやってみました。

Fusion IP-Phone Smart (以下 FIPS と略すことがあります) を使うので、維持費は0円、あと受信も0円です。

前提条件

  • Fusion IP-Phone Smart の契約をするため、クレジットカードが必要です。ちなみにクレジットカード1枚で1アカウントのようです(追加で500円払って別途手続すれば一応複数持てるらしいが…) あと、契約は事前に済ませておくことをお勧めします。 050電話番号、SIPアカウント、SIPアカウントパスワードが必要です。
  • /usr/sbin/sendmail からメールを送信可能にしておいてください。実はここちょっと面倒です。Raspberry Pi が置いてある場所が自宅内の場合、契約しているプロバイダが OP25B を実施していると思われますので、 25/tcp でメールを直接外に送れません。Raspberry Pi で動いている MTA(postfix, exim)が、プロバイダのメールサーバへ relayhost できる状態にしておく必要があります。
  • ご自宅のブロードバンドルーターのポートフォワードの設定で、 5060/tcp, 5060/udp, 50600/udp~50900/udp が外から Raspberry Pi に届く状態にしておいてください。でないと着信できません。また、このとき iptables で FIPSの SIP サーバ、61.213.230.153 からのみ接続可能な状態にしておきましょう。(参考: Raspberry Pi と iptables (2) - Raspberry Pi を何年か使い続けるブログ
  • どこかの DDNS に登録し(無料のもので構いません)、使用可能な状態にしておいてください。これも着信に必要です。 必要ありませんでした。DDNS 等がなくても着信まで可能でした。失礼しました。

インストール

基本的には

# sudo aptitude install asterisk iaxmodem hylafax-server hylafax-client

だけでいいはずです。依存するパッケージもここで入るようです。他の方の記事とかを見る限りではみなさん自分でビルドされている(最新版使いたかったらそうならざるを得ませんね)ようですが、この項はインストールだけは aptitude に依存します。

なお、以後は全て sudo su - root した状態で作業しています。

Asterisk 本体の設定

念のため、編集する設定ファイルは作業前にバックアップをとっておくことをお勧めします。

ここは、 languageprefix, runuser, rungroup のコメントアウトを外すだけです。

# diff asterisk.conf asterisk.conf.original
29c29
< languageprefix = yes          ; Use the new sound prefix path syntax.
---
> ;languageprefix = yes         ; Use the new sound prefix path syntax.
60,61c60,61
< runuser = asterisk            ; The user to run as.
< rungroup = asterisk           ; The group to run as.
---
> ;runuser = asterisk           ; The user to run as.
> ;rungroup = asterisk          ; The group to run as.

sip.conf はこれだけ書いておけばいいです。既にあるほうの sip.conf は、書き換える前に cp -p sip.conf sip.conf.original なりしてとっておいてください。

[general]
context=default
allowoverlap=no
udpbindaddr=0.0.0.0
tcpenable=no
tcpbindaddr=0.0.0.0   
transport=udp
srvlookup=yes
allowguest=no
localnet=192.168.0.XXX/255.255.255.0
register => 12345678:abcdefgh@smart.0038.net
qualify=yes
[fusion-smart]
type=friend
username=12345678
fromuser=12345678
secret=abcdefgh
host=smart.0038.net
fromdomain=smart.0038.net
context=default
insecure=port,invite
canreinvite=no
disallow=all
allow=ulaw
allow=alaw
dtmfmode=inband
nat=yes
faxdetect=yes
  • localnet

Raspberry Pi の自分の IP アドレス(LAN内)を書いておいてください。

  • register

「12345678」は FIPS の SIPアカウント、「abcdefgh」は SIP アカウントパスワードを記入してください。

  • username, fromuser

FIPS の SIP アカウントを記入してください。(register で書いたものと同じ)

  • secret

FIPS の SIP アカウントパスワードを記入してください。(register で書いたものと同じ)

  • nat

「yes」にしてください。

  • faxdetect

「yes」にしてください。

  • externhost

不要です。

ここまでやれば、FIPS へのレジストまではうまくいくと思います。 asterisk のコンソールを起動してみましょう。

# asterisk -vvvvr
Asterisk 1.8.13.1~dfsg1-3+deb7u3, Copyright (C) 1999 - 2012 Digium, Inc. and others.
Created by Mark Spencer <markster@digium.com>
Asterisk comes with ABSOLUTELY NO WARRANTY; type 'core show warranty' for details.
This is free software, with components licensed under the GNU General Public
License version 2 and other licenses; you are welcome to redistribute it under
certain conditions. Type 'core show license' for details.
=========================================================================
  == Parsing '/etc/asterisk/asterisk.conf':   == Found
Running as group 'asterisk'
  == Parsing '/etc/asterisk/extconfig.conf':   == Found
Connected to Asterisk 1.8.13.1~dfsg1-3+deb7u3 currently running on rpi120 (pid = 1973)
Verbosity is at least 4
rpi120*CLI> sip show peers
Name/username              Host                                    Dyn Forcerport ACL Port     Status
fusion-smart/12345678      61.213.230.153                               N             5060     OK (6 ms)
1 sip peers [Monitored: 1 online, 0 offline Unmonitored: 0 online, 0 offline]

sip show peers の結果がこんな感じになっていれば、Asterisk が正常に起動しており、なおかつ FIPS への接続も出来ていることになります。ただし、ここまでの設定ではまだ extensions.conf の設定もしていないので、FAX が応答するところまでは行きません。

もしこの状態で FIPS の電話番号に掛けてみたら?

  == Using SIP RTP CoS mark 5
[Dec 23 11:37:24] NOTICE[2081]: chan_sip.c:22753 handle_request_invite: Call from '12345678' (61.213.230.153:5060) to extension '12345678' rejected because extension not found in context 'default'.

「ただいま電話に出ることが出来ません」とのアナウンスが流れ、なおかつ Asterisk のコンソールに上記のようなメッセージが出たら、「着信には成功した」ということです。(着信はしたけど extension の設定がなされていないので FAX が起動していないだけ)

extension の設定は、iaxmodem と hylafax 側の設定が終わったらやります。

iaxmodem の設定

地味にめんどくさいです。慎重にやりましょう。

/etc/init.d/iaxmodem

aptitude でインストールする iaxmodem の起動スクリプトは、実はそのままでは動きません。実際に使ってみたところ、「起動は出来るけど停止できない(iaxmodem は自力でPIDファイルを作れないのに、起動スクリプト内に --make-pidfile が指定されてない)」「そもそもモデムデバイス名(ttyIAX)を指定するところがない」とか散々でした。これ使ってる人ほんとにいるの?

というわけで、やっつけで直しました。*1

#! /bin/sh
#
### BEGIN INIT INFO
# Provides:          iaxmodem
# Required-Start:    $syslog $local_fs $network
# Required-Stop:     $syslog $local_fs $network
# Should-Start:      asterisk
# Should-Stop:       asterisk
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Software modem with IAX2 connectivity
# Description:       Use this software modem with Asterisk or another
#                    IPBX with IAX2 connectivity to send and receive
#                    faxes over VoIP.
### END INIT INFO

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/bin/iaxmodem
DAEMON_OPTS=ttyIAX
NAME=iaxmodem
DESC=iaxmodem

test -x $DAEMON || exit 0

set -e

case "$1" in
  start)
        echo -n "Starting $DESC: "
        start-stop-daemon --start --quiet --background --make-pidfile --pidfile /var/run/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS
        echo "$NAME."
        ;;
  stop)
        echo -n "Stopping $DESC: "
        start-stop-daemon --stop --quiet --oknodo --pidfile /var/run/$NAME.pid \
                --exec $DAEMON -- $DAEMON_OPTS
        echo "$NAME."
        ;;
  restart)
        echo -n "Stopping $DESC: "
        start-stop-daemon --stop --quiet --oknodo --pidfile /var/run/$NAME.pid \
                --exec $DAEMON -- $DAEMON_OPTS
        echo "$NAME."
        sleep 1
        echo -n "Starting $DESC: "
        start-stop-daemon --start --quiet --background --make-pidfile --pidfile /var/run/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS
        echo "$NAME."
        ;;
  status)
        if [ -s /var/run/$NAME.pid ]; then
            RUNNING=$(cat /var/run/$NAME.pid)
            if [ -d /proc/$RUNNING ]; then
                if [ $(readlink /proc/$RUNNING/exe) = $DAEMON ]; then
                    echo "$NAME is running."
                    exit 0
                fi
            fi

            # No such PID, or executables don't match
            echo "$NAME is not running, but pidfile existed."
            rm /var/run/$NAME.pid
            exit 1
        else
            rm -f /var/run/$NAME.pid
            echo "$NAME not running."
            exit 1
        fi
        ;;
  *)
        N=/etc/init.d/$NAME
        echo "Usage: $N {start|stop|restart|status}" >&2
        exit 1
        ;;
esac

exit 0

/etc/asterisk/iax.conf

基本的にはこの通りに書いちゃって大丈夫です。bandwidth, jitterbuffer あたりは、FIPS だといじくってもあんまり変わらない雰囲気でした。disallow/allow は使うコーデックの設定です。FIPS では G.722 も使えるのですが、自分の手許で実際に使ってみたらかえって破滅的に FAX の転送がだめになった(6割近くがエラーになった)ので、ここでは設定していません。

[general]
bindport=4569
iaxcompat=yes
language=ja
bandwidth=medium
disallow=all
allow=ulaw
allow=alaw
allow=gsm
jitterbuffer=no
;dropcount=2
;maxjitterbuffer=500
;maxexcessbuffer=80
;minexcessbuffer=10
;jittershrinkrate=1
;tos=lowdelay
;mailboxdetail=yes

[iaxmodem]
type=friend
username=iaxmodem
secret=password
host=dynamic
disallow=all
allow=ulaw
allow=alaw
allow=gsm
requirecalltoken=no
context=fax-out

/etc/iaxmodem/ttyIAX

iax.conf の username と secret は、ここの peername と secret と合わせてある必要があります。

device          /dev/ttyIAX
owner           uucp:uucp
mode            660
port            4570
refresh         300
server          127.0.0.1
peername        iaxmodem
secret          password
cidname         John Doe
cidnumber       8005551212
codec           slinear

ここまで設定したら、 /etc/init.d/iaxmodem restart で、iaxmodem が正常に起動・終了するか試してください。

# /etc/init.d/iaxmodem restart
Stopping iaxmodem: iaxmodem.
Starting iaxmodem: iaxmodem.
# ps -ef | grep iaxmodem
uucp      2058     1  0 16:25 ?        00:02:08 /usr/bin/iaxmodem ttyIAX

owner が uucp のプロセスがひとつ、このプロセスイメージ名で起動していればOKです。*2

Hylafax の設定

ここでちょっと注意点。/etc/init.d/hylafax を読む限りでは、 /etc/hylafax 内の設定ファイルは Hylafax の起動時に /var/spool/hylafax/etc にまるごとコピーされます。設定を変更する場合は、 /etc/hylafax 側を編集しましょう。

faxsetup

faxsetup を実行します。faxsetup コマンドは、まず(起動時と同じように) /etc/hylafax の設定ファイルを /var/spool/hylafax/etc にコピーします。

# /usr/sbin/faxsetup

続いて、対話形式で hylafax の設定を行います。既定値と異なる入力をするのは以下の項目です。他は既定値のままでよいです。

No scheduler config file exists, creating one from scratch.
Country code [1]? 81
Area code []? 50
Long distance dialing prefix [1]? 0
International dialing prefix [011]? 001

Do you want to run faxaddmodem to configure a modem [yes]? no

/etc/hylafax/config.ttyIAX

/etc/hylafax の中にいない場合は、新規で作成します。

CountryCode:            81
AreaCode:               50
FAXNumber:              +81.50.XXXX.XXXX
LongDistancePrefix:     0
InternationalPrefix:    001
DialStringRules:        etc/dialrules
ServerTracing:          0xFFF
SessionTracing:         0xFFF
RecvFileMode:           0600
LogFileMode:            0600
DeviceMode:             0600
RingsBeforeAnswer:      1
SpeakerVolume:          off
GettyArgs:              "-h %l dx_%s"
LocalIdentifier:        "050.XXXX.XXXX"
TagLineFont:            etc/lutRS18.pcf
TagLineFormat:          "From %%l|%c|Page %%P of %%T"
MaxRecvPages:           200
#
#
#
#
# Modem-related stuff: should reflect modem command interface
# and hardware connection/cabling (e.g. flow control).
#
ModemType:              Class1          # use this to supply a hint

#
# Enabling this will use the hfaxd-protocol to set Caller*ID
#
#ModemSetOriginCmd:     AT+VSID="%s","%d"

#
# If "glare" during initialization becomes a problem then take
# the modem off-hook during initialization, and then place it
# back on-hook when done.
#
#ModemResetCmds:        "ATH1\nAT+VCID=1"       # enables CallID display
#ModemReadyCmds:        ATH0

Class1AdaptRecvCmd:     AT+FAR=1
Class1TMConnectDelay:   400             # counteract quick CONNECT response

#
# If you have trouble with V.17 receiving or sending,
# you may want to enable one of these, respectively.
#
Class1RMQueryCmd:      "!24,48,72,96"  # enable this to disable V.17 receiving
Class1TMQueryCmd:      "!24,48,72,96"  # enable this to disable V.17 sending

#
# You'll likely want Caller*ID display (also displays DID) enabled.
#
ModemResetCmds:         AT+VCID=1       # enables CallID display

#
# The pty does not support changing parity.
#
PagerTTYParity:         none

#
# If you are "missing" Caller*ID data on some calls (but not all)
# and if you do not have adequate glare protection you may want to
# not answer based on RINGs, but rather enable the CallIDAnswerLength
# for NDID, disable AT+VCID=1 and do this:
#
#RingsBeforeAnswer: 0
#ModemRingResponse: AT+VRID=1

# Uncomment DATE and TIME if you really want them, but you probably don't.
#CallIDPattern:          "DATE="
#CallIDPattern:          "TIME="
CallIDPattern:          "NMBR="
CallIDPattern:          "NAME="
CallIDPattern:          "ANID="
#CallIDPattern:          "USER="        # username provided by call
#CallIDPattern:          "PASS="        # password provided by call
#CallIDPattern:          "CDID="        # DID context in call
CallIDPattern:          "NDID="
#CallIDAnswerLength:    4

変更の必要があるのは、CountryCode、AreaCode、FAXNumber、LocalIdentifier、TagLineFormat です。LongDistancePrefix と InternationalPrefix は…これは変えても変えなくてもいいかもしれないです。

CountryCode は 81 固定です。 AreaCode は FIPS なら 50 です。(市外局番の先頭1文字をとったものが入ります)

FAXNumber はこのフォーマットで自分の FIPS の番号を書いてください。LocalIdentifier に書いたものは、送信する FAX のヘッダに書かれます。送信を意識する場合はここを変えておいてください。TagLineFormat はその送信ヘッダのフォーマットです。

( /etc/hylafax/config の内容で上記とかぶる箇所があったら、同じように編集しておいてください)

/etc/hylafax/sendfax.conf

送信時のリトライ回数を定めます。

MaxTries: 2
MaxDials: 2

基本的には 2 か 3 でいいです。MaxTries と MaxDials は同じ数字にしておいたほうがいいかもしれません。 以下は hylafax の中の人のコメント。

Both MaxTries and MaxDials can be set in your faxq config file
(/var/spool/hylafax/etc/config).

Note, however, that these settings are only used in cases where the
client did not set them. So if you have MaxTries: 3 in your config file
but the client uses MaxTries: 12, then the latter takes precedence.

Lee.

Server-wide MaxTries / MaxDials configuration

ここまで来たら、一度 hylafax の再起動をします。

# /etc/init.d/hylafax restart

正常に再起動したら、次へ進みます。

/etc/hylafax/hfaxd.conf

2か所編集します。まず JobFmt。faxstat コマンド実行時の出力フォーマットをここで決めます。(これの変更は、 hylafax を再起動しなくても faxstat の出力に反映されます)

#JobFmt:                "%-3j %3i %1a %6.6o %-12.12e %5P %5D %7z %.25s"
JobFmt:                 "%-5j %1a %-12.12e %5P %5D %Y %.27s"

JobFmt を "%-5j %1a %-27.27e %5P %5D %10Z %.25s" とする人がどうにも多いのですが、 %Z って UNIXTIME なので読みづらくてしょうがないので、 %Y にします。あと、%e は相手の CallID(電話番号)ですが、27桁もいらないので %-12.12e にしました。ちなみに、JobFmt をどのように設定しようと faxstat コマンドの出力はジョブナンバーごとにソートされないらしく、何か手はないかを探したのですが、結局のところ faxstat -d | sort -n でやったほうが早いみたいです。 *3

次に TimeZone。これは一行追加してください。同じく faxstat コマンド出力時のタイムゾーンを決めます。( GMT か local かの二択っぽいですが…)

TimeZone:               local

ほかはいじらなくても動きます。

Asterisk の着信設定(extensions.conf)

/etc/asterisk/extensions.conf

[globals]
USEVOICEMAIL=YES
SPEAKINGCLOCK=317
ECHOTEST=333
MYNUMBER=05012345678

[default]
exten => 12345678,1,Dial(IAX2/iaxmodem)
exten => 12345678,n,Hangup

まず、 [globals] セクションの MYNUMBER を自分の FIPS の 050 番号に書き直してください。

次に [default] セクションはこの2行を書きます。(12345678 の部分は、自分の SIP アカウントに書き直してください)

[fax-out]
exten => _X.,1,Set(CALLERID(num)=${MYNUMBER})
exten => _X.,n,Set(CALLERID(name)=${MYNUMBER})
exten => _0.,n,Dial(SIP/${EXTEN}@fusion-smart,300,T)
exten => _X.,n,Hangup

最後に、この [fax-out] セクションを extensions.conf の末尾に加えてください。

/etc/hylafax/FaxDispatch

受信した FAX をメールで転送する設定です。基本的にはこの3行が書いてあれば事足りると思います。

SENDTO=aaaa@example.co.jp
FROMADDR=faxserver@example.co.jp
FILETYPE=pdf;

他にも設定可能な項目はあるみたいですが、あんまり使いそうにないですね。(faxrcvd の変数がそのまま使えるみたいです)

http://www.hylafax.org/man/6.0.3/faxrcvd.1m.html

extensions.conf を書き換えたので、ここで /etc/init.d/asterisk reload しておいてください。

ここまでで、あらかたの設定は完了です。次回は受信の動作確認と、必要に応じての送信設定をします。

*1:start の時に既に起動しているかのチェックをしていないので、restart と stop だけでいいかもしれません…

*2:複数起動しているとまともに動作しないと思います

*3:2014.12.26 JobFmtを再修正