Virtual PBX. Part 2: Solve security issues with Asterisk and set up calls



In the previous article, we looked at a simple installation of an IP PBX (IP PBX) Asterisk 16 from a regular repository on a RuVDS virtual server with Ubuntu 20.04 . In such a configuration, you should not expose the VoIP service to the public: you need to make additional settings, including those related to information security.



Defining the threat model



To begin with, let's figure out what risks a company that has placed a virtual PBX on the Internet will face. All their diversity comes down to a short list:



  • confidential data leaks and content corruption (session hijacking);
  • unauthorized access to corporate information systems due to vulnerabilities in Asterisk and other software on the server, in particular, due to incorrect configuration;
  • virtual PBX disruption due to denial of service attacks;
  • reselling traffic after hacking a PBX (the most common type of attack).


Some of the vulnerabilities are directly related to the Asterisk software. IP PBX developers regularly release patches, and system administrators can only install updates in a timely manner. This method does not guarantee complete security, so it is also worth limiting clients' access to the IP telephony server. Let's see what needs to be done to organize secure telephony.



Configuring a firewall



The easiest way to protect yourself is to restrict client connections to a firewall. Since VDS has real IP, there is no need to solve problems with traffic passing through NAT. It remains to allow incoming connections from subscribers, and block all others using Netfilter . On virtual servers RuVDS with Ubuntu, it is configured using the preinstalled UFW (Uncomplicated Firewall) utility . If you don't have the ufw package installed, it's easy to fix:



sudo apt-get install ufw


First, let's check the status:



sudo ufw status verbose


By default, UFW is disabled (Status: inactive), but you should not rush to enable it: if you do not change the settings, all incoming packets will begin to be hacked at the root and you will lose access to the server via SSH. At a minimum, you should allow incoming connections on port 22, while you can use the pre-installed OpenSSH application profile (view profiles: sudo ufw app list):



#    SSH 
#   IP,   
sudo ufw allow OpenSSH
#    IP (  )
sudo ufw allow from XXX.XXX.XXX.XXX to any port 22
#       IP ()    Asterisk
sudo ufw allow from XXX.XXX.XXX.XXX
#   
sudo ufw enable


To view the filtering policy, use the command:



sudo ufw status verbose




To delete rules, you need to see their numbers:



sudo ufw status numbered
sudo ufw delete N




There are other tools for configuring Netfiler (the same iptables), but you should not combine different utilities - this is fraught with problems. You won't be able to do without filtering traffic, because your Asterisk will not stand for an hour when open to all winds, as such funny pictures will appear in the console:





Since remote users are at home (in theory), as a rule, they have a real dedicated IP, and we don't need anything else. Otherwise, you should take care of creating a secure virtual private network: it will also come in handy for accessing other corporate resources that should not be exposed to the public. More sophisticated defenses (fail2ban, etc.) are not directly related to Asterisk. We'll look at them in general context in other posts as well.



Getting rid of unnecessary modules



This part of the configuration is not directly related to security, but is generally necessary. In addition, the fewer opportunities your PBX provides to clients, the more difficult it is to hack it - the absence of unnecessary functionality will to a certain extent complicate the life of potential attackers.



The minimum PBX functionality looks like this:



  • SIP support;
  • Support for the G711 alaw only codec (if you wish, you can add all available codecs);
  • Call recording;
  • Support for WAV format (if desired, you can add support for all available formats);
  • Optional : support for storing call detail on the database server.


To manage the Asterisk service interactively, use the built-in text console:



sudo asterisk -rvv


Module files * .so are stored in the / usr / lib / asterisk / modules / directory . Upload and download can be in the console without having to restart the server (the module name is specified without an extension, for example, chan_sip instead chan_sip.so ): the Asterisk Module settings found in the configuration file /etc/asterisk/modules.conf . By default, all available modules are loaded automatically at server startup, but this can be easily changed using the autoload = yes | no parameter . Let's edit the configuration file, after making a backup copy of the distribution file:



module load NAME

module unload NAME








sudo mv /etc/asterisk/modules.conf /etc/asterisk/modules.conf.b
sudo nano /etc/asterisk/modules.conf


There are two approaches to configuration. In the first case, we enable autoloading of all existing modules, and disable unnecessary ones through modules.conf (section [modules] ): Note, here we specify the file name with the extension. The second option is to disable autoloading of all and specify only the necessary modules in the [modules] section of the modules.conf file , for example, like this: After editing, change the access rights:



[modules]

autoload=yes

noload => module_name.so












[modules]

autoload = no

load => chan_sip.so

load => codec_alaw.so

load => format_wav.so

load => app_dial.so

load => res_musiconhold.so








sudo chown asterisk:asterisk /etc/asterisk/modules.conf
sudo chmod 640 /etc/asterisk/modules.conf




