A WireGuard UWP VPN plugin.

Overview

WireGuard UWP

A Universal Windows Platform (UWP) VPN Plug-in for WireGuard® written in Rust.

Windows provides a plug-in based model for adding 3rd-party VPN protocols. VPN profiles backed by such a plugin are referred to as Plugin/3rd-party/UWP profiles, as opposed to Native profiles (i.e. built-in SSTP, IKEv2).

WireGuard is a VPN protocol that aims to be: Fast, Modern and Secure. Principles which dovetail quite nicely with the Rust programming language. The actual noise-based WireGuard implementation comes from Cloudflare's boringtun.

With the rapidly maturing Rust for Windows bindings, this projects serve as a fun experiment in putting all the above together.

Building

Make sure you have Rust installed. Then, once you've cloned the repo just simply run:

$ cargo build --release

The project currently only builds on Windows but given the Windows-specific nature, that's not considered a limitation.

Installing

Once you've successfully built the project, you can install it by running the following commands in a powershell prompt from the repo root:

copy appx\* target\release
Add-AppxPackage -Register .\target\release\AppxManifest.xml

NOTE: This does an in-place sort of installation in that the installed app will refer to the binaries in your target\release folder. So you may encounter issues if you modify those after installation. This is just a stop-gap until a proper .appx can be generated.

Running

To get your VPN tunnel up and running:

  1. Open Windows Settings and navigate to the VPN page: Network & Internet > VPN.
  2. Select Add a VPN connection.
  3. From the VPN provider dropdown select WireGuard UWP VPN.
  4. Give your new VPN profile a name under Connection name.
  5. Enter the remote endpoint hostname or IP address under Server name or address.
  6. Hit Save.

The settings you can tweak from the Windows Settings UI are limited to just the profile name and remote endpoint's hostname. To modify the private key, public key, remote port etc we must set those values manually. From a powershell prompt:

$vpnConfig = @'
<WireGuard>
    <Interface>
        <PrivateKey>...</PrivateKey>
        <Address>10.0.0.2/32</Address>
        <Address>2001:db8::2/64</Address>
        <DNS>1.1.1.1</DNS>
        <DNSSearch>vpn.example.com</DNSSearch>
        <DNSSearch>foo.corp.example.com</DNSSearch>
    </Interface>
    <Peer>
        <PublicKey>...</PublicKey>
        <Port>51000</Port>
        <AllowedIPs>10.0.0.0/24</AllowedIPs>
        <AllowedIPs>10.10.0.0/24</AllowedIPs>
        <AllowedIPs>10.20.0.0/24</AllowedIPs>
        <AllowedIPs>2001:db8::/64</AllowedIPs>
        <PersistentKeepalive>25</PersistentKeepalive>
    </Peer>
</WireGuard>
'@

Set-VpnConnection -Name ProfileNameHere -CustomConfiguration $vpnConfig

The only required values are PrivateKey, Address, PublicKey, & Port. The rest are optional. You may repeat Address multiple times to assign multiple IPv4 & IPv6 addresses to the virtual interface. Similarly, you may specify AllowedIPs multiple times to define the routes that should go over the virtual interface.

You should now be able to select the new profile and hit Connect.

NOTE: Ideally, you could just specify Port colon separated with the hostname but the corresponding API for retrieving that value is statically typed as a HostName.

NOTE: You should make sure to set a PersistentKeepalive value on the remote side for each WireGuard UWP-based client because the UWP VPN plugin model offers limited options for the plugin to perform periodic actions. Generally, the plugin will only be woken if there are packets that need to be encapsulated or if there are incoming buffers from the remote that need to be decapsulated. The platform does provide a GetKeepAlivePayload it will call on occasion but the interval in which it will be called cannot be controlled by the plugin author or the user but rather the platform itself. Hence it's important to make sure the server will keep the tunnel alive by sending the periodic keep alives in-band.

NOTE: The main foreground app is planned to offer a simple UI for setting and modifying these values.

This has only been tested on Windows 10 21H1 (19043.1348) but should work on any updated Windows 10 or 11 release. It'll probably work on older versions but no guarantees.

Address

You must specify one or more IPv4 and/or IPv6 addresses to assign to the virtual interface.

DNS

DNS servers are plumbed via Name Resolution Policy Table (NRPT) Rules. You can print the current set of rules applied while a VPN profile backed by the plugin is connected via either:

CMD:

netsh namespace show effectivepolicy

