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:
- Can the client resolve the name?
- Which IP address does the client try first?
- Can the client reach TCP port 22 on that address?
- Does the server delay before offering the SSH banner or before authentication?
- Is the delay caused by reverse DNS, IPv6,
.localname 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:
- Run
ssh -vvv hostand note where it pauses. - Compare
ssh -4 hostandssh -6 host. - Check name resolution with
dscacheutil -q host -a name host. - Inspect resolver and network state with
scutil --dnsandscutil --nwi. - Test TCP port 22 with
nc -vz, including-4and-6. - Confirm Remote Login with
systemsetup -getremotelogin. - Verify that
sshdis listening on the address family the client is using. - Check
UseDNSand other server-side SSH settings withsshd -T. - Only then consider host-specific
AddressFamily inetor 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.