We look at the list of loaded modules in the Asterisk console:



module show





We add other modules to taste. This is how the modules.conf file will look for configuring an IP PBX with a sufficiently developed functionality:



Content of modules.conf
[modules]



autoload=no ; /usr/lib/asterisk/modules/



; VoIP (SIP)

load => chan_sip.so

load => res_sorcery_config.so

load => res_pjproject.so ; res_rtp_asterisk.so

load => res_rtp_asterisk.so

load => app_dial.so ; res_musiconhold.so

load => app_echo.so

load => bridge_simple.so ;

load => app_bridgewait.so

load => app_transfer.so ;

load => app_verbose.so ;

load => app_voicemail.so ; res_adsi.so

load => app_playback.so ;

load => app_stack.so

load => app_confbridge.so ;

load => app_directory.so

load => res_adsi.so

load => app_system.so ;

load => app_queue.so ;



;

load => func_devstate.so

load => app_chanisavail.so ; ChanIsAvail

load => func_cut.so ; cut



;

load => res_musiconhold.so

load => pbx_config.so



;

load => codec_a_mu.so

load => codec_adpcm.so

load => codec_alaw.so

load => codec_ulaw.so

load => codec_gsm.so

load => codec_lpc10.so

load => codec_g726.so

load => codec_g722.so



;

load => format_gsm.so ; Raw GSM data

load => format_h263.so ; Raw h263 data

load => format_pcm.so ; Raw uLaw 8khz Audio support (PCM)

load => format_wav_gsm.so ; Microsoft WAV format (Proprietary GSM)

load => format_wav.so ; Microsoft WAV format (8000hz Signed Linear)

load => format_mp3.so ; mp3-format



; Dahdi ( VDS )

;load => chan_dahdi.so



;

load => res_parking.so



; res_monitor.so,

load => func_periodic_hook.so

load => func_strings.so ; STRFTIME

; CALLERID, res_monitor.so

load => func_callerid.so

load => func_volume.so

;

load => res_monitor.so

load => app_mixmonitor.so ; app_mixmonitor.so app_dial.so

load => func_channel.so



; MySQL ( )

;load => cdr_mysql.so

;load => res_config_mysql.so ; MySQL RealTime Configuration Driver



; MySQL ODBC ( )

;load => res_odbc.so

;load => res_config_odbc.so

;load => cdr_odbc.so ;



; SNMP ( )

;load => res_snmp.so



; /var/spool/asterisk/outgoing/ ( )

;load => pbx_spool.so



; ( )

;load => app_exec.so ; exec execif

;load => app_while.so ; dialplan

;load => res_sorcery_astdb.so

;load => res_sorcery_realtime.so

;load => app_read.so

;load => app_stack.so

;load => cdr_csv.so ; /var/log/asterisk/cdr-csv/Master.csv

;load => func_cdr.so

;load => func_logic.so

;load => func_timeout.so

;load => func_shell.so

;load => pbx_ael.so

;load => res_ael_share.so

;load => res_agi.so

;load => res_speech.so ; res_agi.so





Note: You can comment out a line using a semicolon.



After modifying the modules.conf file, you must reload modules from the Asterisk console:



module reload



If you need to restart Asterisk, use the following command instead of the built-in console:



sudo systemctl restart asterisk


All called modules must be installed, otherwise Asterisk will fail when trying to load them. For example, to support the MP3 format, you have to install the asterisk-mp3 package , but to work with the MySQL server directly, you need asterisk-mysql :



sudo apt-get install asterisk-mp3
sudo apt-get install asterisk-mysql


Finding packages available in the repository is easy using the command:



apt-cache search asterisk


In fact, there are many more modules for Asterisk, we have not listed all of them. If you, for example, install a PBX on a physical server and want to connect analog lines to it through a telephony interface board, you will need the asterisk-dahdi package .



Configuring VoIP



Now let's change the sip.conf file so that we can work with Asterisk:



sudo nano /etc/asterisk/sip.conf


Add the following lines to the [general] section , if you haven't already: The first parameter protects Asterisk from brute-force attacks. If you do not enable it, the server will inform attackers when the subscriber does not exist. Having found a valid number, a hacker can proceed to brute force passwords. If alwaysauthreject = yes , authentication errors for existing and non-existent subscribers look the same and it is more difficult to guess the password. The parameter allowguest = no disables the so-called. guest calls to PBX users. You can also change the port that Asterisk listens to to a non-standard port using the bindport directive (similarly, the address that listens to the VoIP service is configured using bindaddr ).



alwaysauthreject=yes

allowguest=no








In the sip.conf file we have registered subscribers (peers - from English peers) PBX. If the user works from fixed IP, it is worth limiting his connectivity. It is also necessary to create strong passwords, introduce a limit on the number of calls and, of course, register connections to external VoIP providers (the so-called trunks - from the English trunk):



