proxy

command module
v0.0.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 22, 2025 License: MIT Imports: 38 Imported by: 0

README

proxy

Go Report Card REUSE status Renovate enabled

Overview

The proxy program acts as a multi‑user terminal server and relay 📡, accepting incoming SSH client connections on the front‑end (listeners 👂) and proxying these connections to one or more TELNET servers on the back‑end (targets 🎯).

This project was originally developed to meet the needs of the BAN.AI Public Access Multics system and the DPS8M Simulator project, but may be useful to anyone who wants to offer SSH access to legacy systems.

Features

  • ✅ SSH ⟷ TELNET gateway
  • ✅ Full IPv6 support
  • ✅ Access control whitelist/blacklist (by IP address or CIDR block)
  • ✅ Independent console and session logging (by date/time and host)
  • ✅ Automatic log‑file compression (using gzip, xz, or zstandard)
  • ✅ Banners for accepted, denied, and blocked connections (configurable per target)
  • ✅ Session connection monitoring and idle time tracking (with optional timeouts)
  • ✅ Translation of SSH window‑change events to TELNET NAWS messages
  • ✅ Interactive connection management for administrators
  • ✅ User access to TELNET features (e.g., line BREAK, AYT) and statistics
  • ✅ Transparent key remapping mode (translating movement keys to Emacs sequences)
  • ✅ Optional support for management using systemd on Linux (running in a sandbox)
  • ✅ Link filtering
  • ✅ Live streaming connection sharing (read‑only)
    • 🤝 Allows users to share their session with one or more viewers

Usage

Installation

A recent version of Go 🐹 is required to build proxy from source code.

  • You can clone the git repository 🌱 and build the source code using make:

    git clone https://gitlab.com/dps8m/proxy.git
    cd proxy
    make
    
    • If you don’t have a (POSIX) make available for some reason, then building with go build is sufficient.

    • A .cross.sh cross‑compilation helper script is provided (which can be called with make cross) that attempts to build proxy binaries for all supported GOOS and GOARCH combinations. At the time of writing, 41 usable binaries are built for 12 operating systems (IBM AIX, Android, Apple macOS, Dragonfly BSD, FreeBSD, illumos, Linux, NetBSD, OpenBSD, Plan 9, Solaris, and Microsoft Windows) running on 13 different hardware architectures.

  • You can also install this software using go install 📦:

    go install gitlab.com/dps8m/proxy@latest
    
    • Installations using go install download the required sources, compile, and install the binary to ${GOEXE}/proxy (which will be ${HOME}/go/bin/proxy for most users).
Invocation
  • The proxy command can be invoked with the following command‑line arguments:
Usage of ./proxy:
  -0, --allow-root              Allow running as root (UID 0)
  -l, --ssh-addr strings        SSH listener address(es)
                                   [e.g., ":2222", "[::1]:8000"]
                                   (multiple allowed) (default ":2222")
  -n, --no-banner               Disable SSH connection banner
  -t, --telnet-host string      Default TELNET target [host:port]
                                   (default "127.0.0.1:6180")
  -a, --alt-host string         Alternate TELNET target(s) [sshuser@host:port]
                                   (multiple allowed)
  -d, --debug                   Debug TELNET option negotiation
  -G, --no-gops                 Disable the "gops" diagnostics agent
                                   (See https://github.com/google/gops)
  -L, --log-dir string          Base directory for logs (default "./log")
  -o, --no-log                  Disable all session logging
                                   (for console logging see "--console-log")
  -c, --console-log string      Enable console logging ["quiet", "noquiet"]
  -C, --compress-algo string    Compression algorithm ["gzip", "xz", "zstd"]
                                   (default "gzip")
  -s, --compress-level string   Compression level for gzip and zstd algorithms
                                   ["fast", "normal", "high"]
                                   (default "normal")
  -x, --no-compress             Disable session and console log compression
  -p, --log-perm octal          Permissions (octal) for new log files
                                   [ e.g., "600", "644"] (default "600")
  -P, --log-dir-perm octal      Permissions (octal) for new log directories
                                   [e.g., "755", "750"] (default "750")
  -i, --idle-max int            Maximum connection idle time allowed [seconds]
  -m, --time-max int            Maximum connection link time allowed [seconds]
  -b, --blacklist string        Enable blacklist [filename] (no default)
  -w, --whitelist string        Enable whitelist [filename] (no default)
  -D, --ssh-delay float         Delay for incoming SSH connections
                                   ["0.0" to "30.0" seconds] (no default)
  -v, --version                 Show version information

Most of these command‑line arguments are straightforward with usage that should be obvious, and those that require demystification are, hopefully, documented here:

  • Logging of sessions is enabled by default. Logging of console messages is disabled by default.

    • Console logging, if enabled, supports two modes: quiet and noquiet. In quiet mode, all non‑fatal messages are logged only to the log file, where in noquiet mode, messages are logged to both the console and the log file.
  • All incoming SSH users are connected to the default TELNET target, unless their supplied SSH username matches an alternate target enabled with the ‑‑alt‑host flag. The alt‑host syntax is sshuser@host:port, where sshuser is the SSH username, and the host:port is the TELNET target.

  • All users connecting with SSH are shown a banner which includes details such as the date and time of the session, their IP address, and possibly a resolved host name. This can be disabled with ‑‑no‑banner.

  • The ‑‑no‑banner command disables only those lines described above. It does not disable the file‑based banner content. These are the three primary text files which can be displayed to connecting SSH users:

    File Purpose
    block.txt Displayed before disconnecting connections matching the blacklist
    deny.txt Displayed when denying target sessions (e.g., during graceful shutdown)
    issue.txt Displayed to users before their actual session with the target begins
    • When multiple are targets defined using the ‑‑alt‑host functionality, the system will display a file that matches ‑NAME before the .txt extension. For example, if you have defined a target as oldunix@10.0.5.9:3333 the proxy will look for block‑oldunix.txt, deny‑oldunix.txt, and issue‑oldunix.txt files to serve to the connected user, before beginning their session with the target (via TELNET to 10.0.5.9:3333). If any of the target‑specific text files do not exist, then the standard files will be served.
    • To disable the file‑based banner for specific targets only, you can create empty files using the naming scheme described above. You can also remove all of these files if you don’t want to use this functionality.
  • You need to start proxy using the ‑‑whitelist and/or ‑‑blacklist argument to enable the access control functionality. If only the whitelist is enabled, then all connections will be denied by default. Note that if only the whitelist is enabled, it will be impossible to exempt individual IP addresses within a range that has been blocked. It is recommended that you both lists when using the access control feature.

    • The format of the whitelist and blacklist is an IPv4 or IPv6 address (e.g., 23.215.0.138, 2600:1406:bc00:53::b81e:94ce), or a CIDR block (e.g., 123.45.0.0/17 which covers 123.45.0.0 to 123.45.127.255, or 2600:1408:ec00:36::/64 covering 2600:1408:ec00:36:0000:0000:0000:0000 to 2600:1408:ec00:36:ffff:ffff:ffff:ffff).

    • The whitelist always takes precedence over the blacklist. If an address is allowed due to a whitelist match that would have otherwise been blocked by the blacklist, it is tagged as EXEMPTED in the logs.

  • The ‑v or ‑‑version command shows detailed version information, including the versions of any embedded dependencies as well as the version of the Go compiler used to build the software:

DPS8M Proxy v0.0.4 (2025-Jul-22 g5c43905) [linux/amd64]

+===========================+=========+
| Component                 | Version |
+===========================+=========+
| dps8m/proxy               | v0.0.4  |
| google/gops               | v0.3.28 |
| klauspost/compress        | v1.18.0 |
| spf13/pflag               | v1.0.7  |
| ulikunitz/xz              | v0.5.12 |
| golang.org/x/crypto       | v0.40.0 |
| golang.org/x/sys          | v0.34.0 |
| golang.org/x/term         | v0.33.0 |
| kernel.org/.../libcap/cap | v1.2.76 |
| kernel.org/.../libcap/psx | v1.2.76 |
| Go compiler (gc)          | v1.24.5 |
+===========================+=========+
  • If you need to see additional details about the proxy binary, you can run go version ‑m proxy.
Port binding
  • If you want to listen on the regular SSH port of 22 (without running as root, which is strongly discouraged), on Linux systems you can use setcap to allow the proxy to bind to privileged ports:

    sudo setcap 'cap_net_bind_service=+ep' "/path/to/proxy"
    
  • If this is necessary (i.e., a non‑root user on Linux is attempting to bind an SSH listener to a privileged port and the CAP_NET_BIND_SERVICE capability is not currently effective), the software should provide a warning message with the above instructions.

Admin interaction
  • The running proxy can be controlled interactively with the following admin console commands:
    • ? — Show help text
    • c — Show proxy configuration
    • v — Show version details
    • s — Show connection statistics
    • l — List active connections
    • k — Kill a connection
    • d — Deny new connections
    • r — Reload access control lists
    • q — Graceful shutdown
    • Q — Immediate shutdown (also via ^C)

Most of these admin console commands are straightforward and should be self‑explanatory, although there are a few options that merit further clarification:

  • When the Graceful shutdown mode is active, all new connections are denied (and are served an appropriate deny.txt banner). Once all clients have disconnected, the proxy software will exit. Note that new monitoring sessions can still connect to observe active users, as these sessions are automatically closed when their observation target disconnects.

  • When the Deny new connections mode is active, all new connections are denied (and are served an appropriate deny.txt banner). In addition, any console logging of new connection attempts, including any denied and/or rejected connections, is suppressed. This can be useful if the admin console is overwhelmed with logging activity (such as during bot attacks, busy periods, or when troubleshooting). Activating this mode can help reduce console noise, making it easier to perform admin actions such as viewing the configuration, or listing and killing active connections.

  • The k command, which kills a connection, takes either a Session ID as an argument (shown when listing active connections with the l command) or *, which kills all active connections.

If it is detected that you have a UTF-8 capable terminal, then some console output will be augmented with icons or emoji glyphs (and in a future version, UTF-8 box drawing symbols will be used for drawing tables).

Signals
  • The proxy also acts on the following signals (on systems where signals are supported):

    Signal Action
    SIGINT Enables the Immediate shutdown mode
    SIGQUIT Enables the Immediate shutdown mode
    SIGUSR1 Enables the Graceful shutdown mode
    SIGUSR2 Enables the Deny new connections mode
    SIGHUP Reloads access control lists (‑‑whitelist, ‑‑blacklist)
    SIGDANGER Attempts to immediately free as much memory as possible (AIX‑only)
Management with systemd

If you’re running the proxy on a Linux system, you can use systemd to manage the service (while maintaining access to the interactive admin console).

  • The systemd integration requires systemd version 247 or later (Nov. 2020), and a recent version of tmux.

  • With minor changes 🔧 to the unit file, this setup can also work with systemd as old as version 229 (Feb. 2016).
  • See the detailed instructions in the systemd/dps8m‑proxy.service file for full installation instructions.
User interaction

Users connected via SSH can send ^] (i.e., Control + ]) during their session to access the following following TELNET control features:

  • ] — sends a literal Control‑] to the target TELNET host

  • 0 — sends a literal NUL to the target TELNET host

  • A — sends an IAC AYT (Are You There?) to the target TELNET host

  • B — sends an IAC BREAK signal to the target TELNET host

  • I — sends an IAC INTERRUPT signal to the target TELNET host

  • K — toggles the transparent key remapping mode, which translates modern xterm/VT320 movement key inputs to Emacs sequences:

    Input Output
    Control + Up Escape, [
    Control + Down Escape, ]
    Control + Right Escape, f
    Control + Left Escape, b
    Home Control + A
    Delete Control + D
    End Control + E
    Up Escape + v
    Down Control + V
    Up Control + P
    Down Control + N
    Right Control + F
    Left Control + B
  • N — sends an IAC NOP (No Operation) to the target TELNET host

  • S — displays the status the session, sharing information, and some statistics:

    >> LNK ‑ The username '_gRSyWHxPcMp2MWvtmWWF' can be used to share this session.
    >> SSH ‑ in:   58 B,   out: 4.82 KiB, in rate:   4 B/s, out rate: 381 B/s
    >> NVT ‑ in: 4.82 KiB, out:   57 B,   in rate: 381 B/s, out rate:   4 B/s
    >> LNK ‑ link time: 13s (Emacs keymap enabled)
    
  • X — disconnects from the target TELNET host (and ends the SSH session)

