Asteriskについて 調査内容まとめ


Asteriskについて調査したのでメモ。
※編集中

### Asteriskについて
- DigiumのMark Spencerによって始められたオープンソースのPBX
- 多くのLinuxディストリビューション上で動作する

- **対応するプロトコル**
    - IP系
        - SIP
        - H.323
        - UNISTIM
        - IAX(Inter Asterisk eXchange)
        - MGCP
        - Skinny(Cisco)
    - レガシー系
        - BRI/PRI(ISDNボード必要)
        - アナログ(アナログボード必要)
        - ゲートウェイを使用することでSIP-アナログ、SIP-ISDNも接続可能

- **前提となるパッケージ類(バージョン16の場合)**
    - GCC
    - G++(GNU-C++)
    - OpenSSL
    - Ncurses
    - bison
    - カーネルソース(DAHDIを使う場合)
    - libxml2
    - SQLite3
    - libuuid-devel
    - uuid-devel
    - json-c
    - json-c-devel

- 設定手順は下記を参照
Asterisk 16 - VoIP-Info.jp https://voip-info.jp/index.php/Asterisk_16

### Asterisk 設定ファイル
- Asteriskは様々な設定ファイルで構成され、
それぞれの設定によりAsteriskの動作をコントロールすることができる
- Asteriskの設定ファイルは、通常「/etc/asterisk」ディレクトリの配下にある

#### 特に重要なファイル
- **sip.conf (pjsip.conf)**
    - SIPアカウントやネットワークの設定を記述する。
    - 将来的にSIPチャネルはPjSipが標準となる模様

- **extensions.conf**
    - ダイヤルプランの設定を記述する。内線電話番号ごとの発着信時の振る舞いを設定できる。

---

### 設定ファイル 詳細

#### [sip.conf]
- 16以降でchan_sipをどうしても使いたい場合にはMACアドレス認証を使う

```
[general]
maxexpirey=3600
defaultexpirey=3600
context=default
bindport=5060
bindaddr=0.0.0.0
srvlookup=yes
disallow=all
allow=ulaw
allow=alaw
allow=gsm
language=ja
localnet=192.168.0.0/255.255.0.0

[201]
type=friend
defaultuser=201
secret=pass
canreinvite=no
host=dynamic

[202]
type=friend
defaultuser=202
secret=pass
canreinvite=no
host=dynamic

[203]
type=friend
defaultuser=203
secret=pass
canreinvite=no
host=dynamic
```
- **[general]セクション**
    - 「sip.conf」内全てで適用される項目
    - ここで設定した値は各ピアのデフォルト値として使用されるものもある

- **[201][202][203]セクション**
    - それぞれSIPアカウントを定義
    - [ ]内の数字は内線番号と捉えることができ、任意の文字列を指定できる

|[general]||
| :- |  :- | 
|**maxexpirey**|外部からのREGISTER要求に対し、許可する最大の(間隔)秒数を指定|
|**defaultexpirey**|デフォルトのREGISTER要求(入り、出ともに)間隔(秒数)を指定|
|**context**|デフォルトのコンテキストを指定。「extensions.conf」内で定義するコンテキストと関連付く。基本的に変更不要|
|**bindport（port）**|SIPでの通信に使用するポート番号を指定。デフォルトは5060。|
|**bindaddr**|SIPコネクションを受け入れるIPアドレスを指定。デフォルトは0.0.0.0（全てのアドレスを受け入れる）|
|**srvlookup**|DNSのSRVレコード検索の有無を指定。デフォルトはno（無効）。ただし、yes（有効）が推奨とされている。|
|**disallow**|非許容とするコーデックを指定。allだと全てのコーデックの使用を禁止する。通常、allowパラメータと同時に定義される。|
||特定のCODECを有効にするにはまずallで全て禁止にしてからallow|
|**allow**|許容するコーデックを指定。デフォルトはall。複数指定の場合には列挙|
|**language**|言語を指定。デフォルトは英語。|
|**localnet**|ローカルと解釈されるネットワークをアドレス/マスクの形で指定|

