Announcing wg2nd: Migrate WireGuard Configurations to networkd
Today, I am excited to release
wg2nd, a tool specifically engineered to convert WireGuard configurations
wg-quick(8) format to
systemd-networkd compatible configurations.
wg2nd serves as a bridge to translate
wg-quick configurations into
networkd configurations without
requiring additional setup.
networkd is a feature-complete network manager, allowing users greater
control over WireGuard tunnels. This tool also addresses potential reliability issues that may arise
networkd interferes with tunnels it doesn't manage. Moreover,
wg2nd can batch-convert
Goals of the Project
wg-quickconfigurations except those that involve
PostDownscripts, which are omitted.
Security: Private and symmetric keys are stored in keyfiles with restricted access permissions.
wg2ndleverages the same formally-verified Curve25519 implementation employed in WireGuard. All operations involving private keys are executed in constant-time. Additionally, the web port operates entirely on the client-side. It does not transmit or store any sensitive data.
wg2ndgenerates configurations deterministically with respect to the input WireGuard configuration. When updates are made to the WireGuard source configurations, only the corresponding elements in the output will be altered. This ensures that configurations from a VPN provider can be batch-converted without generating unnecessary files or inducing unexpected behavioral changes.
Keyfiles for both private and symmetric keys are named according to the public key of the relevant interface or peer. These keyfiles are encoded in base32 rather than base64 to avoid issues with the Unix path separator present in base64 encoding. The public key corresponding to a keyfile can be obtained using the following command:
echo $KEY | sed -E 's/\.(priv|sym)key//' | base32 -d | base64
This approach effectively ensures that if two interfaces share the same private key, a single shared keyfile will be generated. The
fwmarkfield employs a SipHash of the interface name, enabling the generation of identical network and netdev files across separate program invocations, while minimizing the risk of
Compatibility and Limitations
wg2nd is designed for high compatibility but comes with some caveats:
Dynamic Firewall Installation: Unlike
wg-quick, which installs a firewall by default when a default route is specified,
wg2nddoes not. However, an equivalent firewall can be generated if desired.
Pre/Post Interface Setup Scripts:
wg2nddoes not handle
PostDownscript snippets, which
FwMark and Table Handling:
wg2nduses a deterministic method for generating
fwmarkbased on the interface name. This contrasts with
wg-quick, which dynamically checks availability. This deterministic approach is necessary because a static value must be chosen for configuration. However, this could result in a birthday collision if a large number of interfaces are ported. (Such a scenario becomes only remotely probable after porting around 500 interfaces.)
The web port has been developed by converting the
C++ implementation into WebAssembly (WASM). It offers an
entirely browser-based experience, converting your WireGuard configurations into a series of Bash commands to configure
the interface. This allows you to experiment within your browser.
The code is dual-licensed under the GPL-2.0 and MIT licenses. Feel free to send me patches via email or submit pull requests through GitHub.
For further details, including installation instructions, please consult the project README.