[Openvpn-devel] Add Interactive Service developer documentation

Message ID 20180412184845.1175-1-simon@rozman.si
State Superseded
Headers show
Series [Openvpn-devel] Add Interactive Service developer documentation | expand

Commit Message

Simon Rozman April 12, 2018, 8:48 a.m. UTC
The OpenVPN Interactive Service documentation from
https://community.openvpn.net/openvpn/wiki/OpenVPNInteractiveService was
upgraded with a description of the client-service communication flow,
service registry configuration, and non-default instance installation.
---
 doc/interactive-service-notes.txt | 316 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 316 insertions(+)
 create mode 100644 doc/interactive-service-notes.txt

--
2.15.1 (Apple Git-101)

Hi,

I'm back. :)

I took the short Interactive Service introduction found at
https://community.openvpn.net/openvpn/wiki/OpenVPNInteractiveService and
extended it with my experience while developing the eduVPN client.

This document is not up to the RFC standards nor it intends to be.

It's written using reStructuredText markup as suggested by Iliya, but keeping
the filename and ".txt" extension as suggested by Samuli.

I suggest replacing the
https://community.openvpn.net/openvpn/wiki/OpenVPNInteractiveService wiki page
with this document analogous to the Management Interface Notes document
published online at
https://openvpn.net/index.php/open-source/documentation/miscellaneous/79-management-interface.html.

Your comments are welcome.

Best regards,
Simon

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

Comments

Selva Nair April 12, 2018, 7:05 p.m. UTC | #1
Hi,

On Thu, Apr 12, 2018 at 2:48 PM, Simon Rozman <simon@rozman.si> wrote:

Moving up the most important part:

Hi,
> I'm back. :)
>

Welcome back!


> I took the short Interactive Service introduction found at
> https://community.openvpn.net/openvpn/wiki/OpenVPNInteractiveService and
> extended it with my experience while developing the eduVPN client.
> This document is not up to the RFC standards nor it intends to be.
> It's written using reStructuredText markup as suggested by Iliya, but
> keeping
> the filename and ".txt" extension as suggested by Samuli.
> I suggest replacing the
> https://community.openvpn.net/openvpn/wiki/OpenVPNInteractiveService wiki
> page


+1 to that and to keep it up to date.


> with this document analogous to the Management Interface Notes document
> published online at
> https://openvpn.net/index.php/open-source/documentation/misc
> ellaneous/79-management-interface.html.


This one too occasionally needs to be kept in sync with the source

Your comments are welcome.


Thanks for writing this up. Some minor comments below:

The OpenVPN Interactive Service documentation from
> https://community.openvpn.net/openvpn/wiki/OpenVPNInteractiveService was
> upgraded with a description of the client-service communication flow,
> service registry configuration, and non-default instance installation.
> ---
>  doc/interactive-service-notes.txt | 316 ++++++++++++++++++++++++++++++
> ++++++++
>  1 file changed, 316 insertions(+)
>  create mode 100644 doc/interactive-service-notes.txt
>
> diff --git a/doc/interactive-service-notes.txt
> b/doc/interactive-service-notes.txt
> new file mode 100644
> index 00000000..9b3b8f6c
> --- /dev/null
> +++ b/doc/interactive-service-notes.txt
> @@ -0,0 +1,316 @@
> +=================================
> +OpenVPN Interactive Service Notes
> +=================================
> +
> +
> +Introduction
> +============
> +
> +OpenVPN Interactive Service, also known as "iservice" or
> +"OpenVPNServiceInteractive", is a Windows system service which allows
> +unprivileged users to do certain privileged operations required by
> OpenVPN, such
> +as adding routes. This removes the need to always run OpenVPN as
> administrator,
> +which was the case for a long time, and continues to be the case for
> OpenVPN
> +2.3.x.
> +
> +The 2.4.x release and git "master" versions of OpenVPN contain the
> Interactive
> +Service code and OpenVPN-GUI is setup to use it by default. Starting from
> +version 2.4.0, OpenVPN-GUI is expected to be started as user (do not
> right-click
> +and "run as administrator" or do not set the shortcut to run as
> administrator).
> +This ensures that OpenVPN and the GUI run with limited privileges.
> +
> +
> +How It Works
> +============
> +
> +Here is a brief explanation of how the Interactive Service works, based on
> +`Gert's email`_ to openvpn-devel mailing list. The example user, *joe*,
> is not
> +an administrator, and does not have any other extra privileges.
> +
> +- OpenVPN-GUI runs as a *joe*
> +- Interactive Service runs as a local Windows service with maximum
> privileges
> +- OpenVPN-GUI connects to the Interactive Service and asks it "run
> openvpn.exe
> +  with the following arguments, using the *joe*'s credentials" - Windows
> can do
> +  this - pass credentials across a pipe, which you can't fake
> +- Interactive Service forks openvpn.exe, and runs this as the user *joe*,
> and
> +  keeps a "service pipe" between Interactive Service and openvpn.exe
> +- If openvpn.exe wants to do ipconfig/route/dns stuff, it sends these as
> +  requests over the service pipe to the Interactive Service, which will
> then
> +  execute them (and clean up should openvpn.exe crash)
> +- ``--up`` scripts are run by openvpn.exe itself, which is already
> running as
> +  *joe*, all privileges are nicely in place
> +- Scripts run by the GUI will run as user *joe*, so that automated tasks
> like
> +  mapping of drives work as expected

+
> +This also avoids the use of scripts for privilege escalation to admin (as
> was
> +possible by running an ``--up`` script from openvpn.exe which is run as
> admin).

+
>

Considering the more formal style used below, the above paragraph could be
rewritten too. IMO, its not necessary to preserve the "original"
description of
"How it works". Just saying..


> +
> +Client-Service Communication
> +============================
> +
> +Connecting
> +----------
> +
> +The client (OpenVPN GUI) and the Interactive Service communicate using a
> named
> +message pipe. By default, the service provides the
> ``\\.\pipe\openvpn\service``
> +named pipe.
> +
> +The client connects to the pipe for read/write and sets the pipe state to
> the
>

state to the --> state to


> +``PIPE_READMODE_MESSAGE``::
> +
> +   HANDLE pipe = CreateFile(_T("\\\\.\\pipe\\openvpn\\service"),
> +       GENERIC_READ | GENERIC_WRITE,
> +       0,
> +       NULL,
> +       OPEN_EXISTING,
> +       FILE_FLAG_OVERLAPPED,
> +       NULL);
> +
> +   if (pipe == INVALID_HANDLE_VALUE)
> +   {
> +       // Error
> +   }
> +
> +   DWORD dwMode = PIPE_READMODE_MESSAGE;
> +   if (!SetNamedPipeHandleState(pipe, &dwMode, NULL, NULL)
> +   {
> +       // Error
> +   }
> +
> +
> +openvpn.exe Startup
> +-------------------
> +
> +After the client is connected to the service, the client must send a
> startup
> +message to have the service start the openvpn.exe process. The startup
> message
> +is comprised of three UTF-16 strings delimited by U0000 zero characters::
> +
> +   startupmsg     = workingdir WZERO openvpnoptions WZERO stdin WZERO
> +
> +   workingdir     = WSTRING
> +   openvpnoptions = WSTRING
> +   stdin          = WSTRING
> +
> +   WSTRING        = *WCHAR
> +   WCHAR          = %x0001-FFFF
> +   WZERO          = %x0000
> +
> +``workingdir``
> +   Represents the folder openvpn.exe process should be started in.
> +
> +``openvpnoptions``
> +   String contains ``--config`` and other OpenVPN command line options,
> without
> +   the ``argv[0]`` executable name ("openvpn" or "openvpn.exe"). When
> there is
> +   only one option specified, the ``--config`` option is assumed and the
> option
> +   is the configuration filename.
> +
> +   Please, note that the interactive service validates the options (e.g.
> OpenVPN
>

Please, note --> Please note  or just "Note" considering the overall style

+   config file must reside in one of the approved folders, or the invoking
> user


Actually only one approved folder (and its subfolders) is supported. That
is, the
one defined by the global_config_dir. For all other folders the user must
be
authorized.

Even when the config file is in the approved folder, additional options
added to
the command line are restricted to a limited set unless the user is
authorized.


> +   must be a member of local Administrators group, or a member of the

+   "OpenVPN Administrators" group).
>

More precisely, that would be the group pointed to by the registry key
HKLM\Software\OpenVPN\ovpn_admin_group which defaults to
"OpenVPN Administrators".


> +
> +``stdin``
> +   The content of the ``stdin`` string is sent to the openvpn.exe process
> to its
> +   stdin stream after it starts.
> +
> +   When a ``--management ... stdin`` option is present, the openvpn.exe
> process
> +   will prompt for the management interface password on start. In this
> case, the
> +   ``stdin`` must contain the password appended with an LF (U000A) to
> simulate
> +   the [Enter] key after the password is "typed" in.
> +
> +   The openvpn.exe's stdout is redirected to ``NUL``. Should the client
> require
> +   openvpn.exe's stdout, one should specify ``--log`` option.
> +
> +The message must be written in a single ``WriteFile()`` call.

+Example::
> +
> +   // Prepare the message.
> +   size_t msg_len =
> +       wcslen(workingdir) + 1 +
> +       wcslen(options   ) + 1 +
> +       wcslen(manage_pwd) + 1;
> +   wchar_t *msg_data = (wchar_t*)malloc(msg_len*sizeof(wchar_t));
> +   _snwprintf(msg_data, msg_len, L"%s%c%s%c%s",
> +       workingdir, L'\0',
> +       options, L'\0',
> +       manage_pwd)
> +
> +   // Send the message.
> +   DWORD dwBytesWritten;
> +   if (!WriteFile(pipe,
> +       msg_data,
> +       msg_len*sizeof(wchar_t),
> +       &dwBytesWritten,
> +       NULL))
> +   {
> +       // Error
> +   }
> +
> +   // Sanitize memory, since the stdin component of the message
> +   // contains the management interface password.
> +   SecureZeroMemory(msg_data, msg_len*sizeof(wchar_t));
> +   free(msg_data);
> +
> +
> +openvpn.exe Process ID
> +----------------------
> +
> +After receiving the startup message, the Interactive Service validates
> the user
> +and specified options before launching the openvpn.exe process.
> +
> +The Interactive Service replies with a process ID message. The process ID
> +message is comprised of three UTF-16 strings delimited by LFs (U000A)::
> +
> +   pidmsg  = L"0x00000000" WLF L"0x" pid WLF L"Process ID"
> +
> +   pid     = 8*8WHEXDIG
> +
> +   WHEXDIG = WDIGIT / L"A" / L"B" / L"C" / L"D" / L"E" / L"F"
> +   WDIGIT  = %x0030-0039
> +   WLF     = %x000a
> +
> +``pid``
> +   An UTF-16 eight-character hexadecimal process ID of the openvpn.exe
> process
>

A UTF-16


> +   the Interactive Service launched on client's behalf.
> +
> +
> +openvpn.exe Termination
> +-----------------------
> +
> +The pipe between the client and the service is kept open until the
> openvpn.exe
> +process terminates.
> +
> +Should the openvpn.exe process terminate with an error, the Interactive
> Service
> +sends an error message to the client before disconnecting the pipe.
>

May be also mention that the service never terminates openvpn.exe process
-- not even
when it is stopped or restarted. So its up to the client to monitor the
process
and terminate it.


> +
> +
> +Error Messages
> +--------------
> +
> +In case of an error, the Interactive Service sends an error message to the
> +client. Error messages are comprised of three UTF-16 strings delimited by
> LFs
> +(U000A)::
> +
> +   errmsg = L"0x" errnum WLF func WLF msg
> +
> +   errnum = 8*8WHEXDIG
> +   func   = WSTRING
> +   msg    = WSTRING
> +
> +``errnum``
> +
> +   An UTF-16 eight-character hexadecimal error code. Typically, it is one
> of the
>

An --> A


> +   Win32 error codes returned by ``GetLastError()``.
> +
> +   However, it can be one of the Interactive Service specific error codes:
> +
> +   ===================== ==========
> +   Error                 Code
> +   ===================== ==========
> +   ERROR_OPENVPN_STARTUP 0x20000000
> +   ERROR_STARTUP_DATA    0x20000001
> +   ERROR_MESSAGE_DATA    0x20000002
> +   ERROR_MESSAGE_TYPE    0x20000003
> +   ===================== ==========
> +
> +``func``
> +   The name of the function call that failed or an error description.
> +
> +``msg``
> +  The error description returned by a
> +  ``FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, 0, errnum, ...)`` call.
> +
> +
> +Interactive Service Configuration
> +=================================
> +
> +The Interactive Service settings are read from the
> +``HKEY_LOCAL_MACHINE\SOFTWARE\OpenVPN`` registry key by default.
> +
> +All the following registry values are of the ``REG_SZ`` type:
> +
> +*Default*
> +   Installation folder (required)
>