|[201] ||
| :- |  :- | 
|**type**|ユーザ（user）、ピア（peer）、フレンド（friend）のいずれかを指定。|
||　　user：着信専用|
||　　peer：発信専用|
||　　friend：発信・着信の双方が可能。通常はfriendを指定する。|
|**defaultuser**|認証で使用するユーザ名を指定。|
|**secret**|認証で使用するパスワードを指定。|
|**canreinvite**|Asteriskが音声ストリーム（RTPパケット）を中継するかどうかを指定。|
||　　yes：中継をせず、エンドポイント間で音声ストリームを送受信する。|
||　　no：中継する。|
|**host**|内線番号に対するIPアドレス（or ホスト名）を指定。dynamicを指定すると任意となる。
||DHCP割り当てなどでIPアドレスが固定されない場合があるため、通常はdynamicを指定する。|


---

#### [pjsip.conf]
- pjsipでは同一のユーザ名/パスワードで複数のUA(SIPクライアント)がRegisterできる
- Asterisk 16からPjSIPはデフォルトでbundled扱いでダウンロード/コンパイルが行われる
- パラメータは下記を参考に記載
    - https://voip-info.jp/index.php/Asterisk_pjsip_parameters

**transport= について**

- いくつかのセクションで transport= を指定できるが、これが省略された場合には
「最初のtype=transportで指定された」トランスポートが使用される

```
[transport-udp]
type = transport
protocol = udp
bind = 0.0.0.0:5070

[hikari-hgw]
type = registration
transport = transport-udp
outbound_auth = hikari-hgw
server_uri = sip:XXX.XXX.XXX.XXX
client_uri = sip:3@XXX.XXX.XXX.XXX
retry_interval = 60

[hikari-hgw]
type = endpoint
context = from-hikari-hgw
dtmf_mode = inband
disallow = all
allow = ulaw
direct_media = no
send_pai = yes
inband_progress = yes
from_user = 3
from_domain = XXX.XXX.XXX.XXX
language = ja
outbound_auth = hikari-hgw
aors = hikari-hgw
```

**セクション名**

- 殆どの場合は任意の名前をつけることができる（例：トランスポート[transport-udp-nat]）
- endpoint、aor では下記のようにセクション名と機能が関係するので注意する
    - インバウンドSIPリクエストの「From」ヘッダーのSIPURIのユーザー部分と一致する必要あり
    （エンドポイントに識別セクションが構成されている場合は例外。
    その場合インバウンドリクエストは、「From」ヘッダーのユーザーに対してではなく、IPによって照合される）

```
[  SectionName ]
ConfigOption = Value
ConfigOption = Value
```
    

**グローバル設定**

- 全体の設定を指定
- グローバル設定を使用する場合にはtype=globalのセクションを記載する

```
[global]
type=global
max_forwards = 50
```

**インクルード**

- Asteriskの他の設定ファイル同様に#includeが使える

```
…
bind = 0.0.0.0:5070

#include pjsip_phones.conf
#include pjsip_trunk_hikari.conf
```

**トランスポート**

- res_pjsipがトランスポート層でどのように動作するかを構成
    - TCP、UDP、WebSocketなどのプロトコル
    - TLS / SSLなどの暗号化方式の構成オプションなど
- 複数のトランスポートセクションを設定できる
    - 異なるポートまたはプロトコルを使用する必要がある
    - 同じIPバージョン（IPv4またはIPv6）の複数のTCPまたはTLSトランスポートは不可

```
[transport-udp]
type = transport
protocol = udp
bind = 0.0.0.0:5070
```

**ACL**

- すべてのインバウンドSIP通信で動作するアクセス制御リストなどの機能
- 書き方が複数ある
    - pjsip.conf内でtype=aclで定義する
    - alc.conf内で定義したものをプルする
        - alc.conf内の記法は'[ ]'で定義されるセクション名がACLの名前
        - PjSIPの各所(endpointなど)から'acl=名前'で参照される
     - pjsip.confに複数のACL(type=acl)を書くとそのセクション名にかかわらず後ろにあるACLの方が勝つ
     - deny,permitはこの順でないとpermitしてdenyしてしまうため逆に書くと使えなくなる

- pjsip.conf内の場合
     - グローバルなACLとして動作する
     - 他で設定されたACL(endpointなど)よりも優先使用される(BASELINE)
     - 何も設定されていない場合には『全許可』(ACLなし) 
     - この方法の場合にはCLIからmodule reload res_pjsip.soだけで反映される
     - このACLを抜けてこないと各endpointなどのACLは参照されない
  
[全拒否の場合]

 ```
       [acl]
       type = acl
       deny = 0.0.0.0/0.0.0.0
 ```

