Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

StatusManagerEvent signal is sent before backend client service is ready #238

Open
savely-krasovsky opened this issue Feb 13, 2024 · 14 comments
Assignees
Labels
bug fixed Issue is claimed to be fixed, but should be tested before closing it need testing Need more testing to see if issue us still present

Comments

@savely-krasovsky
Copy link

As far as I got it, from some point there was a change then StatusChange and AttentionRequired became "private" signals. There is LogForward method which allows to receive some signals with net.openvpn.v3.backends as sender. But I cannot receive any signals from net.openvpn.v3.sessions (while docs clearly says it should be proxified).

It lead me to the situation where I cannot track state of session initialization: I am importing configuration (Import), creating new session (NewTunnel), but if I will immediately call something like LogForward or Ready, I will get this error: Backend VPN process is not ready.

Without any signals I could not do it without manual sleeps in the code.

I use godbus, it's a bit more lower level than Python's dbus, but even if I didn't apply any Match filter and just print ALL signals my app is getting, I still unable to find any signals from sessions.

@savely-krasovsky
Copy link
Author

savely-krasovsky commented Feb 13, 2024

I also relatively often get this error Object does not exist at path “/net/openvpn/v3/sessions” while trying to create session NewTunnel right after Import. I guess session daemon shuts down sometime and after importing configuration it needs time to spin up again. But I have no clue how to fix it without another sleep...

UPD. Oh I could even get Object does not exist at path “/net/openvpn/v3/configuration” while trying to Import configuration. Probably this is not ok and something crashing?

@dsommers
Copy link
Member

I've not pushed out yet some new code which uses this feature from Python. It will be part of the project once the code is properly tested. But you can have a look at it here: https://gist.github.com/dsommers/d4447dba169b1278bcab4b7ebd235761

The approach to use is to listen to SessionManagerEvent. That is sent from the net.openvpn.v3.sessions service (openvpn3-service-sessionmgr).

To check if your setup is functional, try running this command as root: openvpn3-admin version --services. That should wake up all of the accessible services and retrieve the version of each service.

@savely-krasovsky
Copy link
Author

savely-krasovsky commented Feb 14, 2024

I see the SessionManagerEvent signal, but it doesn't guarantee that session is up and ready for the calls. If I will try to immediately call LogForward after receiving this signal I am getting Backend VPN process is not ready. Sleep for 3000 ms helps, but it doesn't look good...

@savely-krasovsky
Copy link
Author

To check if your setup is functional, try running this command as root: openvpn3-admin version --services. That should wake up all of the accessible services and retrieve the version of each service.

I am creating client app, so not sure how to ensure that D-Bus interfaces are running. After trying to call them I could get Object does not exist at path [service], but seems like they start to spin up after that, so next calls works, but it doesn't look good from frontend app developer point. Are there any methods to init services before calling them without root (as Flatpak app for example)?

@dsommers
Copy link
Member

dsommers commented Feb 14, 2024

Depending on the system itself, I have seen that it in some cases the client process has not settled quickly enough, so a little delay is needed currently. I'm re-doing the D-Bus implementation (see the 171 issue ticket), which seems to be far more efficient in general. I'll have a look closer at when the SessionManagerEvent is sent, like after the client has properly registered. Until that point is reached, the session path needed for the LogForward may indeed not be ready just yet.

There are several things happening when NewTunnel is called:

  • sessionmgr calls backendstarter:StartClient
  • sessionmgr sends SessionManagerEvent signal
  • backendstarter kicks off a openvpn3-service-client (client) process
  • client issues RegistrationRequest signal to sessionmgr
  • sessionmgr calls client:RegistrationConfirmation which includes the D-Bus path to the configuration
  • client calls log:AssignSession (the logger service) - which is needed to allow client logs to be forwarded
  • client calls configmgr:Fetch to retrieve the configuration profile and parses it.
  • client responds to the RegistrationConfirmation call with the configuration profile name it retrieved.

When all these steps are done, that's when the session path will be fully functional. That SessionManagerEvent signal should probably be moved down to when the sessionmgr completes the RegistrationConfirmation call. That's when it is sure the configuration profile has been retrieved and parsed.

But it's awesome that you're looking into a client app! Keep us updated and we can collaborate further on these efforts.

@savely-krasovsky
Copy link
Author

savely-krasovsky commented Feb 14, 2024

@dsommers thanks for clarifying. Yes, I understand that calling NewTunnel cause a lot of work under the hood, but currently SessionManagerEvent mostly useless, because it still requires a sleep. In my opinion this should be fixed at some point.

But I still don't understand what I can do with Object does not exist at path [service] errors. Just trying to call services until they will finally available doesn't seem good for me. Is it even known issues or there is something wrong with my system?

@dsommers
Copy link
Member

dsommers commented Feb 14, 2024

I'll definitely try to improve the situation with v22_dev, once that is ready, yes.

Generally speaking, the challenge with D-Bus is that there are no strict delivery guarantees on signals. At least that's my experience so far. In many ways, it's not unreasonable to compare it with UDP traffic. Most of the time it works just fine, but it may be delayed.

In this case, since the NewTunnel results in two binaries being started (first via D-Bus (openvpn3-service-backendstart, second via a fork() + execve() call - openvpn3-service-client), this does introduces some random latencies - which can be quite annoying. So when the SesionManagerEvent is sent almost immediately after the StartClient call, I believe the situation will be improved by putting it later in the chain.

@dsommers dsommers changed the title Don't understand from the docs how to subscribe on session signals StatusManagerEvent signal is sent before backend client service is ready Feb 14, 2024
@dsommers dsommers added the bug label Feb 14, 2024
@savely-krasovsky
Copy link
Author

savely-krasovsky commented Mar 13, 2024

@dsommers is there any workaround to pre-activate all necessary D-Bus services? Currently client user should click "Connect" button like 2 or 3 times to finally connect. Because of Object does not exist at path “/net/openvpn/v3/... errors. We are getting this issue every time after cold PC boot. I guess sure we can make some python script and put it in in ~/.config/autostart or even create systemd one-shot user service. But it's kinda too much? Maybe there are better workarounds for now? Just running openvpn3-admin version --services before connecting should be ok?

@dsommers
Copy link
Member

What is this "Connect" button? Do you have some code providing such a button? Also, have a look at the OpenVPN 3 Indicator project; we've recently embraced that project as an alternative GUI for OpenVPN 3 Linux.

That said, the common behaviour across D-Bus libraries is to give that "Object does not exist" behaviour if the D-Bus service is not running and not starting quick enough. That even goes for the gdbus command line against various services as well. The service needs to start incredibly quickly to respond in time to avoid that error. On a slower system this happens far more often than on systems being more responsive.

The approach I've taken in GDBus++ and the refactoring of openvpn3-linux, is to do a for-loop check doing a StartServiceByName and then GetNameOwner. That usually works after the first round, some times on slow responses it needs 2 rounds. I've found a sleep of 0.4 seconds is usually enough between each round if it fails. You can see the C++ code here: https://codeberg.org/OpenVPN/gdbuspp/src/commit/584d477fb3fbb9b3905cf20463fb10c56edbbfb7/gdbuspp/proxy/utils.cpp#L170 I do consider this more like a hack. A more appropriate approach would be to listen for a D-Bus signal from the D-Bus daemon when a specific service name is registered and hold back until that happens. But glib2 is generally not happy about acting on signals while processing in a method call; even though the GDBus++ might be more easily capable of doing that.

@savely-krasovsky
Copy link
Author

savely-krasovsky commented Mar 14, 2024

@dsommers thanks for the reply! Very useful. Well, by "connect" button I mean starting an OpenVPN3 session. Then I call consequently Import, Connect, etc I got those errors. Thanks for the detailed answer, now I know where to dig... Currently as a workaround I am just calling openvpn3-admin version --services, mitigates the problem completely, but feels wrong.

@savely-krasovsky
Copy link
Author

Well, it worked! Much better solution, thank you again.

@dsommers
Copy link
Member

Just a note ... you seem to import configurations each time. Consider using persistent configuration imports.

$ openvpn3 config-import --persistent --name CONFIG_NAME --config CONFIG_FILE

With this approach, the configuration profile will always be present on the system for the user which did the import. To grant more users access, have a look at the openvpn3 config-acl command. Granting root access will make it possible to use the openvpn3-session@CONFIG_NAME.service systemd unit file to start a VPN session during boot.

And once imported, all you need to do: openvpn3 session-start --config CONFIG_NAME ... even after a reboot; no import needed.

@savely-krasovsky
Copy link
Author

savely-krasovsky commented Mar 15, 2024

Yes, I know about persistent configurations, but in our case we dynamically fetch and assign configurations for each user based on conditions (e.g. where OpenVPN over UDP could be blocked). Today it could ok, tomorrow already not.

@dsommers dsommers self-assigned this May 2, 2024
@dsommers dsommers added need testing Need more testing to see if issue us still present fixed Issue is claimed to be fixed, but should be tested before closing it labels May 2, 2024
@dsommers
Copy link
Member

dsommers commented May 2, 2024

This should be fixed with the latest devsnapshot. The issuing of the "session created" signal is now postponed until after the session object is created and the backend VPN client process has completed the registration with the session manager.

https://codeberg.org/OpenVPN/openvpn3-linux/src/commit/87872f6c5d6f5913e5ccf955f424919b426512f2/src/sessionmgr/tunnel-queue.cpp#L200

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug fixed Issue is claimed to be fixed, but should be tested before closing it need testing Need more testing to see if issue us still present
Projects
None yet
Development

No branches or pull requests

2 participants