macOS SSH Slow to Connect: Troubleshooting IPv6, DNS, and Remote Login

Published · Updated · System Administration

SSH should feel boring. You type ssh hostname, the server asks for whatever authentication it needs, and you get a shell. When it pauses for 30, 60, or 120 seconds before anything useful happens, the delay is usually not random. It is almost always name resolution, address-family selection, routing, or a server side lookup happening before authentication.

The original version of this post came from a Mac OS X 10.5 Leopard problem: after a reinstall, SSH to other Macs on the local network tried IPv6 first, waited too long, and eventually fell back to IPv4. Disabling IPv6 on the client made the symptom go away, but it was more of a workaround than a diagnosis.

That old instinct is still useful. When SSH is slow to connect between Macs, separate the problem into phases:

  1. Can the client resolve the name?
  2. Which IP address does the client try first?
  3. Can the client reach TCP port 22 on that address?
  4. Does the server delay before offering the SSH banner or before authentication?
  5. Is the delay caused by reverse DNS, IPv6, .local name resolution, routing, firewall policy, or account configuration?

Do that in order and the problem gets much less mysterious.

First, Identify Where SSH Is Waiting

Start with verbose client output:

ssh -vvv skadi.local

You are looking for the last line printed before the pause. A delay near this line is usually a network or address-selection problem:

debug1: Connecting to skadi.local [fe80::214:51ff:fe28:e74e%en0] port 22.

A delay after the TCP connection opens but before authentication is more likely to be server-side SSH configuration, reverse DNS, PAM, directory services, or account lookup.

For a quick timing check, run:

time ssh -vvv skadi.local true

The true command keeps the remote session short. The verbose log tells you where the delay happens; time tells you whether your change actually improved anything.

Compare IPv4 and IPv6

If the verbose output shows an IPv6 address first, test IPv4 and IPv6 separately:

ssh -4 skadi.local
ssh -6 skadi.local

You can also use the explicit OpenSSH option:

ssh -o AddressFamily=inet skadi.local
ssh -o AddressFamily=inet6 skadi.local

If ssh -4 connects immediately and ssh -6 hangs, you have learned something important: SSH is not the root problem. The client is choosing an IPv6 destination that is advertised, partially configured, filtered, or unreachable.

On a local Mac network, that often involves .local names and link-local IPv6 addresses. Link-local addresses are only meaningful on a specific interface, which is why you may see a zone suffix such as %en0 or %en1 in the address. If the wrong interface, stale neighbor state, or a half-working IPv6 path gets involved, SSH can spend a while proving that the first address is bad before it tries the next one.

Check What The Name Resolves To

Do not guess which address SSH is using. Ask the system resolver:

dscacheutil -q host -a name skadi.local

For DNS configuration and resolver order:

scutil --dns

For current network reachability state:

scutil --nwi

If you are using a .local name, remember that macOS treats that as multicast DNS territory. That is convenient for home and lab networks, but it is not the same operational model as normal unicast DNS. On a managed network, I would rather SSH to a real DNS name or a stable address than depend on .local discovery for anything important.

For a quick TCP test, skip SSH authentication entirely:

nc -vz skadi.local 22
nc -vz -4 skadi.local 22
nc -vz -6 skadi.local 22

If nc -4 works and nc -6 hangs, you are looking at an address-family or network path issue. If both connect quickly, move up the stack and look at SSH daemon behavior.

Use A Client-Side Workaround Carefully

If you need to get work done while you investigate, forcing IPv4 for a specific host is reasonable:

Host skadi skadi.local
    AddressFamily inet
    ConnectTimeout 5

Put that in ~/.ssh/config.

I prefer scoping this to the specific host instead of turning off IPv6 globally. IPv6 is not automatically the villain. The bug is usually that one path is advertised as usable when it is not actually usable. A narrow SSH config entry keeps the workaround close to the symptom and avoids surprising other applications.

The same idea works one command at a time:

ssh -o AddressFamily=inet -o ConnectTimeout=5 skadi.local

ConnectTimeout is not a fix. It just prevents the default TCP timeout from making every failed attempt feel like a coffee break.

