The first connection after a reboot works. Every attempt after it hangs at the connecting stage and eventually times out, and the only reliable cure is another reboot. That pattern is not a profile problem and it is not a credentials problem. Something in the background is still holding the state from the previous attempt, and the next attempt collides with it.

On macOS, the something is usually the IKE daemon.

The pattern: connects once, then times out

A connection that works exactly once per boot points at state that survives a disconnect but not a reboot. Profiles survive both, so the profile is not the variable. Credentials survive both too, unless the server locks the account. What changes at reboot is the set of running daemons and the sockets they hold.

That narrows the investigation before you open a single log. The question becomes which process owns the IKE port and what it thinks it is doing.

Two daemons, one port

The system runs racoon when a connection speaks IKE version 1. Current releases also bring in iked for IKEv2 and the newer IPsec stack. Both can bind UDP 500 and UDP 4500, and both can keep a half-open security association after a connection attempt is cancelled at the password prompt or interrupted by a network change.

When that happens, the next attempt does not start clean. It tries to negotiate while the old association still occupies the peer's state, and the exchange stalls instead of failing with a clear error. The user sees a spinner, then a timeout.

Find the owner before killing anything, because the answer determines which service you restart and which log you read next.

sudo lsof -i :500 -i :4500
ps -ef | grep -E "racoon|iked"

Read the output as two facts: which process holds the port, and whether more than one of them is present. Two IKE daemons competing for the same socket explains a lot of intermittent behaviour that looks like a flaky server.

Restart the job rather than the process

On older systems, killing the process and letting the next connection start it again is enough. On current releases the daemon is managed by launchd, and signalling the process alone can leave the job in a state where it is neither running nor scheduled to start. Stop and start the job instead.

sudo launchctl stop com.apple.racoon
sudo launchctl start com.apple.racoon

If launchd has no record of the job, killing the process by name still forces a fresh negotiation on the next attempt. The test is the same either way: no process should be holding the port when you try to connect again. Confirm that with the same lsof command rather than assuming the restart worked.

Then connect once and read the client log from the beginning. A negotiation that advances past phase 1 and then reports a transmit failure is repeating the local socket problem; a negotiation rejected by the peer is a different ticket entirely.

When the server is the one refusing

Not every second connection fails locally. A server can refuse a new login for a fixed window after a disconnect, and the client's timeout looks identical to a stuck daemon. The discriminator is cheap: if restarting the daemon does not help but a different account connects immediately, the window is server-side and the Mac was never the problem.

Split-tunnel policy produces the same shape from the other direction. A server that requires all traffic in the tunnel will drop a client configured for split tunneling during negotiation, and the client reports a timeout rather than a policy rejection. Changing the profile to send everything through the tunnel may make it connect, but that is a policy decision to make with the network owner, not a repair to apply quietly.

Read the peer's log before changing the client again. A rejection, a policy mismatch, and a silent drop are three different causes that all look like "connecting" on the Mac's screen.

Older clients and the 64-bit kernel

The legacy Cisco IPSec client loads a kernel extension built for 32-bit and PowerPC systems. On a Mac booted into the 64-bit kernel, that extension cannot load, and the client fails early with error 51 because it cannot reach the VPN subsystem at all. No amount of daemon restarting fixes a kernel extension that is the wrong architecture.

Reloading the extension can work for a while and then fail again on the next boot. The durable answers are to run the older kernel where that is still supported, or to move to the built-in client that ships with the system. Check the architecture before spending an evening on a third-party client that cannot load.

  • Reproduce once, then check which daemon owns UDP 500 before touching the profile.
  • Read the first failure after phase 1: a transmit error points at the local socket.
  • Restart the launchd job, not only the process, and confirm the port is free.
  • Try a second account to separate a server-side reauth window from a client fault.
  • Record the kernel architecture before blaming the client.

A VPN that works exactly once is a state problem until proven otherwise. Clearing the daemon is faster than rebooting, and it preserves the log evidence that a reboot would have thrown away.

Skyldar greinar