Connection sharing
  • The user can share 🤝 the username presented above with others, allowing the session to be viewed live 👀 (read‑only) by one or more viewers:

    $ ssh _gRSyWHxPcMp2MWvtmWWF@proxybox
    
    CONNECTION from remote.com [18.17.16.15] started at 2025/07/15 08:22:55.
    This is a READ‑ONLY shared monitoring session.
    Send Control‑] to disconnect.
    

History

This is a from‑scratch re‑implementation (in Go 🐹) of an older legacy program of the same name.

The original software used a multi‑process architecture and consisted of nearly 15,000 lines of haphazardly constructed code: ≅14,000 lines of mostly C‑Kermit 🐸 (yes, the programming language) and ksh93 🐚 (along with some C 💻, Python 🐍, and Perl 🐪) which was difficult to maintain, configure, and securely install.

This new implementation uses many lightweight Goroutines 🚀 instead of spawning multiple processes, resulting in significantly improved performance and reduced system overhead.

Stats

The new proxy program is considerably simpler than its legacy predecessor (code statistics 📈 provided by scc):

Language Files Lines Blank Comment Code Complexity Bytes Uloc
Go 14 5472 1182 276 4014 1029 138195 2571
Makefile 1 272 52 61 159 32 8561 188
Markdown 1 481 96 0 385 0 20326 368
Shell 1 49 13 22 14 0 1501 30
Systemd 1 207 35 105 67 0 7461 134
Total 18 6481 1378 464 4639 1061 176044 3280

