Skip to content

trzsz/tsshd

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

84 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

tsshd: UDP-based SSH Server with Roaming Support

MIT License GitHub Release 中文文档

tsshd is a UDP-based SSH server built for unreliable networks. It supports seamless roaming across networks and IP changes, and works well on high-latency links such as cellular connections and unstable Wi-Fi.

tsshd aims to be fully compatible with OpenSSH while providing additional capabilities:

  • Survives sleep, wake, and temporary network loss.
  • Roams seamlessly across networks and IP changes.
  • Supports UDP port forwarding (Local and Remote).

Comparison

tsshd was inspired by mosh, and the tsshd works like mosh-server, while the tssh --udp works like mosh.

Feature mosh ( mosh-server ) tssh ( tsshd )
Low Latency ?? KCP
Keep Alive
Client Roaming
Local Echo & Line Editing Not Planned
Multi Platform / Windows mosh#293
SSH X11 Forwarding mosh#41
SSH Agent Forwarding mosh#120
SSH Port Forwarding mosh#337
Output Scrollback mosh#122
OSC52 Sequence mosh#637
ProxyJump mosh#970
tmux -CC Integration mosh#1078

tssh and tsshd works exactly like ssh, there are no plans to support local echo and line editing, and will not have the mosh issues: mosh#1041, mosh#1281, mosh#1295, etc.

How to use

  1. Install tssh on the client ( your local machine ).

  2. Install tsshd on the server ( the remote host ).

  3. Use tssh --udp xxx to log in. The usage is the same as standard SSH.

    • Latency-sensitive users can specify the --kcp option.
    • Alternatively, configure the following in ~/.ssh/config to omit the --udp or --kcp option:
      Host xxx
          #!! UdpMode  ( Yes | QUIC | KCP )
      

How it works

  • The tssh plays the role of ssh on the client side, while the tsshd acts as sshd on the server side.

  • The tssh first logs in to the server normally as an ssh client, and then starts a new tsshd process on the server, where each session has its own tsshd process.

  • The tsshd process listens on a random UDP port in the range 61001–61999 (configurable via TsshdPort), and sends the port number and session secret keys back to the tssh process through the SSH channel. The SSH connection is then closed, and tssh communicates with tsshd over UDP.

Installation

  • Install with apt on Ubuntu

    sudo apt install tsshd
    sudo apt update && sudo apt install software-properties-common
    sudo add-apt-repository ppa:trzsz/ppa && sudo apt update
    
    sudo apt install tsshd
  • Install with apt on Debian

    sudo apt install tsshd
    sudo apt install curl gpg
    curl -s 'https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x7074ce75da7cc691c1ae1a7c7e51d1ad956055ca' \
      | gpg --dearmor -o /usr/share/keyrings/trzsz.gpg
    echo 'deb [signed-by=/usr/share/keyrings/trzsz.gpg] https://ppa.launchpadcontent.net/trzsz/ppa/ubuntu jammy main' \
      | sudo tee /etc/apt/sources.list.d/trzsz.list
    sudo apt update
    
    sudo apt install tsshd
  • Install with yum on Linux

    sudo yum install tsshd
    • Install with gemfury repository.

      echo '[trzsz]
      name=Trzsz Repo
      baseurl=https://yum.fury.io/trzsz/
      enabled=1
      gpgcheck=0' | sudo tee /etc/yum.repos.d/trzsz.repo
      
      sudo yum install tsshd
    • Install with wlnmp repository. It's not necessary to configure the epel repository for tsshd.

      curl -fsSL "https://sh.wlnmp.com/wlnmp.sh" | bash
      
      sudo yum install tsshd
  • Install with yay on ArchLinux

    yay -S tsshd
    yay -Syu
    yay -S tsshd
  • Install with Homebrew on MacOS

    brew install tsshd
    brew install tsshd
  • Install with scoop on Windows

    scoop install tsshd
    scoop bucket add extras
    scoop install tsshd

    Need to allow C:\Users\<user>\scoop\apps\tsshd\<version>\tsshd.exe through the firewall for it to work properly.

  • Install with Go ( Requires go 1.25 or later )

    go install github.com/trzsz/tsshd/cmd/tsshd@latest
    # latest release
    go install github.com/trzsz/tsshd/cmd/tsshd@latest
    
    # latest development version (main branch)
    go install github.com/trzsz/tsshd/cmd/tsshd@main

    The binaries are usually located in ~/go/bin/ ( C:\Users\your_name\go\bin\ on Windows ).

  • Build from source ( Requires go 1.25 or later )

    sudo make install
    git clone --depth 1 https://github.com/trzsz/tsshd.git
    cd tsshd
    make
    sudo make install
  • Download from the GitHub Releases and install locally

    download and install locally
    sudo apt install /tmp/tsshd_*.deb
    
    sudo dpkg -i /tmp/tsshd_*.deb
    
    sudo dnf install /tmp/tsshd_*.rpm
    
    sudo yum install /tmp/tsshd_*.rpm
    
    sudo rpm -i /tmp/tsshd_*.rpm
    
    tar zxvf tsshd_*.tar.gz && sudo cp tsshd_*/tsshd /usr/bin/