Check Remote Login On The Mac

On the target Mac, confirm that Remote Login is enabled:

sudo systemsetup -getremotelogin

Enable it if appropriate:

sudo systemsetup -setremotelogin on

Then verify that sshd is listening:

sudo lsof -nP -iTCP:22 -sTCP:LISTEN
netstat -an | grep '\.22 .*LISTEN'

If the Mac is listening on IPv4 but not IPv6, or vice versa, compare that with the address family your client is trying first. The server-side sshd_config options that matter here are usually AddressFamily and ListenAddress.

On current macOS, be careful when editing /etc/ssh/sshd_config. Managed Macs may have configuration profiles or MDM policy involved, and a local edit may not survive the next management run. For one machine in a lab, a local edit may be fine. For a fleet, make the policy explicit in management tooling.

Look For Server-Side DNS Delays

Not every slow SSH connection is a client routing problem. Some delays happen after the TCP connection succeeds because the server tries to look up the client's address.

Check the server's SSH configuration:

sudo sshd -T | grep -i usedns

If UseDNS yes is set, sshd may perform reverse DNS checks on connecting clients. Broken reverse DNS can make logins pause before authentication. In many environments, UseDNS no is the more practical setting:

UseDNS no

Do not cargo-cult that change into every server without understanding your environment. If you rely on host-based authentication, audit trails tied to verified names, or older access-control assumptions, DNS behavior may matter. For ordinary admin SSH on Macs, though, reverse DNS delays are more likely to be annoying than useful.

After changing sshd_config, validate the configuration before restarting anything:

sudo sshd -t

Then restart Remote Login in the least surprising way for your environment. On a single Mac, toggling Remote Login off and on is often enough. On managed Macs, use the management layer.

Do Not Confuse Account Problems With Network Problems

If the connection opens quickly but authentication is slow or fails, shift your attention to the account and directory-service side. Can the user log in locally? Is the account allowed to use SSH? Is the Mac bound to a directory service that is slow or unavailable? Is the user a network account that requires an identity provider, VPN, or cached credential path?

For local account administration, I have a separate guide on adding macOS users remotely from the command line. That is the right problem space when the network path is healthy but the account state is wrong.

For SSH delays, keep asking: did we reach port 22 quickly? If yes, debug the server and account path. If no, debug resolution, address selection, routing, firewalling, and IPv6.

When Disabling IPv6 Makes Sense

Disabling IPv6 is a blunt instrument. It can be acceptable as a temporary test:

networksetup -listallnetworkservices
networksetup -setv6off "Wi-Fi"

And you can restore automatic IPv6 later:

networksetup -setv6automatic "Wi-Fi"

But I would treat that as a diagnostic step, not the final answer. If turning off IPv6 fixes SSH, the useful conclusion is not "IPv6 is bad." The useful conclusion is "this client is selecting an IPv6 path that does not work." Fix the resolver, routing, firewall, router advertisements, or host-specific SSH configuration so the machine has an honest view of the network.

A Practical Troubleshooting Order

When SSH to a Mac is slow to connect, I would work through it like this:

  1. Run ssh -vvv host and note where it pauses.
  2. Compare ssh -4 host and ssh -6 host.
  3. Check name resolution with dscacheutil -q host -a name host.
  4. Inspect resolver and network state with scutil --dns and scutil --nwi.
  5. Test TCP port 22 with nc -vz, including -4 and -6.
  6. Confirm Remote Login with systemsetup -getremotelogin.
  7. Verify that sshd is listening on the address family the client is using.
  8. Check UseDNS and other server-side SSH settings with sshd -T.
  9. Only then consider host-specific AddressFamily inet or temporary IPv6 disablement.

That sequence keeps you from papering over the wrong layer. Slow SSH is frustrating because it looks like one problem from the terminal prompt, but it can be caused by several different subsystems. Treat the pause as a clue. Find the phase where it happens, and the fix usually becomes much less dramatic.

For more practical systems notes and engineering troubleshooting, start at Slaptijack.

Slaptijack's Koding Kraken