358 lines
19 KiB
Markdown
358 lines
19 KiB
Markdown
_**Asterisk**_ is a SIP server for telecomunications between IP devices. We use it to make a voice and video streams between the Dipal app user and the intercom. Makaw listens for events from Asterisk via ARI. When someone calls the flat from the intercom, Asterisk executes the _**stasis**_ application, which is implemented in our Makaw. We can get the flat number and send it as a notification to the user, after which Makaw returns control to Asterisk again. The frontend application connects directly to Asterisk as a SIP server and uses WebRTC to stream.
|
||
|
||
# Installation from package repository
|
||
|
||
> Each version of Asterisk is unstable and may contain many bugs. {.is-warning}
|
||
|
||
```text
|
||
sudo apt update
|
||
sudo apt install asterisk
|
||
```
|
||
|
||
> The package in APT is usually outdated, but rather stable. {.is-warning}
|
||
|
||
To restart the Asterisk service:
|
||
|
||
```text
|
||
sudo systemctl restart asterisk
|
||
```
|
||
|
||
To close the Asterisk service:
|
||
|
||
```text
|
||
sudo systemctl stop asterisk
|
||
```
|
||
|
||
## Testing
|
||
|
||
To test, let's connect to the Asterisk console:
|
||
|
||
```text
|
||
sudo rasterisk
|
||
```
|
||
|
||
Which will bring you into the Asterisk command-line client. You will see this prompt after the basic Asterisk information is displayed:
|
||
|
||
```text
|
||
asterisk*CLI>
|
||
```
|
||
|
||
To change the verbosity of the console, use the following:
|
||
|
||
```text
|
||
core set verbose 4
|
||
```
|
||
|
||
To check the version of Asterisk, enter:
|
||
|
||
```text
|
||
sudo rasterisk -V
|
||
```
|
||
|
||
If any error occurs, you can see the service log or logs from files:
|
||
|
||
```text
|
||
sudo journalctl -eu asterisk -f
|
||
sudo vim /var/log/asterisk/full
|
||
```
|
||
|
||
# pjsip.conf
|
||
|
||
res\_pjsip configuration is stored in pjsip.conf.
|
||
|
||
To activate PJSIP add chan\_sip to noload and delete res\_pjsip in modules.conf.
|
||
|
||
```text
|
||
noload => chan_sip.so
|
||
;noload => res_pjsip.so
|
||
```
|
||
|
||
## Intercom
|
||
|
||
```text
|
||
[domofon]
|
||
type=endpoint
|
||
direct_media=no
|
||
rtp_symmetric=yes
|
||
force_rport=yes
|
||
rewrite_contact=yes
|
||
allow=alaw,h264
|
||
transport=transport-udp
|
||
context=internal
|
||
aors=domofon
|
||
auth=domofon
|
||
|
||
[domofon]
|
||
type=auth
|
||
auth_type=userpass
|
||
password=your_password
|
||
username=domofon
|
||
|
||
[domofon]
|
||
type=aor
|
||
max_contacts=1
|
||
```
|
||
|
||
### Endpoint
|
||
|
||
<figure class="table op-uc-figure_align-center op-uc-figure"><table class="op-uc-table"><thead class="op-uc-table--head"><tr class="op-uc-table--row"><th class="op-uc-p op-uc-table--cell op-uc-table--cell_head">Variable</th><th class="op-uc-p op-uc-table--cell op-uc-table--cell_head">Description</th></tr></thead><tbody><tr class="op-uc-table--row"><td class="op-uc-p op-uc-table--cell">direct_media</td><td class="op-uc-p op-uc-table--cell">determines whether media may flow directly between endpoints (default: "yes")</td></tr><tr class="op-uc-table--row"><td class="op-uc-p op-uc-table--cell">rtp_symmetric</td><td class="op-uc-p op-uc-table--cell">user agents (UAs) use the same socket/port binding to send and receive RTP stream packets</td></tr><tr class="op-uc-table--row"><td class="op-uc-p op-uc-table--cell">force_rport</td><td class="op-uc-p op-uc-table--cell">causes Asterisk to always send responses back to the address/port from which it received requests</td></tr><tr class="op-uc-table--row"><td class="op-uc-p op-uc-table--cell">rewrite_contact</td><td class="op-uc-p op-uc-table--cell">allow contact header to be rewritten with the source IP address port (default: "no")</td></tr><tr class="op-uc-table--row"><td class="op-uc-p op-uc-table--cell">allow</td><td class="op-uc-p op-uc-table--cell">allow codecs in order of preference</td></tr><tr class="op-uc-table--row"><td class="op-uc-p op-uc-table--cell">transport</td><td class="op-uc-p op-uc-table--cell">set the default transports; the order determines the primary default transport</td></tr><tr class="op-uc-table--row"><td class="op-uc-p op-uc-table--cell">context</td><td class="op-uc-p op-uc-table--cell">default context for incoming calls (from extensions.conf); defaults to 'default'</td></tr><tr class="op-uc-table--row"><td class="op-uc-p op-uc-table--cell">aors</td><td class="op-uc-p op-uc-table--cell">AoRs to be used with the endpoint (default: "")</td></tr><tr class="op-uc-table--row"><td class="op-uc-p op-uc-table--cell">auth</td><td class="op-uc-p op-uc-table--cell">authentication objects associated with the endpoint (default: "")</td></tr></tbody></table></figure>
|
||
|
||
### Auth
|
||
|
||
<figure class="table op-uc-figure_align-center op-uc-figure"><table class="op-uc-table"><thead class="op-uc-table--head"><tr class="op-uc-table--row"><th class="op-uc-p op-uc-table--cell op-uc-table--cell_head">Variable</th><th class="op-uc-p op-uc-table--cell op-uc-table--cell_head">Description</th></tr></thead><tbody><tr class="op-uc-table--row"><td class="op-uc-p op-uc-table--cell">auth_type</td><td class="op-uc-p op-uc-table--cell">may be "userpass" for plain text passwords or "md5" for pre-hashed credentials. (default: "userpass")</td></tr><tr class="op-uc-table--row"><td class="op-uc-p op-uc-table--cell">password, username</td><td class="op-uc-p op-uc-table--cell">credentials for registration</td></tr></tbody></table></figure>
|
||
|
||
### AoR
|
||
|
||
<figure class="table op-uc-figure_align-center op-uc-figure"><table class="op-uc-table"><thead class="op-uc-table--head"><tr class="op-uc-table--row"><th class="op-uc-p op-uc-table--cell op-uc-table--cell_head">Variable</th><th class="op-uc-p op-uc-table--cell op-uc-table--cell_head">Description</th></tr></thead><tbody><tr class="op-uc-table--row"><td class="op-uc-p op-uc-table--cell">max_contacts</td><td class="op-uc-p op-uc-table--cell">maximum number of contacts that can bind to an AoR (default: "0")</td></tr></tbody></table></figure>
|
||
|
||
## Client
|
||
|
||
This configuration example is for registering a client application with Asterisk using WebRTC.
|
||
|
||
```text
|
||
[15]
|
||
type=endpoint
|
||
direct_media=no
|
||
context=from-external
|
||
allow=vp8,vp9,h264,alaw
|
||
transport=transport-wss
|
||
webrtc=yes
|
||
auth=15
|
||
aors=15
|
||
|
||
[15]
|
||
type=auth
|
||
auth_type=userpass
|
||
password=your_password
|
||
username=15
|
||
|
||
[15]
|
||
type=aor
|
||
max_contacts=10
|
||
```
|
||
|
||
<figure class="table op-uc-figure_align-center op-uc-figure"><table class="op-uc-table"><thead class="op-uc-table--head"><tr class="op-uc-table--row"><th class="op-uc-p op-uc-table--cell op-uc-table--cell_head">Variable</th><th class="op-uc-p op-uc-table--cell op-uc-table--cell_head">Description</th></tr></thead><tbody><tr class="op-uc-table--row"><td class="op-uc-p op-uc-table--cell">webrtc</td><td class="op-uc-p op-uc-table--cell">when set to "yes" this also enables the following values that are needed for webrtc: rtcp_mux, use_avpf, ice_support, and use_received_transport</td></tr></tbody></table></figure>
|
||
|
||
> VP8/VP9 are the default codecs for WebRTC and the only codec for intercom is H264. In this case, a codec difference problem may occur. At the time of writing only Freeswitch can transcode video from one codec to another. {.is-warning}
|
||
|
||
> You can use any name for the client. I chose 15 because it is convenient to call from a smartphone with a fake client (I use Zoiper). {.is-info}
|
||
|
||
# extensions.conf
|
||
|
||
```text
|
||
;-------------------------------------------------------
|
||
; General Section
|
||
;-------------------------------------------------------
|
||
[general]
|
||
static=yes
|
||
writeprotect=yes
|
||
clearglobalvars=yes
|
||
autofallthrough=yes
|
||
|
||
[from-external]
|
||
exten => 200,1,Dial(PJSIP/domofon,120)
|
||
|
||
[invalid]
|
||
exten => _X,1,Stasis(hello)
|
||
same => n,Dial(PJSIP/${EXTEN}&PJSIP/comfortech/${EXTEN},120)
|
||
same => n,Hangup
|
||
exten => _XX,1,Stasis(hello)
|
||
same => n,Dial(PJSIP/${EXTEN}&PJSIP/comfortech/${EXTEN},120)
|
||
same => n,Hangup
|
||
|
||
exten => _1[0-3]X,1,Stasis(hello)
|
||
same => n,Dial(PJSIP/${EXTEN}&PJSIP/comfortech/${EXTEN},120)
|
||
same => n,Hangup
|
||
|
||
[default]
|
||
```
|
||
|
||
`static` if static is set to no, or omitted, then the pbx\_config will rewrite this file when extensions are modified.
|
||
|
||
`writeprotect` if static=yes and writeprotect=no, you can save dialplan by CLI command dialplan save too
|
||
|
||
`clearglobalvars` if clearglobalvars is set, global variables will be cleared and reparsed on a dialplan reload, or Asterisk reload.
|
||
|
||
`autofallthrough` if autofallthrough is set, then if an extension runs out of things to do, it will terminate the call with BUSY, CONGESTION if autofallthrough is not set, then if an extension runs out ofthings to do, Asterisk will wait for a new extension to be dialed
|
||
|
||
`_X`, `_XX`, `_1[0-3]X` it means that dialplans will work with 1-139 numbers
|
||
|
||
`${EXTEN}` variable equal to dialed number
|
||
|
||
# WebRTC
|
||
|
||
WebRTC requires **WSS (WebSocket Secure)** and we need a domain with a certificate. You can use a self-signed certificate, but you cannot use it with a browser and sipML5.
|
||
|
||
## Generate certificate
|
||
|
||
**Let’s Encrypt** is a service offering free SSL certificates through an automated API. The most popular Let’s Encrypt client is EFF’s **Certbot**.
|
||
|
||
Install Certbot:
|
||
|
||
```text
|
||
sudo add-apt-repository ppa:certbot/certbot
|
||
sudo apt-get update
|
||
sudo apt-get install certbot
|
||
```
|
||
|
||
Certbot needs to answer a cryptographic challenge issued by the Let’s Encrypt API in order to prove we control our domain. It uses ports 80 (HTTP) or 443 (HTTPS) to accomplish this. Open up the appropriate port in your firewall:
|
||
|
||
```text
|
||
sudo ufw allow 80
|
||
```
|
||
|
||
Substitute 443 above if that’s the port you’re using. ufw will output confirmation that your rule was added:
|
||
|
||
> Output Rule added Rule added (v6) {.is-success}
|
||
|
||
We can now run Certbot to get our certificate. We’ll use the --standalone option to tell Certbot to handle the challenge using its own built-in web server. The --preferred-challenges option instructs Certbot to use port 80 or port 443. If you’re using port 80, you want --preferred-challenges http. For port 443 it would be --preferred-challenges tls-sni. Finally, the -d flag is used to specify the domain you’re requesting a certificate for. You can add multiple -d options to cover multiple domains in one certificate.
|
||
|
||
```text
|
||
sudo certbot certonly --standalone --preferred-challenges http -d example.com
|
||
```
|
||
|
||
## Configure Asterisk with cerificate
|
||
|
||
This certificate can only be accessed by the root user. Asterisk is executed by asterisk user. The way to fix this problem is to copy the certificate into Asterisk directory and change the owner.
|
||
|
||
If you use Asterisk as a Linux service:
|
||
|
||
```text
|
||
mkdir /etc/asterisk/keys
|
||
sudo cp -L /etc/letsencrypt/live/example.com/cert.pem /etc/asterisk/keys
|
||
sudo cp -L /etc/letsencrypt/live/example.com/privkey.pem /etc/asterisk/keys
|
||
sudo chown asterisk:asterisk /etc/asterisk/keys/cert.pem
|
||
sudo chown asterisk:asterisk /etc/asterisk/keys/privkey.pem
|
||
```
|
||
|
||
You need to enable TLS and add the certificate to http.conf:
|
||
|
||
```text
|
||
[general]
|
||
enabled=no
|
||
tlsenable=yes
|
||
tlsbindaddr=0.0.0.0:8089
|
||
tlscertfile=/etc/asterisk/keys/cert.pem
|
||
tlsprivatekey=/etc/asterisk/keys/privkey.pem
|
||
```
|
||
|
||
## Testing
|
||
|
||
You can use one of 2 sites to test WebRTC from your browser:
|
||
|
||
* https://www.doubango.org/sipml5/call.htm
|
||
* https://tryit.jssip.net/
|
||
|
||
# HTTP server (ARI)
|
||
|
||
The HTTP server in Asterisk is configured via http.conf. Note that this does not describe all of the options available via http.conf - rather, it lists the most useful ones for ARI.
|
||
|
||
Example:
|
||
|
||
```text
|
||
[general]
|
||
enabled = yes
|
||
bindaddr = 0.0.0.0
|
||
bindport = 8088
|
||
```
|
||
|
||
<figure class="table op-uc-figure_align-center op-uc-figure"><table class="op-uc-table"><thead class="op-uc-table--head"><tr class="op-uc-table--row"><th class="op-uc-p op-uc-table--cell op-uc-table--cell_head">Variable</th><th class="op-uc-p op-uc-table--cell op-uc-table--cell_head">Description</th></tr></thead><tbody><tr class="op-uc-table--row"><td class="op-uc-p op-uc-table--cell">enabled</td><td class="op-uc-p op-uc-table--cell">Enable the HTTP server. The HTTP server in Asterisk is disabled by default. Unless it is enabled, ARI will not function!</td></tr><tr class="op-uc-table--row"><td class="op-uc-p op-uc-table--cell">bindaddr</td><td class="op-uc-p op-uc-table--cell">The IP address to bind the HTTP server to. This can either be an explicit local address, or 0.0.0.0 to bind to all available interfaces.</td></tr><tr class="op-uc-table--row"><td class="op-uc-p op-uc-table--cell">bindport</td><td class="op-uc-p op-uc-table--cell">The port to bind the HTTP server to. Client making HTTP requests should specify 8088 as the port to send the request to.</td></tr><tr class="op-uc-table--row"><td class="op-uc-p op-uc-table--cell">prefix</td><td class="op-uc-p op-uc-table--cell">A prefix to require for all requests. If specified, requests must begin with the specified prefix.</td></tr><tr class="op-uc-table--row"><td class="op-uc-p op-uc-table--cell">tlsenable</td><td class="op-uc-p op-uc-table--cell">Enable HTTPS</td></tr><tr class="op-uc-table--row"><td class="op-uc-p op-uc-table--cell">tlsbindaddr</td><td class="op-uc-p op-uc-table--cell">The IP address and port to bind the HTTPS server to. This should be an IP address and port, e.g., 0.0.0.0:8089</td></tr><tr class="op-uc-table--row"><td class="op-uc-p op-uc-table--cell">tlscertfile</td><td class="op-uc-p op-uc-table--cell">The full path to the certificate file to use. Asterisk only supports the .pem format</td></tr><tr class="op-uc-table--row"><td class="op-uc-p op-uc-table--cell">tlsprivatekey</td><td class="op-uc-p op-uc-table--cell">The full path to the private key file. Asterisk only supports the .pem format. If this is not specified, the certificate specified in tlscertfile will be searched for the private key.</td></tr></tbody></table></figure>
|
||
|
||
For creating a certificate, see [WebRTC configuration](http://194.226.0.195:32127/telecom/Asterisk/webrtc)
|
||
|
||
# Fail2Ban
|
||
|
||
To install fail2ban:
|
||
|
||
```text
|
||
sudo apt install fail2ban
|
||
```
|
||
|
||
The default settings of the program are in the /etc/fail2ban/jail.conf file, it is recommended to change the settings in /etc/fail2ban/jail.local, which is a copy of jail.conf.
|
||
|
||
The file contains a section of general settings \[DEFAULT\] and sections of specific settings for certain services (for example, the presence of the \[ssh\] section is demonstrated).
|
||
|
||
```text
|
||
[DEFAULT]
|
||
ignoreip = 127.0.0.1/8
|
||
ignorecommand =
|
||
bantime = 3600
|
||
findtime = 600
|
||
maxretry = 3
|
||
backend = auto
|
||
usedns = warn
|
||
destemail = root@localhost
|
||
sendername = Fail2Ban
|
||
sender = fail2ban@localhost
|
||
banaction = iptables-multiport
|
||
mta = sendmail
|
||
protocol = tcp
|
||
chain = INPUT
|
||
action_ = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
|
||
action_mw = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
|
||
%(mta)s-whois[name=%(__name__)s, dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s", sendername="%(sendername)s"]
|
||
action_mwl = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
|
||
%(mta)s-whois-lines[name=%(__name__)s, dest="%(destemail)s", logpath=%(logpath)s, chain="%(chain)s", sendername="%(sendername)s"]
|
||
action = %(action_)s
|
||
|
||
[ssh]
|
||
enabled = true
|
||
port = ssh
|
||
filter = sshd
|
||
logpath = /var/log/auth.log
|
||
maxretry = 6
|
||
```
|
||
|
||
<figure class="table op-uc-figure_align-center op-uc-figure"><table class="op-uc-table"><thead class="op-uc-table--head"><tr class="op-uc-table--row"><th class="op-uc-p op-uc-table--cell op-uc-table--cell_head">Variable</th><th class="op-uc-p op-uc-table--cell op-uc-table--cell_head">Description</th></tr></thead><tbody><tr class="op-uc-table--row"><td class="op-uc-p op-uc-table--cell">ignoreip</td><td class="op-uc-p op-uc-table--cell">can be a list of IP addresses, CIDR masks or DNS hosts. Fail2ban will not ban a host which matches an address in this list. Several addresses can be defined using space (and/or comma) separator.</td></tr><tr class="op-uc-table--row"><td class="op-uc-p op-uc-table--cell">bantime</td><td class="op-uc-p op-uc-table--cell">the number of seconds that a host is banned.</td></tr><tr class="op-uc-table--row"><td class="op-uc-p op-uc-table--cell">findtime, maxretry</td><td class="op-uc-p op-uc-table--cell">a host is banned if it has generated "maxretry" during the last "findtime" seconds</td></tr><tr class="op-uc-table--row"><td class="op-uc-p op-uc-table--cell">backend</td><td class="op-uc-p op-uc-table--cell">specifies the backend used to get files modification</td></tr><tr class="op-uc-table--row"><td class="op-uc-p op-uc-table--cell">usedns</td><td class="op-uc-p op-uc-table--cell">specifies if jails should trust hostnames in logs, warn when DNS lookups are performed, or ignore all hostnames in logsyes: if a hostname is encountered, a DNS lookup will be performed</td></tr><tr class="op-uc-table--row"><td class="op-uc-p op-uc-table--cell">destemail</td><td class="op-uc-p op-uc-table--cell">destination email address used solely for the interpolations in jail.{conf,local,d/*} configuration files.</td></tr><tr class="op-uc-table--row"><td class="op-uc-p op-uc-table--cell">sender</td><td class="op-uc-p op-uc-table--cell">sender email address used solely for some actions</td></tr><tr class="op-uc-table--row"><td class="op-uc-p op-uc-table--cell">banaction</td><td class="op-uc-p op-uc-table--cell">default banning action (e.g. iptables, iptables-new, iptables-multiport, shorewall, etc) It is used to define a ction_* variables</td></tr><tr class="op-uc-table--row"><td class="op-uc-p op-uc-table--cell">protocol</td><td class="op-uc-p op-uc-table--cell">default protocol (tcp, udp, ...)</td></tr><tr class="op-uc-table--row"><td class="op-uc-p op-uc-table--cell">chain</td><td class="op-uc-p op-uc-table--cell">specify chain where jumps would need to be added in ban-actions expecting parameter chain</td></tr><tr class="op-uc-table--row"><td class="op-uc-p op-uc-table--cell">enabled</td><td class="op-uc-p op-uc-table--cell">enables the jails</td></tr><tr class="op-uc-table--row"><td class="op-uc-p op-uc-table--cell">port</td><td class="op-uc-p op-uc-table--cell">ports to be banned</td></tr><tr class="op-uc-table--row"><td class="op-uc-p op-uc-table--cell">filter</td><td class="op-uc-p op-uc-table--cell">defines the filter to use by the jail</td></tr><tr class="op-uc-table--row"><td class="op-uc-p op-uc-table--cell">logpath</td><td class="op-uc-p op-uc-table--cell">path to the logs</td></tr></tbody></table></figure>
|
||
|
||
## Asterisk configuration
|
||
|
||
1. Copy the configuration file to the local one.
|
||
|
||
```text
|
||
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
|
||
```
|
||
|
||
1. Add to ignoreip the addresses from which you are going to connect to the asterisk.
|
||
2. Add Asterisk jail (see below). You can set up variables however you like.
|
||
|
||
```text
|
||
[asterisk]
|
||
enabled = true
|
||
filter = asterisk
|
||
backend = auto
|
||
port = 5060,5061
|
||
action = iptables-allports[name=ASTERISK, protocol=all, blocktype=DROP]
|
||
logpath = /var/log/asterisk/messages
|
||
findtime = 1m
|
||
maxretry = 5
|
||
bantime = 30d
|
||
```
|
||
|
||
1. (optional) If you have ssh, it is more secure if you add it to the jail.
|
||
|
||
```text
|
||
[sshd]
|
||
enabled = true
|
||
bantime = 60m
|
||
findtime = 1m
|
||
maxretry = 5
|
||
port = ssh
|
||
logpath = %(sshd_log)s
|
||
backend = %(sshd_backend)s
|
||
```
|
||
|
||
## Compiling Asterisk
|
||
To compile Asterisk you need to download its source (for example, [Asterisk 16](https://launchpad.net/ubuntu/+source/asterisk/1:16.2.1~dfsg-2ubuntu1)).
|
||
|
||
```bash
|
||
sudo ./contrib/scripts/install_prereq install
|
||
sudo ./configure --with-jansson-bundled
|
||
sudo make menuselect
|
||
sudo make
|
||
sudo make install
|
||
sudo make samples
|
||
sudo make config
|
||
sudo asterisk -vvvc
|
||
```
|