Serial port proxy to TCP or TELNET
Project description
Ser2tcp
Simple proxy for connecting over TCP, TELNET or SSL to serial port
https://github.com/cortexm/ser2tcp
Features
- can serve multiple serial ports using pyserial library
- each serial port can have multiple servers
- server can use TCP, TELNET or SSL protocol
- TCP protocol just bridge whole RAW serial stream to TCP
- TELNET protocol will send every character immediately and not wait for ENTER, it is useful to use standard
telnetas serial terminal - SSL protocol provides encrypted TCP connection with optional mutual TLS (mTLS) client certificate verification
- servers accepts multiple connections at one time
- each connected client can sent to serial port
- serial port send received data to all connected clients
- non-blocking send with configurable timeout and buffer limit
Installation
pip install ser2tcp
or from source:
pip install .
Uninstall
pip uninstall ser2tcp
Command line options
-h, --help show this help message and exit
-V, --version show program's version number and exit
-v, --verbose Increase verbosity
-u, --usb List USB serial devices and exit
-c CONFIG, --config CONFIG
configuration in JSON format
Verbose
- By default print only ERROR and WARNING messages
-v: will print INFO messages-vv: print also DEBUG messages
Configuration file example
[
{
"serial": {
"port": "/dev/ttyUSB0",
"baudrate": 115200,
"parity": "NONE",
"stopbits": "ONE"
},
"servers": [
{
"address": "127.0.0.1",
"port": 10001,
"protocol": "tcp"
},
{
"address": "0.0.0.0",
"port": 10002,
"protocol": "telnet",
"send_timeout": 5.0,
"buffer_limit": 65536
}
]
}
]
Serial configuration
serial structure pass all parameters to serial.Serial constructor from pyserial library, this allows full control of the serial port.
USB device matching
Instead of specifying port directly, you can use match to find device by USB attributes:
{
"serial": {
"match": {
"vid": "0x303A",
"pid": "0x4001",
"serial_number": "dcda0c2004bc0000"
},
"baudrate": 115200
}
}
Use ser2tcp --usb to list available USB devices with their attributes:
$ ser2tcp --usb
/dev/cu.usbmodem1101
vid: 0x303A
pid: 0x4001
serial_number: dcda0c2004bc0000
manufacturer: Espressif Systems
product: Espressif Device
location: 1-1
Match attributes: vid, pid, serial_number, manufacturer, product, location
- Wildcard
*supported (e.g."product": "CP210*") - Matching is case-insensitive
- Error if multiple devices match the criteria
- Device is resolved when client connects, not at startup (device does not need to exist at startup)
baudrateis optional (default 9600, CDC devices ignore it)
Server configuration
| Parameter | Description | Default |
|---|---|---|
address |
Bind address | required |
port |
TCP port | required |
protocol |
tcp, telnet or ssl |
required |
ssl |
SSL configuration (required for ssl protocol) |
- |
send_timeout |
Disconnect client if data cannot be sent within this time (seconds) | 5.0 |
buffer_limit |
Maximum send buffer size per client (bytes), null for unlimited |
null |
SSL configuration
For ssl protocol, add ssl object with certificate paths:
{
"address": "0.0.0.0",
"port": 10003,
"protocol": "ssl",
"ssl": {
"certfile": "/path/to/server.crt",
"keyfile": "/path/to/server.key",
"ca_certs": "/path/to/ca.crt"
}
}
| Parameter | Description | Required |
|---|---|---|
certfile |
Server certificate (PEM) | yes |
keyfile |
Server private key (PEM) | yes |
ca_certs |
CA certificate for client verification (mTLS) | no |
If ca_certs is specified, clients must provide a valid certificate signed by the CA.
Creating self-signed certificates
Generate CA and server certificate for testing:
# Create CA key and certificate
openssl genrsa -out ca.key 2048
openssl req -new -x509 -days 365 -key ca.key -out ca.crt -subj "/CN=ser2tcp CA" \
-addext "basicConstraints=critical,CA:TRUE" \
-addext "keyUsage=critical,keyCertSign,cRLSign"
# Create server key and certificate signing request
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr -subj "/CN=localhost"
# Sign server certificate with CA
openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt
# For certificate bound to specific domain/IP (SAN - Subject Alternative Name):
openssl req -new -key server.key -out server.csr -subj "/CN=myserver.example.com" -addext "subjectAltName=DNS:myserver.example.com,DNS:localhost,IP:192.168.1.100"
openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -copy_extensions copy
# Clean up CSR
rm server.csr
For mTLS (mutual TLS with client certificates):
# Create client key and certificate
openssl genrsa -out client.key 2048
openssl req -new -key client.key -out client.csr -subj "/CN=client"
openssl x509 -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt
rm client.csr
Testing SSL connection:
# Without client certificate
openssl s_client -connect localhost:10003
# With client certificate (mTLS)
openssl s_client -connect localhost:10003 -cert client.crt -key client.key
Usage examples
ser2tcp -c ser2tcp.conf
Direct running from repository:
python run.py -c ser2tcp.conf
Connecting using telnet
telnet localhost 10002
(to exit telnet press CTRL + ] and type quit)
Installation as service
Linux - systemd user service
- Copy service file:
cp ser2tcp.service ~/.config/systemd/user/ - Create configuration file
~/.config/ser2tcp.conf - Reload user systemd services:
systemctl --user daemon-reload - Start and enable service:
systemctl --user enable --now ser2tcp - To allow user services running after boot you need to enable linger (if this is not configured, then service will start after user login and stop after logout):
sudo loginctl enable-linger $USER
Linux - systemd system service
- Create system user:
sudo useradd -r -s /usr/sbin/nologin -G dialout ser2tcp - Copy service file:
sudo cp ser2tcp-system.service /etc/systemd/system/ser2tcp.service - Create configuration file
/etc/ser2tcp.conf - Reload systemd and start service:
sudo systemctl daemon-reload sudo systemctl enable --now ser2tcp
Useful commands
# Check status
systemctl --user status ser2tcp
# View logs
journalctl --user-unit ser2tcp -e
# Restart
systemctl --user restart ser2tcp
# Stop
systemctl --user stop ser2tcp
For system service, use sudo systemctl instead of systemctl --user.
Requirements
- Python 3.8+
- pyserial 3.0+
Running on
- Linux
- macOS
- Windows
Credits
(c) 2016-2026 by Pavel Revak
Support
- Basic support is free over GitHub issues.
- Professional support is available over email: Pavel Revak.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ser2tcp-2.2.0.tar.gz.
File metadata
- Download URL: ser2tcp-2.2.0.tar.gz
- Upload date:
- Size: 20.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9407dc5620e92130bbe5d5c5c754fbc2bb848791b19b424b5ed9dda9246cadae
|
|
| MD5 |
6709023eeb3b69f54922b584e788c0df
|
|
| BLAKE2b-256 |
59e9212fd73e00ffabc1881b1a69df609501c37cc8d2edeaaa11fee1135a0648
|
Provenance
The following attestation bundles were made for ser2tcp-2.2.0.tar.gz:
Publisher:
publish.yml on cortexm/ser2tcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ser2tcp-2.2.0.tar.gz -
Subject digest:
9407dc5620e92130bbe5d5c5c754fbc2bb848791b19b424b5ed9dda9246cadae - Sigstore transparency entry: 1132462169
- Sigstore integration time:
-
Permalink:
cortexm/ser2tcp@a358d70710095a36ecbf85c295b535ae8aafa07b -
Branch / Tag:
refs/tags/v2.2.0 - Owner: https://github.com/cortexm
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@a358d70710095a36ecbf85c295b535ae8aafa07b -
Trigger Event:
release
-
Statement type:
File details
Details for the file ser2tcp-2.2.0-py3-none-any.whl.
File metadata
- Download URL: ser2tcp-2.2.0-py3-none-any.whl
- Upload date:
- Size: 15.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
89cad6d9e95ef68b7b76e9f015eea61a8d2fc0676fca1be915bdc24edc524822
|
|
| MD5 |
f75ed828526fe398c4eb3ca8fdf38160
|
|
| BLAKE2b-256 |
5bc4d418dfc1b0f73756e7d8202c108a554b3208d1d5ccd0b8425016c34f8842
|
Provenance
The following attestation bundles were made for ser2tcp-2.2.0-py3-none-any.whl:
Publisher:
publish.yml on cortexm/ser2tcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ser2tcp-2.2.0-py3-none-any.whl -
Subject digest:
89cad6d9e95ef68b7b76e9f015eea61a8d2fc0676fca1be915bdc24edc524822 - Sigstore transparency entry: 1132462236
- Sigstore integration time:
-
Permalink:
cortexm/ser2tcp@a358d70710095a36ecbf85c295b535ae8aafa07b -
Branch / Tag:
refs/tags/v2.2.0 - Owner: https://github.com/cortexm
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@a358d70710095a36ecbf85c295b535ae8aafa07b -
Trigger Event:
release
-
Statement type: