OpenVPN / openvpn3

OpenVPN 3 is a C++ class library that implements the functionality of an OpenVPN client, and is protocol-compatible with the OpenVPN 2.x branch.
https://openvpn.net
Other
999 stars 401 forks source link

Problem with DNS on Windows after unexpected process termination #289

Closed savely-krasovsky closed 11 months ago

savely-krasovsky commented 11 months ago

So after some unexpected OpenVPN3-process termination (bug, kill, etc) local resources that has two IPs (both public and private) cannot resolve. For example nslookup works and returns correct IPs, but ping and browser don't work (because they use DNS Service apparently).

Currently it helps to connect again and disconnect properly after it. Then DNS functionality restores. It's okay as workaround. But in our case we use SSO to authorize, so user cannot even connect again. How this could be fixed? What commands does OpenVPN3 run after disconnect was initialized? Could we call those commands manually?

savely-krasovsky commented 11 months ago

As usually, have got an a-ha moment just after creating this issue.

OpenVPN3 creates records in Windows registry for NRPM (Name Resolution Policy Messages). To repair DNS resolution you need to manually remove all registry keys with OpenVPN prefix OpenVPNDNSRouting. They are located here: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters\DnsPolicyConfig

lstipakov commented 11 months ago

Our clients (OpenVPN Connect) , which use openvpn3 core library, also run privileged agent process, which is also a part of core library. Agent is responsible for actions which require elevated privileges, such as setting up routing. In addition it has fail-safe logic, which kicks in when client process dies. In this case we revert all changes, including DNS.

savely-krasovsky commented 11 months ago

@lstipakov we also use agent, but written in Go. Thanks for the link, I didn't know that your own agent is also open source.

savely-krasovsky commented 11 months ago

@lstipakov could I ask why wouldn't you use ovpncli API for the agents? AFAIK you propose this API for the end users, but for your own product use OpenVPN3 internals to implement agents. I am started to think that ovpncli is not very well tested for desktop OS'es and mainly tested for mobile ones.

lstipakov commented 11 months ago

If you mean OpenVPNClient class from ovpncli.hpp - this is for building clients using core library. It doesn't really deal with IPC, which is needed by what we call "agent" - a separate process which does privileged operations and has fail-safe functionality. In openvpn2 this is called "interactive service".

You can check openvpn\client\win\cmdagent.hpp and openvpn\ovpnagent\win\ovpnagent.cpp for implementation details.

Agents are used by our desktop clients (Windows and Mac).

Can you tell a bit more about your agent implementation in Go? We are curious.

savely-krasovsky commented 11 months ago

@lstipakov thanks for the answer. Well, our team is not very skilled with C++, so we just took OpenVPN3's OpenVPNClient class and built privileged agent around it using Go and SWIG wrapper. We listen for events, set configuration, provide with creds and manage it with Connect/Disconnect/Pause/Resume.

It works pretty well with few caveats:

  1. Windows and Linux don't have build-in reconnection support (while macOS has MacLifeCycle class which pauses and resumes connection automatically).
  2. We are not happy that OpenVPNClient for Windows does not allow us to manually select interface we want to use. It's probably okay if you use ovpn-dco driver, because only OpenVPN apps will use it, but in our case it's wintun. In that case OpenVPN3 randomly picks any wintun interface it will find. Or maybe we don't understand something.

