Joining the NPSTN.

15 February 2021

In a previous post I talked about what I had to do to get a classic touch tone telephone (wow, I didn't know how much they were going for on the collector's market...) onto my home network with some scrounged parts and a Cisco ATA. This is all well and good, but the question then becomes, what do I do with it? How do I make it do something actually useful? Or failing that, something interesting?

I also mentioned in a previous post that I'd considered putting up a Project MF node at home but it seems like it'd be more hassle than it'd be worth. I love working on stuff, but I do have a limit for how much time and effort I'll put into a fun project. So later that night I went wandering through my bookmark collection on my tablet before bed, which I do from time to time when I can't decide what to read. I presently came upon Famicoman, whose various works I've been following for a while. In particular, I stumbled across this article about something called NPSTN, which is a VoIP network for people who're into classic telephony. Basically, if you join you can get your own block of phone numbers on an isolated VoIP network to experiment with.

It didn't take me long to sign up for an account on the website and request a block of numbers. In the meantime over subsequent evenings I found a Raspberry Pi burning a hole in my shelf, which Famicoman remarked was plenty powerful enough to run an NPSTN switch. It didn't take me very long to install the latest build of Raspberry Pi OS (I much preferred the name Raspbian, but it's not my project so I'll deal) and follow his instructions for setting up Asterisk:

{22:57:25 @ Sat Jan 30}
[pi @ switch ~] (2) $ sudo -s

# A few pre-requisite packages need to be installed first.  I forgot a few
# at first and had to go back for them.
root@switch:/home/pi# apt-get install libedit-dev sqlite3 libsqlite3-dev libjansson-dev libxml2-dev uuid-dev lsof tcpdump libssl-dev libcurl4-openssl-dev subversion sox mpg123 festival php

root@switch:/home/pi# cd /usr/local/src/
root@switch:/usr/local/src# git clone https://gerrit.asterisk.org/asterisk
root@switch:/usr/local/src# cd asterisk/

# Lots and lots of output elided...
root@switch:/usr/local/src/asterisk# ./configure

# You can safely skip this step and use the more-than-adequate defaults,
# but I wanted to enable MP3 support.
root@switch:/usr/local/src/asterisk# make menuselect

root@switch:/usr/local/src/asterisk# contrib/scripts/get_mp3_source.sh

# I should have done `make -j3` to speed up compilation.
root@switch:/usr/local/src/asterisk# make

# Install the compiled binaries.
root@switch:/usr/local/src/asterisk# make install

# Install a basic set of configs.
root@switch:/usr/local/src/asterisk# make samples

# Install service management scripts appropriate to the platform.
root@switch:/usr/local/src/asterisk# make config

# Install scripts for logrotate to manage Asterisk's log files.
root@switch:/usr/local/src/asterisk# make install-logrotate

# I can has Asterisk?
root@switch:/usr/local/src/asterisk# systemctl start asterisk.service
root@switch:/usr/local/src/asterisk# ps ax | grep [a]sterisk
12367 ?        Ssl   41:22 /usr/sbin/asterisk

# Yeah!