Supported Terminals

The following clients or terminals support the tsshd server:

  • trzsz-ssh ( tssh ) – An SSH client designed as a drop-in replacement for the OpenSSH client.

  • rootshell - A free, Metal-accelerated terminal emulator for iPhone, iPad, Vision Pro, and Mac.

Reconnection

┌───────────────────────┐                ┌───────────────────────┐
│                       │                │                       │
│    tssh (process)     │                │    tsshd (process)    │
│                       │                │                       │
│ ┌───────────────────┐ │                │ ┌───────────────────┐ │
│ │                   │ │                │ │                   │ │
│ │  KCP/QUIC Client  │ │                │ │  KCP/QUIC Server  │ │
│ │                   │ │                │ │                   │ │
│ └───────┬───▲───────┘ │                │ └───────┬───▲───────┘ │
│         │   │         │                │         │   │         │
│         │   │         │                │         │   │         │
│ ┌───────▼───┴───────┐ │                │ ┌───────▼───┴───────┐ │
│ │                   ├─┼────────────────┼─►                   │ │
│ │   Client  Proxy   │ │                │ │   Server  Proxy   │ │
│ │                   ◄─┼────────────────┼─┤                   │ │
│ └───────────────────┘ │                │ └───────────────────┘ │
└───────────────────────┘                └───────────────────────┘
  • The client KCP/QUIC Client and Client Proxy are on the same machine and in the same process, and the connection between them will not be interrupted.

  • The server KCP/QUIC Server and Server Proxy are on the same machine and in the same process, and the connection between them will not be interrupted.

  • If the client doesn't receive a heartbeat from the server for a period of time, it might be due to network changes causing the original connection to be interrupted. In this case, the Client Proxy will re-establish a connection to the Server Proxy, and communicate through the new connection after successful authentication. From the perspective of the KCP/QUIC Client and the KCP/QUIC Server, the connection is never interrupted.

Security Model

  • Client Proxy and KCP/QUIC Client run in the same process, and Server Proxy and KCP/QUIC Server run in the same process on the server. The proxy implements the net.PacketConn interface, so packets are exchanged directly in memory rather than through the local network stack. This prevents other local processes from intercepting or injecting packets.

  • Server Proxy accepts packets from only one authenticated client address at a time. If the client reconnects from a new IP or port (for example after a network change), the new Client Proxy must authenticate again. Once authenticated, the new address replaces the previous one and packets from the old address are ignored.

  • When a Client Proxy connects or reconnects, it sends an authentication packet encrypted with AES-256-GCM. The encryption key is a session-specific key generated by the server and delivered to the client through the SSH channel during login.

  • The Server Proxy verifies the client ID and ensures that the authentication sequence number is strictly monotonically increasing across all previously observed authentication packets to prevent replay attacks. Upon successful verification, the server marks the client address as authenticated and responds with an encrypted authentication acknowledgment.

  • Communication between the client and server uses encrypted transports provided by kcp-go or quic-go. QUIC uses TLS 1.3 as the underlying security protocol to ensure confidentiality and integrity of transmitted data, and supports key updates throughout the connection lifecycle. For KCP, a custom rekey mechanism is implemented to periodically rotate encryption keys with forward secrecy, ensuring that all traffic remains encrypted end-to-end.

Configurations

Server Configuration (tsshd)

  • By default, tsshd reuses OpenSSH configuration (default /etc/ssh/sshd_config on Unix-like systems), ensuring behavior is consistent with OpenSSH.

  • If $XDG_CONFIG_HOME/tsshd/sshd_config exists (default ~/.config/tsshd/sshd_config), tsshd prefers it over the OpenSSH config, even if it is empty.

