aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/adminregistry.md39
-rw-r--r--docs/attacksurface.md46
-rw-r--r--docs/buildrun.md98
-rw-r--r--docs/enterprise.md113
-rw-r--r--docs/netquirk.md33
5 files changed, 329 insertions, 0 deletions
diff --git a/docs/adminregistry.md b/docs/adminregistry.md
new file mode 100644
index 00000000..4289fb38
--- /dev/null
+++ b/docs/adminregistry.md
@@ -0,0 +1,39 @@
+# Registry Keys for Admins
+
+These are advanced configuration knobs that admins can set to do unusual things
+that are not recommended. There is no UI to enable these, and no such thing is
+planned. These registry keys may also be removed at some point in the future.
+The uninstaller will clean up the entirety of `HKLM\Software\WireGuard`. Use
+at your own risk, and please make sure you know what you're doing.
+
+#### `HKLM\Software\WireGuard\LimitedOperatorUI`
+
+When this key is set to `DWORD(1)`, the UI will be launched on desktops of
+users belonging to the Network Configuration Operators builtin group
+(S-1-5-32-556), with the following limitations for members of that group:
+
+ - Configurations are stripped of all public, private, and pre-shared keys;
+ - No version update popup notifications are shown, and updates are not permitted, though a tab still indicates the availability;
+ - Adding, removing, editing, importing, or exporting configurations is forbidden; and
+ - Quitting the manager is forbidden.
+
+However, basic functionality such as starting and stopping tunnels remains intact.
+
+```
+> reg add HKLM\Software\WireGuard /v LimitedOperatorUI /t REG_DWORD /d 1 /f
+```
+
+#### `HKLM\Software\WireGuard\DangerousScriptExecution`
+
+When this key is set to `DWORD(1)`, the tunnel service will execute the commands
+specified in the `PreUp`, `PostUp`, `PreDown`, and `PostDown` options of a
+tunnel configuration. Note that this execution is done as the Local System user,
+which runs with the highest permissions on the operating system, and is therefore
+a real target of malware. Therefore, you should enable this option only with the
+utmost trepidation. Rather than use `%i`, WireGuard for Windows instead sets the
+environment variable `WIREGUARD_TUNNEL_NAME` to the name of the tunnel when
+executing these scripts.
+
+```
+> reg add HKLM\Software\WireGuard /v DangerousScriptExecution /t REG_DWORD /d 1 /f
+```
diff --git a/docs/attacksurface.md b/docs/attacksurface.md
new file mode 100644
index 00000000..a495ba41
--- /dev/null
+++ b/docs/attacksurface.md
@@ -0,0 +1,46 @@
+# Attack Surface
+
+_This is an evolving document, describing currently known attack surface, a few mitigations, and several open questions. This is a work in progress. We document our current understanding with the intent of improving both our understanding and our security posture over time._
+
+WireGuard for Windows consists of four components: a kernel driver, and three separate interacting userspace parts.
+
+### WireGuardNT
+
+WireGuardNT is a kernel driver. It exposes:
+
+ - A miniport driver to the ndis stack, meaning any process on the system that can access the network stack in a reasonable way can send and receive packets, hitting those related ndis handlers.
+ - A UDP port parsing WireGuard packets.
+ - There are also various ndis OID calls, accessible to certain users, which hit further code.
+ - A PNP and Close notifier added to the NDIS device file.
+ - IOCTLs are added to the NDIS device file, and those IOCTLs are restricted to `O:SYD:P(A;;FA;;;SY)(A;;FA;;;BA)S:(ML;;NWNRNX;;;HI)`. The IOCTL allows userspace to get and set configuration, adapter state, and read log messages from a ring buffer.
+
+### Tunnel Service
+
+The tunnel service is a userspace service running as Local System, responsible for creating WireGuardNT adapters and configuring them. It exposes:
+
+ - A global mutex is used for WireGuardNT interface creation, with the same DACL as the pipe, but first CreatePrivateNamespace is called with a "Local System" SID.
+ - After some initial setup, it uses `AdjustTokenPrivileges` to remove all privileges, except for `SeLoadDriverPrivilege`, so that it can remove the interface when shutting down. This latter point is rather unfortunate, as `SeLoadDriverPrivilege` can be used for all sorts of interesting escalation. Future work includes forking an additional process or the like so that we can drop this from the main tunnel process.
+
+### Manager Service
+
+The manager service is a userspace service running as Local System, responsible for starting and stopping tunnel services, and ensuring a UI program with certain handles is available to Administrators. It exposes:
+
+ - Extensive IPC using unnamed pipes, inherited by the UI process.
+ - A readable `CreateFileMapping` handle to a binary ringlog shared by all services, inherited by the UI process.
+ - It listens for service changes in tunnel services according to the string prefix "WireGuardTunnel$".
+ - It manages DPAPI-encrypted configuration files in `C:\Program Files\WireGuard\Data`, which is created with `O:SYG:SYD:PAI(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)`, and makes some effort to enforce good configuration filenames.
+ - The actual DPAPI-encrypted configuration files are created with `O:SYG:SYD:PAI(A;;FA;;;SY)(A;;SD;;;BA)`.
+ - It uses `WTSEnumerateSessions` and `WTSSESSION_NOTIFICATION` to walk through each available session. It then uses `WTSQueryUserToken` to get the token belonging to each session and then determines whether or not it is an administrator token. To determine that, it calls `CheckTokenMembership(CreateWellKnownSid(WinBuiltinAdministratorsSid))` on a duplicated impersonation token, as well as and calling `GetTokenInformation(TokenElevation)` on it. If either of these are false, then it fetched the linked token using `GetTokenInformation(TokenLinkedToken)` and queries the same. Only then does it spawn the UI process as that the elevated user token, passing it three unnamed pipe handles for IPC and the log mapping handle, as described above.
+ - In the event that the administrator has set `HKLM\Software\WireGuard\LimitedOperatorUI` to 1, sessions are started for users that are a member of group S-1-5-32-556 (determined sing `CheckTokenMembership(CreateWellKnownSid(WinBuiltinNetworkConfigurationOperatorsSid))` on it and its linked token), with a more limited IPC interface, in which these non-admin users are denied private keys and tunnel editing rights. (This means users can potentially DoS the IPC server by draining notifications too slowly, or exhausting memory of the manager by spawning too many watcher go routines, or by sending garbage data that Go's `gob` decoder isn't expecting.)
+
+### UI
+
+The UI is a process running for each user who is in the Administrators group (per the above), running with the elevated high integrity linked token. It exposes:
+
+ - Since the UI process is executed with an elevated token, it runs at high integrity and should be immune to various shatter attacks, modulo the great variety of clever bypasses in the latest Windows release.
+ - It uses `AdjustTokenPrivileges` to remove all privileges.
+ - It renders highlighted config files to a msftedit.dll control, which typically is capable of all sorts of OLE and RTF nastiness that we make some attempt to avoid.
+
+### Updates
+
+A server hosts the result of `b2sum -l 256 *.msi > list && signify -S -e -s release.sec -m list && upload ./list.sec`, with the private key stored on an HSM. The MSIs in that list are only the latest ones available, and filenames fit the form `wireguard-${arch}-${version}.msi`. The updater, running as part of the manager service, downloads this list over TLS and verifies the signify Ed25519 signature of it. If it validates, then it finds the first MSI in it for its architecture that has a greater version. It then downloads this MSI from a predefined URL to a randomly generated (256-bits) file name inside `C:\Windows\Temp` with permissions of `O:SYD:PAI(A;;FA;;;SY)(A;;FR;;;BA)`, scheduled to be cleaned up at next boot via `MoveFileEx(MOVEFILE_DELAY_UNTIL_REBOOT)`, and verifies the BLAKE2b-256 signature. If it validates, then it calls `WinTrustVerify(WINTRUST_ACTION_GENERIC_VERIFY_V2, WTD_REVOKE_WHOLECHAIN)` on the MSI. If it validates, then it executes the installer with `msiexec.exe /qb!- /i`, using the elevated token linked to the IPC UI session that requested the update. Because `msiexec` requires exclusive access to the file, the file handle is closed in between the completion of downloading and the commencement of `msiexec`. Hopefully the permissions of `C:\Windows\Temp` are good enough that an attacker can't replace the MSI from beneath us.
diff --git a/docs/buildrun.md b/docs/buildrun.md
new file mode 100644
index 00000000..3d356f2a
--- /dev/null
+++ b/docs/buildrun.md
@@ -0,0 +1,98 @@
+# Building, Running, and Developing
+
+### Building
+
+Windows 10 64-bit or Windows Server 2019, and Git for Windows is required. The build script will take care of downloading, verifying, and extracting the right versions of the various dependencies:
+
+```text
+C:\Projects> git clone https://git.zx2c4.com/wireguard-windows
+C:\Projects> cd wireguard-windows
+C:\Projects\wireguard-windows> build
+```
+
+### Running
+
+After you've built the application, run `amd64\wireguard.exe` or `x86\wireguard.exe` to install the manager service and show the UI.
+
+```text
+C:\Projects\wireguard-windows> amd64\wireguard.exe
+```
+
+Since WireGuard requires a driver to be installed, and this generally requires a valid Microsoft signature, you may benefit from first installing a release of WireGuard for Windows from the official [wireguard.com](https://www.wireguard.com/install/) builds, which bundles a Microsoft-signed driver, and then subsequently run your own wireguard.exe. Alternatively, you can craft your own installer using the `quickinstall.bat` script.
+
+### Optional: Localizing
+
+To translate WireGuard UI to your language:
+
+1. Upgrade `resources.rc` accordingly. Follow the pattern.
+
+2. Make a new directory in `locales\` containing the language ID:
+
+ ```text
+ C:\Projects\wireguard-windows> mkdir locales\<langID>
+ ```
+
+3. Configure and run `build` to prepare initial `locales\<langID>\messages.gotext.json` file:
+
+ ```text
+ C:\Projects\wireguard-windows> set GoGenerate=yes
+ C:\Projects\wireguard-windows> build
+ C:\Projects\wireguard-windows> copy locales\<langID>\out.gotext.json locales\<langID>\messages.gotext.json
+ ```
+
+4. Translate `locales\<langID>\messages.gotext.json`. See other language message files how to translate messages and how to tackle plural. For this step, the project is currently using [CrowdIn](https://crowdin.com/translate/WireGuard); please make sure your translations make it there in order to be added here.
+
+5. Run `build` from the step 3 again, and test.
+
+6. Repeat from step 4.
+
+### Optional: Creating the Installer
+
+The installer build script will take care of downloading, verifying, and extracting the right versions of the various dependencies:
+
+```text
+C:\Projects\wireguard-windows> cd installer
+C:\Projects\wireguard-windows\installer> build
+```
+
+### Optional: Signing Binaries
+
+Add a file called `sign.bat` in the root of this repository with these contents, or similar:
+
+```text
+set SigningCertificate=8BC932FDFF15B892E8364C49B383210810E4709D
+set TimestampServer=http://timestamp.entrust.net/rfc3161ts2
+```
+
+After, run the above `build` commands as usual, from a shell that has [`signtool.exe`](https://docs.microsoft.com/en-us/windows/desktop/SecCrypto/signtool) in its `PATH`, such as the Visual Studio 2017 command prompt.
+
+### Alternative: Building from Linux
+
+You must first have Mingw and ImageMagick installed.
+
+```text
+$ sudo apt install mingw-w64 imagemagick
+$ git clone https://git.zx2c4.com/wireguard-windows
+$ cd wireguard-windows
+$ make
+```
+
+You can deploy the 64-bit build to an SSH host specified by the `DEPLOYMENT_HOST` environment variable (default "winvm") to the remote directory specified by the `DEPLOYMENT_PATH` environment variable (default "Desktop") by using the `deploy` target:
+
+```text
+$ make deploy
+```
+
+### [`wg(8)`](https://git.zx2c4.com/wireguard-tools/about/src/man/wg.8) Support for Windows
+
+The command line utility [`wg(8)`](https://git.zx2c4.com/wireguard-tools/about/src/man/wg.8) works well on Windows. Being a Unix-centric project, it compiles with a Makefile and MingW:
+
+```text
+$ git clone https://git.zx2c4.com/wireguard-tools
+$ PLATFORM=windows make -C wireguard-tools/src
+$ stat wireguard-tools/src/wg.exe
+```
+
+It interacts with WireGuard instances run by the main WireGuard for Windows program.
+
+When building on Windows, the aforementioned `build.bat` script takes care of building this.
diff --git a/docs/enterprise.md b/docs/enterprise.md
new file mode 100644
index 00000000..8430cc99
--- /dev/null
+++ b/docs/enterprise.md
@@ -0,0 +1,113 @@
+# Enterprise Usage
+
+WireGuard for Windows has been designed from the ground-up to make full use of standard Windows service, ACL, and CLI capabilities, making WireGuard deployable in enterprise scenarios or as part of Active Directory domains.
+
+### Installation
+
+While consumer users are generally directed toward [wireguard-installer.exe](https://download.wireguard.com/windows-client/wireguard-installer.exe), this installer simply takes care of selecting the correct MSI for the architecture, validating signatures, and executing it. Enterprise admins can instead [download MSIs directly](https://download.wireguard.com/windows-client/) and deploy these using [Group Policy Objects](https://docs.microsoft.com/en-us/troubleshoot/windows-server/group-policy/use-group-policy-to-install-software). The installer makes use of standard MSI features and should be easily automatable. The additional MSI property of `DO_NOT_LAUNCH` suppresses launching WireGuard after its installation, should that be required.
+
+### Tunnel Service versus Manager Service and UI
+
+The "manager service" is responsible for displaying a UI on select users' desktops (in the system tray), and responding to requests from the UI to do things like add, remove, start, or stop tunnels. The "tunnel service" is a separate Windows service for each tunnel. These two services may be used together, or separately, as described below. The various commands below will log errors and status to standard error, or, if standard error does not exist, to standard output.
+
+### Tunnel Service
+
+A tunnel service may be installed or uninstalled using the commands:
+
+```text
+> wireguard /installtunnelservice C:\path\to\some\myconfname.conf
+> wireguard /uninstalltunnelservice myconfname
+```
+
+This creates a service called `WireGuardTunnel$myconfname`, which can be controlled using standard Windows service management utilites, such as `services.msc` or [`sc`](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/sc-query).
+
+If the configuration filename ends in `.conf`, it is interpreted as a normal [`wg-quick(8)`](https://git.zx2c4.com/wireguard-tools/about/src/man/wg-quick.8) configuration file. If it ends in `.conf.dpapi`, it is considered to be that same configuration file, but encrypted using [`CryptProtectData(bytes, "myconfname")`](https://docs.microsoft.com/en-us/windows/win32/api/dpapi/nf-dpapi-cryptprotectdata).
+
+The tunnel service may be queried and modified at runtime using the standard [`wg(8)`](https://git.zx2c4.com/wireguard-tools/about/src/man/wg.8) command line utility. If the configuration file is a `.conf.dpapi` one, then Local System or Administrator permissions is required to interact with it using `wg(8)`; otherwise users of `wg(8)` must have Local System or Administrator permissions, or permissions the same as the owner of the `.conf` file. Invocation of `wg(8)` follows usual patterns on other platforms. For example:
+
+```text
+> wg show myconfname
+interface: myconfname
+ public key: lfTRXEWxt8mZc8cjSvOWN3tqnTpWw4v2Eg3qF6WTklw=
+ private key: (hidden)
+ listening port: 53488
+
+peer: JRI8Xc0zKP9kXk8qP84NdUQA04h6DLfFbwJn4g+/PFs=
+ endpoint: 163.172.161.0:12912
+ allowed ips: 0.0.0.0/0
+ latest handshake: 3 seconds ago
+ transfer: 6.55 KiB received, 4.13 KiB sent
+```
+
+The `PreUp`, `PostUp`, `PreDown`, and `PostDown` configuration options may be specified to run custom commands at various points in the lifetime of a tunnel service, but only if the correct registry key is set. [See `adminregistry.md` for information.](adminregistry.md)
+
+### Manager Service
+
+The manager service may be installed or uninstalled using the commands:
+
+```text
+> wireguard /installmanagerservice
+> wireguard /uninstallmanagerservice
+```
+
+This creates a service called `WireGuardManager`, which can be controlled using standard Windows service management utilites, such as `services.msc` or [`sc`](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/sc-query).
+
+When executing `wireguard` with no arguments, the command first attempts to show the UI if the manager service is already running; otherwise it starts the manager service, waits for it to create a UI in the system tray, and then shows the main manager window. Therefore, `wireguard /installmanagerservice` is suitable for silent installation, whereas `wireguard` alone is suitable for interactive startup.
+
+The manager service monitors `%ProgramFiles%\WireGuard\Data\Configurations\` for the addition of new `.conf` files. Upon seeing one, it encrypts the file to a `.conf.dpapi` file, makes it unreadable to users other than Local System, confers the administrator only the ability to remove it, and then deletes the original unencrypted file. (Configurations can always be _exported_ later using the export feature of the UI.) Using this, configurations can programmatically be added to the secure store of the manager service simply by copying them into that directory.
+
+The UI is started in the system tray of all builtin Administrators when the manager service is running. A limited UI may also be started in the system tray of all builtin Network Configuration Operators, if the correct registry key is set. [See `adminregistry.md` for information.](adminregistry.md)
+
+### Diagnostic Logs
+
+The manager and all tunnel services produce diagnostic logs in a shared ringbuffer-based log. This is shown in the UI, and also can be dumped to standard out using the command:
+
+```text
+> wireguard /dumplog > C:\path\to\diagnostic\log.txt
+```
+
+Alternatively, the log can be tailed continuously, for passing it to logging services:
+
+```text
+> wireguard /dumplog /tail | log-ingest
+```
+
+Or it can be monitored in PowerShell by piping to `select`:
+
+```text
+PS> wireguard /dumplog /tail | select
+```
+
+### Updates
+
+Administrators are notified of updates within the UI and can update from within the UI, but updates can also be invoked at the command line using the command:
+
+```text
+> wireguard /update
+```
+
+Or, to log the status of that command:
+
+```text
+> wireguard /update 2> C:\path\to\update\log.txt
+```
+
+One could have Task Scheduler run it daily at 3am:
+
+```text
+> schtasks /create /f /ru SYSTEM /sc daily /tn "WireGuard Update" /tr "%PROGRAMFILES%\WireGuard\wireguard.exe /update" /st 03:00
+```
+
+### Driver Removal
+
+The tunnel service creates a network adapter at startup and destroys it at shutdown. If there are no more network adapters, the driver may be removed with:
+
+```text
+> wireguard /removedriver
+```
+
+Or, to log the status of that command:
+
+```text
+> wireguard /removedriver 2> C:\path\to\removal\log.txt
+```
diff --git a/docs/netquirk.md b/docs/netquirk.md
new file mode 100644
index 00000000..d53c8cdb
--- /dev/null
+++ b/docs/netquirk.md
@@ -0,0 +1,33 @@
+# Network Configuration Quirks
+
+As part of setting up a WireGuard tunnel, the tunnel service also sets up various network configuration parameters that are in one way or another related to the original configuration.
+
+### Routing
+
+The tunnel service takes all the allowed IPs from each peer, deduplicates them, and adds them to the routes for the WireGuard interface. The service then monitors which interface on the system has a default route (a route with a `/0` CIDR) that is not the WireGuard interface itself, and, if no MTU has been specified in the configuration, it sets the MTU of the WireGuard interface to be 80 less than the MTU of that default route interface. WireGuardNT also monitors the routing table and determines the outgoing route that does not loopback to itself, and then sends each packet using `IP_PKTINFO`/`IPV6_PKTINFO`. It keeps track of the incoming interface and source address for received packets, and always replies to the sender in that way.
+
+### Firewall Considerations for `/0` Allowed IPs
+
+If an interface has only one peer, and that peer contains an Allowed IP in `/0`, then WireGuard enables a so-called "kill-switch", which adds firewall rules to do the following:
+
+- Packets from the tunnel service itself are permitted, so that WireGuard packets can flow successfully.
+- If the configuration specifies DNS servers, then packets sent to port `53` are only permitted if they are to one of those DNS servers. This is to prevent Windows' [ordinary multihomed DNS resolution behavior](https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/dd197552%28v%3Dws.10%29), so that DNS queries only go to the DNS server specified, rather than multiple DNS servers.
+- Loopback packets are permitted, and packets actually going through the WireGuard tunnel are permitted.
+- DHCP for IPv4 and IPv6 and NDP for IPv6 are permitted.
+- All other packets are blocked.
+
+This prevents traffic from leaking outside the tunnel.
+
+If you'd like to use a default route _without_ having these restrictive kill-switch semantics, one may use the routes `0.0.0.0/1` and `128.0.0.0/1` in place of `0.0.0.0/0`, as well as `::/1` and `8000::/1` in place of `::/0`. This achieves nearly the same thing, but does not activate the above firewalling semantics. (The UI's editor has a checkbox that toggles this.) And users without the need for a `/0` route at all do not have to worry about this, and instead fall back to ordinary Windows routing and DNS behavior.
+
+### Considerations for non-`/0` Allowed IPs
+
+When the above conditions do not apply, routing and DNS information is handed to Windows in the typical way for Windows to manage. This includes its [ordinary multihomed DNS resolution behavior](https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/dd197552%28v%3Dws.10%29) as well as its ordinary routing table resolution. Users may make use of the normal Windows firewalling and network configuration capabilities to firewall this as needed. One firewall rule is added, however, which allows the tunnel service to send and receive WireGuard packets.
+
+### Network List Manager
+
+Windows assigns a unique GUID to each new WireGuard adapter. The application takes pains to make this GUID deterministic, so that firewall policy (such as "public" vs "private" network categorization) can be consistently applied to the tunnel's network. This determinism is based on the configuration of the tunnel. Therefore, if the WireGuard configuration changes, so too will the unique GUID. Technical details are described in [a mailing list post](https://lists.zx2c4.com/pipermail/wireguard/2019-June/004259.html).
+
+### Adapter Lifetime
+
+WireGuard's network adapter is created dynamically when a tunnel is started and destroyed when a tunnel is stopped. This means that additional filters, address families, or protocols should be bound to the adapter programmatically, possibly through use of dangerous script execution in the configuration file or by way of automatic NDIS layer binding.