Amnezia-Client Architecture: Main Components, Layer Structure, and Source Code Organization
Amnezia Client uses a layered, cross-platform architecture separating the QML user interface, core application logic, VPN engine, protocol implementations, and a privileged background service that communicates via local IPC sockets.
The amnezia-vpn/amnezia-client repository implements this modular design in C++ and Qt, enabling consistent behavior across Windows, macOS, Linux, Android, and iOS while maintaining strict separation between UI concerns and system-level VPN operations.
User Interface Layer (QML Controllers)
The UI layer consists of QML front-end files backed by thin C++ controllers that expose core objects to the declarative interface. This layer handles all user interactions, settings management, and connection status displays without directly accessing networking APIs.
Key implementations reside in:
client/ui/controllers/qml/pageController.cpp– Manages page navigation and view state transitionsclient/ui/models/installedAppsModel.cpp– Provides data models for split-tunneling application lists
These controllers register as QML singletons during application startup, allowing QML code to invoke C++ methods while keeping the interface responsive on the main thread.
Core Application Layer
The Application Core coordinates between the UI, persistent settings, and the VPN engine. The entry point at client/amneziaApplication.cpp bootstraps the Qt application, registers QML types, and instantiates the primary coordinator.
The CoreController (client/core/controllers/coreController.cpp) serves as the central hub:
- Creates and manages the
VpnConnectionobject - Handles protocol selection and container configuration
- Registers singleton helpers for protocol metadata, container management, and QR-code generation
This layer maintains the application state machine and ensures thread-safe communication between the UI thread and background VPN operations.
VPN Engine and Protocol Implementations
The VPN Engine centers on the VpnConnection class defined in client/vpnConnection.h. This class runs the selected VPN protocol in a dedicated thread, emitting state change signals that propagate back to the UI through the CoreController.
Concrete protocol implementations live in client/core/protocols/:
openVpnProtocol.cpp– Manages OpenVPN daemon lifecycle and log parsingwireGuardProtocol.cpp– Handles WireGuard tunnel interface creationxrayProtocol.cpp– Implements XRay/VMess proxy protocolsikev2VpnProtocolWindows.cpp– Windows-specific IKEv2 integration
Each protocol implementation knows how to start and stop its underlying daemon, parse connection logs, and translate low-level events into the application's standardized state machine.
Configuration Management (Configurators)
Configurators generate the protocol-specific configuration files required by each daemon. Located in client/core/configurators/, these helpers translate user settings from the UI into valid daemon configurations:
openVpnConfigurator.cppproduces.ovpnfiles with cipher and transport optionswireguardConfigurator.cppgenerates WireGuard.conffiles with private keys and peer endpointsxrayConfigurator.cppassembles XRay JSON configurations with obfuscation settings
These components pull data from the UI models, apply user-selected transport or obfuscation options, and write the final configuration to the service directory before the daemon launches.
Background Service and IPC Layer
The Background Service (amneziavpn-service) is a separate privileged executable that runs the actual VPN containers, manages routing tables, enforces kill-switch rules, and performs other operations requiring elevated privileges.
Key service files:
service/server/main.cpp– Daemon entry point and initializationservice/server/killswitch.cpp– Network kill-switch implementation to prevent traffic leaks
The IPC Layer (ipc/ipcserver.cpp and ipc/ipcserverprocess.cpp) provides local-socket based message passing between the UI process and the service. The UI sends action requests (start VPN, stop VPN, fetch logs) through this channel, and the service responds with status updates.
Platform Abstraction Layer
Platform-specific helpers isolate OS-dependent functionality in client/platforms/:
- Windows:
client/platforms/windows/windowsfirewall.cppmanipulates the Windows Filtering Platform for kill-switch functionality - macOS:
client/platforms/macos/macosfirewall.cpphandles macOS firewall and route table updates - Linux:
client/platforms/linux/linuxnetworkwatcher.cppmonitors network interface changes
These wrappers normalize firewall manipulation, route table updates, and network monitoring across operating systems while presenting a unified interface to the core VPN engine.
Utilities and Build System
Supporting infrastructure includes:
common/logger/logger.cpp– Structured logging throughout the applicationcommon/crypto/cryptoUtils.cpp– Cryptographic utilities for key generation and certificate handlingCMakeLists.txt– Cross-platform build configuration using Conan for third-party dependencies
Component Interaction Flow
Understanding the data flow clarifies how these layers interact:
- UI invokes methods on CoreController (registered as QML singleton)
- CoreController creates a VpnConnection thread and selects the appropriate Protocol implementation
- Protocol uses a Configurator to generate daemon config files, then instructs the Service via IPC to launch the daemon
- Service runs the daemon, applies routing/firewall rules through platform helpers, and reports status back through IPC
This separation ensures that UI crashes or terminations do not affect the active VPN tunnel, as the privileged service maintains the connection independently.
Code Examples
Starting a VPN connection from QML using the exposed CoreController:
// main.qml
import QtQuick 2.15
import QtQuick.Controls 2.15
import CoreController 1.0
Button {
text: "Connect"
onClicked: {
// "0" is the index of the first server in the list
CoreController.openConnectionByIndex(0)
}
}
The C++ side forwards this call to the ConnectionController, which instantiates VpnConnection, selects the protocol, generates configuration via the appropriate configurator, and signals the service to start the daemon.
Using the low-level VpnConnection class directly for headless operation or testing:
#include "client/vpnConnection.h"
#include "client/core/controllers/connectionController.h"
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
// Create a VPN connection object (no UI)
auto vpn = std::make_unique<VpnConnection>(nullptr, nullptr);
ConnectionController controller(vpn.get());
// Choose WireGuard protocol and start it
controller.selectProtocol(ProtocolEnumNS::Proto::WireGuard);
controller.start(); // launches the daemon via WireGuardProtocol
QObject::connect(vpn.get(), &VpnConnection::stateChanged,
[](VpnConnection::State s){ qDebug() << "State:" << s; });
return app.exec();
}
Summary
- Layered Architecture: Amnezia-client separates UI (QML), core logic (CoreController), VPN engine (VpnConnection), protocols, and system service through clean interfaces
- Protocol Support: Modular protocol implementations in
client/core/protocols/support OpenVPN, WireGuard, XRay/VMess, and IKEv2 with platform-specific variants - Configuration Pipeline: Dedicated configurators translate UI settings into daemon-specific configs before service launch
- Privilege Separation: The UI process communicates with a privileged background service via IPC, isolating dangerous operations from the user interface
- Cross-Platform: Platform abstraction layers in
client/platforms/handle OS-specific firewall and routing logic while sharing common protocol code
Frequently Asked Questions
What programming languages does amnezia-client use?
The codebase is primarily C++ (Qt framework) for the engine and service, QML (Qt Meta Language) for the user interface, and CMake for the build system. Platform-specific components may use Objective-C++ on macOS/iOS or Java/Kotlin integrations on Android, but the core VPN logic remains portable C++.
How does the UI communicate with the VPN service?
Communication occurs through a local socket IPC layer implemented in ipc/ipcserver.cpp. The UI process sends serialized command messages (start, stop, status queries) to the amneziavpn-service daemon, which executes privileged operations and returns state updates asynchronously.
Where are the VPN protocol implementations located?
Protocol implementations reside in client/core/protocols/, with each protocol having its own translation unit. For example, WireGuard logic is in client/core/protocols/wireGuardProtocol.cpp, while XRay/VMess handling lives in client/core/protocols/xrayProtocol.cpp. These classes inherit from a common base and implement virtual methods for starting, stopping, and monitoring the respective daemons.
Is amnezia-client cross-platform?
Yes. The architecture uses platform abstraction layers in client/platforms/ to isolate OS-specific code (firewall rules, route management, service installation) while keeping the core VPN engine and UI code platform-agnostic. The same VpnConnection and protocol classes compile for Windows, macOS, Linux, Android, and iOS with appropriate platform helpers linked at build time.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →