Skip to content

OpenVPN Data Channel Offload driver for Windows

License

Notifications You must be signed in to change notification settings

mfil/ovpn-dco-win

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

37 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ovpn-dco-win

Github Actions

Intro

ovpn-dco-win stands for "OpenVPN Data Channel Offload for Windows". It is a modern Windows driver, which functions as virtual network adapter and implements required functionality to handle the OpenVPN data channel. When using ovpn-dco-win, the OpenVPN software doesn't send data traffic back and forth between user and kernel space (for encryption, decryption and routing), but operations on payload take place in Windows kernel. The driver is being developed using modern frameworks - WDF, NetAdapterCx and DMF. Because of that, the code is easier to read and maintain comparison to existing NDIS miniport drivers. Speed-wise the new driver performs significantly better comparison to tap-windows6, so it should eliminate the bottleneck which hampers the performance of OpenVPN on Windows.

Installation

To use the driver, you must install it first. By default Windows doesn't load test-signed driver. To make Windows load the driver, run following command as Administrator:

Bcdedit.exe -set TESTSIGNING ON

and restart. Then install the driver using devcon tool (available as part of WDK):

devcon install ovpn-dco.inf ovpn-dco

ovpn-dco-cli

The project includes ovpn-dco-cli command line tool, which works as development test bed, reference client and API usage example. With that you can setup VPN tunnel between two Windows hosts or between Windows and Linux host using ./ovpn-cli tool from ovpn-dco Linux project.

To set up Windows <-> Windows tunnel, on first host run:

ovpn-dco-cli.exe udp i4 0.0.0.0 1194 192.168.100.200 1194 10.8.0.2 255.255.255.0 10.8.0.1 data64.key 0

where "0.0.0.0 1194" local IP address/port to bind the socket, "192.168.100.200 1194" remote address/port, "10.8.0.2" is a local VPN IP.

On the second Windows host run:

ovpn-dco-cli.exe udp i4 0.0.0.0 1194 192.168.100.100 1194 10.8.0.1 255.255.255.0 10.8.0.1 data64.key 1

Note that remote IP, VPN IP and key direction (last 0/1 digit) are different.

To set up tunnel between Windows and Linux, run on the second (Linux) host:

# ip link add dev ovpn0 type ovpn-dco
# ip link set ovpn0 up
# ip link set mtu 1428 dev ovpn0

# ip addr add dev ovpn0 10.8.0.1/24

# tests/ovpn-cli ovpn0 new_peer 1194 0 192.168.100.100 1194 10.8.0.2
# tests/ovpn-cli ovpn0 new_key 0 aes 1 tests/data64.key

where 192.168.100.150 is a Linux host IP address, 192.168.100.100 is a Windows host IP address.

After you've established tunnel, you should be able to ping hosts (10.8.0.1 <-> 10.8.0.1) and run iperf tests (iperf3 -s 10.8.0.2 on the first host, iperf3 -c 10.8.0.2 on the second) via VPN tunnel.

Please note that using ovpn-dco-cli tool in production is a very bad idea, because it doesn't do any key negotiation and use a static key (data64.key) instead.

API Usage

To use the driver, client needs to get file handle by calling CreateFile. One can either use symbolic link or device interface to get the file path. Here is example from ovpn-dco tool (see below):

HANDLE h = CreateFileA("\\\\.\\ovpn-dco", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, NULL);

After getting handle, client uses DeviceIOControl and Read/WriteFile calls to set up connection and send/receive control packets. See uapi.h for the list of IOCTL commands and ovpn-dco-cli.cpp on how to use those.

  • First, client needs to initialize peer with OVPN_IOCTL_NEW_PEER command. Client passes OVPN_NEW_PEER structure, which contains local/remote IP address/port (either IPv4 or IPv6) and transport protocol (TCP or UDP).

  • After initializing peer, client passed cipher algorithm (supported are "none" and "AES-GCM"), crypto keys and peer-id as part of OVPN_CRYPTO_DATA structure using OVPN_IOCTL_NEW_KEY command. Description of openvpn crypto is beyond the scope of this document.

  • After setting up crypto, client may set keepalive parameters (OVPN_SET_PEER struct) for the session via OVPN_IOCTL_SET_PEER command. Keepalive interval defines how often to send special keepalive packet in the absence of outgoing data traffic. Keepalive timeout defines when to notify userspace (by completing read request with an error) in the absence of incoming data traffic.

  • To start VPN session, client sends OVPN_IOCTL_START_VPN command. This signals driver to start network adapter.

  • After starting VPN session, client sets up network adapter (IP address, netmask, gateway) and routing.

To send and receive control channel packets, client uses Read/WriteFile calls. It is recommended to use overlapped IO by passing FILE_FLAG_OVERLAPPED to CreateFile call and OVERLAPPED structure to Read/WriteFile calls. ovpn-dco-cli uses ASIO, which abstracts those low-level details.

OpenVPN support

Thanks to Arne Schwabe, there is now a beta version of the openvpn-gui client with dco-win support. Installer could be found here: https://swupdate.openvpn.net/beta-downloads/win-dco/openvpn-install-dco-preview-Win10.exe It was built from "dco" branch in Arne's github repo https://github.com/schwabe/openvpn/tree/dco. See https://github.com/schwabe/openvpn/blob/dco/README.dco.md for more info about current and general limitations.

To use ovpn-dco-win with openvpn2, add the following lines to the .ovpn profile:

  windows-driver ovpn-dco-win
  tun-mtu 1428

OpenVPN3 support is in progress and coming soon.

Logging

Logging is performed via TraceLogging API, which is based on ETW. To see logs on a target machine:

  1. Run traceview.exe as administrator
  2. File -> Create New Log Session
  3. Manually Entered Control GUID -> 4970F9cf-2c0c-4f11-b1cc-e3a1e9958833 -> OK
  4. Choose Source Of Decoding Information -> Auto -> OK
  5. Press "Next" -> "Finish"

To collect logs for analysis:

  1. Run administrator command prompt
  2. Run wpr -start ovpn-dco-win.wprp (wprp file is in driver source tree)
  3. Interact with the driver
  4. To stop log collection, run wpr -stop ovpn-dco-win.etl

The etl file could be opened, for example, by Windows Performance Analyzer (wpa.exe).

To see logs in attached debbuger (windbg), use tracelog.exe in administrator command prompt:

  • tracelog -start MyTrace -guid #4970F9cf-2c0c-4f11-b1cc-e3a1e9958833 -rt -kd

Limitations

  • Minimum supported Windows version is Windows 10 20H1. This will unlikely to change.
  • The driver is under development and the code is not production quality yet.
  • Supported cipher are "none" (for testing only) and AES-128(-192-256)-GCM.
  • Driver is test-signed (properly signed binaries will be provided later).

Questions

Contact Lev Stipakov [email protected] (lev__ on #openvpn-devel)

About

OpenVPN Data Channel Offload driver for Windows

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C++ 68.1%
  • C 23.2%
  • NSIS 8.7%