This appears to be the same underlying problem reported in the previously closed issue, but it is still reproducible with OpenVPN 2.7.6 and ovpn-dco-win 2.8.4 on Windows 11.
Refered to the previus ticket #629
I was able to reproduce this issue and implement a working workaround.
Environment
- Windows 11 Pro 25H2 x64, OS Build 26200.8875
- OpenVPN Community 2.7.6
- OpenVPN GUI 11.65.0.0
- ovpn-dco-win 2.8.4
- OpenVPN GUI running as a standard, non-elevated user
OpenVPN reports the operating system internally as:
Windows version: 10.0.26200, amd64
This is still Windows 11; Windows 11 retains the NT version number 10.0 for compatibility.
Symptoms
The relevant error was:
Using device interface: ...\ovpn-dco
CreateFile failed on ovpn-dco device: ... Access is denied. (errno=5)
Failed to open ovpn-dco adapter
The same OpenVPN profile worked correctly when OpenVPN GUI was started with Run as administrator.
Adding:
also allowed OpenVPN GUI to connect as a standard user, but throughput was significantly lower.
This confirmed that the VPN profile, authentication, routing, server, and DCO driver itself were working. The failure occurred specifically when a non-elevated openvpn.exe process tried to open the ovpn-dco device interface.
Troubleshooting already attempted
The following actions did not solve the problem:
- uninstalling OpenVPN;
- deleting all ovpn-dco adapter instances;
- removing every ovpn-dco driver package from the Windows Driver Store;
- rebooting;
- reinstalling OpenVPN;
- reinstalling ovpn-dco-win 2.8.4;
- recreating the DCO adapter;
- resetting the Windows network stack;
- verifying that
OpenVPNServiceInteractive was running;
- verifying that the user was a member of the
OpenVPN Administrators group.
After a complete uninstall, Driver Store cleanup, reboot, and clean reinstall, the newly created DCO device still returned:
Access is denied. (errno=5)
The failing operation remained the CreateFile() call against the ovpn-dco device path.
Root cause identified
The DCO driver was installed, loaded, and discoverable, but the effective per-device security descriptor did not allow the standard user's OpenVPN process to open the DCO device interface.
Reinstalling the driver did not correct that per-device ACL.
The workaround was to modify the security descriptor of the ovpn-dco Plug and Play device instance and grant access only to the current Windows user's SID.
What the workaround script does
The PowerShell script must be run once as administrator.
It performs the following operations:
-
Stops running openvpn.exe and openvpn-gui.exe processes.
-
Checks whether a persistent DCO adapter exists by running:
tapctl.exe list --hwid ovpn-dco
-
If the requested adapter does not exist, creates one with:
tapctl.exe create --hwid ovpn-dco --name "OpenVPN DCO User"
-
Uses Windows SetupAPI to enumerate currently present devices in the Network device class:
{4d36e972-e325-11ce-bfc1-08002be10318}
-
Selects only devices whose hardware ID is exactly:
-
Reads the per-device security descriptor through:
using SetupDiGetDeviceRegistryPropertyW().
-
Saves the original device instance IDs and SDDL security descriptors to a JSON backup under:
C:\ProgramData\OpenVPN\DcoAclFix
-
Retrieves the SID of the current Windows user.
-
Adds the following access-control entry to the device DACL:
(A;;GRGWGX;;;<CURRENT_USER_SID>)
This grants Generic Read, Generic Write, and Generic Execute access only to the current user.
-
Writes the updated security descriptor through:
SetupDiSetDeviceRegistryPropertyW(..., SPDRP_SECURITY_SDS, ...)
-
Restarts each affected DCO device with:
pnputil.exe /restart-device <INSTANCE_ID>
-
Optionally updates a specified .ovpn profile by:
The script does not grant device access to Everyone.
It does not modify the ACL of the ovpn-dco kernel service.
It modifies only the security descriptors of present Plug and Play devices whose hardware ID is exactly ovpn-dco.
How to locate and verify the OpenVPN profile
Before running the script with -ConfigPath, first identify the exact .ovpn profile used by the failing connection.
The profile filename is normally visible in the OpenVPN log, for example:
It may also correspond to the connection name displayed by OpenVPN GUI.
Open PowerShell as Administrator and list the .ovpn profiles in the standard OpenVPN directories:
$OpenVpnRoots = @(
"$env:USERPROFILE\OpenVPN",
"$env:ProgramFiles\OpenVPN"
) | Where-Object {
Test-Path -LiteralPath $_
}
Get-ChildItem `
-Path $OpenVpnRoots `
-Filter "*.ovpn" `
-File `
-Recurse `
-ErrorAction SilentlyContinue |
Sort-Object FullName |
Select-Object FullName, LastWriteTime
Find the profile whose filename matches the profile shown in the OpenVPN log or OpenVPN GUI.
Set its exact path in a variable:
$ProfilePath = "C:\Path\To\Client.ovpn"
Verify that the file exists:
Test-Path -LiteralPath $ProfilePath
The result must be:
Review the relevant profile directives before making changes:
Get-Content -LiteralPath $ProfilePath |
Select-String -Pattern '^\s*(remote|dev|dev-node|disable-dco)\b'
Confirm that this is the correct VPN profile before continuing.
Create an additional manual backup:
$ManualBackup = "$ProfilePath.manual-backup-$(Get-Date -Format 'yyyyMMdd-HHmmss')"
Copy-Item `
-LiteralPath $ProfilePath `
-Destination $ManualBackup
Write-Host "Manual profile backup: $ManualBackup"
The script also creates its own timestamped profile backup when -ConfigPath is used, but this manual backup provides an additional recovery copy.
How to run the workaround
Save or download the script as:
Fix-OpenVpnDcoAcl-English-Generic.ps1
For example, place it in the current user's Downloads directory.
Close OpenVPN GUI completely.
Open PowerShell as Administrator and define the script path:
$ScriptPath = "$env:USERPROFILE\Downloads\Fix-OpenVpnDcoAcl-English-Generic.ps1"
Verify that the script exists:
Test-Path -LiteralPath $ScriptPath
The result must be:
Allow scripts only for the current PowerShell process and unblock the downloaded file:
Set-ExecutionPolicy -Scope Process Bypass -Force
Unblock-File -LiteralPath $ScriptPath
Run the script and provide the previously verified OpenVPN profile:
& $ScriptPath -ConfigPath $ProfilePath
Administrator privileges are required only while applying the device ACL change.
When -ConfigPath is used, the script:
-
backs up the original device ACLs;
-
creates the persistent DCO adapter if necessary;
-
grants the current user's SID access to the DCO device;
-
restarts the affected device;
-
creates a timestamped backup of the .ovpn file;
-
removes disable-dco;
-
removes existing dev-node directives;
-
adds:
dev-node "OpenVPN DCO User"
An automatically created profile backup will have a name similar to:
Client.ovpn.bak-20260806-153000
After the script completes:
- Close the elevated PowerShell window.
- Start OpenVPN GUI normally.
- Do not use Run as administrator.
- Connect using the modified profile.
After applying this per-device ACL change, OpenVPN GUI was able to open the DCO device successfully as a standard user. DCO remained enabled and normal throughput was restored.
Running the ACL fix without modifying a profile
The script can also be run without -ConfigPath:
In that mode, it changes the DCO device ACL but does not modify any .ovpn file.
The profile must then be edited manually:
-
Remove or comment out:
-
Remove any existing dev-node directive.
-
Add:
dev-node "OpenVPN DCO User"
Using -ConfigPath is safer when the exact profile has already been identified and verified because the script creates a timestamped backup before modifying it.
ACL rollback
To restore the most recent DCO device ACL backup, close OpenVPN GUI, open PowerShell as Administrator, and run:
$ScriptPath = "$env:USERPROFILE\Downloads\Fix-OpenVpnDcoAcl-English-Generic.ps1"
Set-ExecutionPolicy -Scope Process Bypass -Force
Unblock-File -LiteralPath $ScriptPath
& $ScriptPath -Rollback
The script restores the original per-device SDDL values from the newest backup under:
C:\ProgramData\OpenVPN\DcoAclFix
It then restarts the affected DCO devices.
To see the available ACL backups:
Get-ChildItem `
-LiteralPath "C:\ProgramData\OpenVPN\DcoAclFix" `
-Filter "DcoAclBackup-*.json" |
Sort-Object LastWriteTime -Descending |
Select-Object FullName, LastWriteTime
To restore a specific ACL backup:
$AclBackup = "C:\ProgramData\OpenVPN\DcoAclFix\DcoAclBackup-YYYYMMDD-HHMMSS.json"
& $ScriptPath `
-Rollback `
-BackupFile $AclBackup
Restoring the original OpenVPN profile
The ACL rollback does not automatically restore a modified .ovpn profile.
List the profile backups created by the script:
$ProfileDirectory = Split-Path -Parent $ProfilePath
$ProfileFileName = Split-Path -Leaf $ProfilePath
Get-ChildItem `
-LiteralPath $ProfileDirectory `
-Filter "$ProfileFileName.bak-*" |
Sort-Object LastWriteTime -Descending |
Select-Object FullName, LastWriteTime
Select the backup that should be restored:
$ProfileBackup = "C:\Path\To\Client.ovpn.bak-YYYYMMDD-HHMMSS"
Restore it:
Copy-Item `
-LiteralPath $ProfileBackup `
-Destination $ProfilePath `
-Force
The separate manual backup created before running the script can also be restored in the same way.
After restoring the original profile, restart OpenVPN GUI normally.
Conclusion
This appears to show that, on affected systems, reinstalling OpenVPN or ovpn-dco-win does not address the actual failure.
The driver is installed, loaded, and discoverable, but the effective per-device security descriptor prevents the intended non-elevated OpenVPN process from opening the DCO device interface.
This script is a workaround, not an upstream fix.
The driver installer or device creation path should ensure that newly created ovpn-dco device instances receive a security descriptor compatible with OpenVPN GUI's intended non-elevated execution model. Access could potentially be granted to the appropriate OpenVPN local group or through another suitably restricted device ACL.
Fix-OpenVpnDcoAcl-English-Generic.zip
This appears to be the same underlying problem reported in the previously closed issue, but it is still reproducible with OpenVPN 2.7.6 and ovpn-dco-win 2.8.4 on Windows 11.
Refered to the previus ticket #629
I was able to reproduce this issue and implement a working workaround.
Environment
OpenVPN reports the operating system internally as:
This is still Windows 11; Windows 11 retains the NT version number
10.0for compatibility.Symptoms
The relevant error was:
The same OpenVPN profile worked correctly when OpenVPN GUI was started with Run as administrator.
Adding:
also allowed OpenVPN GUI to connect as a standard user, but throughput was significantly lower.
This confirmed that the VPN profile, authentication, routing, server, and DCO driver itself were working. The failure occurred specifically when a non-elevated
openvpn.exeprocess tried to open the ovpn-dco device interface.Troubleshooting already attempted
The following actions did not solve the problem:
OpenVPNServiceInteractivewas running;OpenVPN Administratorsgroup.After a complete uninstall, Driver Store cleanup, reboot, and clean reinstall, the newly created DCO device still returned:
The failing operation remained the
CreateFile()call against the ovpn-dco device path.Root cause identified
The DCO driver was installed, loaded, and discoverable, but the effective per-device security descriptor did not allow the standard user's OpenVPN process to open the DCO device interface.
Reinstalling the driver did not correct that per-device ACL.
The workaround was to modify the security descriptor of the ovpn-dco Plug and Play device instance and grant access only to the current Windows user's SID.
What the workaround script does
The PowerShell script must be run once as administrator.
It performs the following operations:
Stops running
openvpn.exeandopenvpn-gui.exeprocesses.Checks whether a persistent DCO adapter exists by running:
If the requested adapter does not exist, creates one with:
Uses Windows SetupAPI to enumerate currently present devices in the Network device class:
Selects only devices whose hardware ID is exactly:
Reads the per-device security descriptor through:
using
SetupDiGetDeviceRegistryPropertyW().Saves the original device instance IDs and SDDL security descriptors to a JSON backup under:
Retrieves the SID of the current Windows user.
Adds the following access-control entry to the device DACL:
This grants Generic Read, Generic Write, and Generic Execute access only to the current user.
Writes the updated security descriptor through:
Restarts each affected DCO device with:
Optionally updates a specified
.ovpnprofile by:removing
disable-dco;removing existing
dev-nodedirectives;adding:
The script does not grant device access to
Everyone.It does not modify the ACL of the
ovpn-dcokernel service.It modifies only the security descriptors of present Plug and Play devices whose hardware ID is exactly
ovpn-dco.How to locate and verify the OpenVPN profile
Before running the script with
-ConfigPath, first identify the exact.ovpnprofile used by the failing connection.The profile filename is normally visible in the OpenVPN log, for example:
It may also correspond to the connection name displayed by OpenVPN GUI.
Open PowerShell as Administrator and list the
.ovpnprofiles in the standard OpenVPN directories:Find the profile whose filename matches the profile shown in the OpenVPN log or OpenVPN GUI.
Set its exact path in a variable:
Verify that the file exists:
The result must be:
Review the relevant profile directives before making changes:
Confirm that this is the correct VPN profile before continuing.
Create an additional manual backup:
The script also creates its own timestamped profile backup when
-ConfigPathis used, but this manual backup provides an additional recovery copy.How to run the workaround
Save or download the script as:
For example, place it in the current user's Downloads directory.
Close OpenVPN GUI completely.
Open PowerShell as Administrator and define the script path:
Verify that the script exists:
The result must be:
Allow scripts only for the current PowerShell process and unblock the downloaded file:
Run the script and provide the previously verified OpenVPN profile:
Administrator privileges are required only while applying the device ACL change.
When
-ConfigPathis used, the script:backs up the original device ACLs;
creates the persistent DCO adapter if necessary;
grants the current user's SID access to the DCO device;
restarts the affected device;
creates a timestamped backup of the
.ovpnfile;removes
disable-dco;removes existing
dev-nodedirectives;adds:
An automatically created profile backup will have a name similar to:
After the script completes:
After applying this per-device ACL change, OpenVPN GUI was able to open the DCO device successfully as a standard user. DCO remained enabled and normal throughput was restored.
Running the ACL fix without modifying a profile
The script can also be run without
-ConfigPath:In that mode, it changes the DCO device ACL but does not modify any
.ovpnfile.The profile must then be edited manually:
Remove or comment out:
Remove any existing
dev-nodedirective.Add:
Using
-ConfigPathis safer when the exact profile has already been identified and verified because the script creates a timestamped backup before modifying it.ACL rollback
To restore the most recent DCO device ACL backup, close OpenVPN GUI, open PowerShell as Administrator, and run:
The script restores the original per-device SDDL values from the newest backup under:
It then restarts the affected DCO devices.
To see the available ACL backups:
To restore a specific ACL backup:
Restoring the original OpenVPN profile
The ACL rollback does not automatically restore a modified
.ovpnprofile.List the profile backups created by the script:
Select the backup that should be restored:
Restore it:
The separate manual backup created before running the script can also be restored in the same way.
After restoring the original profile, restart OpenVPN GUI normally.
Conclusion
This appears to show that, on affected systems, reinstalling OpenVPN or ovpn-dco-win does not address the actual failure.
The driver is installed, loaded, and discoverable, but the effective per-device security descriptor prevents the intended non-elevated OpenVPN process from opening the DCO device interface.
This script is a workaround, not an upstream fix.
The driver installer or device creation path should ensure that newly created ovpn-dco device instances receive a security descriptor compatible with OpenVPN GUI's intended non-elevated execution model. Access could potentially be granted to the appropriate OpenVPN local group or through another suitably restricted device ACL.
Fix-OpenVpnDcoAcl-English-Generic.zip