install_dir used below is undefined. Define it here?


> +
> +``exe_path``
> +   The absolute path to the openvpn.exe binary; defaults to
> +   ``install_dir "\bin\openvpn.exe"``.
> +
> +``config_dir``
> +   The path to the configuration folder; defaults to ``install_dir
> "\config"``.
> +
> +``priority``
> +   openvpn.exe process priority; one of the following strings:
> +
> +   - ``"IDLE_PRIORITY_CLASS"``
> +   - ``"BELOW_NORMAL_PRIORITY_CLASS"``
> +   - ``"NORMAL_PRIORITY_CLASS"`` (default)
> +   - ``"ABOVE_NORMAL_PRIORITY_CLASS"``
> +   - ``"HIGH_PRIORITY_CLASS"``
> +
> +``ovpn_admin_group``
> +   The name of the local group, whose members are authorized to use the
> +   Interactive Service unrestricted; defaults to ``"OpenVPN
> Administrators"``
> +
> +
> +Multiple Interactive Service Instances
> +======================================
> +
> +OpenVPN 2.4.5 extended the Interactive Service to support multiple
> side-by-side
> +running instances. This allows clients to use different Interactive
> Service
> +versions with different settings and/or openvpn.exe binary version on the
> same
> +computer.
> +
> +OpenVPN installs the default Interactive Service instance only. The
> default
> +instance is used by OpenVPN GUI client and also provides backward
> compatibility.
> +
> +
> +Installing a Non-default Interactive Service Instance
> +-----------------------------------------------------
> +
> +1. Choose a unique instance name. For example: "$v2.5-test". The instance
> name
> +   is appended to the default registry path and service name. We choose
> to start
> +   it with a dollar "$" sign analogous to Microsoft SQL Server instance
> naming
> +   scheme. However, this is not imperative.

+
> +   Appending the name to the registry path and service name also implies
> the
> +   name cannot contain characters not allowed in Windows paths: "<", ">",
> double
> +   quote etc.
> +
> +2. Create an ``HKEY_LOCAL_MACHINE\SOFTWARE\OpenVPN$v2.5-test`` registry
> key and
> +   configure the Interactive Service instance configuration appropriately.
> +
> +   This allows using slightly or completely different settings from the
> default
> +   instance.
> +
> +   See the `Interactive Service Configuration`_ chapter for the list of
> registry
>

chapter --> section ? And is that "_" a part of markup or a stale character?


> +   values.
> +
> +3. Create and start the instance's Windows service from an elevated
> command
> +   prompt::
> +
> +      sc create "OpenVPNServiceInteractive$v2.5-test" \
> +         start= auto \
> +         binPath= "<path to openvpnserv.exe> -instance interactive
> $v2.5-test" \
> +         depend= tap0901/Dhcp \
> +         DisplayName= "OpenVPN Interactive Service (v2.5-test)"
> +
> +      sc start "OpenVPNServiceInteractive$v2.5-test"
> +
> +   This allows using the same or a different version of openvpnserv.exe
> than the
> +   default instance.
> +
> +   Please, mind the spacing around "=" character in ``sc`` command line
> options.
>

Please, mind the spacing around "=" --> Notice the space after "="

+
> +4. Set your OpenVPN client to connect to the
> +   ``\\.\pipe\openvpn$v2.5-test\service``.
> +
> +   This allows the client to select different installed Interactive
> Service
>

different --> a different


> +   instance at run-time, thus allowing different OpenVPN settings and
> versions.
> +
> +   At the time writing, the OpenVPN GUI client supports connecting to the
> +   default Interactive Service instance only.
> +
> +.. _`Gert's email`: https://www.mail-archive.com/o
> penvpn-devel@lists.sourceforge.net/msg00097.html
> --
> 2.15.1 (Apple Git-101)
>
>
Do you also plan to document the service <--> openvpn.exe communication?
Or is that beyond the scope of this file? Anyway, could be a separate patch
:)

Thanks,

