# Where Are Network Interface Handling Routines Located in Amnezia-Client?

> Discover network interface handling routines in Amnezia Client. Explore platform-specific utility classes and the central Daemon class for robust network management. Find the code now.

- Repository: [Amnezia VPN/amnezia-client](https://github.com/amnezia-vpn/amnezia-client)
- Tags: internals
- Published: 2026-07-29

---

**Network interface handling routines in amnezia-client are implemented across platform-specific utility classes under `client/platforms/<os>/daemon/`, orchestrated by the high-level `Daemon` class in [`client/daemon/daemon.cpp`](https://github.com/amnezia-vpn/amnezia-client/blob/main/client/daemon/daemon.cpp).**

The amnezia-client repository manages VPN network interfaces—specifically WireGuard TUN devices—through a layered architecture that separates high-level connection state from OS-specific system calls. This design allows the client to create, configure, query, and destroy network interfaces across Linux, Windows, and macOS while sharing common data structures and activation logic.

## High-Level Daemon Orchestration

The **network interface lifecycle** is driven by the central `Daemon` singleton, which coordinates activation, deactivation, and existence checks regardless of the underlying platform.

### Entry Points for Interface Management

In [`client/daemon/daemon.cpp`](https://github.com/amnezia-vpn/amnezia-client/blob/main/client/daemon/daemon.cpp), three critical methods manage the interface state:

- **`Daemon::activate()`**: Parses the configuration, validates the interface state, and triggers platform-specific creation if the interface does not exist.
- **`Daemon::deactivate()`**: Gracefully shuts down the tunnel and removes the interface.
- **`Daemon::interfaceExists()`**: Queries the current platform utility to verify whether the TUN device is already active.

These methods rely on the **`InterfaceConfig`** data structure defined in [`client/daemon/interfaceconfig.h`](https://github.com/amnezia-vpn/amnezia-client/blob/main/client/daemon/interfaceconfig.h), which encapsulates private keys, peer configurations, allowed IPs, MTU settings, and routing rules.

## Platform-Agnostic Abstraction Layer

Before reaching OS-specific code, all operations pass through the abstract **`WireguardUtils`** base class, located in [`client/platforms/common/wireguardutils.h`](https://github.com/amnezia-vpn/amnezia-client/blob/main/client/platforms/common/wireguardutils.h) (generated during the build process).

This pure virtual interface exposes standardized methods for network interface handling:

- `addInterface()`: Creates the TUN device.
- `deleteInterface()`: Destroys the TUN device.
- `updatePeer()`: Configures WireGuard peer endpoints and keys.
- `updateRoutePrefix()` / `deleteRoutePrefix()`: Manages routed subnets.

The daemon accesses these capabilities through a singleton helper (`wgutils()`), ensuring that high-level logic remains decoupled from kernel-specific implementations.

## Platform-Specific Implementations

Each operating system provides a concrete subclass of `WireguardUtils` that implements the actual system calls and driver interactions required to manipulate network interfaces.

### Linux Implementation ([`wireguardutilslinux.cpp`](https://github.com/amnezia-vpn/amnezia-client/blob/main/wireguardutilslinux.cpp))

On Linux, the implementation resides in [`client/platforms/linux/daemon/wireguardutilslinux.cpp`](https://github.com/amnezia-vpn/amnezia-client/blob/main/client/platforms/linux/daemon/wireguardutilslinux.cpp). The **`WireguardUtilsLinux`** class launches the `amneziawg-go` user-space WireGuard process, communicates via the UAPI (Userspace API), and configures kernel networking through netlink sockets.

Key responsibilities include:
- Starting the `amneziawg-go` binary with the interface name (e.g., `amn0`).
- Writing base64-decoded private keys and peer configurations via UAPI.
- Monitoring route changes via [`client/platforms/linux/daemon/linuxroutemonitor.cpp`](https://github.com/amnezia-vpn/amnezia-client/blob/main/client/platforms/linux/daemon/linuxroutemonitor.cpp).

```cpp
// Excerpt from client/platforms/linux/daemon/wireguardutilslinux.cpp
bool WireguardUtilsLinux::addInterface(const InterfaceConfig &config) {
    // Start the user-space WireGuard process (amneziawg-go)
    m_tunnel.start(appPath.filePath("amneziawg-go"), {"-f", "amn0"});
    if (!m_tunnel.waitForStarted(WG_TUN_PROC_TIMEOUT))
        return false;

    // Retrieve the generated interface name (normally “amn0”)
    m_ifname = waitForTunnelName(wgNameFile);
    if (m_ifname.isNull())
        return false;

    // Build the UAPI configuration message (private key, peer, etc.)
    QString msg = QStringLiteral("set=1\nprivate_key=%1\nreplace_peers=true\n")
                      .arg(QString(QByteArray::fromBase64(config.m_privateKey.toUtf8()).toHex()));
    // …append additional fields from `config`…
    int err = uapiErrno(uapiCommand(msg));
    return err == 0;
}

```

### Windows Implementation ([`wireguardutilswindows.cpp`](https://github.com/amnezia-vpn/amnezia-client/blob/main/wireguardutilswindows.cpp))

The Windows-specific logic in [`client/platforms/windows/daemon/wireguardutilswindows.cpp`](https://github.com/amnezia-vpn/amnezia-client/blob/main/client/platforms/windows/daemon/wireguardutilswindows.cpp) utilizes the **Wintun** driver and the WireGuard Windows API to manage the virtual network adapter.

```cpp
// Excerpt from client/platforms/windows/daemon/wireguardutilswindows.cpp
bool WireguardUtilsWin::addInterface(const InterfaceConfig &config) {
    // Create a Wintun adapter
    WINTUN_ADAPTER *adapter = wintunCreateAdapter(L"AmneziaVPN", WG_INTERFACE, 0);
    if (!adapter) return false;

    // Store the interface name for later UAPI communication
    m_ifname = QString::fromWCharArray(wintunGetAdapterName(adapter));

    // Configure the interface via the WireGuard Windows API
    WG_IOCTL_INTERFACE iface = {};
    iface.private_key = decodeBase64(config.m_privateKey);
    // …populate peers, allowed IPs, MTU, etc.…
    DWORD ret = DeviceIoControl(adapter, WG_IOCTL_SET_INTERFACE, &iface,
                                sizeof(iface), nullptr, 0, nullptr, nullptr);
    return ret != 0;
}

```

### macOS Implementation ([`wireguardutilsmacos.cpp`](https://github.com/amnezia-vpn/amnezia-client/blob/main/wireguardutilsmacos.cpp))

On macOS, [`client/platforms/macos/daemon/wireguardutilsmacos.cpp`](https://github.com/amnezia-vpn/amnezia-client/blob/main/client/platforms/macos/daemon/wireguardutilsmacos.cpp) handles interface creation by either invoking the native WireGuard kernel extension or launching the user-space binary, followed by UAPI configuration similar to the Linux flow.

```cpp
// Excerpt from client/platforms/macos/daemon/wireguardutilsmacos.cpp
bool WireguardUtilsMac::addInterface(const InterfaceConfig &config) {
    // Launch the macOS WireGuard user-space binary
    QProcess wg;
    wg.start("/usr/local/bin/wg", {"-f", "amn0"});
    if (!wg.waitForStarted()) return false;

    // Send UAPI configuration (similar to Linux)
    QString msg = QStringLiteral("set=1\nprivate_key=%1\nreplace_peers=true\n")
                      .arg(QString(QByteArray::fromBase64(config.m_privateKey.toUtf8()).toHex()));
    // …send via local socket to the “amn0.sock” file…
    int err = uapiErrno(uapiCommand(msg));
    return err == 0;
}

```

## Routing and Kill-Switch Helpers

Beyond basic interface creation, the amnezia-client manages routing tables and firewall rules through supplementary helpers. Low-level route manipulation occurs in platform-specific router files:

- [`service/server/router_linux.cpp`](https://github.com/amnezia-vpn/amnezia-client/blob/main/service/server/router_linux.cpp)
- [`service/server/router_mac.cpp`](https://github.com/amnezia-vpn/amnezia-client/blob/main/service/server/router_mac.cpp)
- [`service/server/router_win.cpp`](https://github.com/amnezia-vpn/amnezia-client/blob/main/service/server/router_win.cpp)

These files handle the insertion and deletion of routes to ensure traffic flows through the VPN tunnel. Additionally, kill-switch functionality—blocking traffic outside the VPN—is implemented in [`client/daemon/killswitch.h`](https://github.com/amnezia-vpn/amnezia-client/blob/main/client/daemon/killswitch.h) with supporting logic in OS-specific firewall files such as [`client/platforms/linux/daemon/linuxfirewall.cpp`](https://github.com/amnezia-vpn/amnezia-client/blob/main/client/platforms/linux/daemon/linuxfirewall.cpp).

## Code Examples

The following patterns demonstrate how the high-level daemon coordinates with platform utilities to manage the network interface lifecycle.

**Activate a VPN connection (high-level):**

```cpp
// Assuming `jsonConfig` contains the WireGuard configuration received from the UI…
InterfaceConfig cfg;
if (!Daemon::parseConfig(jsonConfig, cfg)) {
    qWarning() << "Invalid config";
    return;
}
Daemon *d = Daemon::instance();
bool ok = d->activate(cfg);        // Triggers interface creation if it does not exist

```

**Check whether the interface already exists (used inside `activate()`):**

```cpp
if (!wgutils()->interfaceExists()) {
    wgutils()->addInterface(cfg);   // Platform-specific implementation is called
}

```

## Summary

- **Network interface handling routines** are centralized in [`client/daemon/daemon.cpp`](https://github.com/amnezia-vpn/amnezia-client/blob/main/client/daemon/daemon.cpp) through the `Daemon` class, which delegates platform-specific work to `WireguardUtils` subclasses.
- **Platform abstractions** are defined in [`client/platforms/common/wireguardutils.h`](https://github.com/amnezia-vpn/amnezia-client/blob/main/client/platforms/common/wireguardutils.h) and implemented separately for Linux, Windows, and macOS under `client/platforms/<os>/daemon/`.
- **Interface creation** involves starting background processes (Linux/macOS) or creating Wintun adapters (Windows), followed by UAPI configuration.
- **Routing and kill-switch logic** resides in `service/server/router_*.cpp` and [`client/daemon/killswitch.h`](https://github.com/amnezia-vpn/amnezia-client/blob/main/client/daemon/killswitch.h) to secure traffic routing.

## Frequently Asked Questions

### What is the entry point for creating a VPN interface in amnezia-client?

The entry point is **`Daemon::activate()`** in [`client/daemon/daemon.cpp`](https://github.com/amnezia-vpn/amnezia-client/blob/main/client/daemon/daemon.cpp). This method validates the configuration, checks for existing interfaces via `Daemon::interfaceExists()`, and calls `wgutils()->addInterface()` to trigger the platform-specific creation routine.

### How does amnezia-client handle platform differences for network interfaces?

The project uses an abstract base class **`WireguardUtils`** declared in [`client/platforms/common/wireguardutils.h`](https://github.com/amnezia-vpn/amnezia-client/blob/main/client/platforms/common/wireguardutils.h). Concrete implementations for each OS—`WireguardUtilsLinux`, `WireguardUtilsWin`, and `WireguardUtilsMac`—provide the specific logic required to interact with the Windows Wintun driver, Linux netlink sockets, or macOS kernel extensions.

### Where is the network interface configuration data structured?

Configuration data is stored in the **`InterfaceConfig`** structure defined in [`client/daemon/interfaceconfig.h`](https://github.com/amnezia-vpn/amnezia-client/blob/main/client/daemon/interfaceconfig.h). This header encapsulates all WireGuard parameters including private keys, peer public keys, allowed IPs, DNS settings, and MTU values passed between the UI and the daemon.

### Which file handles routing table updates on Linux?

Routing table monitoring and updates on Linux are managed by **[`client/platforms/linux/daemon/linuxroutemonitor.cpp`](https://github.com/amnezia-vpn/amnezia-client/blob/main/client/platforms/linux/daemon/linuxroutemonitor.cpp)**, while the actual insertion and deletion of routes occur in [`service/server/router_linux.cpp`](https://github.com/amnezia-vpn/amnezia-client/blob/main/service/server/router_linux.cpp). These components work together to ensure the default gateway and split-tunnel routes correctly target the WireGuard interface.