We are currently in the process of fixing the first problem manually by calling Pause/Resume using Network Link Manager for Windows (using Go's direct syscalls for calls and OLE IConnectionPoint sink interface to listen network related events) and NetworkManager DBus events for Linux (also there is an option to listen directly for Netlink kernel events).

But I'm a little scared by your answer. So we are using it not as you intended? Why would it even work for desktops if OpenVPNClient is mainly for mobile devices?

lstipakov commented 11 months ago

I am a bit confused by your statement we also use agent, but written in Go. From what you have just described it looks for me that you have single privileged process. Is that so?

I wouldn't say it is a "wrong" way to use core library. On the other hand, I believe in principle of least privilege. You need elevated privileges when you modify network settings, routing etc - something that you do a handful of times. You don't need elevated privileges when you encrypt, decrypt and transfer data - things which VPN app does all the time. If there is a vulnerability (like arbitrary code execution) in data path, its impact would be limited with privilege separation. With a single privileged process it would be worse.

As I said, we use agent as a separate privileged process on macOS and Windows. Our Linux client also utilizes multiple processes, however it uses other means, not agent API - @dsommers can tell more. I am not too much into mobile clients, but my understanding is that apps are already executed in isolation and privilege separation, like we do in desktop, is not needed / doesn't apply there.

You are right, you cannot specify interface manually, unlike dev-node option in openvpn2. Besides, wintun support is not actively maintained as we are switching to dco-win. For the missing functionality (like selecting certain interface) you are very welcome to submit patches, though :)

savely-krasovsky commented 11 months ago

@lstipakov yes, maybe I didn't understand agent term correctly. We use single privileged process that allows GUI app to manage TUN-interface and other network settings. Our case mostly covers Windows and macOS.

I know that in case of Linux openvpn3-linux project does it more properly, but currently it's broken for the newer distros (https://github.com/OpenVPN/openvpn3-linux/issues/171).

Does ours "agent" less secure than yours in theory in case of Windows and macOS?

lstipakov commented 11 months ago

I don’t know your implementation, so cannot really say if it is more or less secure than ours. But on a general level it might be a good idea to follow principle of least privilege. We do it also in openvpn2-based OpenVPN-GUI Windows client. Lähetetty iPhonestaSavely Krasovsky @.***> kirjoitti 8.12.2023 kello 16.35: @lstipakov yes, maybe I didn't understand agent term correctly. We use single privileged process that allows GUI app to manage TUN-interface and other network settings. Our case mostly covers Windows and macOS. I know that in case of Linux openvpn3-linux project does it more properly, but currently it's broken for the newer distros (OpenVPN/openvpn3-linux#171). Does ours "agent" less secure than yours in case of Windows and macOS?

—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you were mentioned.Message ID: @.***>

savely-krasovsky commented 11 months ago

@lstipakov I understand the principle. I'm just thinking maybe I missing something. I don't know how I could encrypt, decrypt and transfer data outside of privileged process if I use OpenVPNClient. ovpn-dco-win probably should help, because it will do it in kernel space. But what I can do in case of macOS?

lstipakov commented 11 months ago

You need privileges only for limited set of operations, so you may want to reverse you question and ask instead "how can I setup routing etc with unprivileged process"? Above I pointed to agent implementation - it is running as a separate process (as a service in Windows), functions as HTTP server and replies to 3 POST requests:

A fair amount of agent code is HTTP stack, which you get for free in Go I think. The rest employs TunClient class hierarchy, for which we don't have SWIG bindings. It should not be difficult to reimplement it in Go, though.

The same approach is used in macOS - there is agent process, running as daemon and functioning as HTTP server.

With dco-win (same for Linux and FreeBSD modules) we have crypto and network communication in kernel, so if something goes wrong there we're in trouble. We put things into the kernel to avoid user space/kernel space context switch for every packet, which greatly improves performance but brings some risks, too. On the other hand, the kernel modules have limited functionality and we try to keep only performance-critical things there, delegating many things to userspace (or example, TLS handshake).

savely-krasovsky commented 11 months ago

@lstipakov I see, thanks. A room for improvement for us. But does OpenVPNClient able to run without root priveledges and still able to reuse setup ready for use TUN interface?

savely-krasovsky commented 11 months ago

@lstipakov we found out, that OpenVPN3 already supports ovpnagent while using as library. But for some reason it has not documented at all. Instead of rewriting ovpnagent in Go, we decided to compile agent using CMake target ovpnagent and add definition to ovpnclillib: OPENVPN_COMMAND_AGENT. It allows OpenVPN3 to establish TUN interface using agent without any root/admin privileges.

I think it should be the default way of use for win/mac. Otherwise many people would misuse it.