PowerShell:

Get-DnsClientNrptPolicy -Effective

If any number of DNS servers are specified in the config, the plugin will plumb one NRPT rule with the namespace set to .; this means the rule will apply to all domains. While NRPT rules do support matching based on domain suffixes/prefixes to apply domain-specific DNS servers, we just use a single wildcard rule.

You will note another rule plumbed while the plugin is connected, for the specific domain used to connect to the remote endpoint. This is added automatically by the platform so that if the tunnel is interrupted and needs to be re-established, we don't end up in a situation wherein we can't resolve the remote's hostname.

You can also specify one more optional search domains. These will be added to the VPN interface's Connection-specific DNS Suffix Search List. The first specified search domain will also be the primary Connection-specific DNS Suffix, as can be confirmed with ipconfig /all after connecting. You'll see an additional suffix-type NRPT rule for each such search domain configured, with the specific DNS servers set to whatever was configured.

Routing

If you'd like all traffic to flow over the VPN interface while connected, you can just add a catch-all route (0.0.0.0/0 or ::/0 as appropriate):

$vpnConfig = @'
<WireGuard>
    <Interface>
        <PrivateKey>...</PrivateKey>
        <Address>10.0.0.2/32</Address>
        <DNS>1.1.1.1</DNS>
    </Interface>
    <Peer>
        <PublicKey>...</PublicKey>
        <Port>51000</Port>
        <AllowedIPs>0.0.0.0/0</AllowedIPs>
        <PersistentKeepalive>25</PersistentKeepalive>
    </Peer>
</WireGuard>
'@

Set-VpnConnection -Name ProfileNameHere -CustomConfiguration $vpnConfig

If you'd like to exclude certain routes from going over the VPN interface, you can specify one or more ExcludedIPs elements:

$vpnConfig = @'
<WireGuard>
    <Interface>
        <PrivateKey>...</PrivateKey>
        <Address>10.0.0.2/32</Address>
        <DNS>1.1.1.1</DNS>
    </Interface>
    <Peer>
        <PublicKey>...</PublicKey>
        <Port>51000</Port>
        <AllowedIPs>0.0.0.0/0</AllowedIPs>
        <ExcludedIPs>192.168.1.0/24</ExcludedIPs>
        <PersistentKeepalive>25</PersistentKeepalive>
    </Peer>
</WireGuard>
'@

Set-VpnConnection -Name ProfileNameHere -CustomConfiguration $vpnConfig

This usually only makes sense if you have a catch-all route to carve out some exceptions. Also note that there will usually already be a specific route entry for your local subnet so no need to explicitly exclude it.

To print the routing table in cmd.exe run:

route print

Tracing

The plugin emits a number of ETW under the Event Provider identified by a specific GUID (c4522a55-401f-4b81-93f9-aa0d1db734c4). The events are emitted with the help of the rust_win_etw crate which provides a way to define & emit ETW events from your Rust code.

To consume these events, there are a number of different tools which can be used. rust_win_etw provides a quick rundown on how to capture them: https://github.com/microsoft/rust_win_etw#how-to-capture-and-view-events

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.


"WireGuard" and the "WireGuard" logo are registered trademarks of Jason A. Donenfeld.

You might also like...
WireGuard frontend for mitmproxy (WIP)
WireGuard frontend for mitmproxy (WIP)

mitmproxy_wireguard Transparently proxy any device that can be configured as a WireGuard client! Work-In-Progress. Architecture DONE multi-threaded /

Rust utility crate for parsing, encoding and generating x25519 keys used by WireGuard

WireGuard Keys This is a utility crate for parsing, encoding and generating x25519 keys that are used by WireGuard. It exports custom types that can b

WireGuard gateway with SNI for portable connectivity.

Gateway This is a daemon that controls gateway servers. Gateway servers are servers that fulfil three major purposes: facilitating connectivity betwee

User-space Wireguard gateway allowing sharing network connection from environment where usual routing rules are inaccessible.

wgslirpy A command line tool (and a Rust library) for accepting incoming connections within a Wireguard link and routing them to external network usin

Bevy plugin for the GGRS P2P rollback networking library.

Bevy_GGRS Bevy plugin for the 👉 GGRS P2P rollback networking library. The plugin creates a custom stage with a separate schedule, which handles corre

Barebones egui_baseview vst2 plugin with basic parameter control
Barebones egui_baseview vst2 plugin with basic parameter control