deny=0.0.0.0/0.0.0.0 ;prohibiting connections from all nodes

permit=xxx.xxx.xxx.xxx/24 ;allow connections from a specific subnet

secret=_ ;subscriber passwords must be resistant to brute force

call-limit=2 ; limiting the number of simultaneous calls



As a result, the sip.conf file will look something like this:



Sip.conf content
[general]

context=default

allowoverlap=no

udpbindaddr=0.0.0.0

tcpenable=no

tcpbindaddr=0.0.0.0

transport=udp

srvlookup=yes

alwaysauthreject=yes

allowguest=no



; SIPNET c chan_sip

; register

[sipnet]

remotesecret=

defaultuser=

host=sipnet.ru

type=peer

context=sipnet-trunk; dialplan ( extensions.conf)

insecure=invite

callbackextension=s

fromuser=

fromdomain=sipnet.ru

disallow=all

allow=alaw,ulaw

nat=no

directmedia=no

dtmfmode=rfc2833



[office](!)

; , .

; .

type=friend

host=dynamic ; , IP

nat=no ; NAT

deny=0.0.0.0/0.0.0.0 ;

call-limit=2

qualify=yes ; 2

dtmfmode=rfc2833 ; dtmf , rfc2833

; ,

disallow=all

allow=ulaw

allow=alaw

allow=g729

allow=g723

allow=g726

allow=h261

allow=h263

allow=h264

allow=h263p



; () office

[1001](office)

permit=XXX.XXX.XXX.XXX/Netmask

secret=_

callerid= <1001>

context=homeoffice ; dialplan ( extensions.conf)



[1002](office)

permit=YYY.YYY.YYY.YYY

secret=_

callerid= <1002>

context=homeoffice





In this case, the subscriber 1001 can connect from any address of a specific subnet, and 1002 - only from a fixed IP. We also gave subscribers a number, password, name and context, which will be used in the call routing plan (dialplan). Instructions for configuring trunks are best taken on the sites of service providers: in our case, this is SIPNET . The parameters are similar to those of other peers - extensions. Note also that the context specified in the configuration file (we will talk about this entity below) must exist in dialplan.



After making changes to the sip.conf configuration file, you need to restart the SIP module via the Asterisk console:



sip reload



Other built-in console commands for working with the SIP module:



sip show peers- displaying the status of all trunks / peers;

sip show registry- display of all registrations;

sip show channels- display of active channels;

sip show settings- viewing the global settings of the SIP module.





Dialplan and all-all-all



Call routing plan or dialplan is often referred to as the heart of Asterisk. It is stored in the /etc/asterisk/extensions.conf file and is essentially a script that makes the PBX respond to external events. Calling plan scripts can be written in different languages, but we will consider the built-in one, which appeared in the first versions of the popular IP PBX. After configuring and starting Asterisk, there will be some content in the extensions.conf file . Replace it with our own: The script syntax is pretty straightforward, we'll go into more detail in the next article. Note only that Asterisk's Calling Plan is based on four central concepts:



[general]

static=yes

writeprotect=no

priorityjumping=no

autofallthrough=yes

clearglobalvars=no



;

[default]

exten => _X.,1,NoOp()

same => n,Busy()

same => n,HangUp()



; homeoffice

[homeoffice]

;

exten => _1XXX,1,Dial(SIP/${EXTEN})

; SIPNET

exten => _.7XXXXXXXXXX,1,Dial(SIP/${EXTEN}@sipnet)



; sipnet-trunk, SIPNET

[sipnet-trunk]

;








  • Contexts - named parts of the code communicating with each other (names are enclosed in square brackets): sets of instructions;
  • (extensions) — , exten;
  • — , ( ) ( n — next). exten same;
  • (applications) — . , Dial — , .


Extensions sort calls by a mask using a set of patterns, starting with an underscore - it makes our PBX understand that we are talking about a pattern:



exten => _1XXX,1,Dial(SIP/${EXTEN})



Next, the priority is indicated and the call to the application with passing arguments to it is quite simple.



Restart dialplan using Asterisk console:



dialplan reload



To see the current dialplan, use the command:



dialplan show







Note that, for example, modules you have loaded can make changes to dialplan.



Now the PBX allows internal subscribers to communicate with each other, as well as to make external calls within Russia via SIPNET. This is not much, but enough for the second lesson. In the current configuration, the deprecated chan_sip module has been used , which will eventually be discontinued in Asterisk. In the next article we will look at migrating to the PjSIP libraryto work with the VoIP protocol stack, as well as extend dialplan for receiving incoming calls, organizing conferences and solving other call routing tasks. Attentive readers might have noticed that some of the loaded modules were not used in the examples: we will need them to learn how to record calls, create queues and do other interesting tricks.





Read our blog)










All Articles