Selva
<div dir="ltr">Hi,<div><br><div class="gmail_extra"><div class="gmail_quote">On Thu, Apr 12, 2018 at 2:48 PM, Simon Rozman <span dir="ltr">&lt;<a href="mailto:simon@rozman.si" target="_blank">simon@rozman.si</a>&gt;</span> wrote:</div><div class="gmail_quote"><br></div><div class="gmail_quote">Moving up the most important part:</div><div class="gmail_quote"><div class="gmail_quote"><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi,<br>I&#39;m back. :)<br></blockquote><div><br></div><div>Welcome back!</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">I took the short Interactive Service introduction found at<br><a href="https://community.openvpn.net/openvpn/wiki/OpenVPNInteractiveService" target="_blank">https://community.openvpn.net/<wbr>openvpn/wiki/OpenVPNInteractiv<wbr>eService</a> and<br>extended it with my experience while developing the eduVPN client.<br>This document is not up to the RFC standards nor it intends to be.<br>It&#39;s written using reStructuredText markup as suggested by Iliya, but keeping<br>the filename and &quot;.txt&quot; extension as suggested by Samuli.<br>I suggest replacing the<br><a href="https://community.openvpn.net/openvpn/wiki/OpenVPNInteractiveService" target="_blank">https://community.openvpn.net/<wbr>openvpn/wiki/OpenVPNInteractiv<wbr>eService</a> wiki page</blockquote><div class="gmail_quote"><br></div><div class="gmail_quote">+1 to that and to keep it up to date.</div><div class="gmail_quote"> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">with this document analogous to the Management Interface Notes document<br>published online at<br><a href="https://openvpn.net/index.php/open-source/documentation/miscellaneous/79-management-interface.html" target="_blank">https://openvpn.net/index.php/<wbr>open-source/documentation/misc<wbr>ellaneous/79-management-interf<wbr>ace.html</a>.</blockquote><div class="gmail_quote"><br></div><div class="gmail_quote">This one too occasionally needs to be kept in sync with the source</div><div class="gmail_quote"><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Your comments are welcome.</blockquote><div class="gmail_quote"><br></div><div class="gmail_quote">Thanks for writing this up. Some minor comments below:</div></div><div class="gmail_quote"><br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">The OpenVPN Interactive Service documentation from<br>
<a href="https://community.openvpn.net/openvpn/wiki/OpenVPNInteractiveService" rel="noreferrer" target="_blank">https://community.openvpn.net/<wbr>openvpn/wiki/OpenVPNInteractiv<wbr>eService</a> was<br>
upgraded with a description of the client-service communication flow,<br>
service registry configuration, and non-default instance installation.<br>
---<br>
 doc/interactive-service-notes<wbr>.txt | 316 ++++++++++++++++++++++++++++++<wbr>++++++++<br>
 1 file changed, 316 insertions(+)<br>
 create mode 100644 doc/interactive-service-notes.<wbr>txt<br>
