Open ruzko opened 9 months ago
I finally did some reading on OpenZiti.
So the idea is that this would be for the browser->Moonfire leg? And it would be an alternative to binding a TCP port which is reachable by the client (over the LAN, VPN, or public Internet)? And Moonfire could use Ziti APIs to provide authenticated identity and possibly even role-based authorization, as an alternative to the current password->web session or Unix socket permissions-based authentication and/or the per-user permissions in its own database?
I'm looking through a few details of how it might work.
Build/linking: we'd have to link to the OpenZiti APIs. I don't know if it's too compatible with the "build a zero-dependencies, almost-pure-Rust binary" approach I've adopted. How would you feel about this being an optional feature not included in the main release builds?
Threading model: I don't see this documented in their SDK docs. Currently Moonfire uses a multi-threaded tokio reactor. Is Ziti thread-safe? or would we need to handle all Ziti operations in one thread?
General lifecycle: looks like for each [[bind]] ziti = ...
item we'd set up a service with ziti_listen
. Then in ziti_client_cb
, ziti_accept
it, then in ziti_conn_cb
set up a matching hyper
Connection
. We receive data via ziti_read_cb
; we start writes via ziti_write
and get their completion status via ziti_write_cb
. Closing happens by ziti_close
(locally initiated) / ziti_close_cb
(fully closed by either party).
Flow control: I'm a little concerned that I don't see much mention of this.
ziti_read_cb
. Hyper expects to drive the thing, reading when it wants to. How do we bridge those? Is there a way to tell Ziti "stop reading for a while" / "start reading again"? or do we have to buffer everything that comes in and just drop the connection abruptly if the inbound buffer becomes absurdly large?tokio::io::AsyncWrite
impl in which poll_write
returns not ready between our call to ziti_write
and the matching ziti_write_cb
acknowledgement. Possibly we have to layer on our own buffering and only start those writes after reaching a threshold or on poll_flush
calls to avoid short writes though, as if I'm understanding correctly only one write can be in flight at once.btw, there's something vaguely similar I've been thinking of adding: Cloudflare Tunnel support, perhaps via the libcfd
crate if it matures a bit. Comparing the two...
When Tunnel is combined with Cloudflare Access, our comprehensive Zero Trust access solution, users are authenticated by major identity providers (like Gsuite and Okta) without the help of a VPN.
libcfd
would be a pure Rust approach: rustls
rather than openssl
, tokio
rather than libuv
, easily able to be added to the default zero-dependencies binary.A third option in this general space is Tailscale. Again it's a commercial freemium service thing. They have a page here on enabling https that mentions Caddy integration; we could rely on something external (tailscale's software or caddy) or add similar integration to Moonfire.
Thanks for replying :) I had some trouble getting Moonfire up and running reliably, and to connect to the cameras in my network. I needed to have a working prototype (for my thesis) two weeks after this issue was opened, so I restarted work on a NVR project in Python I'd developed previously. If I manage to get some funding to keep working after my thesis finishes in June; I'm still keen on reimplementing stuff in Rust for Moonfire.
A central theme in the thesis is how transparency and digital self-sovereignity is crucial for building trust and security in a rapidly IoT-connected world. The NVR project I'm working on for the thesis is licensed AGPLv3-or-later, to ensure that users always have access to the source code, even if a service provider decides to sell it as a service; e.g. by linking their cams to a cloud-hosted NVR server.
This might be a little off-topic, but may I ask why you chose GPLv3-or-later over AGPLv3-or-later for Moonfire?
So the idea is that this would be for the browser->Moonfire leg? And it would be an alternative to binding a TCP port which is reachable by the client (over the LAN, VPN, or public Internet)? And Moonfire could use Ziti APIs to provide authenticated identity and possibly even role-based authorization, as an alternative to the current password->web session or Unix socket permissions-based authentication and/or the per-user permissions in its own database?
Yes, to all of that. A future possibility as well is splicing into the radio circuits of an existing camera with a daugtherboard running openziti SDK, so the cam <--> Moonfire connection is zero trust as well; or running openziti SDK on an open-firmware cam.
How would you feel about this being an optional feature not included in the main release builds? Sure, that'd be alright. In order to make use of Openziti the user would have to get access to a ziti network (ziti controller + ziti edge router) either via a network provider like Netfoundry; or by spinning up their own network. Since Moonfire philosophy is minimalistic wrt deps and binary size, having ZT as a build option or separate release for those who need it makes sense.
I've got good experiences with using Cloudflare Tunnels, as well as their Access thing. It works. Buut it's kinda sus that it has a couple neat features, that can easily enable Cloudflare (or attackers in their infra) to extract info; and the backend is proprietary. It works and I use it for some non-critical services, but I don't feel good about it.
Same deal with Tailscale, although they're significantly smaller and don't have as much of a stranglehold on global network infra as CF. It's also way more sysadmin oriented. There's thankfully an open implementation of Tailscale's backend, Headscale, but I couldn't get it to work right.
For the technicalities of using Openziti in Rust, I'm not sure. My experience is via the Python SDK, which uses the C SDK under the hood; but there are probably differences between using it in Python or Rust. Pinging @dovholuknf, who has helped me out a lot regarding Python; could you chime in?
Hi!
I'm building a free software project to offer predator alerts and deterrence for farms, using NVR and zero-trust, overlay mesh networking. There aren't any NVR offerings which implement zero-trust principles directly at this time, so in testing I've mostly had to try "bolting on" that capability, using OpenZiti and their tunnelers.
The OpenZiti maintainers suggested on a forum post I made about my project, that embedding OpenZiti using their SDKs would be ideal. OpenZiti has SDKs for embedding zero-trust communication in applications, which is superior to the tunneling approach both in terms of security and usability. They don't have a rust SDK yet, but the C SDK is usable via FFI.
OpenZiti can bootstrap a regular browser session into zero-trust without needing to install anything on the client device, by relying on an OIDC provider. For PWAs like Moonfire, this is nice.
Being written in Rust, Moonfire is a prime candidate for security-minded environments.
I'd like to see integrated support for zero-trust networking in Moonfire, and am prepared to spend ~40 hours on it initially. Is integrated zero-trust via OpenZiti something you'd consider supporting in Moonfire?
*edit: this would touch on https://github.com/scottlamb/moonfire-nvr/issues/27, https://github.com/scottlamb/moonfire-nvr/issues/26, https://github.com/scottlamb/moonfire-nvr/issues/216, https://github.com/scottlamb/moonfire-nvr/issues/154, and https://github.com/scottlamb/moonfire-nvr/issues/133