When using the standard Windows SSH client together with tmux, some users occasionally see unwanted “noise” characters appear in the terminal. One practical workaround is to run SSH from a WSL1 Alpine environment instead of using the Windows-native SSH session.
However, WSL1 Alpine has a key limitation in this setup: it cannot resolve certain hostnames (notably those relying on mDNS). To address this, the approach described here offloads hostname resolution to Windows—where resolution works correctly—and then feeds the resolved IP address back into the SSH command running inside Alpine.
The solution consists of two small tools working together:
resolve-proxy.c: runs on Windows and resolves a fully qualified domain name (FQDN) into one or more IP addresses.ssh-wrap.c: runs on WSL1 Alpine and wrapssshso that it can transparently replace a hostname with an IP address resolved via Windows.
The combined outcome is that you can keep using WSL1 Alpine SSH (to avoid the tmux noise issue), while still benefiting from Windows’ ability to resolve hostnames that Alpine cannot.
resolve-proxy.c provides a minimal command-line resolver on Windows. Given an FQDN, it prints resolved IP address(es) to standard output, which can then be consumed by other tools.
-
Uses Windows networking APIs (
WSAStartup,getaddrinfo) to perform DNS/name resolution. -
Supports:
-4to restrict output to IPv4-6to restrict output to IPv6--firstto print only the first resolved address
-
Prints each resolved address on its own line in a canonical textual form using
InetNtopA.
This makes it suitable as a simple “resolver backend” that can be invoked from WSL tooling.
ssh-wrap.c wraps SSH execution inside Alpine so that, if the target is a hostname (not already an IP literal), it resolves the hostname using an external resolver command and then forces SSH to connect to the resolved IP.
-
Reads effective SSH configuration
- Executes:
ssh -G <user args...> - Captures the output and extracts the final resolved SSH parameters.
- Looks for
hostnamefirst (preferred), then falls back tohost.
- Executes:
-
Determines whether resolution is needed
- If the extracted host is already an IPv4/IPv6 literal, it is used as-is.
- Otherwise, it resolves the hostname by calling an external resolver command.
-
Invokes the resolver
- The resolver program is selected via the environment variable
SSH_HOST_RESOLVER. - If not set, it defaults to
resolvehost. - The wrapper runs:
<resolver> <hostname>and captures stdout.
- The resolver program is selected via the environment variable
-
Parses the resolver output
- Accepts multi-line output and selects the first valid IP address found.
- Ignores blank lines and comment lines starting with
#. - Validates IP strings using
inet_pton(both IPv4 and IPv6 supported).
-
Executes SSH with an overridden HostName
-
Finally executes:
ssh <user args...> -o HostName=<resolved_ip>
-
This preserves the user’s SSH arguments and configuration, but forces the final network connection to use the resolved IP.
-
With this setup:
- You run SSH from WSL1 Alpine (reducing the chance of terminal corruption/noise when using
tmux). - You still successfully connect to hosts that require Windows-style name resolution (including environments where WSL1 Alpine cannot resolve mDNS-derived names).
- The wrapper is transparent: you keep using your usual SSH invocation style, while the tool injects the necessary
HostName=<IP>override only when required.
This design assumes you have a Windows-accessible resolver executable available to WSL (for example, via a mounted Windows path), and that Alpine can execute it either directly or through a small shim. The key contract is simple: the resolver must print one or more IP addresses to stdout so the wrapper can select the first valid one.