Friday, October 05, 2012

Setup ntpd

To synchronize your unix to the HK time servers:

1.    service stop ntpd
2.    ntpdate  // we set a sensible time first
3.    vi /etc/ntp.conf and put the followings.


driftfile /var/lib/ntp/drift

4.    service start ntpd

Soon, you will see the ntp status.  For illustration:
#ntpq -pn
     remote           refid      st t when poll reach   delay   offset  jitter
*   2 u   60   64   17    7.094    7.683   3.114
+     3 u   61   64   17   10.296    6.702   4.906     .LOCL.          10 l    -   64   37    0.000    0.000   0.008

The actual ip addresses will be different as you are assigned random servers from the pool.  The important thing is the '*' sign in front of one of them, meaning that your server is now getting time from internet.

If you are unable to synchronize with the time servers, please check that UDP port 123 is opened.

Thursday, October 04, 2012

How to restrict ssh login by ip address

SSH restriction can be accomplished in below two files.

1.    /etc/hosts.allow

sshd:  sshd:

2.    /etc/hosts.deny

sshd: ALL

The access control software consults the above two files.   Search stops at the first match.

Wednesday, October 03, 2012

Iptables Rule for Asterisk

The default iptables ruleset will block SIP traffic. To allow it, we
need below:

# SIP on UDP port 5060. Other SIP servers may need TCP port 5060 as well
iptables -A INPUT -p udp -m udp --dport 5060 -j ACCEPT
# RTP - the media stream
# (related to the port range in /etc/asterisk/rtp.conf)
iptables -A INPUT -p udp -m udp --dport 10000:20000 -j ACCEPT

Or we use -I to insert the rules at specified rule number (the topmost
rule is numbered 1)
iptables -I INPUT 2 -p udp -m udp --dport 5060 -j ACCEPT
iptables -I INPUT 2 -p udp -m udp --dport 10000:20000 -j ACCEPT

Resize Unix Root File System

The resize2fs program will resize ext2, ext3, or ext4 file systems.
It can be used to enlarge or shrink an unmounted file system located on
device. If the filesystem is mounted, it can be used to expand the size
of the mounted filesystem, assuming the kernel supports on-line resizing.

First of all, we need to add a new partition.
# fdisk <disk>

Command (m for help): n

Command action
e extended
p primary partition (1-4)

and input the required partition size and lastly 'w' to write the
changes to partition table.

# shutdown -r now (or use partprobe)

# pvcreate <the new partition>

# vgextend VolGroup /dev/xvda3 (add the new physical volume to a
volume group)

# lvextend /dev/VolGroup/lv_root /dev/xvda3 (extend an existing logical
volume with the newly created physical volume)

# resize2fs /dev/mapper/VolGroup-lv_root (at last, we run resize2fs to
enlarge the filesystem)

Friday, September 07, 2012

IVR with night mode (go to voice mailbox straightaway after office hours)

We just have a client who operates a small call center. Their hotline
is served with an IVR which provides some self-serviced functions and an
option to talk to agents. After office hours, callers should be sent to
voice mailbox straightaway as all agents are off-duty.

This time-conditional forward is implemented using GotoIfTime function.

Here is an example that we provided.

When the caller presses the IVR option for agent, the GotoIfTime() will
determine whether it is within office hours.
exten => s,1,noop
exten => s,n,GotoIfTime(${CS-HOUR},*,*,*?open)
exten => s,n(closed),Playback(after-office-hour-msg)
exten => s,n,Voicemail(vm-night-mode@context,s)
exten => s,n,Hangup()
exten => s,n(open),noop
exten => s,n,PlayBack(queue-greeting)
exten => s,n,Queue(agent-queue,,,,60)
exten => s,n(queue-busy),Playback(queue-busy)
exten => s,n,Voicemail(vm-day-mode@context,s)
exten => s,n,Hangup()

The variable CS-HOUR is defined previously as.
exten => s,n,Set(CS-HOUR="09:00-22:30")

We could have office hours for night shift as well. For instance,
exten => s,n,Set(CS-HOUR="22:30-09:00")

Friday, August 31, 2012

How to setup SIP account in Android 4.0 ICS

There are many SIP-compliant soft phones like Xlite, 3CX, Linphone, Sipdroid etc. on Windows and Smartphones.  These software turn our PC or Smartphones to a SIP end point such that we could enjoy benefits from VOIP, such as cost reduction and roaming.  

With native SIP stack support in Android ICS, we could conveniently configure a SIP account without the need of a 3rd party apps.  Here describes the procedures involved.

Firstly, open Settings in the 'Phone' apps

Scroll to Internet Call Settings and Add the SIP account

The SIP account information is obtained from our SIP provider.  It usually consists of three information: SIP username, password and the SIP server name or ip address.

We could also specify when the internet call should be used.

Lastly, please check that your mobile network will not block the VOIP traffic.

Monday, August 27, 2012

