Setting Up Virtual Serial Ports and Modems in Linux

Introduction

A long time ago, in decades far, far away, before the Internet and TCP/IP, in the universe of digital telecommunications, serial communications reigned supreme. These were the days of RS-232 comports, modems and dial-up BBSes.

But this is current year. RS232 ports, screeching modems and dial-up BBSes are relics of a bygone era. And even should your computer still have a physical comport and you could manage to pick up an old modem at a flea sale, there's nothing to connect to; dial-up BBSes moved online decades ago. So what's a retro guy to do? Virtualize.

In this tutorial, for Linux users, we will install and configure three components:

tty0tty - null modem emulator; creates pairs of virtual comports connected by virtual null serial cables
tcpser - emulates a Hayes-compatible modem; creates piped tunnels between serial and tcp ports
minicom - communications package for communicating over a serial port

Before beginning, make sure your system is up-to-date and you have your kernel headers and source installed and the Linux development environment in place. For Debian-based distros, do the following:

$> sudo apt-get update
$> sudo apt-get install linux-headers-$(uname -r)
$> apt-get source linux-image-$(uname -r)
$> sudo apt-get install dpkg-dev

tty0tty—Virtual ComPorts

tty0tty is a kernel module that creates virtual serial ports that will look and behave exactly like physical RS232 hardware ports on your system. To install and configure tty0tty, run the following commands:

$> git clone https://github.com/freemed/tty0tty
$> cd tty0tty
$> make
$> cp pts/tty0tty /usr/local/bin/
$> sudo cp module/tty0tty.ko /lib/modules/$(uname -r)/kernel/drivers/misc/
$> sudo depmod
$> sudo modprobe tty0tty
$> sudo chmod 666 /dev/tnt*

To verify tty0tty is running, do:

$> ls -l /dev/tnt*
crw-rw-rw- 1 root root 246, 0 May 24 08:32 /dev/tnt0
crw-rw-rw- 1 root root 246, 1 May 24 08:32 /dev/tnt1
crw-rw-rw- 1 root root 246, 2 May 24 08:32 /dev/tnt2
crw-rw-rw- 1 root root 246, 3 May 24 08:32 /dev/tnt3
crw-rw-rw- 1 root root 246, 4 May 24 08:32 /dev/tnt4
crw-rw-rw- 1 root root 246, 5 May 24 08:32 /dev/tnt5
crw-rw-rw- 1 root root 246, 6 May 24 08:32 /dev/tnt6
crw-rw-rw- 1 root root 246, 7 May 24 08:32 /dev/tnt7

Make sure the permissions on the ports are set to crw-rw-rw-.

You'll undoubtedly want tty0tty to load whenever you start your system, so edit either /etc/modules or /etc/modules.conf (depending on which your system has) and add the line tty0tty.

Note: Should you ever update your Linux kernel, you will need to reinstall tty0tty.

We're now ready to install tcpser.

Virtual Modem—tcpser

tcpser is a virtual Hayes-compatible modem emulator which sits between a serial port and the internet, translating between RS232 and tcp/ip, so that anything talking to the comport will think it's seeing a Hayes modem. There are several ways to obtain tcpser.

Repositories

If tcpser is available in your Linux distro's repositories, this may be the easiest way to install it. Under Debian-based distros, do:

$> sudo apt-get install tcpser

Debian package

After Ubuntu 18.04 (Bionic) tcpser was removed from the Ubuntu repositories. However, the Debian .deb package can still be obtained and installed manually from the Bionic repositories. For the AMD64 version (visit here or here for other versions), do this:

$> wget http://security.ubuntu.com/ubuntu/pool/universe/t/tcpser/tcpser_1.0rc12-2build1_amd64.deb
$> deb tcpser_1.0rc12-2build1_amd64.deb
$> rm tcpser_1.0rc12-2build1_amd64.deb

Manual installation

If the above methods fail, there are two forks available at Github. To install from fozztexx (or see go4retro):

$> wget https://github.com/FozzTexx/tcpser/archive/master.zip
$> unzip master.zip
$> cd tcpser-master
$> make
$> sudo cp -p tcpser /usr/local/bin
$> rm master.zip

Run tcpser

Whichever method above you used to install tcpser, load it now:

$> sudo tcpser -d /dev/tnt1 -s 115200 -p 6400 -n5551212=vert.synchro.net:23

The above will load tcpser, establish a pipe between /dev/tnt1 and ip port 6400, set an emulated speed of 115200 baud, and associate the phone number 555-1212 with vert.synchro.net port 23. Anything communicating with /dev/tnt0 will now think it's talking to a Hayes modem. Run man tcpser or see here for much more info.

To verify that tcpser is running, run the following. If you get no response, tcpser is not running.

$> ps cax | grep tcpser
27106 pts/10 Sl 0:00 tcpser
27107 pts/10 Sl 0:00 tcpser
27108 pts/10 Sl 0:00 tcpser
27109 pts/10 Sl 0:00 tcpser

Comm Software—Minicom

minicom should also be available from your repository. Install and configure it.

$> sudo apt-get install minicom
$> sudo minicom -s

Select "Serial port setup", type "A" and change the default serial port to /dev/tnt0. <Esc> out, select "Save setup as dfl", then "Exit from minicom". Finally, restart minicom:

$> minicom

You should see something like this (note Port /dev/tnt0):

Welcome to minicom 2.7.1

OPTIONS: I18n
Compiled on Dec 23 2019, 02:06:26.
Port /dev/tnt0

Press CTRL-A Z for help on special keys

















CTRL-A Z for help | 115200 8N1 | NOR | Minicom 2.7 | ANSI | Offline | tnt0

If you see the message minicom: cannot open /dev/tnt0: Permission denied it probably means you forgot to change permissions on the virtual ports, so run sudo chmod 666 /dev/tnt* then start minicom.

So does it work? Type ATDT5551212 and press enter. Minicom should connect to the telnet BBS you configured tcpser for when you ran it (vert.synchro.net:23 in our example).

Minicom has a built-in phone directory, which you can access via Ctrl-A D. Here you can store frequently called numbers, but you'll need to associate each number to a BBS by adding -n parameters to the tcpser command line.

To exit minicom, type Ctrl-A X.

Epilogue

We're done. From now on, as long as tty0tty and tcpser are configured and running as above, anything talking to /dev/tnt0 will think it's seeing a Hayes-compatible modem. For its part, all serial communications sent to a tcpser virtual modem will be routed out its configured tcp/ip port, while traffic coming into that port will be routed to the virtual RS232 com port.

You can run additional instances of tcpser, attaching them to the odd-numbered /dev/tnt*, and each corresponding even-numbered /dev/tnt* will appear to have a modem connected. Just remember to change the assigned tcp/ip port to something unique for each virtual modem. And finally, while tty0tty defaults to four port-pairs, with a simple edit to the source, it can support up to 128 port pairs.