<br>
diff --git a/doc/interactive-service-note<wbr>s.txt b/doc/interactive-service-note<wbr>s.txt<br>
new file mode 100644<br>
index 00000000..9b3b8f6c<br>
--- /dev/null<br>
+++ b/doc/interactive-service-note<wbr>s.txt<br>
@@ -0,0 +1,316 @@<br>
+=============================<wbr>====<br>
+OpenVPN Interactive Service Notes<br>
+=============================<wbr>====<br>
+<br>
+<br>
+Introduction<br>
+============<br>
+<br>
+OpenVPN Interactive Service, also known as &quot;iservice&quot; or<br>
+&quot;OpenVPNServiceInteractive&quot;, is a Windows system service which allows<br>
+unprivileged users to do certain privileged operations required by OpenVPN, such<br>
+as adding routes. This removes the need to always run OpenVPN as administrator,<br>
+which was the case for a long time, and continues to be the case for OpenVPN<br>
+2.3.x.<br>
+<br>
+The 2.4.x release and git &quot;master&quot; versions of OpenVPN contain the Interactive<br>
+Service code and OpenVPN-GUI is setup to use it by default. Starting from<br>
+version 2.4.0, OpenVPN-GUI is expected to be started as user (do not right-click<br>
+and &quot;run as administrator&quot; or do not set the shortcut to run as administrator).<br>
+This ensures that OpenVPN and the GUI run with limited privileges.<br>
+<br>
+<br>
+How It Works<br>
+============<br>
+<br>
+Here is a brief explanation of how the Interactive Service works, based on<br>
+`Gert&#39;s email`_ to openvpn-devel mailing list. The example user, *joe*, is not<br>
+an administrator, and does not have any other extra privileges.<br>
+<br>
+- OpenVPN-GUI runs as a *joe*<br>
+- Interactive Service runs as a local Windows service with maximum privileges<br>
+- OpenVPN-GUI connects to the Interactive Service and asks it &quot;run openvpn.exe<br>
+  with the following arguments, using the *joe*&#39;s credentials&quot; - Windows can do<br>
+  this - pass credentials across a pipe, which you can&#39;t fake<br>
+- Interactive Service forks openvpn.exe, and runs this as the user *joe*, and<br>
+  keeps a &quot;service pipe&quot; between Interactive Service and openvpn.exe<br>
+- If openvpn.exe wants to do ipconfig/route/dns stuff, it sends these as<br>
+  requests over the service pipe to the Interactive Service, which will then<br>
+  execute them (and clean up should openvpn.exe crash)<br>
+- ``--up`` scripts are run by openvpn.exe itself, which is already running as<br>
+  *joe*, all privileges are nicely in place<br>
+- Scripts run by the GUI will run as user *joe*, so that automated tasks like<br>
+  mapping of drives work as expected</blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+<br>
+This also avoids the use of scripts for privilege escalation to admin (as was<br>
+possible by running an ``--up`` script from openvpn.exe which is run as admin).</blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">+<br></blockquote><div><br></div><div>Considering the more formal style used below, the above paragraph could be</div><div>rewritten too. IMO, its not necessary to preserve the &quot;original&quot; description of</div><div>&quot;How it works&quot;. Just saying..</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+<br>
+Client-Service Communication<br>
+============================<br>
+<br>
+Connecting<br>
+----------<br>
+<br>
+The client (OpenVPN GUI) and the Interactive Service communicate using a named<br>
+message pipe. By default, the service provides the ``\\.\pipe\openvpn\service``<br>
+named pipe.<br>
+<br>
+The client connects to the pipe for read/write and sets the pipe state to the<br></blockquote><div><br></div><div>state to the --&gt; state to</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+``PIPE_READMODE_MESSAGE``::<br>
+<br>
+   HANDLE pipe = CreateFile(_T(&quot;\\\\.\\pipe\\op<wbr>envpn\\service&quot;),<br>
+       GENERIC_READ | GENERIC_WRITE,<br>
+       0,<br>
+       NULL,<br>
+       OPEN_EXISTING,<br>
+       FILE_FLAG_OVERLAPPED,<br>
+       NULL);<br>
+<br>
+   if (pipe == INVALID_HANDLE_VALUE)<br>
+   {<br>
+       // Error<br>
+   }<br>
+<br>
+   DWORD dwMode = PIPE_READMODE_MESSAGE;<br>
+   if (!SetNamedPipeHandleState(pipe<wbr>, &amp;dwMode, NULL, NULL)<br>
+   {<br>
+       // Error<br>
+   }<br>
+<br>
+<br>
+openvpn.exe Startup<br>
+-------------------<br>
+<br>
+After the client is connected to the service, the client must send a startup<br>
+message to have the service start the openvpn.exe process. The startup message<br>
+is comprised of three UTF-16 strings delimited by U0000 zero characters::<br>
+<br>
+   startupmsg     = workingdir WZERO openvpnoptions WZERO stdin WZERO<br>
+<br>
+   workingdir     = WSTRING<br>
+   openvpnoptions = WSTRING<br>
+   stdin          = WSTRING<br>
+<br>
+   WSTRING        = *WCHAR<br>
+   WCHAR          = %x0001-FFFF<br>
+   WZERO          = %x0000<br>
+<br>
+``workingdir``<br>
+   Represents the folder openvpn.exe process should be started in.<br>
+<br>
+``openvpnoptions``<br>
+   String contains ``--config`` and other OpenVPN command line options, without<br>
+   the ``argv[0]`` executable name (&quot;openvpn&quot; or &quot;openvpn.exe&quot;). When there is<br>
+   only one option specified, the ``--config`` option is assumed and the option<br>
+   is the configuration filename.<br>
+<br>
+   Please, note that the interactive service validates the options (e.g. OpenVPN<br></blockquote><div><br></div><div>Please, note --&gt; Please note  or just &quot;Note&quot; considering the overall style</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+   config file must reside in one of the approved folders, or the invoking user</blockquote><div><br></div><div>Actually only one approved folder (and its subfolders) is supported. That is, the</div><div>one defined by the global_config_dir. For all other folders the user must be </div><div>authorized.</div><div><br></div><div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255)">Even when the config file is in the approved folder, additional options added to</div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255)">the command line are restricted to a limited set unless the user is authorized.</div></div><div>  </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+   must be a member of local Administrators group, or a member of the </blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">+   &quot;OpenVPN Administrators&quot; group).<br></blockquote><div><br></div><div><div>More precisely, that would be the group pointed to by the registry key </div><div>HKLM\Software\OpenVPN\ovpn_adm<wbr>in_group which defaults to</div><div>&quot;OpenVPN Administrators&quot;.</div></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+<br>
+``stdin``<br>
+   The content of the ``stdin`` string is sent to the openvpn.exe process to its<br>
+   stdin stream after it starts.<br>
+<br>
+   When a ``--management ... stdin`` option is present, the openvpn.exe process<br>
+   will prompt for the management interface password on start. In this case, the<br>
+   ``stdin`` must contain the password appended with an LF (U000A) to simulate<br>
+   the [Enter] key after the password is &quot;typed&quot; in.<br>
+<br>
+   The openvpn.exe&#39;s stdout is redirected to ``NUL``. Should the client require<br>
+   openvpn.exe&#39;s stdout, one should specify ``--log`` option.<br>
+<br>
+The message must be written in a single ``WriteFile()`` call.</blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+Example::<br>
+<br>
+   // Prepare the message.<br>
+   size_t msg_len =<br>
+       wcslen(workingdir) + 1 +<br>
+       wcslen(options   ) + 1 +<br>
+       wcslen(manage_pwd) + 1;<br>
+   wchar_t *msg_data = (wchar_t*)malloc(msg_len*sizeo<wbr>f(wchar_t));<br>
+   _snwprintf(msg_data, msg_len, L&quot;%s%c%s%c%s&quot;,<br>
+       workingdir, L&#39;\0&#39;,<br>
+       options, L&#39;\0&#39;,<br>
+       manage_pwd)<br>
+<br>
+   // Send the message.<br>
+   DWORD dwBytesWritten;<br>
+   if (!WriteFile(pipe,<br>
+       msg_data,<br>
+       msg_len*sizeof(wchar_t),<br>
+       &amp;dwBytesWritten,<br>
+       NULL))<br>
+   {<br>
+       // Error<br>
+   }<br>
+<br>
+   // Sanitize memory, since the stdin component of the message<br>
+   // contains the management interface password.<br>
+   SecureZeroMemory(msg_data, msg_len*sizeof(wchar_t));<br>
+   free(msg_data);<br>
+<br>
+<br>
+openvpn.exe Process ID<br>
+----------------------<br>
+<br>
+After receiving the startup message, the Interactive Service validates the user<br>
+and specified options before launching the openvpn.exe process.<br>
+<br>
+The Interactive Service replies with a process ID message. The process ID<br>
+message is comprised of three UTF-16 strings delimited by LFs (U000A)::<br>
+<br>
+   pidmsg  = L&quot;0x00000000&quot; WLF L&quot;0x&quot; pid WLF L&quot;Process ID&quot;<br>
+<br>
+   pid     = 8*8WHEXDIG<br>
+<br>
+   WHEXDIG = WDIGIT / L&quot;A&quot; / L&quot;B&quot; / L&quot;C&quot; / L&quot;D&quot; / L&quot;E&quot; / L&quot;F&quot;<br>
+   WDIGIT  = %x0030-0039<br>
+   WLF     = %x000a<br>
+<br>
+``pid``<br>
+   An UTF-16 eight-character hexadecimal process ID of the openvpn.exe process<br>
</blockquote><div><br></div><div>A UTF-16</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">+   the Interactive Service launched on client&#39;s behalf.<br>
+<br>
+<br>
+openvpn.exe Termination<br>
+-----------------------<br>
+<br>
+The pipe between the client and the service is kept open until the openvpn.exe<br>
+process terminates.<br>
+<br>
+Should the openvpn.exe process terminate with an error, the Interactive Service<br>
+sends an error message to the client before disconnecting the pipe.<br>
</blockquote><div><br></div><div>May be also mention that the service never terminates openvpn.exe process -- not even</div><div>when it is stopped or restarted. So its up to the client to monitor the process</div><div>and terminate it.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">+<br>
+<br>
+Error Messages<br>
+--------------<br>
+<br>
+In case of an error, the Interactive Service sends an error message to the<br>
+client. Error messages are comprised of three UTF-16 strings delimited by LFs<br>
+(U000A)::<br>
+<br>
+   errmsg = L&quot;0x&quot; errnum WLF func WLF msg<br>
+<br>
+   errnum = 8*8WHEXDIG<br>
+   func   = WSTRING<br>
+   msg    = WSTRING<br>
+<br>
+``errnum``<br>
+<br>
+   An UTF-16 eight-character hexadecimal error code. Typically, it is one of the<br></blockquote><div><br></div><div>An --&gt; A </div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+   Win32 error codes returned by ``GetLastError()``.<br>
+<br>
+   However, it can be one of the Interactive Service specific error codes:<br>
+<br>
+   ===================== ==========<br>
+   Error                 Code<br>
+   ===================== ==========<br>
+   ERROR_OPENVPN_STARTUP 0x20000000<br>
+   ERROR_STARTUP_DATA    0x20000001<br>
+   ERROR_MESSAGE_DATA    0x20000002<br>
+   ERROR_MESSAGE_TYPE    0x20000003<br>
+   ===================== ==========<br>
+<br>
+``func``<br>
+   The name of the function call that failed or an error description.<br>
+<br>
+``msg``<br>
+  The error description returned by a<br>
+  ``FormatMessageW(FORMAT_MESSAG<wbr>E_FROM_SYSTEM, 0, errnum, ...)`` call.<br>
+<br>
+<br>
+Interactive Service Configuration<br>
+=============================<wbr>====<br>
+<br>
+The Interactive Service settings are read from the<br>
+``HKEY_LOCAL_MACHINE\SOFTWARE<wbr>\OpenVPN`` registry key by default.<br>
+<br>
+All the following registry values are of the ``REG_SZ`` type:<br>
+<br>
+*Default*<br>
+   Installation folder (required)<br></blockquote><div><br></div><div>install_dir used below is undefined. Define it here?</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+<br>
+``exe_path``<br>
+   The absolute path to the openvpn.exe binary; defaults to<br>
+   ``install_dir &quot;\bin\openvpn.exe&quot;``.<br>
+<br>
+``config_dir``<br>
+   The path to the configuration folder; defaults to ``install_dir &quot;\config&quot;``.<br>
+<br>
+``priority``<br>
+   openvpn.exe process priority; one of the following strings:<br>
+<br>
+   - ``&quot;IDLE_PRIORITY_CLASS&quot;``<br>
+   - ``&quot;BELOW_NORMAL_PRIORITY_CLASS<wbr>&quot;``<br>
+   - ``&quot;NORMAL_PRIORITY_CLASS&quot;`` (default)<br>
+   - ``&quot;ABOVE_NORMAL_PRIORITY_CLASS<wbr>&quot;``<br>
+   - ``&quot;HIGH_PRIORITY_CLASS&quot;``<br>
+<br>
+``ovpn_admin_group``<br>
+   The name of the local group, whose members are authorized to use the<br>
+   Interactive Service unrestricted; defaults to ``&quot;OpenVPN Administrators&quot;``<br>
+<br>
+<br>
+Multiple Interactive Service Instances<br>
+=============================<wbr>=========<br>
+<br>
+OpenVPN 2.4.5 extended the Interactive Service to support multiple side-by-side<br>
+running instances. This allows clients to use different Interactive Service<br>
+versions with different settings and/or openvpn.exe binary version on the same<br>
+computer.<br>
+<br>
+OpenVPN installs the default Interactive Service instance only. The default<br>
+instance is used by OpenVPN GUI client and also provides backward compatibility.<br>
+<br>
+<br>
+Installing a Non-default Interactive Service Instance<br>
+-----------------------------<wbr>------------------------<br>
+<br>
+1. Choose a unique instance name. For example: &quot;$v2.5-test&quot;. The instance name<br>
+   is appended to the default registry path and service name. We choose to start<br>
+   it with a dollar &quot;$&quot; sign analogous to Microsoft SQL Server instance naming<br>
+   scheme. However, this is not imperative. </blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+<br>
+   Appending the name to the registry path and service name also implies the<br>
+   name cannot contain characters not allowed in Windows paths: &quot;&lt;&quot;, &quot;&gt;&quot;, double<br>
+   quote etc.<br>
+<br>
+2. Create an ``HKEY_LOCAL_MACHINE\SOFTWARE\<wbr>OpenVPN$v2.5-test`` registry key and<br>
+   configure the Interactive Service instance configuration appropriately.<br>
+<br>
+   This allows using slightly or completely different settings from the default<br>
+   instance.<br>
+<br>
+   See the `Interactive Service Configuration`_ chapter for the list of registry<br></blockquote><div><br></div><div>chapter --&gt; section ? And is that &quot;_&quot; a part of markup or a stale character?</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+   values.<br>
+<br>
+3. Create and start the instance&#39;s Windows service from an elevated command<br>
+   prompt::<br>
+<br>
+      sc create &quot;OpenVPNServiceInteractive$v2.<wbr>5-test&quot; \<br>
+         start= auto \<br>
+         binPath= &quot;&lt;path to openvpnserv.exe&gt; -instance interactive $v2.5-test&quot; \<br>
+         depend= tap0901/Dhcp \<br>
+         DisplayName= &quot;OpenVPN Interactive Service (v2.5-test)&quot;<br>
+<br>
+      sc start &quot;OpenVPNServiceInteractive$v2.<wbr>5-test&quot;<br>
+<br>
+   This allows using the same or a different version of openvpnserv.exe than the<br>
+   default instance.<br>
+<br>
+   Please, mind the spacing around &quot;=&quot; character in ``sc`` command line options.<br></blockquote><div><br></div><div>Please, mind the spacing around &quot;=&quot; --&gt; Notice the space after &quot;=&quot; </div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+<br>
+4. Set your OpenVPN client to connect to the<br>
+   ``\\.\pipe\openvpn$v2.5-test\<wbr>service``.<br>
+<br>
+   This allows the client to select different installed Interactive Service<br></blockquote><div><br></div><div>different --&gt; a different</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+   instance at run-time, thus allowing different OpenVPN settings and versions.<br>
+<br>
+   At the time writing, the OpenVPN GUI client supports connecting to the<br>
+   default Interactive Service instance only.<br>
+<br>
+.. _`Gert&#39;s email`: <a href="https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg00097.html" rel="noreferrer" target="_blank">https://www.mail-archive.com/o<wbr>penvpn-devel@lists.sourceforge<wbr>.net/msg00097.html</a><br>
--<br>
2.15.1 (Apple Git-101)<br><br></blockquote><div><br></div><div>Do you also plan to document the service &lt;--&gt; openvpn.exe communication?</div><div>Or is that beyond the scope of this file? Anyway, could be a separate patch :)</div><div><br></div><div>Thanks,</div><div><br></div><div>Selva </div></div></div></div></div>
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

