【ハンズオン】AWS上にAsterisk13をインストールして電話してみる

# はじめに

[Asterisk](https://www.asterisk.org/)とはオープンソースのIP-PBXです。
SIPサーバとも言いますが、要は一般的な電話の機能を提供するソフトウェアです。

2012年からAndroidアプリの[相談電話](https://play.google.com/store/apps/details?id=foo.bar.soudan)というサービスを個人で運営しています。
これはAWS上にサーバ構築しているのですが、

- CentOS 5.4
- Asteirsk 1.8.5

で動いていてとても古いのです。

きっかけは「[【未解決問題】AWSのEC2インスタンスをt1.microからt2.microにしたい話](https://qiita.com/hamham/items/307adcd4841f5f39c226)」に書いたとおり、インスタンスタイプを小さくしてコスト削減をしたいだけなのですが、うまくいかずいっそ作り直してしまおうという結論になりました。

ということで再構築の第一歩としてAWS上にインスタンスを立て、AsteriskをインストールしてスマホのSIPクライアントから通話できるまでをまとめたいと思います。

# プラットフォームの選定

まずOSですが、CentOSから移行するにあたり同じRHEL系でAWSに最適なものにしたいということで

- Amazon Linux 2 AMI (HVM)

を選定しました。
もともとコスト削減が目的ということで、インスタンスタイプは最小のt2.nanoにします

Asteriskは1.8系を使い続けてもよかったのですが、どうせなら新しいバージョンを使おうと考えました。
[VoIp-Info.jpのAsteriskのページ](https://voip-info.jp/index.php/Asterisk#.E5.90.84.E3.83.90.E3.83.BC.E3.82.B8.E3.83.A7.E3.83.B3.E3.81.AE.E6.83.85.E5.A0.B1)を見ると、

> 現在(2018年6月)ならばAsterisk 13がお勧めです。

ということで

- Asterisk 13.x

を選定しました。

# AWS側の設定
## インスタンスの起動

Amazon LinuxのAMIを選択してセットアップを進めます。


## セキュリティグループの設定

セキュリティグループはこんな感じに設定します。

![SG.JPG](https://qiita-image-store.s3.amazonaws.com/0/272753/3993671d-f96e-d7f7-0d10-2701741360d0.jpeg)


厳密には空けなくてもよいポートもあるかもしれません。
インターネット経由で不特定多数の端末から通信させるのでソースIP制限はしません。
**SSHはIPで絞れるようなら絞っておきましょう！**

## ソース/宛先チェックの無効化
忘れがちなポイントなのですが、AWSではソース/宛先チェックがデフォルト有効になっています。
**SIPサーバはNATのように宛先を中継する動きをするので無効化しなければなりません。**
EC2のマネージメントコンソールから設定します。

![SourceDestCheck.JPG](https://qiita-image-store.s3.amazonaws.com/0/272753/2439e4d1-f869-7d81-6381-3f14f0da13fd.jpeg)


## ElasticIPの取得と関連付け
固定のグローバルIPを割り振りたかったのでElasticIPを取得して起動したインスタンスに紐付けます。
ちなみに、ElasticIPはインスタンスに割り当てて使う分には無料です。
**割り当てずに放っておいたり、割り当てたインスタンスが停止している場合はお金がかかります。**
東京リージョンで1時間あたり＄0.005なので、1日だと＄0.12、1ヶ月＄3.6（＝約400円）になります。

# Asteriskの導入
## SSH接続
起動したインスタンスにSSHで接続します。
Amazon Linuxなので"ec2-user"でログインした後、「sudo su」で"root"ユーザーになって作業します。

## Asteriskインストールの前準備

以下のパッケージをインストールしておきます。

```shell-session
# yum -y update 
# yum -y groupinstall 'Development Tools'
# yum -y install ncurses-devel
# yum -y install libuuid-devel
# yum -y install sqlite-devel
# yum -y install libxml2-devel
```
## Asterisk13のダウンロード
Asteriskをwgetでダウンロードします。

```shell-session
# cd /usr/src
# wget http://downloads.asterisk.org/pub/telephony/asterisk/asterisk-13-current.tar.gz
# tar xvfz asterisk-13-current.tar.gz
```

これで13系の最新バージョンをとってきます。
tarを解凍すると私の場合は「asterisk-13.22.0」のディレクトリが展開されました。
**タイミングによってマイナーバージョンは異なる**ので以後のディレクトリは環境によって読み替えてください。

## さらに前準備

Asterisk13系ではビルドで必要なパッケージを自動でとってくるスクリプトが用意されてます。
（それでも結局configureでエラーが出て個別にパッケージいれる必要が出てきたりするのですが・・）

```shell-session
# cd /usr/src/asterisk-13.22.0/contrib/scripts/
# ./install_prereq install
# ./install_prereq install-unpackaged
```

これで準備が整いました。

## configureする

configureします。

```shell-session
# cd /usr/src/asterisk-13.22.0/
# ./configure
```

以下のようなアスキーアートがでれば成功です。

```shell-session
configure: Menuselect build configuration successfully completed

               .$$$$$$$$$$$$$$$=..      
            .$7$7..          .7$$7:.    
          .$$:.                 ,$7.7   
        .$7.     7$$$$           .$$77  
     ..$$.       $$$$$            .$$$7 
    ..7$   .?.   $$$$$   .?.       7$$$.
   $.$.   .$$$7. $$$$7 .7$$$.      .$$$.
 .777.   .$$$$$$77$$$77$$$$$7.      $$$,
 $$$~      .7$$$$$$$$$$$$$7.       .$$$.
.$$7          .7$$$$$$$7:          ?$$$.
$$$          ?7$$$$$$$$$$I        .$$$7 
$$$       .7$$$$$$$$$$$$$$$$      :$$$. 
$$$       $$$$$$7$$$$$$$$$$$$    .$$$.  
$$$        $$$   7$$$7  .$$$    .$$$.   
$$$$             $$$$7         .$$$.    
7$$$7            7$$$$        7$$$      
 $$$$$                        $$$       
  $$$$7.                       $$  (TM)     
   $$$$$$$.           .7$$$$$$  $$      
     $$$$$$$$$$$$7$$$$$$$$$.$$$$$$      
       $$$$$$$$$$$$$$$$.                
```

###ちなみに

configureでエラーが出る場合はパッケージが足りてない場合が多いです。
内容をググって必要なパッケージを入れましょう
**よくあるエラーは[AsteriskドキュメントのCommon Issues](http://www.asteriskdocs.org/en/3rd_Edition/asterisk-book-html-chunk/Installing_id294543.html)にまとまってます。**
Amazon Linuxであれば上記リンクのCentOSを例にやれば大丈夫でしょう。

## makeする
準備が整ったのでビルドします。結構時間かかります。

```shell-session
# make
```
以下のメッセージが出れば成功です

```shell-session
 +--------- Asterisk Build Complete ---------+
 + Asterisk has successfully been built, and +
 + can be installed by running:              +
 +                                           +
 +                make install               +
 +-------------------------------------------+
```

## make installする

インストールします。

```shell-session
# make install
```
以下のメッセージが出れば成功です

```shell-session
 +---- Asterisk Installation Complete -------+
 +                                           +
 +    YOU MUST READ THE SECURITY DOCUMENT    +
 +                                           +
 + Asterisk has successfully been installed. +
 + If you would like to install the sample   +
 + configuration files (overwriting any      +
 + existing config files), run:              +
 +                                           +
 + For generic reference documentation:      +
 +    make samples                           +
 +                                           +
 + For a sample basic PBX:                   +
 +    make basic-pbx                         +
 +                                           +
 +                                           +
 +-----------------  or ---------------------+
 +                                           +
 + You can go ahead and install the asterisk +
 + program documentation now or later run:   +
 +                                           +
 +               make progdocs               +
 +                                           +
 + **Note** This requires that you have      +
 + doxygen installed on your local system    +
 +-------------------------------------------+
```

## 起動設定

設定ファイルの設定と自動起動スクリプトの生成をします。
**EC2だとこのtouchが必要**です。やらないとmake configが失敗します。

```shell-session
# make samples
# touch /etc/redhat-release
# make config
```
## 起動・停止の確認
ここまでできたらAsteriskが起動できることと停止できることを確認します。

```shell-session
# /etc/init.d/asterisk start
Starting asterisk (via systemctl):                         [  OK  ]

# /etc/init.d/asterisk stop
Stopping asterisk (via systemctl):                         [  OK  ]

```

# Asteriskの初期設定

Asteriskの設定で**特に重要なものはsip.confとextensions.confの2つ**です。
この2つを設定してあげる必要があります。

- sip.conf
   - SIPサーバとしての設定を記載する
   - 電話番号ごとの設定（内線番号、ログインパスワードなど）もここに記載する
- extensions.conf
   - 電話番号ごとの振る舞いを記載する。（電話を鳴らすとか、留守電に転送するとか）

## 元のファイルの退避

まずは2つのファイルをコピーして退避しておきましょう

```shell-session

# cd /etc/asterisk/
# cp -p sip.conf sip.conf.bak
# cp -p extensions.conf extensions.conf.bak

```

## sip.confの設定
内線番号3001と3002を使うことを例にサンプルを記載します。
1.8系の設定ファイルをベースにしているので要らない設定もあるかもしれませんが、とりあえずバージョン13でも動くことは確認しました。

``` ini:sip.conf
[general]
maxexpirey=3600
defaultexpirey=3600
context=default
port=5060
bindaddr=0.0.0.0
srvlookup=yes
allowguest=no
disallow=all
allow=ulaw
allow=alaw
allow=gsm
language=ja
nat=yes
externip=xxx.xxx.xxx.xxx　　/ElasticIPで取得したグローバルIPを記載
localnet=172.xxx.xxx.xxx/255.255.255.0　　/VPCのローカルサブネット範囲を記載

[3001]
type=friend
defaultuser=3001
secret=xxxxxxxx　　/パスワードを記載
canreinvite=no
host=dynamic
dtmfmode=rfc2833
context=default
qualify=yes
callgroup=1
pickupgroup=1
mailbox=3001

[3002]
type=friend
defaultuser=3002
secret=xxxxxxxx　　/パスワードを記載
canreinvite=no
host=dynamic
dtmfmode=rfc2833
context=default
qualify=yes
callgroup=1
pickupgroup=1
mailbox=3002
```

**重要なのは"nat=yes"としているところとグローバルIPを指定しているところ**です。
これを設定しないとうまく動きません。
内線番号側に指定するパスワードはSIPクライアントから接続するときに使います。


## extensions.confの設定
こちらは内線30XXについて電話できるように設定します。
defaultセクションにviなどで追記してください。

```ini:extensions.conf
[default]
; Local SIP phones 3000-3099
exten => _30XX,1,GotoIf($["${USEVOICEMAIL}"="YES"]?use-vm)
exten => _30XX,n,Dial(SIP/${EXTEN})
exten => _30XX,n,Hangup
exten => _30XX,n(use-vm),Dial(SIP/${EXTEN},30)
exten => _30XX,n,NoOp(${DIALSTATUS})
exten => _30XX,n,GotoIf($["${DIALSTATUS}"="BUSY"]?vm-rec)
exten => _30XX,n,GotoIf($["${DIALSTATUS}"="NOANSWER"]?vm-rec)
exten => _30XX,n,GotoIf($["${DIALSTATUS}"="CHANUNAVAIL"]?vm-rec)
exten => _30XX,n,Hangup
exten => _30XX,n(vm-rec),Answer()
exten => _30XX,n,Wait(1)
exten => _30XX,n,Voicemail(${EXTEN})
exten => _30XX,n,Hangup
```

## ログ出力レベルを下げる

デフォルトの設定のままだと、/var/log/asterisk/messagesにログを吐きまくってディスク容量を食いつぶしてしまいます。
**/etc/asterisk/logger.conf**の該当箇所を修正することで抑止できます。
デフォルトはnotice、warning、errorの3種類を出力しますが、notice、warningは削ってもよいと思います。

```ini:logger.conf
[logfiles]
messages => notice,warning,error
```

## Asteriskを起動

sip.confとextensions.confを再読込するために起動しましょう。

```shell-session
# /etc/init.d/asterisk start
Starting asterisk (via systemctl):                         [  OK  ]
```

##Asterisk CLIに入る

以下のコマンドでCLIに入れます。

```shell-session
# asterisk -vvvr
Asterisk 13.22.0, Copyright (C) 1999 - 2014, 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.
=========================================================================
Connected to Asterisk 13.22.0 currently running on ip-172-xxx-xxx-xxx (pid = xxxxx)
ip-172-xxx-xxx-xxx*CLI>

```
ちなみにオプションの「ｖ」の数によってデバッグレベルが変わります。
「-r」だとデバッグなし、「-vvvvvr」だと最大のデバッグレベルです。

この状態でコンソールを起動すると、SIPクライアント側でレジストや発信／着信が行われた場合に画面に表示されますのでデバッグでも使えます。


# SIPクライアントから通話してみる

## SIPクライアントの選定
SIPクライアントは、Windows、Mac、Linux、iOS、Androidなどあらゆるプラットフォームで出てます。
メジャーどころで私が使ったことのあるものだと以下があります

- Zoiper
- Linphone
- CSipSimple
- Sipdroid
- X-Lite

私としてはZoiperがオススメです。

また、電話のテストをするには2台必要です（自動応答だけなら1台でもいいですが）
上記のSIPクライアントどれかインストールしてみてください

## SIPクライアントの設定
SIPクライアントによって設定項目の名前は異なりますが、以下の3つを入力すればよいです。

- username（内線番号）
   - 3001、3002
- password
   - sip.confで設定した内線番号ごとのパスワード
- Domain、Host
   - サーバに付与されているグローバルIPアドレス

うまくいけばログインが成功している旨が出るはずです。
Asterisk CLIにもメッセージが出ていると思います。
ダメならCLIのメッセージを見てみましょう。
**メッセージが表示されないならネットワーク的に到達できていない**と思われます。

### Zoiperの設定例

AndroidのZoiperでやった場合の設定例です。
隠してあるところにはElasticIPを入れましょう。

![zoiper01.jpg](https://qiita-image-store.s3.amazonaws.com/0/272753/a79b0bcc-935c-4083-64f3-8b7bcea399a3.jpeg)

![zoiper02.jpg](https://qiita-image-store.s3.amazonaws.com/0/272753/022d061c-af9e-f0db-c51c-e8000fc4c520.jpeg)

outbound proxyの設定はスキップでよいです。
![zoiper03.jpg](https://qiita-image-store.s3.amazonaws.com/0/272753/9940a566-98df-fb17-9c8b-9feaf8a3e249.jpeg)

![zoiper04.jpg](https://qiita-image-store.s3.amazonaws.com/0/272753/71fe17a2-9eb4-2bf6-f1b8-c5d7fedab789.jpeg)

「Account is ready」となっているのが成功している証拠です。
![zoiper05.jpg](https://qiita-image-store.s3.amazonaws.com/0/272753/bcf630ee-7b52-5624-684d-d4da28cd9def.jpeg)



## 電話をかけてみる
3001から3002に電話をかけてみましょう。
うまくいけばリンギングして、電話をとれば音声通話ができるはずです。
ダメならメッセージを見てみましょう。
ちなみに、**うまくいかない場合はSIPクライアントを変えてみる**のも手です。
経験上SIPクライアントは相性問題があり、サーバの設定は問題なくてもSIPクライアントによって使えない場合があります。
※ はじめはZoiperでなくLinphoneでやってたのですが、Android版のLinphoneでは着信できるけど発信できないという事象に遭遇しました。

# 最後に
ということで5年ぶりくらいにAsteriskを触りました。
最新バージョンにしたものの使いこなしてないので違いはよくわからず。
やっぱりサーバ構築して電話がつながったときは結構嬉しいです。

[相談電話](https://play.google.com/store/apps/details?id=foo.bar.soudan)のサーバ移行計画としては、始めの5%くらいができた感じでしょうか。
引き続き作業して記事にしていこうと思います。

続きはこちら

- [【ハンズオン】Amazon Linux2にApache、PHP、MySQLをインストールする](https://qiita.com/hamham/items/fd77bb0bb167a150dc8e)

## 参考にしたサイト
- [AWS上にAsteriskサーバ構築して内線電話環境つくってみよう](https://qiita.com/ganezasan/items/05b16a2254f066f6bbdc)
- [Asterisk13インストール to Debian Jessie （その1）](https://www.lonnie.co.jp/voip/asterisk13-1/)
- [Asterisk１３のインストール](http://www.spanky-world.com/asterisk/asterisk-page040.html)
- [[Asterik] configure: WARNING: *** Please install the SQLite3 development package. on Asterik](http://matrixsust.blogspot.com/2014/03/asterik-configure-warning-please.html)
- [SIPクライアント（AndroidのIP電話アプリ）の比較](http://blog.jikoman.jp/2015/08/sip-client.html)