Some security tips for Asterisk deployment

Unless your Asterisk server is purely for internal use, you will
inevitably face the potential threats from hackers who look for security
loopholes to abuse your system.

Here are some protection measures that we should consider.

1. Disallow guest call unless you really need it

In the [general] section of sip.conf, set allowguest=no

2. Always reject with '401 Unauthorized' for unauthorized INVITE or
REGISTER, instead of letting the requester know whether there was a
matching peer.

In [general] section of sip.conf, set alwaysauthreject = yes

3. Make use of permit= and deny= in sip peer definition to restrict
which clients we will accept.

4. Empty the [default] context

5. We always use strong password in our sip entities.

6. If we really need to enable AMI on a public ip address, make use of
the permit and deny to restrict which client can access Asterisk via AMI.

7. Sip username should be different from the extensions. That would
make guessing less easy.

8. Deploy iptables and fail2ban. We can then monitor the asterisk log
file to spot intruders and block them accordingly.

9. We can also change the port (default 5060) that Asterisk listens to.
(bindport=5060 in sip.conf). This approach applies when we only need
to handle known peers such as branch offices or remote extensions.

Monday, August 20, 2012

Working with Asterisk 10 t38 gateway

Below describes my experience with Asterisk 10 t38 gateway.

I am using Hylafax (open-source version 5.2.7) + iaxmodem (1.1.0) + Asterisk 10.7.0 + t38 ISP for oubound fax. 

There are a couple of ways to send t38 faxes to the ISP for PSTN termination, such as Digium's commercial Fax for Asterisk module,  the commercial Hylafax Enterprise Edition or the Asterisk Application SendFAX.  However, these solutions could not support utf8 fax tagline which is one of our primary faxing requirements.

On the other hand, the open-source hylafax not only support utf8 tag line, but also feature fax scheduler and mysql integration for better job management.  The next step is to let Asterisk act as t38 gateway between the iax side and the t38 ISP side.

iax Setup

We would get better result when jitter buffer is disabled in the iaxmodem configurations.

Add 'nojitterbuffer' to /etc/iaxmodem/

Also in the iax2 peer definition in Asterisk, we add:

Asterisk Setup

We need both Asterisk 10 and spandsp (eg spandsp-0.0.6) for the t38 gateway to work. 

 *CLI> module show like fax
Module                         Description                              Use Count                     Generic FAX Applications                 1             Spandsp G.711 and T.38 FAX Technologies  0          

In the sip.conf, we enable t38 on sip call as below.
t38pt_udptl = yes,redundancy,maxdatagram=400

t38pt_udptl = yes,redundancy,maxdatagram=400
jbenable = no

To turn on gateway mode, we use the FAXOPT function as below.
exten => _1500.,1,NoOp(${CALLERID(all)})
   same => n,Set(CALLERID(num)=${EXTEN:0:8})
   same => n,Set(FAXOPT(gateway)=yes)
   same => n,Dial(SIP/t38gw/${EXTEN:11:8})

Send the fax

Just before we go ahead, it is better to use a source tiff supported by Asterisk, eg, the one created by ReceiveFAX.

We also need to check the UDPTL ports are opened for t38 traffic.  These ports are defined in /etc/asterisk/udptl.conf.


We start by calling the 'sendfax' hylafax command, passing in the source tiff and required utf8 tagline string.  The selected iaxmodem is then dialed and t30 audio is passed via the iax channel to the t38 partner via Asterisk which acts as t38 gateway.


We could get detailed logging of the t38 session with below commands.
sip set debug on
rtp set debug on
udptl set debug on

The log should show the t38 capabilities reported by both sides in a fax session.  One possible reason for failed fax is the incorrect value of t38 datagram.  Note the use of t38pt_udptl = yes,redundancy,maxdatagram=400 to override the datagram value returned by the t38 receiver which incorrectly advertises a tiny datagram value such as 72.

Another problem we might see is the 'RTP read too short' error.  It is worthwhile to check whether we disable jitter buffer along the audio path upon seeing this error .

Tuesday, June 26, 2012

How to send attachment with unix 'mail' command

We can send attachment with the uuencode command as below:

uuencode file-to-be-attached  file-to-be-attached | mail -s "subject" send-to -- -r send-from

the 1st parameter to uuencode is the file to be attached while the 2nd parameter is the filename seen by the recipient.

In case uuencode command is not found on your system, you can get it as below:

yum install sharutils

Saturday, June 16, 2012

MOH not working in Asterisk 1.4.x

According to Asterisk documentation, we need to answer a channel before playing back or moh.

In 1.4.x, if you encounter problem where moh is not working even after answer, you might fix it as below:

exten => s, 1, Answer
exten => s, n, SetMusicOnHold(default)
exten => s, n, Playback(silence/1) ; play back something to trigger the audio flow
exten => s, n, Queue(myqueue)

Friday, May 04, 2012

