Staging
Contents
Prerequisites
Required hardware:
- A hardware modem (not a software modem/winmodem, must be the real deal)
- A computer to install linux on to talk to the a modem (Can be anything that a modern linux distribution will run on. Raspberry Pi, Pi clone, x86 machine, etc)
- A client device (windows 9x PC for example) with a modem
- Some form of PSTN to connect the two modems
The exact hardware I’ve used
- Generic x86_64 PC running Ubuntu Server 18.04
- Matrix “MX Modem” (more on this later)
- USB to RS232 serial adapter (DE-9) to connect to the modem (Must support hardware flow control)
- DE-9 to DB-25 serial adapter
- Linksys PAP2T analog telephone adapter (ATA)
- x86 based Windows 95 PC with a US Robotics Sportster 28800 ISA modem
Software used
- Ubuntu server 18.04
- PPP
- getty
- Asterisk
Choose your hardware
Modem hardware varies greatly but thankfully nothing special is required. This tutorial should work with any dial-up modem that presents itself as a serial device to the operating system.
The PSTN
We need a way to connect our modem (serving as an ISP) to clients. There are many ways to approach this:
- Use the actual PSTN via real phone lines
- Use a PBX to provide local connectivity
- Build your own circuity (not covered here, would require extra config as you would not have dial tone)
- Fake PSTN using VoIP ATAs and a software PBX
I've gone with the fourth option. Here's the breakdown:
- Asterisk, a VoIP PBX, is configured on the dial-in server to accept connections from two SIP client accounts and route calls between them.
- A Linksys PAP2T ATA, which supports two phone lines, is set up as both of those SIP clients connected to the PBX.
- The ISP side modem is connected to the first line and the client device is on the second line.
Asterisk set up
- Install asterisk
- Append configuration for the two SIP clients to the end of
/etc/asterisk/sip.conf[pap2t-ispmodem] context=default type=friend secret=password qualify=200 ; Qualify peer is no more than 200ms away host=dynamic ; This device registers with us directmedia=yes ; Send RTP directly to the peer to reduce latency and jitter regexten=881 nat=no [pap2t-client] context=default type=friend secret=password qualify=200 ; Qualify peer is no more than 200ms away host=dynamic ; This device registers with us directmedia=yes ; Send RTP directly to the peer to reduce latency and jitter regexten=882 nat=no
- Edit
/etc/asterisk/extensions.confand make two changes:
Search for[default](should be around line 672) and comment outinclude => demo
After that commented out line add a new line withexten => _X!,1,Dial(SIP/pap2t-ispmodem, 20)
The _X! tells this dial plan rule to match any number a client dials and send the call to the pap2t-ispmodem client - Enable the asterisk service so it starts on boot
sudo systemctl enable asterisk
-
Start asterisk
sudo systemctl start asterisk - Open the asterisk console to confirm your ATA lines are registered
sudo asterisk -rvvvv
dialupserver*CLI> sip show peers Name/username Host Dyn Forcerport Comedia ACL Port Status Description pap2t-client/pap2t-client 10.1.8.112 D No No 5061 OK (7 ms) pap2t-ispmodem/pap2t-ispm 10.1.8.112 D No No 5060 OK (6 ms) 2 sip peers [Monitored: 2 online, 0 offline Unmonitored: 0 online, 0 offline]
If you make changes to your configuration after starting asterisk you can use the
reloadcommand in the console to reload the configuration.
sudo apt-get install asterisk
ATA SIP Registration example:
-- Registered SIP 'pap2t-ispmodem' at 10.1.8.112:5060
> Saved useragent "Linksys/SPA2102-5.2.5" for peer pap2t-ispmodem
NOTICE[4253]: chan_sip.c:24592 handle_response_peerpoke: Peer 'pap2t-ispmodem' is now Reachable. (7ms / 200ms)
-- Registered SIP 'pap2t-client' at 10.1.8.112:5061
> Saved useragent "Linksys/SPA2102-5.2.5" for peer pap2t-client
NOTICE[4253]: chan_sip.c:24592 handle_response_peerpoke: Peer 'pap2t-client' is now Reachable. (5ms / 200ms)
Successful call example:
== Using SIP RTP CoS mark 5
> 0x7fa234059e30 -- Strict RTP learning after remote address set to: 10.1.8.112:16482
-- Executing [88567682@default:1] Dial("SIP/pap2t-client-00000002", "SIP/pap2t-ispmodem, 20") in new stack
== Using SIP RTP CoS mark 5
-- Called SIP/pap2t-ispmodem
-- SIP/pap2t-ispmodem-00000003 is ringing
> 0x7fa1f8252350 -- Strict RTP learning after remote address set to: 10.1.8.112:16384
-- SIP/pap2t-ispmodem-00000003 answered SIP/pap2t-client-00000002
-- Channel SIP/pap2t-ispmodem-00000003 joined 'simple_bridge' basic-bridge <5f9983eb-3f93-49d1-90b3-c91c545c2d38>
-- Channel SIP/pap2t-client-00000002 joined 'simple_bridge' basic-bridge <5f9983eb-3f93-49d1-90b3-c91c545c2d38>
> Bridge 5f9983eb-3f93-49d1-90b3-c91c545c2d38: switching from simple_bridge technology to native_rtp
> Remotely bridged 'SIP/pap2t-client-00000002' and 'SIP/pap2t-ispmodem-00000003' - media will flow directly between them
> 0x7fa1f8252350 -- Strict RTP learning after remote address set to: 10.1.8.112:16384
> 0x7fa234059e30 -- Strict RTP learning after remote address set to: 10.1.8.112:16482
-- Channel SIP/pap2t-client-00000002 left 'native_rtp' basic-bridge <5f9983eb-3f93-49d1-90b3-c91c545c2d38>
-- Channel SIP/pap2t-ispmodem-00000003 left 'native_rtp' basic-bridge <5f9983eb-3f93-49d1-90b3-c91c545c2d38>
== Spawn extension (default, 88567682, 1) exited non-zero on 'SIP/pap2t-client-00000002'
> 0x7fa1f8252350 -- Strict RTP learning after remote address set to: 10.1.8.112:16384
Whether you want to call this a Public Switched Telephone Network or a Private Switched Telephone Network is up to you (Thanks @itsybitsydots)
The dial-in-server
- Install Debian/Ubuntu/Raspbian per the usual methods (not covered here)
- Update to latest packages and reboot if required
- Connect USB to RS232 adaptor and confirm it shows up as /dev/ttyUSBXXX (
ls /dev/to check) In my case it presents as/dev/ttyUSB0
My serial adaptor is a "ID 1a86:7523 QinHeng Electronics HL-340 USB-Serial adaptor"
Full lsusb output:# sudo lsusb -v Bus 004 Device 003: ID 1a86:7523 QinHeng Electronics HL-340 USB-Serial adapter Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 1.10 bDeviceClass 255 Vendor Specific Class bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 8 idVendor 0x1a86 QinHeng Electronics idProduct 0x7523 HL-340 USB-Serial adapter bcdDevice 2.54 iManufacturer 0 iProduct 2 USB2.0-Ser! iSerial 0 bNumConfigurations 1 Configuration Descriptor: bLength 9 bDescriptorType 2 wTotalLength 39 bNumInterfaces 1 bConfigurationValue 1 iConfiguration 0 bmAttributes 0x80 (Bus Powered) MaxPower 96mA Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 0 bAlternateSetting 0 bNumEndpoints 3 bInterfaceClass 255 Vendor Specific Class bInterfaceSubClass 1 bInterfaceProtocol 2 iInterface 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x82 EP 2 IN bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0020 1x 32 bytes bInterval 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x02 EP 2 OUT bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0020 1x 32 bytes bInterval 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x81 EP 1 IN bmAttributes 3 Transfer Type Interrupt Synch Type None Usage Type Data wMaxPacketSize 0x0008 1x 8 bytes bInterval 1 Device Status: 0x0000 (Bus Powered) - Install ppp (and getty if your distro doesn’t have it by default)
sudo apt-get install ppp mgetty
- Many of the old guides were written when inittab was still around but its 2019 and systemd has taken over.
We need to create a systemd service for mgetty so edit/lib/systemd/system/mgetty.servicewith your text editor of choice with elevated privileges (sudo)[Unit] Description=External Modem Documentation=man:mgetty(8) Requires=systemd-udev-settle.service After=systemd-udev-settle.service [Service] Type=simple ExecStart=/sbin/mgetty /dev/ttyUSB0 Restart=always PIDFile=/var/run/mgetty.pid.ttyUSB0 [Install] WantedBy=multi-user.target
-
Configure mgetty by editing
/etc/mgetty/mgetty.configwith your text editor of choice with elevated privileges (sudo)
Comment out everything except the debug level and append the section for configuring the serial devicedebug 9 port ttyUSB0 port-owner root port-group dialout port-mode 0660 data-only yes ignore-carrier no toggle-dtr yes toggle-dtr-waittime 500 rings 2 #autobauding yes speed 9600
- Enable the mgetty service so it starts on boot
sudo systemctl enable mgetty.service
-
Start mgetty
sudo systemctl start mgetty.service - Configure ppp by editing
/etc/ppp/options
Like above comment out everything except these settings# Define the DNS server for the client to use ms-dns 8.8.8.8 # async character map should be 0 asyncmap 0 # Require authentication auth # Use hardware flow control crtscts # We want exclusive access to the modem device lock # Show pap passwords in log files to help with debugging show-password # Require the client to authenticate with pap +pap # If you are having trouble with auth enable debugging debug # Heartbeat for control messages, used to determine if the client connection has dropped lcp-echo-interval 30 lcp-echo-failure 4 # Cache the client mac address in the arp system table proxyarp # Disable the IPXCP and IPX protocols. noipx
- Create a device option file by editing
/etc/ppp/options.ttyUSB0
local lock nocrtscts 192.168.32.1:192.168.32.105 netmask 255.255.255.0 noauth proxyarp lcp-echo-failure 60
- Create the user used for PAP authentication
sudo useradd -G dialout,dip,users -m -g users -s /usr/sbin/pppd dial - Change the password (I set it to dial)
sudo passwd dial - Edit
/etc/ppp/pap-secretsand append the username and password (quotes included)
dial * "dial" * - Enable packet forwarding for IP4 by editing
/etc/sysctl.confnet.ipv4.ip_forward=1 -
Last step for the dial-up server is to configure the firewall to allow forwarding of traffic from PPP out onto the network (and off to the internet)
- On linux distros with iptables you need to add a line to
/etc/rc.localto enable masquerading. If your ethernet interface is named eth0 you would add this line:iptables -t nat -A POSTROUTING -s 192.168.32.0/24 -o eth0 -j MASQUERADE -
On modern Ubuntu installs ufw is used instead of iptables so the procedure is a bit different. Follow this guide but you can omit
-o eth0and use-s 192.168.32.0/24
https://help.ubuntu.com/lts/serverguide/firewall.html.en#ip-masquerading
- On linux distros with iptables you need to add a line to
sudo apt-get update sudo apt-get upgrade sudo reboot
Debugging
Choice of USB to RS232 adapter seems to be crucial and very finicky. The USB adapter Ive been using on a raspberry pi, which worked perfectly would not work a properly on a x86_64 debian system. To debug modem communication and baud rate use either minicom (or your editor of choice!) to open a session over serial. Sending the command AT followed by enter should result in your modem replying OK
I actually ran into a bug in Debian 9.5 with my ch341 based usb to serial where setting the baud rate was not working. (Seems to be this: https://bugzilla.redhat.com/show_bug.cgi?id=1235715)