egui_baseview_test_vst2 Based on baseview_test_vst2 Barebones baseview/egui_baseview vst2 plugin. It implements an egui ui for the vst gain effect exa

Barebones imgui_baseview vst2 plugin with basic parameter control
Barebones imgui_baseview vst2 plugin with basic parameter control

imgui_baseview_test_vst2 Based on baseview_test_vst2 Barebones baseview/imgui_baseview vst2 plugin. It implements a imgui-rs ui for the vst gain effec

A Rust compiler plugin and support library to annotate overflow behavior

overflower This project contains a compiler plugin and supporting library to allow the programmer to annotate their code to declare how integer overfl

Hammerspoon plugin and API to interact with Yabai socket directly

Yabai.spoon NOTE: no longer using it or intending to maintain it see #2. Yabai.spoon is lua 5.4 library to interact with yabai socket directly within

Comments
  • support multiple peers

    support multiple peers

    This app work very well I would like to add multiple peers to to config

    $vpnConfig = @'
    <WireGuard>
        <Interface>
            <PrivateKey>foo</PrivateKey>
            <Address>10.0.0.2/32</Address>
            <Port>51820</Port>
        </Interface>
        <Peer>
            <PublicKey>bar</PublicKey>
            <AllowedIPs>10.0.0.254/32</AllowedIPs>
            <Port>51820</Port>
            <PersistentKeepalive>5</PersistentKeepalive>
        </Peer>
        <Peer>
            <PublicKey>baz</PublicKey>
            <AllowedIPs>10.0.0.253/32</AllowedIPs>
            <Port>51820</Port>
            <PersistentKeepalive>5</PersistentKeepalive>
        </Peer>
    </WireGuard>
    '@
    
    Set-VpnConnection -Name wg-rust -CustomConfiguration $vpnConfig
    

    It will failed at parsing the config : duplicate field Peer image

    I think multiple peer is a common use case. Is there's any way to support that?

    opened by hoyho 1
Owner
Luqman Aden
Luqman Aden
wireguard tool to manage / generate configuration. Maintain one yaml configuration file to quickly build wireguard network.

wgx wireguard tool to manage / generate configuration. Maintain one yaml configuration file to quickly build wireguard network. Usage wgx --h USAGE:

yinheli 6 Nov 3, 2022
Simple VPN implemented using rust

fubuki Simple VPN implemented using rust fubuki是类似与tincVPN的简单组网工具 不支持对等NAT 支持的平台: Windows Linux 工作机制 它由一台拥有公网IP的服务器来维持各个内网客户端的实际地址映射,在客户端和客户端之间实现P2P通信

XTY 84 Dec 31, 2022
MASQ Network 121 Dec 20, 2022
A super naive, (possibly unreliable), VPN implementation.

Poor Man's VPN A super naive, (possibly unreliable), VPN implementation. Try on Docker Containers You can test the VPN on docker containers. up.sh scr

algon 2 Sep 7, 2022
Final Project for "Computer Networking Security": A Layer-3 VPN implementation over TLS

Final Project for "Computer Networking Security": A Layer-3 VPN implementation over TLS

Siger Yang 2 Jun 7, 2022
A virtual network tool (or VPN)

switch A virtual network tool (VPN) 将不同网络下的多个设备虚拟到一个局域网下 示例: 在一台mac设备上运行,获取到ip 10.13.0.2: 在另一台windows上运行,获取到ip 10.13.0.3: 此时这两个设备之间就能用ip相互访问了 输入"list"

null 49 Jan 21, 2023
A private network system that uses WireGuard under the hood.

innernet A private network system that uses WireGuard under the hood. See the announcement blog post for a longer-winded explanation. innernet is simi

Tonari, Inc 4.1k Dec 29, 2022
A cross-platform, user-space WireGuard port-forwarder that requires no system network configurations.

Cross-platform, user-space WireGuard port-forwarder that requires no system network configurations.

Aram Peres 629 Jan 4, 2023
A Prometheus exporter for WireGuard

wireguard_exporter An asynchronous Prometheus exporter for wireguard wireguard_exporter runs wg show [..] and scrapes the output to build Prometheus m

Kevin K. 15 Dec 29, 2022
WireGuard front for mitmproxy (WIP)

mitmguard work-in-progress WireGuard front for mitmproxy Architecture DONE multi-threaded / asynchronous WireGuard server using tokio: one worker thre

Fabio Valentini 23 Jan 5, 2023