Call forward from Elastix to PSTN via SIP trunk fails

This article applies to Elastix 2.0.0-36.

In Elastix, we might see failed call forward (CF) if the call path is:

PSTN-->Elastix-->Call Forward->SIP trunk->PSTN

The reason is that most SIP trunk providers routes call only if the call
is from a registered caller. In the case above, the caller is indeed
the outside party and therefore CF fails.

To circumvent this problem, we should configure SIP trunk as below.

Outbound Caller ID: <a valid CID for this trunk>
CID Options: Block Foreign CIDs

That instructs Elastix to send the trunk CID instead of foreign CID.
CID defined for user/extensions are transmitted.

Wednesday, March 14, 2012

sendmail: unable to qualify my own domain name

In /var/log/maillog, if we see messages like 'unable to qualify my own domain name' and it takes abnormally long time for sendmail to restart, it is likely due to sendmail failing to find the FQDN of your host.

Look in /etc/hosts, you should append host name at the end:               localhost.localdomain localhost your-host-name


Sunday, March 04, 2012

Multi-company agent queues

Recently, we helped a customer to build a call center whereas his agent team needs to answer incoming calls for 4 companies.  The below requirements are of high priority.

  • agent is able to identify which company is being called so that she could prepare the appropriate greetings
  • company-specific call queue configurations (greetings, queue length, timeout, voicemail,agent structure)
  • call is sent to agent in specific order such that customer always talk to the more experienced agent first
  • visitor is sent to voicemail directly during non-office hours
  • calls must not go to agent's personal voicemail; they have to be circulated within the agent team until answered or queue timeout.

In the first place, we subscribed 4 HK DID from a HK ITSP and make changes in /etc/sip.conf below.

register => xxxxxxxx,secret@itsp_trunk
; we need to let this itsp know our SIP contact via REGISTRATION
; for receiving incoming calls
; this 'register' is required by this particular itsp

type = friend
host = itsp_trunk_ip
username = xxxxxxxx ; info required to send calls to itsp
secret = secret
nat = yes
disallow = all
allow = alaw,ulaw,gsm
canreinvite = no
dtmfmode = rfc2833
insecure = port,invite
context = agent_team

Next, we create 4 Asterisk queues and send them the corresponding calls in dial plan.  The company being called is shown as caller name on the agents' Grandstream IP Phones.
Specific call distribution order is achieved by queue member penalty.  Member with lower penalty always get call first.
GotoIfTime() is used to send visitor to voicemail during non-office hours.
The company-specific greetings, busy messages and non-office hour messages are put in /var/lib/asterisk/sounds/customized.

We also use a member timeout of 15s so as to avoid connecting to agent's personal voicemail (which has a longer timeout).

; queues of other 3 companies are defined similary
strategy = ringall
maxlen = 5
ringinuse = no
timeout = 15 ; we ring a member for 15s before considering timeout and ring the next agent
member => SIP/tina,1
member => SIP/johnson,2
member => SIP/may,2
member => SIP/kathy,3

; the DID numbers are 5804xxxx
exten => _XXXXXXXX,1,noop(Enter Queue)
exten => _XXXXXXXX,n,Set(company=${IF($[ ${EXTEN} = 58041231]?company-a)})
exten => _XXXXXXXX,n,Set(company=${IF($[ ${EXTEN} = 58041232]?company-b:${company})})
exten => _XXXXXXXX,n,Set(company=${IF($[ ${EXTEN} = 58041233]?company-c:${company})})
exten => _XXXXXXXX,n,Set(company=${IF($[ ${EXTEN} = 58041234]?company-d:${company})})

; we jump to 'closed' extension after office hours
exten => _XXXXXXXX,n,GotoIfTime(18:15-09:00,mon-fri,*,*?closed)
exten => _XXXXXXXX,n,GotoIfTime(*,sat-sun,*,*?closed)
exten => _XXXXXXXX,n(office-hr),answer
exten => _XXXXXXXX,n,wait(1)
exten => _XXXXXXXX,n,Playback(customized/${company}-greeting)
; agent ip phone will show the company as caller name
; so she could prepare greetings accordingly
exten => _XXXXXXXX,n,Set(CALLERID(name)="${company}")
exten => _XXXXXXXX,n,Queue(${company}-queue|Tt|||180)
exten => _XXXXXXXX,n,Playback(customized/${company}-busy)
exten => _XXXXXXXX,n,Voicemail(${EXTEN}@agent_team)
exten => _XXXXXXXX,n,Hangup()
exten => _XXXXXXXX,n(closed),Playback(customized/${company}-after-hours)
exten => _XXXXXXXX,n,Voicemail(${EXTEN}@agent_team)
exten => _XXXXXXXX,n,Hangup()

; each agent queue has its own voicemail
; where the voicemail name is same as the DID number
XXXXXXXX => XXXXXXXX,company-a,,,attach=yes|format=wav49
; the other 3 voicemails are defined similarly