Patch

diff --git a/doc/interactive-service-notes.txt b/doc/interactive-service-notes.txt
new file mode 100644
index 00000000..9b3b8f6c
--- /dev/null
+++ b/doc/interactive-service-notes.txt
@@ -0,0 +1,316 @@ 
+=================================
+OpenVPN Interactive Service Notes
+=================================
+
+
+Introduction
+============
+
+OpenVPN Interactive Service, also known as "iservice" or
+"OpenVPNServiceInteractive", is a Windows system service which allows
+unprivileged users to do certain privileged operations required by OpenVPN, such
+as adding routes. This removes the need to always run OpenVPN as administrator,
+which was the case for a long time, and continues to be the case for OpenVPN
+2.3.x.
+
+The 2.4.x release and git "master" versions of OpenVPN contain the Interactive
+Service code and OpenVPN-GUI is setup to use it by default. Starting from
+version 2.4.0, OpenVPN-GUI is expected to be started as user (do not right-click
+and "run as administrator" or do not set the shortcut to run as administrator).
+This ensures that OpenVPN and the GUI run with limited privileges.
+
+
+How It Works
+============
+
+Here is a brief explanation of how the Interactive Service works, based on
+`Gert's email`_ to openvpn-devel mailing list. The example user, *joe*, is not
+an administrator, and does not have any other extra privileges.
+
+- OpenVPN-GUI runs as a *joe*
+- Interactive Service runs as a local Windows service with maximum privileges
+- OpenVPN-GUI connects to the Interactive Service and asks it "run openvpn.exe
+  with the following arguments, using the *joe*'s credentials" - Windows can do
+  this - pass credentials across a pipe, which you can't fake
+- Interactive Service forks openvpn.exe, and runs this as the user *joe*, and
+  keeps a "service pipe" between Interactive Service and openvpn.exe
+- If openvpn.exe wants to do ipconfig/route/dns stuff, it sends these as
+  requests over the service pipe to the Interactive Service, which will then
+  execute them (and clean up should openvpn.exe crash)
+- ``--up`` scripts are run by openvpn.exe itself, which is already running as
+  *joe*, all privileges are nicely in place
+- Scripts run by the GUI will run as user *joe*, so that automated tasks like
+  mapping of drives work as expected
+
+This also avoids the use of scripts for privilege escalation to admin (as was
+possible by running an ``--up`` script from openvpn.exe which is run as admin).
+
+
+Client-Service Communication
+============================
+
+Connecting
+----------
+
+The client (OpenVPN GUI) and the Interactive Service communicate using a named
+message pipe. By default, the service provides the ``\\.\pipe\openvpn\service``
+named pipe.
+
+The client connects to the pipe for read/write and sets the pipe state to the
+``PIPE_READMODE_MESSAGE``::
+
+   HANDLE pipe = CreateFile(_T("\\\\.\\pipe\\openvpn\\service"),
+       GENERIC_READ | GENERIC_WRITE,
+       0,
+       NULL,
+       OPEN_EXISTING,
+       FILE_FLAG_OVERLAPPED,
+       NULL);
+
+   if (pipe == INVALID_HANDLE_VALUE)
+   {
+       // Error
+   }
+
+   DWORD dwMode = PIPE_READMODE_MESSAGE;
+   if (!SetNamedPipeHandleState(pipe, &dwMode, NULL, NULL)
+   {
+       // Error
+   }
+
+
+openvpn.exe Startup
+-------------------
+
+After the client is connected to the service, the client must send a startup
+message to have the service start the openvpn.exe process. The startup message
+is comprised of three UTF-16 strings delimited by U0000 zero characters::
+
+   startupmsg     = workingdir WZERO openvpnoptions WZERO stdin WZERO
+
+   workingdir     = WSTRING
+   openvpnoptions = WSTRING
+   stdin          = WSTRING
+
+   WSTRING        = *WCHAR
+   WCHAR          = %x0001-FFFF
+   WZERO          = %x0000
+
+``workingdir``
+   Represents the folder openvpn.exe process should be started in.
+
+``openvpnoptions``
+   String contains ``--config`` and other OpenVPN command line options, without
+   the ``argv[0]`` executable name ("openvpn" or "openvpn.exe"). When there is
+   only one option specified, the ``--config`` option is assumed and the option
+   is the configuration filename.
+
+   Please, note that the interactive service validates the options (e.g. OpenVPN
+   config file must reside in one of the approved folders, or the invoking user
+   must be a member of local Administrators group, or a member of the
+   "OpenVPN Administrators" group).
+
+``stdin``
+   The content of the ``stdin`` string is sent to the openvpn.exe process to its
+   stdin stream after it starts.
+
+   When a ``--management ... stdin`` option is present, the openvpn.exe process
+   will prompt for the management interface password on start. In this case, the
+   ``stdin`` must contain the password appended with an LF (U000A) to simulate
+   the [Enter] key after the password is "typed" in.
+
+   The openvpn.exe's stdout is redirected to ``NUL``. Should the client require
+   openvpn.exe's stdout, one should specify ``--log`` option.
+
+The message must be written in a single ``WriteFile()`` call.
+
+Example::
+
+   // Prepare the message.
+   size_t msg_len =
+       wcslen(workingdir) + 1 +
+       wcslen(options   ) + 1 +
+       wcslen(manage_pwd) + 1;
+   wchar_t *msg_data = (wchar_t*)malloc(msg_len*sizeof(wchar_t));
+   _snwprintf(msg_data, msg_len, L"%s%c%s%c%s",
+       workingdir, L'\0',
+       options, L'\0',
+       manage_pwd)
+
+   // Send the message.
+   DWORD dwBytesWritten;
+   if (!WriteFile(pipe,
+       msg_data,
+       msg_len*sizeof(wchar_t),
+       &dwBytesWritten,
+       NULL))
+   {
+       // Error
+   }
+
+   // Sanitize memory, since the stdin component of the message
+   // contains the management interface password.
+   SecureZeroMemory(msg_data, msg_len*sizeof(wchar_t));
+   free(msg_data);
+
+
+openvpn.exe Process ID
+----------------------
+
+After receiving the startup message, the Interactive Service validates the user
+and specified options before launching the openvpn.exe process.
+
+The Interactive Service replies with a process ID message. The process ID
+message is comprised of three UTF-16 strings delimited by LFs (U000A)::
+
+   pidmsg  = L"0x00000000" WLF L"0x" pid WLF L"Process ID"
+
+   pid     = 8*8WHEXDIG
+
+   WHEXDIG = WDIGIT / L"A" / L"B" / L"C" / L"D" / L"E" / L"F"
+   WDIGIT  = %x0030-0039
+   WLF     = %x000a
+
+``pid``
+   An UTF-16 eight-character hexadecimal process ID of the openvpn.exe process
+   the Interactive Service launched on client's behalf.
+
+
+openvpn.exe Termination
+-----------------------
+
+The pipe between the client and the service is kept open until the openvpn.exe
+process terminates.
+
+Should the openvpn.exe process terminate with an error, the Interactive Service
+sends an error message to the client before disconnecting the pipe.
+
+
+Error Messages
+--------------
+
+In case of an error, the Interactive Service sends an error message to the
+client. Error messages are comprised of three UTF-16 strings delimited by LFs
+(U000A)::
+
+   errmsg = L"0x" errnum WLF func WLF msg
+
+   errnum = 8*8WHEXDIG
+   func   = WSTRING
+   msg    = WSTRING
+
+``errnum``
+
+   An UTF-16 eight-character hexadecimal error code. Typically, it is one of the
+   Win32 error codes returned by ``GetLastError()``.
+
+   However, it can be one of the Interactive Service specific error codes:
+
+   ===================== ==========
+   Error                 Code
+   ===================== ==========
+   ERROR_OPENVPN_STARTUP 0x20000000
+   ERROR_STARTUP_DATA    0x20000001
+   ERROR_MESSAGE_DATA    0x20000002
+   ERROR_MESSAGE_TYPE    0x20000003
+   ===================== ==========
+
+``func``
+   The name of the function call that failed or an error description.
+
+``msg``
+  The error description returned by a
+  ``FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, 0, errnum, ...)`` call.
+
+
+Interactive Service Configuration
+=================================
+
+The Interactive Service settings are read from the
+``HKEY_LOCAL_MACHINE\SOFTWARE\OpenVPN`` registry key by default.
+
+All the following registry values are of the ``REG_SZ`` type:
+
+*Default*
+   Installation folder (required)
+
+``exe_path``
+   The absolute path to the openvpn.exe binary; defaults to
+   ``install_dir "\bin\openvpn.exe"``.
+
+``config_dir``
+   The path to the configuration folder; defaults to ``install_dir "\config"``.
+
+``priority``
+   openvpn.exe process priority; one of the following strings:
+
+   - ``"IDLE_PRIORITY_CLASS"``
+   - ``"BELOW_NORMAL_PRIORITY_CLASS"``
+   - ``"NORMAL_PRIORITY_CLASS"`` (default)
+   - ``"ABOVE_NORMAL_PRIORITY_CLASS"``
+   - ``"HIGH_PRIORITY_CLASS"``
+
+``ovpn_admin_group``
+   The name of the local group, whose members are authorized to use the
+   Interactive Service unrestricted; defaults to ``"OpenVPN Administrators"``
+
+
+Multiple Interactive Service Instances
+======================================
+
+OpenVPN 2.4.5 extended the Interactive Service to support multiple side-by-side
+running instances. This allows clients to use different Interactive Service
+versions with different settings and/or openvpn.exe binary version on the same
+computer.
+
+OpenVPN installs the default Interactive Service instance only. The default
+instance is used by OpenVPN GUI client and also provides backward compatibility.
+
+
+Installing a Non-default Interactive Service Instance
+-----------------------------------------------------
+
+1. Choose a unique instance name. For example: "$v2.5-test". The instance name
+   is appended to the default registry path and service name. We choose to start
+   it with a dollar "$" sign analogous to Microsoft SQL Server instance naming
+   scheme. However, this is not imperative.
+
+   Appending the name to the registry path and service name also implies the
+   name cannot contain characters not allowed in Windows paths: "<", ">", double
+   quote etc.
+
+2. Create an ``HKEY_LOCAL_MACHINE\SOFTWARE\OpenVPN$v2.5-test`` registry key and
+   configure the Interactive Service instance configuration appropriately.
+
+   This allows using slightly or completely different settings from the default
+   instance.
+
+   See the `Interactive Service Configuration`_ chapter for the list of registry
+   values.
+
+3. Create and start the instance's Windows service from an elevated command
+   prompt::
+
+      sc create "OpenVPNServiceInteractive$v2.5-test" \
+         start= auto \
+         binPath= "<path to openvpnserv.exe> -instance interactive $v2.5-test" \
+         depend= tap0901/Dhcp \
+         DisplayName= "OpenVPN Interactive Service (v2.5-test)"
+
+      sc start "OpenVPNServiceInteractive$v2.5-test"
+
+   This allows using the same or a different version of openvpnserv.exe than the
+   default instance.
+
+   Please, mind the spacing around "=" character in ``sc`` command line options.
+
+4. Set your OpenVPN client to connect to the
+   ``\\.\pipe\openvpn$v2.5-test\service``.
+
+   This allows the client to select different installed Interactive Service
+   instance at run-time, thus allowing different OpenVPN settings and versions.
+
+   At the time writing, the OpenVPN GUI client supports connecting to the
+   default Interactive Service instance only.
+
+.. _`Gert's email`: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg00097.html