Windows ARM64 daemon builds from tree with no source changes, but fails to establish peer paths

Author: no84byCreated Sep 7, 2026Updated Sep 7, 2026

Summary

Follow-up to #2072, which was closed in 2023 with "we're working on releasing version 1.12.0 ... that will include Windows ARM64 support". As of 1.16.2 the ARM64 driver ships, but the daemon in the installer is still x64.

On Windows 11 ARM64 the official MSI installs a native ARM64 TapDriver6 (zttap300.sys, PE machine 0xAA64) but an x64 userspace daemon (zerotier-one_x64.exe, PE 0x8664) that runs under emulation. Since ZeroTier does its crypto and packet processing in the userspace daemon, emulation sits on the datapath for every packet.

The repo already contains complete ARM64 build configuration, and it builds with zero source changes — but the resulting daemon does not establish peer paths correctly. Filing this because the second half is probably why the first half isn't shipped, and it may be a known or shallow bug.

What builds (1.16.2, unmodified)

windows/ZeroTierOne.sln has Release|ARM64; ZeroTierOne.vcxproj has ARM64 ItemDefinitionGroups; rustybits/zeroidc.vcxproj has ARM64 configs targeting aarch64-pc-windows-msvc; and the ARM64 linker path points at rustybits\target\aarch64-pc-windows-msvc\release\.

msbuild windows\ZeroTierOne.sln /p:Configuration=Release /p:Platform=ARM64

produces windows\Build\ARM64\Release\zerotier-one_arm64.exe — 6,105,088 bytes, PE machine 0xAA64, -v prints 1.16.2. zeroidc cross-compiled first try.

Two build notes:

  • TapDriver6 fails without the WDK. Not needed in practice — the shipped driver is already native ARM64 and signed.
  • cl : command line warning D9002: ignoring unknown option '/arch:SSE2' — the ARM64 config inherits an x86 switch. Harmless, but suggests the ARM64 path isn't routinely exercised.

Toolchain: VS 2022 Build Tools 17.14, MSVC 14.44.35207 (Hostarm64\arm64), Windows 11 SDK, plus the ARM64 MFC individual component (Microsoft.VisualStudio.Component.VC.MFC.ARM64) — without it the build stops at error MSB8041. Worth adding to build docs regardless of the bug below.

The bug

Swapping the ARM64 daemon in at the service's path (C:\ProgramData\ZeroTier\One\zerotier-one_x64.exe, service restarted, same identity and network):

Works: service runs, zerotier-cli infoONLINE, correct version, network OK, managed IP retained, and it peers DIRECT with another leaf on the same physical host.

Fails: a third-party leaf across a NAT could not reach it for ~10 minutes — 100% ICMP loss, no SSH. That peer's address was absent from the ARM64 daemon's peers table entirely, while from the other side it showed as RELAY with latency -1.

Restoring the shipped x64 daemon on the same host, same identity, same network restored a DIRECT path in under a minute (35–120 ms RTT). One trial each way, so not a root cause — but a peer missing from the table is daemon-level, not slow NAT traversal.

Topology: the ARM64 host is a Parallels guest behind NAT; the unreachable peer is across a WAN. The peer it did hold was on the same physical machine.

Questions

  1. Is the Windows ARM64 configuration expected to work today, or is it carried but untested?
  2. Is a missing peer entry a known symptom on ARM64 — e.g. an alignment/ABI issue in peer or path bookkeeping, or a NEON/AES code path?
  3. Would you take a PR that (a) drops /arch:SSE2 from the ARM64 config and (b) documents the ARM64 MFC prerequisite? Happy to help test an ARM64 artifact if the peering issue is fixed — the signed native driver already ships, so the remaining gap is the daemon.

Environment

  • Windows 11 ARM64 (Parallels guest, Apple silicon host)
  • ZeroTier 1.16.2 (winget ZeroTier.ZeroTierOne), stock MSI install
  • Private network, self-hosted controller
  • Build host = the same ARM64 machine