Files
n2n/doc/Building.md
Marek Sedlak 5f302a95b0 Add native macOS utun support, replacing deprecated tuntaposx TAP driver (#1236)
The tuntaposx kernel extension is no longer supported on modern macOS
(Catalina+, Apple Silicon, Tahoe). This replaces it with native utun
interfaces, adding an L2/L3 translation shim so the n2n wire protocol
remains 100% Ethernet-compatible with Linux/Windows TAP peers.

New files:
- macos/utun.c: utun socket lifecycle (PF_SYSTEM, CTLIOCGINFO, connect)
- macos/arp.c: internal ARP cache/responder for L2 emulation
- macos/route.c: macOS route table management
- tools/tests-utun.c: 24 unit tests for translation shim and ARP cache
- scripts/test_utun.sh: integration test suite

Key changes:
- src/tuntap_osx.c: complete rewrite with Ethernet header synthesis
  (tuntap_read) and stripping (tuntap_write), ARP interception
- src/edge.c: enable signal handlers and N2N_CAN_NAME_IFACE for macOS
- src/n2n.c: add SO_REUSEPORT for multicast socket (fixes multi-edge)
- include/n2n_typedefs.h: add edge_context back-pointer for ARP replies
- doc/Building.md: updated macOS instructions (no kexts required)

Tested: macOS Tahoe (Darwin 25.x, ARM64) <-> Ubuntu Linux TAP edge
via shared supernode with bidirectional ping confirmed.
2026-03-02 22:40:19 +01:00

10 KiB
Raw Permalink Blame History

n2n on macOS

n2n supports macOS Catalina (10.15) and later using the native utun interface. No third-party kernel extensions (kexts) or TUN/TAP drivers are required.

Building

./autogen.sh
./configure
make

If autotools are not available, you can also use CMake:

mkdir build && cd build
cmake ..
make

Running

sudo ./edge -c mynetwork -k mysecretpass -a 192.168.100.1 -l supernode:7777

sudo is required to create utun interfaces.

Running unit tests

make test

For the full integration test suite (requires sudo and starts/stops edge processes):

sudo scripts/test_utun.sh

Differences from Linux

  • The interface name (e.g. utun7) is assigned by the kernel. Use -d utun5 to request a specific interface number.
  • DHCP mode (-a dhcp:...) is not supported. Use static IP or supernode auto-assignment instead.
  • The VPN operates in IP-only mode (Layer 3) on the local interface. Non-IP Ethernet protocols are not supported locally, but full Ethernet compatibility is maintained on the wire with Linux/Windows peers.
  • ARP resolution for remote peers is handled internally by the edge process.
  • Routes bound to the utun interface are automatically cleaned up when the edge process exits (the kernel destroys the interface on fd close).

Legacy macOS (pre-Catalina)

Older versions of macOS that still support kernel extensions can use the tuntaposx TAP driver. This is no longer maintained and not recommended:

brew tap homebrew/cask
brew install --cask tuntap

For more information refer to vendor documentation or the Apple Technical Note.

Build on Windows (Visual Studio)

Requirements

In order to build on Windows the following tools should be installed:

NOTE: In order to skip OpenSSL compilation, edit CMakeLists.txt and replace – is this still valid?

OPTION(N2N_OPTION_AES "USE AES" ON)
with
OPTION(N2N_OPTION_AES "USE AES" OFF)

NOTE: To statically link OpenSSL, add the -DOPENSSL_USE_STATIC_LIBS=true option to the cmake command below.

  • If compilation throws a "config.h: No such file or directory" error, an include/config.h file needs to be obtained from an already configured Linux compilation and put into the include/ directory as discussed here.

In order to run n2n, you will need the following:

  • The TAP drivers should be installed into the system. They can be installed from http://build.openvpn.net/downloads/releases, search for "tap-windows".

  • If OpenSSL has been linked dynamically, the corresponding .dll file should be available onto the target computer.

NOTE: Sticking to this tool chain has historically meant that resulting executables are more likely to be able to communicate with Linux or other OS builds, however efforts are being made to address this concern.

Build (CLI)

In order to build from the command line, open a terminal window and run the following commands:

md build
cd build
cmake ..

MSBuild.exe edge.vcxproj /t:Build /p:Configuration=Release
MSBuild.exe supernode.vcxproj /t:Build /p:Configuration=Release
MSBuild.exe n2n-benchmark.vcxproj /t:Build /p:Configuration=Release

NOTE: If CMake has problems finding the installed OpenSSL library, try to download the official cmake and invoke it with C:\Program Files\CMake\bin\cmake.

NOTE: Visual Studio might not add MSBuild.exe's path to the environment variable %PATH% so you might have difficulties finding and executing it without giving the full path. Regular installations seem to have it reside at "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin\MSBuild.exe"

The compiled .exe files should now be available in the build\Release directory.

Run

The edge.exe program reads the edge.conf file located into the current directory if no option is provided.

Here is an example edge.conf file:

-c=mycommunity
-k=mysecretpass

# supernode IP address
-l=1.2.3.4:5678

# edge IP address
-a=192.168.100.1

The supernode.exe program reads the supernode.conf file located into the current directory if no option is provided.

Here is an example supernode.conf file:

-p=5678

See edge.exe --help and supernode.exe --help for a full list of supported options.

Build on Windows (MinGW)

These steps were tested on a fresh install of Windows 10 Pro with all patches applied as of 2021-09-29.

  • Install Chocolatey (Following instructions on https://chocolatey.org/install)
  • from an admin cmd prompt
    • choco install git mingw make
  • All the remaining commands must be run from inside a bash shell ("C:\Program Files\Git\usr\bin\bash.exe")
    • git clone $THIS_REPO
    • cd n2n
    • ./scripts/hack_fakeautoconf.sh
    • make
    • make test

Due to the hack used to replace autotools on windows, any build created this way will currently have inaccurate build version numbers.

Note: MinGW builds have a history of incompatibility reports with other OS builds, please see #617 and #642. However, if the tests pass, you should have a high confidence that your build will be compatible.

General Building Options

Compiler Optimizations

The easiest way to boosting speed is by allowing the compiler to apply optimization to the code. To let the compiler know, the configuration process can take in the optionally specified compiler flag -O3:

./configure CFLAGS="-O3"

The tools/n2n-benchmark tool reports speed-ups of 200% or more! There is no known risk in terms of instable code or so.

Hardware Features

Some parts of the code can be compiled to benefit from available hardware acceleration. It needs to be decided at compile-time. So, if compiling for a specific platform with known features (maybe the local one), it should be specified to the compiler, for example through the -march=sandybridge (you name it) or just -march=native for local use.

So far, the following portions of n2n's code benefit from hardware features:

AES:               AES-NI
ChaCha20:          SSE2, SSSE3
SPECK:             SSE2, SSSE3, AVX2, AVX512, (NEON)
Pearson Hashing:   AES-NI
Random Numbers:    RDSEED, RDRND (not faster but more random seed)

The compilations flags could easily be combined:

./configure CFLAGS="-O3 -march=native".

OpenSSL Support

Some ciphers' speed can take advantage of OpenSSL support which is disabled by default as the built-in ciphers already prove reasonably fast in most cases. OpenSSL support can be configured using

./configure --with-openssl

which then will include OpenSSL 1.1 if found on the system. This can be combined with the hardware support and compiler optimizations such as

./configure --with-openssl CFLAGS="-O3 -march=native"

Please do no forget to make clean after (re-)configuration and before building (again) using make.

ZSTD Compression Support

In addition to the built-in LZO1x for payload compression (-z1 at the edge's commandline), n2n optionally supports ZSTD. As of 2020, it is considered cutting edge and praised for reaching the currently technologically possible Pareto frontier in terms of CPU power versus compression ratio. ZSTD support can be configured using

./configure --with-zstd

which then will include ZSTD if found on the system. It will be available via -z2 at the edges. Of course, it can be combined with the other features mentioned above:

./configure --with-zstd --with-openssl CFLAGS="-O3 -march=native"

Again, and this needs to be reiterated sufficiently often, please do no forget to make clean after (re-)configuration and before building (again) using make.

SPECK – ARM NEON Hardware Acceleration

By default, SPECK does not take advantage of ARM NEON hardware acceleration even if compiled with -march=native. The reason is that the NEON implementation proved to be slower than the 64-bit scalar code on Raspberry Pi 3B+, see here.

Your specific ARM mileage may vary, so it can be enabled by configuring the definition of the SPECK_ARM_NEON macro:

./configure CFLAGS="-DSPECK_ARM_NEON"

Just make sure that the correct architecture is set, too. -march=native usually works quite well.

Disable Multicast Local Peer Detection

For better local peer detection, the edges try to detect local peers by sending REGISTER packets to a certain multicast address. Also, edges listen to this address to eventually fetch such packets.

If these packets disturb network's peace or even get forwarded by (other) edges through the n2n network, this behavior can be disabled, just add

-DSKIP_MULTICAST_PEERS_DISCOVERY

to your CFLAGS when configuring, e.g.

./configure --with-zstd CFLAGS="-O3 -march=native -DSKIP_MULTICAST_PEERS_DISCOVERY"

Cross compiling on Linux

Using the Makefiles and Autoconf

The Makefiles are all setup to allow cross compiling of this code. You will need to have the cross compiler, binutils and any additional libraries desired installed for the target architecture. Then you can run the ./configure with the appropriate CC and AR environment and the right --host option.

If compiling on Debian or Ubuntu, this can be as simple as the following example:

HOST_TRIPLET=arm-linux-gnueabi
sudo apt-get install binutils-$HOST_TRIPLET gcc-$HOST_TRIPLET
./autogen.sh
export CC=$HOST_TRIPLET-gcc
export AR=$HOST_TRIPLET-ar
./configure --host $HOST_TRIPLET
make

A good starting point to determine the host triplet for your destination platform can be found by copying the ./config.guess script to it and running it on the destination.

This is not a good way to produce binaries for embedded environments (like OpenWRT) as they will often use a different libc environment.