[192.168.1.0/24だけ許可するACL]
 
```
       [acl]
       type = acl
       deny = 0.0.0.0/0.0.0.0
       permit = 192.168.1.0/24
 ```

[acl.confの名前付ACLをACLとして使用する場合]

 ```
      [acl]
      type = acl
      acl = inhouse-phones

 ```

[Contactヘッダーに基づいて制限する場合]

 ```
      [acl]
      type=acl|
      contactdeny=0.0.0.0/0.0.0.0
      contactpermit=209.16.236.0
      contactpermit=209.16.236.1

```
IPではなくContactヘッダーに基づいて制限する構成もできる
     
     
-  alc.conf内での書き方

```
[inhouse-phones]
deny=0.0.0.0/0.0.0.0
permit=192.168.1.0/24
```
セクション名がACLの名前
名前付きACLと言われる
ここで指定した名前をpjsip.confで呼び出す


- その他
     - 全許可しておき各endpointでACLを定義する場合
        - pjsip.confにはACLを書かない。

        - acl.confに下記を記載

``` 
            [myphones]
            type = acl
            deny = 0.0.0.0/0.0.0.0
            permit = 192.168.1.0/24
```

- endpoint設定に以下のように書く

```
            acl = myphones
```
この場合、Asteriskを再起動しないとACLの情報が更新されない

**認証情報(Auth)**

- このセクションにはインバウンドまたはアウトバウンド認証に関連するオプションと資格情報が含まれている
- エンドポイントやレジストなどの他のセクションをこのセクションに関連付ける事ができる
- 複数のエンドポイント、レジストを必要に応じて単一の認証情報で設定できる
- sip.confとの違いは認証情報がピア名(sip.confの[ ]、エンドポイント)に紐付かなくなった点

```
[some-phone]
type = endpoint
.
.
.
auth = phone-auth
outbound_auth = phone-out-auth
```
上記のように複数のauthが指定されているエンドポイントでは2つauthセクションが必要

```[some-phone]エンドポイントに接続、外からの"入り"の際の認証情報（インバウンド）
[phone-auth]
type = auth
username = phone123
password = phonepassword
```

```このエンドポイントからの"出"の際の認証情報（アウトバウンド）
[phone-out-auth]
略
```

- ユーザー名とパスワードの認証の例

```
[auth6001]
type=auth
auth_type=userpass
password=6001
username=6001
```

**エンドポイント**

- 電話やリモートサーバーなどのSIPエンドポイントを構成するためのプロファイル
- コアSIP機能に関連する多数のオプションを提供
- 認証、aor、トランスポートなどの他のセクションに関連している
- 1つ以上のAoRセクションを関連付ける必要がある

```
[6001]
type=endpoint
context=default
disallow=all
allow=ulaw
transport=simpletrans
auth=auth6001
aors=6001
```
エンドポイントが使用する発信者IDを定義する場合は下記を追加する

```
trust_id_outbound=yes
callerid=Spaceman Spiff <6001>
```

**AOR**

- Address Of  Record の略
- エンドポイントに接続できる場所をAsteriskに通知する
- 関連するAORがないとエンドポイントに接続できない
- MWIリクエストのメールボックスへの関連付けや、有効期限や資格設定など、コンタクトのグループ全体に関連する可能性のあるその他のデータも格納する
- Asteriskがインバウンドレジストを受け取ると、利用可能なAORとの照合が行われる

- AORの名前はインバウンドSIPレジストの「To：」ヘッダーにあるSIPURIのユーザー部分（ユーザ名）と一致する必要がある

[SIPユーザーエージェントがAORに対してレジストする構成]

```
[6001]
type=aor
max_contacts=1
```
- この場合Contactオブジェクトは自動的に作成される
    - max_contactsに指定した数が作成、レジストされる（最大10）

[SIPユーザーエージェントがAORに対してレジストしない構成]

```
[6001]
type=aor
contact=sip:6001@192.0.2.1:5060
```

- この場合はContactオブジェクトは手動で割り当てる
- max_contactは指定しなくてよい

---

- 参考文献
    - https://voip-info.jp/index.php/%E3%83%A1%E3%82%A4%E3%83%B3%E3%83%9A%E3%83%BC%E3%82%B8
    - https://ja.wikipedia.org/wiki/Asterisk_(PBX)
    - http://st-asterisk.com/