Asterisk is now up and running. Now to configure it. Thankfully, Famicoman linked to the project docs, which includes links to a bunch of config files that already work so that you don't have to teach yourself Asterisk's config file language just to get a basic proof of concept setup online. What I did was back up the existing /etc/asterisk/*.conf files and download the ones from the docs, one at a time, and put them into /etc/asterisk. Keep in mind that until you get your UCP (User Control Panel) key (it's like an API key) you will not be able to test your Asterisk configuration fully. You will need to make some minor edits to those files to reflect your UCP, the block of phone numbers you'll be managing, and of course the SIP clients that you want to run on the network. However, the files' comments are reflective of most Asterisk config files' comments - they're terse and usually come at the end of the line, which makes it difficult to understand what's going due to line wrapping. Some of the comments also assume more knowledge of Asterisk than you probably have (I did a lot of googling while reading through them. So, to that end, I took my copies of some config files that needed to be edited (not just the project's boilerplate files), redacted the sensitive stuff, and uploaded them here to refer to.

One of those files is my /etc/asterisk/sip.conf file, which contains the login credentials for my SIP devices. The configuration blocks for them are much simpler than they probably otherwise would be because of this:

[ATAs](!)
type = peer
host = dynamic
disallow=all
allow=g722
allow=ulaw
allow=alaw
allow=g729
allow=gsm
allow=ilbc
allow=g726
qualify = yes
insecure = port,invite
canreinvite = no ; don't allow RTP voice traffic to bypass Asterisk
relaxdtmf = yes
progressinband = yes

It seems that Asterisk has a way of defining configuration blocks that can be inherited by other blocks to make the code less complex. Here it defines a SIP calling device, turns off all of the VoIP audio CODECs and re-enables them selectively, among a couple of other tweaks that I haven't analyzed yet to be honest. However, this makes setting up a SIP phone much easier on the server side:

 SIP login for a softphone.
[NXXY000](ATAs)
; This seems to mean the same thing as "authid."  The Asterisk docs say that
; defaultuser is preferable to using authid.
defaultuser = NXXY000

; This is the softphone's password on the switch.
secret = The-King-Of-Nynex

; This is the softphone's username on the switch.
authid = NXXY000

; Caller ID records are user definable.
callerid = "Phantom Phreak <NXX-Y000>"
context = from-internal

After getting all of those config files in place I restarted Asterisk (systemctl restart asterisk.service) so the new settings would take effect. Then it was time for a basic test with a phone. In this case I used a software phone called Twinkle, which has been around for quite a few years (last time I used it was 2006) and is fairly easy to use. Creating a profile in Twinkle was pretty straightforward:

  • Your Name: Phantom Phreak
  • User name: NXXY000
  • Domain: switch (the hostname of my Asterisk box)
  • Authentication name: NXXY000
  • Password: The-King-Of-Nynex
  • Registrar: switch (the hostname of my Asterisk box)
  • Expiry: 3600 seconds (one hour)
  • Register at startup? yes (i.e., log into Asterisk on startup)

Most of the configuration stuff involves mapping "stuff I already know about," like usernames and passwords to "stuff Asterisk calls stuff I already know about," such as "secret" and "defaultuser". I guess it's because there are a couple of Asterisk certifications out there, and certs are always profitable.

So, how can you tell if it worked? While I am by no means an expert with Asterisk (I really should get around to teaching myself so I can post my notes) I did figure out how to tell if and how many registrations Asterisk knew about at one time. I logged into switch (my Asterisk box) and did the following:

{16:14:30 @ Sun Jan 31}
[pi @ switch ~] (2) $ sudo -s
root@switch:/home/pi# asterisk -r
Asterisk GIT-master-060ce10163, Copyright (C) 1999 - 2018, 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 GIT-master-060ce10163 currently running on switch (pid = 12367)
switch*CLI> sip show peers
Name/username             Host                                    Dyn Forcerport Comedia    ACL Port     Status      Description                      
NXXY000/2393000           192.168.0.113                            D  Yes        Yes            5060     OK (1223 ms)                                  
NXXY001/2393001           192.168.0.3                              D  Yes        Yes            5060     OK (57 ms)                                   
NXXY002/2393002           (Unspecified)                            D  Yes        Yes            0        UNKNOWN                                      
5551212/5551212           (Unspecified)                            D  Yes        Yes            0        UNKNOWN                                      
4 sip peers [Monitored: 2 online, 2 offline Unmonitored: 0 online, 0 offline]
switch*CLI>

Two online: My ATA and my softphone. Two offline: Another softphone and a phone for 555-1212. Success.

Now to finish configuring the Cisco ATA that I plugged my batphone into. Time to log back into its control panel as the admin user. As before, I'll try to make the ATA configuration stuff as generic as possible while still being usable with different devices. First I created another account in /etc/asterisk/sip.conf for the ATA and restarted Asterisk again:

; SIP login for an ATA.
[NXXY001](ATAs)
; This seems to mean the same thing as "authid."  The Asterisk docs say that
; defaultuser is preferable to using authid.
defaultuser = NXXY001

; This is the softphone's password on the switch.
secret = I-Got-A-Photographic-Memory

; This is the softphone's username on the switch.
authid = NXXY001

; Caller ID records are user definable.
callerid = "Lord Nikon <NXX-Y001>"
context = from-internal

Settings for the ATA:

  • Line 1's SIP proxy/server: the IP address of your Asterisk box
    • Not all ATAs can do DNS resolution. Mine doesn't unfortunately.
  • Name: Batphone
  • Auth ID/User ID/Username/Resident's Number/Online Number: NXXY001
    • These can be multiple configuration settings on the same unit. Give them all the same value. No, I don't know why there is so much redundancy.

That's pretty much it. If you pick up the phone plugged into the ATA you should hear a dialtone, which means that the ATA successfully registered with Asterisk and should be able to both make and receive calls. Dial the softphone (NXX-Y000) from the telephone in the ATA and the softphone should start ringing. Answer the softphone and talk to yourself over the VoIP connection, with a little extra lag. Victory.

Another thing you can do to test your setup is by dialing one of the test numbers defined in /etc/asterisk/extensions.conf. Try dialing the Echo Test number: NXX-Y931 (where NXX-Y is whatever four digits of phone lines the NPSTN admins have assigned you). If everything is working the Echo Test should pick up immediately and you should hear whatever sound you make into the phone coming back at you.

Here are the default test numbers defined for an NPSTN block:

  • NXX-Y931 - echo test
  • NXX-Y932 - silently picks up and does nothing

don't forget how to document how to poke holes so that the rest of NPSTN can see your switch!

Sometimes, for whatever reason, you just have to reboot your ATA to get it working again. VoIP is like that, unfortunately.