Client Configuration (tssh)

Host xxx
    #!! UdpMode Yes
    #!! TsshdPort 61001-61999
    #!! TsshdPath ~/go/bin/tsshd
    #!! UdpAliveTimeout 86400
    #!! UdpHeartbeatTimeout 3
    #!! UdpReconnectTimeout 15
    #!! ShowNotificationOnTop yes
    #!! ShowFullNotifications yes
    #!! UdpProxyMode UDP
    #!! UdpMTU 1400
  • UdpMode: No (the default: tssh works in TCP mode), Yes (default protocol: QUIC), QUIC (QUIC protocol: faster speed), KCP (KCP protocol: lower latency).

  • TsshdPort: Specifies the port range that tsshd listens on, default is [61001, 61999]. You can specify multiple discrete ports (e.g., 6022,7022) or multiple discrete ranges (e.g., 8010-8020,9020-9030,10080); tsshd will randomly choose an available port. You can also specify the port on the command line using --tsshd-port.

  • TsshdPath: Specifies the path to the tsshd binary on the server, lookup in $PATH if not configured. You can also specify the path on the command line using --tsshd-path.

  • UdpAliveTimeout: If the disconnection lasts longer than UdpAliveTimeout in seconds, tssh and tsshd will both exit, and no longer support reconnection. The default is 86400 seconds.

  • UdpHeartbeatTimeout: If the disconnection lasts longer than UdpHeartbeatTimeout in seconds, tssh will try to reconnect to the server by a new path. The default is 3 seconds.

  • UdpReconnectTimeout: If the disconnection lasts longer than UdpReconnectTimeout in seconds, tssh will display a notification indicating that the connection has been lost. The default is 15 seconds.

  • ShowNotificationOnTop: Whether the connection loss notification is displayed on the top. The default is yes, which may overwrite some of the previous output. Set it to No to display notifications on the current line of the cursor.

  • ShowFullNotifications: Whether to display the full notifications or a brief notification. The default is yes, which may output several lines to the screen. Set it to No will output only one line.

  • UdpProxyMode: The default transport protocol is UDP. If UDP traffic is blocked by firewalls in your network environment, you can set it to TCP to work around the restriction, though this may introduce additional latency.

  • UdpMTU: Sets the maximum transmission unit (MTU) for UDP packets. Default is 1400.

UDP Port Forwarding

When using tssh as the client, UDP port forwarding is supported.

  • Command-line -L / -R options are extended with a udp/ prefix (the / can also be replaced with :, _, or -):

    -L udp/[bind_address:]port:host:hostport
    -L udp:[bind_address:]port:/remote_socket
    -L udp_/local_socket:host:hostport
    -L udp-/local_socket:/remote_socket
    
    -R udp/[bind_address:]port:host:hostport
    -R udp:[bind_address:]port:/local_socket
    -R udp_/remote_socket:host:hostport
    -R udp-/remote_socket:/local_socket
    
  • Configuration is similar to LocalForward and RemoteForward, with an added UDP prefix (case-insensitive):

    UdpLocalForward [bind_address:]port host:hostport
    UdpLocalForward [bind_address:]port /remote_socket
    UdpLocalForward /local_socket host:hostport
    UdpLocalForward /local_socket /remote_socket
    
    UdpRemoteForward [bind_address:]port host:hostport
    UdpRemoteForward [bind_address:]port /local_socket
    UdpRemoteForward /remote_socket host:hostport
    UdpRemoteForward /remote_socket /local_socket
    
  • ForwardUdpTimeout: Sets the idle timeout for UDP forwarding sessions; the corresponding forwarding session will be cleared automatically if no data is sent or received within this period to free resources. Default is 5 minutes.

Contact

Feel free to email the author lonnywong@qq.com, or create an issue. Welcome to join the QQ group: 318578930.

Sponsor

❤️ Sponsor trzsz ❤️, buy the author a drink 🍺 ? Thank you for your support!

About

tsshd is a UDP-based SSH server built for unreliable networks. It supports seamless roaming across networks and IP changes, and works well on high-latency links such as cellular connections and unstable Wi-Fi.

Topics

Resources

License

Stars

Watchers

Forks

Sponsor this project

 

Contributors