Future plans

  • Some features of the legacy software are still missing in this implementation and may be added in future updates. These features include text CAPTCHAs, load‑balancing, fail‑over, flow control, SSH targets, and TELNET listeners.
  • When users access an SSH listener, the connecting client may supply a password or present public keys for authentication. These authentication attempts are currently logged, but are not otherwise used by the proxy. A future update may allow for passwords and public keys to be used for pre‑authentication or to influence target routing.

  • While TELNET protocol support will improve in the future, there are no plans to support the linemode, environment, authentication, or encryption features at this time.
    • If you need these features, you should look into C‑Kermit or Kermit 95.
    • Although directly executing programs isn’t something on the roadmap, it’s not difficult to use socat creatively to connect C‑Kermit to the proxy (i.e., socat TCP‑LISTEN:9876,fork,reuseaddr,nodelay EXEC:kermit,pty,setsid,echo=0,rawer,opost=1,icrnl=1,onlcr,cread).
    • ⚠️ Be aware that doing this securely—safe for public usage—is more involved than one might imagine. Safely configuring the proxy for this type of operation is possible, but beyond the scope of this documentation.

Compressed logs

  • By default, all session log files are compressed 🗜️ automatically when the session terminates, and console log files are compressed when the log rolls over (i.e., when starting a new day).

  • When reviewing logs, administrators often need to search through all the past data, including through the compressed files. We recommend using ripgrep (with the ‑z option) for this task.

Using OpenSSH host keys

If you have existing OpenSSH Ed25519 or RSA host keys that you want to use with the proxy, you’ll first need to convert those keys to standard PEM format.

🚨 NB: These instructions do not include any specific details for safe handling of key file permissions—we assume you are root and that know what you’re doing!

  1. Make a copy of the key files you wish to convert. Be aware that these copies will be overwritten in the conversion process:

    cp /etc/ssh/ssh_host_rsa_key ssh_host_rsa_key.tmp
    cp /etc/ssh/ssh_host_ed25519_key ssh_host_ed25519_key.tmp
    
  2. Convert the keys (using ssh‑keygen) and rename them appropriately:

    ssh-keygen -p -m PEM -N '' -P '' -f ssh_host_rsa_key.tmp
    ssh-keygen -p -m PEM -N '' -P '' -f ssh_host_ed25519_key.tmp
    mv ssh_host_rsa_key.tmp ssh_host_rsa_key.pem
    mv ssh_host_ed25519_key.tmp ssh_host_ed25519_key.pem 
    

Development

Required
  • While not absolutely required, it’s a good idea to have the latest golangci-lint installed. We ship a config file file for it, and try to make sure that all the tests pass when using the most recently released version.
  • It’s also recommended to (manually) use hunspell for spell checking—codespell doesn’t catch everything.
  • The Makefile provides a lint convenience target to help you run all this stuff.

Security

License

  • The proxy program is made available under the terms of the MIT License, with some bundled example and miscellaneous files distributed under the terms of the MIT No Attribution License.

Documentation

Overview

DPS8M Proxy

DPS8M Proxy

DPS8M Proxy

DPS8M Proxy

DPS8M Proxy

DPS8M Proxy

DPS8M Proxy

DPS8M Proxy

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL