Skip to content

skiff/core: bridge dbus to host system for some services like NetworkManager #211

Description

@paralin

https://github.com/igo95862/dbus-forwarding-proxy

Use the proxy to forward NetworkManager and other resources from the SkiffOS host system into the dbus in systemd/dbus-enabled Skiff Core containers.

We will need to add a buildroot package for dbus-forwarding-proxy

Activity

  1. self-assigned this
    on May 31, 2022
  2. changed the title [-]core: add xdg-dbus-proxy[/-] [+]skiff/core: bridge dbus to host system for some services like NetworkManager[/+] on Feb 23, 2023
  3. paralin commented on Feb 23, 2023

    @paralin
    MemberAuthor

    flatpak/xdg-dbus-proxy#47

    This is currently not possible with xdg-dbus-proxy or otherwise. In the issue above:

    This is the situation:

    I have NetworkManager running on the host system.
    I have systemd and dbus running in a privileged Docker container.
    I want nmcli in the container to access the NetworkManager on the host system.
    However: I also need to be able to access dbus services within the container as well.
    

    The goal is to have requests for NetworkManager be routed to the parent dbus, and requests for anything else sent to the container dbus.

    Response:

    What you are asking for is combining two "real" buses into one proxied bus, so that clients can connect to the proxied bus, send requests, and have those requests go to one or the other of the "real" buses, depending on the request; for example you might have NetworkManager on the host's "real" system bus, but some other service (let's say systemd) on a different "real" system bus inside your Docker container. Is that right?

    I don't think that can actually work in general, because D-Bus isn't designed for that. For example, if you send a request like AddMatch or GetNameOwner to org.freedesktop.DBus, where do we send that - the bus with NetworkManager on it, or the bus with systemd on it? The right answer is "it depends".

    [...]

    I think the way to achieve your higher-level goal would be to have a content-aware proxy that provides the service side of the NetworkManager interface inside the container (so to other software inside the container, it pretends to be NetworkManager), and then implements that by turning round and connecting as a client to a socket that comes from outside the container (so to software outside the container, it behaves like a NetworkManager client like nmcli).

    If your aim is to have a security boundary, so that the NetworkManager client can talk to the host NetworkManager but nothing else, then you might want to use xdg-dbus-proxy as well, to provide a filtered version of the real host system bus inside the container. Like this: [diagram]

    Conclusion

    The approach I'll try to implement here is as suggested above: creating a program which pretends to be NetworkManager and forwards those requests to the parent system bus. We can still use xdg-dbus-proxy in skiff core to run a filtered version of the host system bus which prevents the container from accessing anything but NetworkManager.

    This is not the best, because there are other services that would be good to forward too - like the host systemd (for poweroff / sleep). But it'd be a start.

  4. igo95862 commented on Apr 25, 2024

    @igo95862

    Forwarding method calls seems to be very straight forward.

    The "bridge" connects to both "outside" and "inside" D-Bus. After that it acquires org.freedesktop.NetworkManager bus name on the "inside". Now every message received on the "inside" just can to be re-send to the "outside". The "bridge" should maintain a map of message cookies and translate back the response messages. For the "outside" it will look like the "bridge" sends all messages.

    Bridging signals seems more difficult but I think you can mirror the match rules created on the "inside" and recreate the same rules on the "outside" that captures the NetworkManager signals.

    This all is assuming you bridge service on the "outside" to "inside". Bridging from "inside" to "outside" is probably way more difficult.

    I am developing my own D-Bus Python library so I have some understanding of the D-Bus.

  5. igo95862 commented on Apr 25, 2024

    @igo95862

    Bridging signals seems more difficult but I think you can mirror the match rules created on the "inside" and recreate the same rules on the "outside" that captures the NetworkManager signals.

    Actually you can just subscribe to all signals emitted by NetworkManager on the "outside" using wildcard match rules and then just emit them back on the "inside". This is less efficient but saves you the trouble of monitoring the match rules.

  6. paralin commented on Apr 25, 2024

    @paralin
    MemberAuthor

    @igo95862 I looked at doing this in the past and the dbus codebase is so confusing I had a hard time making it happen. Will have another look but let me know if you start a repo somewhere with a prototype and I'll test it out.

  7. igo95862 commented on Apr 25, 2024

    @igo95862

    dbus codebase is so confusing

    D-Bus is a protocol and there are many implementations. I am most familiar with the sd-bus from systemd.

    if you start a repo somewhere with a prototype and I'll test it out.

    I might try putting together a prototype this weekend. Not sure what to implement it in. My Python library is not well suited for the low level work. I might do some C Glib, C++ or Zig.

  8. igo95862 commented on Apr 27, 2024

    @igo95862

    @paralin I created an prototype here: https://github.com/igo95862/dbus-forwarding-proxy

    It can forward a service between different D-Bus instances.

    To build you only need meson, libsystemd and glib.

    For example, forwarding NetworkManager from system bus to session bus:

    ./build/src/dbus-forwarding-proxy --from-dbus-address "unix:path=/run/dbus/system_bus_socket" --service org.freedesktop.NetworkManager --to-dbus-address "$DBUS_SESSION_BUS_ADDRESS"

    I tested it a bit with D-Feet and it seems to work.

    There is also a --pid option that will make it switch to the given PID's mount namespace. This can be used with containers or sandboxes.

    Only method calls are supported at the moment but I think signals will be easy to implement.

  9. paralin commented on Apr 27, 2024

    @paralin
    MemberAuthor

    @igo95862 awesome, thanks! I'll give it a try.

  10. added a commit that references this issue on Jun 22, 2026
  11. paralin commented on Jun 22, 2026

    @paralin
    MemberAuthor

    Landed a candidate fix in 2523634, backed by the new skiffos/skiff-dbus-proxy repo at a40b54bd36a79b6f67153c6dac66d63190124778. I left this open because I verified the proxy build/smoke test, SkiffOS package selection, source/hash fetch, and service syntax, but did not run a live NetworkManager call through a Skiff Core container bus.

  12. paralin commented on Jun 22, 2026

    @paralin
    MemberAuthor

    Status update: candidate fix is on master in 2523634, backed by skiffos/skiff-dbus-proxy at a40b54bd36a79b6f67153c6dac66d63190124778. I verified the proxy build and private-bus smoke test, SkiffOS package selection, source hash fetch, service wrapper syntax, and systemd unit parsing. This still needs your confirmation with a live NetworkManager call through a Skiff Core container bus before I would call it closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions