Building a TCP console server for Windows and FreeBSD
25 Jul 2021 - tsp
Last update 25 Jul 2021
7 mins
A common problem: Sharing a single physical serial port on multiple machines - or
having to access a remote serial port for example for a machine interface, laboratory
equipment, etc. from a remote machine. Or having some annoying Windows (or some Linux version)
only Software required for some FPGAs or microcontrollers that should be used
to flash from a host running some sane open operating system while running the
tools on some isolated virtual machine on one of the XEN
VM hosts. Itās also a nice utility for small datacenter management in case one
has old machines that donāt offer more sophisticated remote management solutions
and wants to access the serial terminals of the machines via the network for manual
setup (like for example when renting root servers, etc.)
The solution: Running a console server thatās reachable via the network. In this
blog post a solution is described that builds on a set of software:
- Server side:
ser2net
to offer a serial (RS232, RS485, etc.) port via the
network, even allowing configuration using RFC2217.
- Unixoid clients (FreeBSD / Linux):
socat
to create a local virtual com port and establish the connection.
- Windows clients:
com0com
to create a local Null-Modem connection that offers two
interconnected virtual serial ports.
hub4com
that also includes com2tcp-rfc2217
which can connect
one side of the local virtual nullmodem ports to a remote RFC2217 service.
Server configuration (FreeBSD)
The server in this case is the host offering the physical serial ports. These might
be RS232 ports, RS485 interfaces or simple USB to TTL/CMOS serial converters.
Hardware (example)
The latest host I personally built consisted of (note: Links are Amazon
affiliate links, this pages author profits from qualified purchases):
Software
First one has to install the ser2net
service. On FreeBSD this is pretty
easy:
pkg install comms/ser2net
On Linux ser2net
is included in many package repositories. Itās configured
via the /usr/local/etc/ser2net.conf
file (/etc/ser2net.conf
on Linux).
Usually there is a sample configuration file thatās also deployed. The configuration
basically includes a list of ports that are exposed on dedicated ports. A typical
configuration line looks like:
7000:telnet:3600:/dev/ttyU0:57600 8DATABITS NONE 1STOPBIT remctl
This line would expose the device /dev/ttyU0
with a default BAUD rate
of 57600
bits per second on port 7000 with 8 bits per byte, no parity
and one stop bit. It would also allow remote control using RFC2217 which allows
the remote to set BAUD rate, byte size, parity and stop bits itself. ser2net
would also allow a raw
mode instead of telnet which is even more easy
when one develops own software - but telnet
mode is supported by the Windows
software mentioned later on.
The third value in the configuration file specifies a timeout value - if no traffic
is routed over the given port for the specified amount of seconds it gets disconnected
automatically.
One might also specify a custom banner thatās displayed on connection:
BANNER:banner:Serial host server
This might be interesting in case there are multiple devices in use to allow
easier manual identification.
After configuration one can auto-start ser2net
on every boot by adding
the setting to /etc/rc.conf
:
Since new rc.init
script system one might also simply use /usr/local/etc/rc.d/ser2net enable
.
After that one can manually start the service:
/usr/local/etc/rc.d/ser2net start
Client side
FreeBSD / Linux
This is rather simple - there is a utility called socat
. On FreeBSD this
is available at net/socat
and can simply be installed using pkg install net/socat
.
Itās also available in most Linux package repositories and preinstalled on many
systems.
To establish a serial port connection one simply executes socat
with the
desired port name:
socat pty,link=/dev/ttyS0,raw,echo=0 tcp:128.66.0.1:7000
In this case it will create the device /dev/ttyS0
on a pseudo terminal and
connect to 128.66.0.1
on port 7000
Microsoft Windows
As usual client configuration on Microsoft Windows is more cumbersome than on
more sane platforms. One first has to install the virtual null modem driver com0com
which requires one to disable driver signature checking at first:
- Select Reboot from the start menu while holding your shift key
- Select to reboot into Recovery options
- Select advanced options
- Press 7 to disable driver signature checking
After reboot you will be able to install com0com
thatās available on SourceForge.
The installer usually already creates a pair of COM ports for you. After that one
also required hub4com
thatās available at the same location.
This program just has to be unpacked into any desired location.
After the virtual COM port is available one can use the command line (cmd.exe
)
and establish a connection using the hub4com
utility:
com2tcp-rfc2217 \\.\COM4 128.66.0.1 7000
In this case the COM port name specifies one of the previously generated virtual
ports, the IP address (or hostname) is the name or address of the server exposing
the port and the last argument the port number.
C:\tools\hub4com>"hub4com" --create-filter=escparse,com,parse --create-filter=pinmap,com,pinmap:"--rts=cts --dtr=dsr" --create-filter=linectl,com,lc:"--br=local --lc=local" --add-filters=0:com --create-filter=telnet,tcp,telnet:" --comport=client" --create-filter=pinmap,tcp,pinmap:"--rts=cts --dtr=dsr --break=break" --create-filter=linectl,tcp,lc:"--br=remote --lc=remote" --add-filters=1:tcp --octs=off "\\.\COM4" --use-driver=tcp "*128.66.0.1:7000"
Open("\\.\COM4", baud=19200, data=8, parity=no, stop=1, octs=off, odsr=off, ox=off, ix=off, idsr=off, ito=0) - OK
Route data COM4(0) --> TCP(1)
Route data TCP(1) --> COM4(0)
Route flow control COM4(0) --> TCP(1)
Route flow control TCP(1) --> COM4(0)
Filters:
________
\->{parse.IN}----------------->
COM4(0) | /
________/<-----{pinmap.OUT}<-{lc.OUT}<-
_______
\->{telnet.IN}------------------------------>
TCP(1) | /
_______/<-----{telnet.OUT}<-{pinmap.OUT}<-{lc.OUT}<-
Socket(0.0.0.0:0) = 188
TCP(1): Connect(188, 128.66.0.1:7000) ...
Started COM4(0)
Started TCP(1)
TCP(1): Connected
TCP(1) START
TCP(1) SEND: WILL 44
TCP(1) SEND: SB 44
1 0 0 4 176 SE
TCP(1) SEND: SB 44
2 7 SE
TCP(1) SEND: SB 44
3 1 SE
TCP(1) SEND: SB 44
4 1 SE
TCP(1) SEND: SB 44
5 9 SE
TCP(1) SEND: SB 44
5 12 SE
TCP(1) SEND: SB 44
5 6 SE
TCP(1) RECV: WILL 3
TCP(1) SEND: DO 3
TCP(1) RECV: WILL 1
TCP(1) SEND: DO 1
TCP(1) RECV: DONT 1
TCP(1) RECV: DO 0
TCP(1) SEND: WILL 0
TCP(1) RECV: WILL 0
TCP(1) SEND: DO 0
TCP(1) RECV: SB 44
107 0 SE
TCP(1) RECV: DO 44
TCP(1) RECV: SB 44
101 0 0 4 176 SE
TCP(1) RECV: SB 44
102 7 SE
TCP(1) RECV: SB 44
103 1 SE
TCP(1) RECV: SB 44
104 1 SE
TCP(1) RECV: SB 44
105 9 SE
TCP(1) RECV: SB 44
105 12 SE
TCP(1) RECV: SB 44
105 6 SE
A quick note on security
Note that there is no authentication and no encryption done. The traffic
is open and the ports can be used by anyone whoās able to reach the service so:
- In the best case use this on a separate virtual network or physical network
- If this is not possible at least configure firewall rules in a way that only
desired clients are able to access the service.
- Never expose
ser2net
directly to the Internet (i.e. donāt publically expose
on machines not properly firewalled - even though such machines shouldnāt exist anyways)
Iām personally using ser2net
on machines that are either running on a separate
virtual network using VLANs or as a service thatās isolated using proper dynamic
OpenFlow configuration when assigning a port to a machine inside the cluster.
This article is tagged: