Mac networking · NAS · Homelab
Mac SSH “No route to host”: check the app, network and port
Find your next check
Select what you have observed. No server details or logs are needed; choices stay in this page. This is a checklist, not a connection test.
If SSH fails to reach a device on your Mac's local network, compare the same address and port in Apple Terminal and the failing app. On macOS 15 or later, check that app's Local Network permission. A successful ping alone does not prove that TCP port 22, SSH authentication or an SFTP session will work.
By Nexus Shell · Published September 18, 2026. For Mac users connecting to a NAS, Raspberry Pi, Linux server or homelab. The symptom picker suggests the next check; it does not scan your network, inspect permissions or ask for a host, password or key.
Updated September 20, 2026: added key-selection checks for “Too many authentication failures”, with an isolated OpenSSH configuration example.
Updated September 28, 2026: added a dedicated host-key change checklist for verified VPS replacements and unexpected identity warnings.
Updated September 30, 2026: added jump-host routing checks and a reproducible, offline two-endpoint configuration example.
Updated October 14, 2026: added checks for an SSH identification-stage disconnect, with a credential-free loopback rehearsal that distinguishes a TCP connection from an SSH handshake.
Updated October 20, 2026: added Tailscale reachability and Mac MagicDNS checks. An online peer, a successful ping and an authorized SSH session are different results.
Updated October 22, 2026: added app-specific outbound filtering checks. A working browser or Terminal connection does not establish another app's network access.
Start with the exact error
- No route to host: check the route and network access. When only one app fails to reach an on-link device, also check macOS Local Network permission and restart that app after saving work.
- Operation timed out: the connection did not complete in time. Check the address, port, VPN route and filtering. It does not prove the password is wrong.
- Connection refused: the TCP connection was actively rejected. Check whether SSH is listening on the intended port; a rejecting firewall can also produce this result.
- Could not resolve hostname: check the hostname or configured SSH alias first. A hostname and a saved connection label are not necessarily the same thing.
- kex_exchange_identification: Connection closed or reset by peer: the connection ended during SSH identification. Check the endpoint, server logs and connection limits before treating this as a bad password.
- Permission denied (publickey): an SSH server answered and authentication failed. Check the account and key selection; Local Network permission is not the first explanation for that connection.
- Too many authentication failures: an SSH server ended the attempt after its allowed failures. Check which keys the client is offering before changing network permissions or server limits.
- REMOTE HOST IDENTIFICATION HAS CHANGED: stop and verify the server's fingerprint through a trusted channel before changing saved trust. Do not disable host-key verification to suppress the message.
For this last warning, follow the host-key verification and scoped replacement steps. A changed server identity is a different task from fixing network reachability or choosing a login key.
1. Compare the same destination in Apple Terminal
Open Terminal on the Mac itself. Use the same server address, SSH port, account and required jump host as your app. These examples use a documentation-only address: replace it with a server you are authorized to access. Do not run them in an already connected remote terminal.
# Inspect the route to your server without changing it (macOS)
route -n get 192.0.2.10
# Check one TCP port, with a five-second connection timeout (macOS nc)
nc -vz -G 5 192.0.2.10 22
# Try SSH with diagnostic output; this can open a login session
ssh -v -o ConnectTimeout=5 -p 22 -l developer 192.0.2.10
The route output identifies the selected interface and gateway; it does not prove delivery. A successful nc result means that one TCP connection completed, not that SSH or your credentials are valid. SSH -v shows how far the attempt reached. If login succeeds, type exit to close that test session. Verify any first-use host fingerprint before accepting it.
For a configured alias, inspect its effective settings locally before comparing it with the app:
ssh -G your-configured-alias
Check hostname, user, port and proxyjump in that output. OpenSSH prints the evaluated configuration and exits; it does not open an SSH session. Your own configuration can include Match exec commands, so use only a configuration you trust. A direct nc probe is not equivalent to a connection through a bastion or proxy.
2. If Terminal works but your SSH app does not
First check that both attempts use the same destination, port and network path. If they differ, fix the comparison before diagnosing an app permission. For an on-link LAN target on macOS 15 or later, open System Settings → Privacy & Security → Local Network and review the failing app's access. Allow access only if you intend that app to communicate with local devices, then reconnect.
Apple documents different treatment for command-line tools launched from Terminal and for app-owned processes. A successful Terminal connection therefore does not establish that another app has the required permission. The Apple Local Network settings guide shows where to review it; Technote TN3179 explains the platform behavior.
If the app was updated while running, save work, end sensitive sessions deliberately, quit the whole app and reopen it. Opening another tab is not the same as restarting the process. Retest the same connection. This is a diagnostic step, not a guarantee that an update caused the failure.
A September 9 user report describes LAN connections recovering after restarting an app updated by Homebrew. That is an independent report, not our reproduction of its macOS internals or proof that every “No route” error has that cause.
Terminal works but the SSH app times out: check outbound filtering
Little Snitch and other process-aware filters can apply different rules to your browser, Terminal and SSH app. A working Terminal session does not prove the app is allowed to contact the same server. Review that app's denied connections before changing server credentials. macOS Local Network permission and an outbound firewall rule are separate controls; granting one does not grant the other.
- Keep the same confirmed destination, SSH port, account and required route in both clients. Note the time of one fresh app attempt; an existing Terminal session is not a fresh connection test.
- In your filter's history, inspect that attempt's process, destination, port and matching rule. Check the actual installed app or helper shown there, rather than assuming a browser rule covers it.
- If an intended connection was denied, review only its relevant rule and active profile. Allow only the app/destination you recognize and are authorized to use. Keep filtering and host-key verification enabled; do not allow every process, open public SSH or reset all rules as a default fix.
- Retry once and verify the intended server identity and task. No denied entry is not proof that the route, DNS or server is healthy; continue with the matching symptom below if it still fails.
See Little Snitch's process, destination and rule-matching reference. Controls differ by filter and version. This checklist does not inspect or change your firewall, and is not a Nexus Shell firewall-compatibility test.
If the website signs in but Nexus Shell Membership keeps waiting, that is an account connection rather than an SSH-server login. Use the website-edition account and outbound-filter checklist. App Store users follow Apple's purchase/restore flow. Do not change your VPS firewall or buy again to address an unconfirmed account connection problem.
3. If the app is missing from Local Network settings
Use the current signed app, launch the intended installed copy, and attempt the local connection once. Review any permission prompt and retry after your decision. Apple notes that an app normally appears after attempting local network access; multiple installed versions can complicate the settings display.
For Nexus Shell, update using the official installer or Homebrew and fully quit and reopen the app. Its connection setup includes an in-process local-network access attempt for recognized local target forms. That helps request OS permission; it cannot grant permission, repair a router or override an administrator's policy. If the app remains absent, contact support with the app/macOS versions and the exact error, without credentials.
4. If both clients fail, check the network path
Confirm the current address and SSH port from the device or provider console. A NAS web interface working on HTTPS does not imply that its SSH service is enabled. A sleeping host, stale DHCP address, guest Wi-Fi isolation, different VLAN or changed VPN route can prevent access. Check those facts before changing sshd configuration.
Compare hostname versus the confirmed address to narrow a name-resolution problem. Inspect the selected route on the Mac. For a private host reached through a VPN or jump server, follow that service's access instructions. A private-looking address by itself does not prove that the destination is on your local link or that the macOS Local Network setting is the relevant control.
If the port is refused, inspect the SSH service and its listen port through an authorized console. If it times out, inspect the route and relevant firewall rules. Keep an existing administrative session open while investigating. Avoid broad firewall resets, opening SSH to the whole internet or changing unrelated permissions as a first step.
Tailscale ping works but SSH fails on Mac
A Tailscale peer answering ping does not prove that its SSH port is reachable or that the remote account is authorized. First distinguish ordinary OpenSSH carried over the tailnet from Tailscale SSH, which applies its own SSH policy. Keep the same destination, port and remote username when comparing Terminal and your app.
- Confirm the peer and its current Tailscale IP through your authorized device list. A LAN address or public hostname may take a different route; a saved connection label is not necessarily a MagicDNS name.
- If you already have the Tailscale CLI, inspect one bounded probe: tailscale ping --c 1 --timeout=5s your-peer. It checks a Tailscale path, not an SSH login. A relayed result is not by itself a failure. CLI availability and installation paths differ between Mac editions.
- For ordinary OpenSSH over Tailscale, check the intended TCP port, the server's SSH listener and the applicable network policy. On your Mac, use the earlier nc probe with the peer's confirmed IP and actual SSH port, then one SSH attempt. Do not test a private server through its public IP and call that the same path.
- If the destination uses Tailscale SSH, it intercepts tailnet traffic to port 22. Both network access and the SSH rule for the source, destination and local OS username must permit the connection. Check mode may require browser reauthentication; a connected VPN does not waive it.
- If TCP succeeds but SSH refuses authentication, move to account or policy checks. If login works but files fail, test the SFTP workflow separately. Do not enable a different SSH server, open a public port or weaken access rules just to silence an unexplained error.
The Tailscale CLI reference explains its ping variants. The Tailscale SSH documentation describes its port, authorization and check-mode behavior. Neither a successful Tailscale probe nor this browser checklist establishes Nexus Shell compatibility with every tailnet policy or reauthentication flow. Keep a working client while checking one non-critical task.
MagicDNS works by IP but not by name on Mac
Compare the peer's confirmed Tailscale IP with its full MagicDNS name. If only the IP works, investigate name resolution before changing SSH credentials. A failing nslookup or host result alone does not establish broken MagicDNS on macOS: these tools can bypass the system resolver used by other applications.
Run these read-only checks in Terminal on the Mac, replacing the example name with your peer's full name. Output can reveal private network names; inspect it locally.
# Inspect macOS resolver configuration; does not change DNS
scutil --dns
# Ask the system host lookup path about one confirmed peer name
dscacheutil -q host -a name your-peer.your-tailnet.ts.net
Check the tailnet DNS configuration and whether this Mac accepts its DNS settings. Another VPN or DNS tool may affect resolution, but its mere presence is not a diagnosis. Shared devices can require the full MagicDNS name. Keep host-key verification when comparing name and IP: a different saved host label may cause a new trust prompt. DNS resolution still does not prove the TCP port or SSH account works.
See Tailscale's MagicDNS guidance, including its macOS resolver caveat. Do not replace system DNS globally, flush caches repeatedly or pin a changing peer address in hosts as an unexplained first fix. The portable Mac VPN/SSH checklist records the comparison steps without requesting credentials or uploading diagnostics.
SSH closes before authentication
If SSH reports kex_exchange_identification: Connection closed by remote host or read: Connection reset by peer, it stopped during identification. A successful TCP probe does not establish an SSH handshake or login. Server policy, connection limits, a wrong service, or an intermediary can close the connection; this message alone does not identify the cause.
Stop automatic retry loops and repeated port scans. Keep an existing administrative session open. Confirm the endpoint and required bastion, then inspect one bounded SSH -v attempt locally using the earlier example. Note the time and stage reached; redact server details before sharing diagnostics.
Through an authorized console, ask the administrator to compare the same-time SSH service logs with the effective configuration for that client. On systemd Linux, review journalctl -u ssh or journalctl -u sshd for the relevant time window; service names, logging access and policy differ. No matching log entry is not proof that the server accepted the connection. A proxy or jump host may need its own logs.
OpenSSH 9.8 introduced default PerSourcePenalties for repeated failed or unauthenticated connections. MaxStartups instead limits concurrent unauthenticated connections. Shared NAT/proxy addresses can affect several users. Check the installed server's version, local manual and effective settings; do not assume the Mac client's version tells you the server's policy. A refusal banner such as Not allowed at this time does not distinguish these causes without server evidence. Do not promise a fixed wait time or disable protections as a default fix.
Our loopback rehearsal uses four temporary TCP listeners and the installed OpenSSH client, without credentials or an SSH server. It shows that a TCP connection and even an SSH version line can precede failure. It does not reproduce sshd rate limits or prove that Nexus Shell bypasses them. Once the server permits the connection, use the first-session checklist and verify one authorized task.
5. Once the server answers, handle the next layer
An authentication error is progress through the network layer, but not a successful login. Compare the SSH account, configured key and authentication requirements. A key passphrase unlocks a local key; it is not necessarily the server account's password. Do not send either credential or a private key to a support thread.
Too many authentication failures: select the key first
One common cause is an SSH client offering several agent keys before reaching the intended key. Inspect the resolved configuration for your trusted alias locally:
ssh -G your-configured-alias | awk '$1 ~ /^(hostname|user|port|identityagent|identityfile|identitiesonly|proxyjump)$/ { print }'
Check every identityfile line, the selected agent, account and jump host. This prints evaluated settings, not a successful login; trusted configuration may still evaluate local Match exec commands. Do not upload the output or a private key to a diagnostic site.
For an existing local key, assign IdentityFile and IdentitiesOnly yes in the intended Host block. Review overlapping Host and Include rules: IdentityFile entries accumulate. Our isolated key-selection fixture and walkthrough shows one selected file versus two matching entries even when IdentitiesOnly remains yes. It uses no real server or keys and does not alter your SSH configuration.
If the private key stays in an external agent such as 1Password, use that provider's supported public-key selector and agent setup. A saved bookmark alone does not prove the SSH client has loaded those settings. The walkthrough links the relevant official instructions. Nexus Shell's own saved-key assignment is a separate workflow; this guide does not claim verified 1Password-agent or SSH Bookmarks integration in Nexus Shell, and exporting a private key is not required to follow the diagnostics.
After checking the settings, test an authorized connection with SSH -v and verify the server fingerprint. A refused intended key still requires account/server investigation. Do not clear all agent keys, raise server authentication limits or disable host-key checks as a default fix.
When terminal login works but files do not
If SSH login succeeds but a file upload fails, investigate the SFTP subsystem, target path and file permissions. A GUI client uses the remote account's rights; it does not automatically elevate an SFTP session with sudo. Its terminal and SFTP engines may also use different authentication settings, so verify the file workflow separately. Follow the remote file editing workflow for permission and conflict checks.
If a forwarded database port is listening but the service still fails, use the SSH tunnel address and verification guide. Local listening, destination reachability and database authentication are separate checks.
Connecting through a jump host
A jump host forwards a connection to the target. The bastion and target can have different accounts, SSH ports and keys; a successful bastion login does not establish that forwarding or target login is allowed. The target address must be reachable from the bastion, not necessarily directly from the Mac.
Use our two-endpoint configuration and offline check to create a separate, reviewed example file. Keep the jump host's settings in its own Host block and select that alias with ProxyJump in the target block. Do not copy a target private key onto the bastion or enable agent forwarding merely to make ProxyJump work.
After saving and adapting the example as nexus-jump-example.conf, inspect both endpoints from your Mac:
ssh -G -F ./nexus-jump-example.conf example-jump
ssh -G -F ./nexus-jump-example.conf example-target
Compare hostname, user, port, identityfile, identitiesonly, forwardagent and proxyjump. A target's key selection is not the jump host's key selection. These commands evaluate trusted configuration and exit; they do not log in or prove either server is reachable. Match exec rules can execute local commands, so do not evaluate an untrusted configuration.
After replacing all example values and reviewing the file, test the authorized target with ssh -v -F ./nexus-jump-example.conf example-target and verify both host fingerprints through a trusted source. Exit when the check is complete. Separate the failure stages:
- Jump login fails: inspect the bastion's own address, port, user and identity from the Mac.
- The forwarding channel is administratively prohibited: ask the administrator to check effective forwarding/destination restrictions and host policy. A shell on the bastion does not prove TCP forwarding is permitted. Do not disable policy to work around it.
- The forwarding channel reports refused, timeout or no route: investigate the bastion-to-target path and target listener. A direct nc probe from the Mac tests a different path.
- The target rejects a key: check the target account and identity, separately from the bastion login.
- Terminal access works but files fail: check the target SFTP subsystem, account rights and the client's file settings separately.
In Nexus Shell, first save the jump server. In the destination connection, use the target's host, port and account, select Network Routing → Via jump host, choose the saved connection and review the route preview. Confirm terminal access before a small authorized file task. This mapping was checked in released v1.7.7 source; it is not a fresh GUI/bastion test or a promise of arbitrary OpenSSH, external-agent, RouterOS or enterprise MFA compatibility.
The nine-check offline fixture and recorded result use only a temporary config, documentation addresses and nonexistent key paths. They check resolved accounts, ports, route and key separation with agent forwarding off; they do not contact servers or prove a firewall policy works. See the official ProxyJump reference and server forwarding controls.
Keep the working connection in Nexus Shell
After confirming the host, port and account, save that connection in Nexus Shell and verify its host fingerprint. Open a terminal and confirm you reached the intended server before starting file or Docker work. The app keeps those tasks in one native Mac workspace; changing clients does not bypass network or server policy.
Nexus Shell requires Apple Silicon and macOS 14.2+. Personal, non-commercial SSH use has a free tier. SFTP, Docker management and monitoring are Pro features; commercial use requires Pro. See current pricing and trial terms. The Local Network permission steps above apply to macOS 15 or later, not every supported macOS version.
What to include when asking for help
Record the macOS and app versions, the exact error, whether the target is on the same LAN or reached through a VPN/bastion, and whether Apple Terminal succeeds with matching settings. Include whether the app was updated while open. Redact hostnames, IP addresses, usernames and local paths before sharing logs, and never include passwords or private keys.
The network checks were reviewed against Apple documentation and Nexus Shell connection-setup code on September 18, 2026. The key-selection fixture was checked locally with macOS OpenSSH 10.3p1 on September 20. This is not a fresh end-to-end test on your Mac, NAS, router or external key agent. See the OpenSSH client manual and key-selection configuration reference. Consult man nc and man route on your Mac for its installed command versions.