tonarino / innernet

A private network system that uses WireGuard under the hood.
https://blog.tonari.no/introducing-innernet
MIT License
5k stars 185 forks source link

Initial GUI - work #179

Open tiphaineruy opened 2 years ago

tiphaineruy commented 2 years ago

Hello !

I've used the project a bit and had some time to dedicate, I've started a proof of concept for a GUI. Not being sure if it's the direction intended for the project to take, I'm checking in with a PR.

INNERNET - GUI

DONE

This PR adds a very crude GUI.

CHANGES

This PR required some medium changes

Screens

Screenshot 2021-12-13 at 03 13 20

Screenshot 2021-12-13 at 02 41 21

TODO

How to test this

You propbably only have to build the binary ( I commited the ui /dist, a lot of people don't want to touch the frontend toolchain) and it should package the UI, then access it at the http://server-endpoint:port/ui/ from an IP on the innernet network ( even non admin peer.)

If you have a dev server on your computer you could just cargo run youInterface and access the endpoint from one of your peed.

nettybun commented 2 years ago

This is a really beautiful UI!

It made me think about some innernet-ecosystem-type questions, maybe better directed at @mcginty, but relevant to this UI PR since it's the first to be putting seeds in the ground 🌱🥇

If innernet wants to (some day) support multiple UI implementations, would embedding a default UI in innernet's binary make this more difficult?

If the Rust backend is configured to statically serve a directory (in addition to the existing REST APIs) then supporting different SPAs may be as easy as overwriting a directory during installation rather than having one baked into the binary.

Something like (totally making this up on the fly):

sudo innernet-server new
# Downloads and unpacks to /var/lib/innernet/ui/
sudo innernet-server install-webserver https://github.com/tiphaineruy/innernet-ui/releases/download/v1.0/index.zip

Not sure what a good default web UI would be - maybe a single index.html page that says "No web UI installed" with installation instructions. @tiphaineruy do you foresee any issues with a installable setup like this; or is having it built-in important for some features to work?

I think this came up for me because I know there will be people who who don't want a web UI, which makes me concerned about the binary size. I haven't built the binary, but looking at the dist/ assets alone it looks like embedding the UI will increase the binary by at least 50%? Is this accurate, and will it change much as the UI development continues? I know it doesn't really matter since space is cheap and it's a server, but for those who aren't using the feature at all, it's a high percentage of the binary that's being unused.

Amazing work and thanks for posting screenshots! :)

tiphaineruy commented 2 years ago

Hmm, lot to unpack

Using the /ui/ embeded

I took this approach for mainly two reasons, 1 - the binary is already exposing a rest api 2 - It kinda what I'm expecting of that kind of library, the ui should be pretty simple, no need asking people to deploy 2 services, see how Hashicorp binaries operate with an http endpoint and the GUI on the /ui/ path.

Issues and mitigations

other

I guess the real question I where @mcginty want to take the library. This being a tool he uses at his workplace. The CIDR approach is what sets it appart from the others in the same domain, eg wiretrustee, tailscale etc... I feel like there is a place for innernet for being the "light" one. Probably by streamlining the ui as much as possible, embeded in the binary, Simplifying the enrollment process with key exchange instead of toml. etc.

Food for thoughts

alerque commented 2 years ago

Not to diminish work on a UI at all (great work on that front, and surely will serve many people well) but I for one am not a fan of web UIs crammed in my service binaries. This is a security and packaging headache.

I would really like to see the default service stay as lean and focused as possible. The Rust can probably be refactored so that there is a common library of functions shared by the interface service, a CLI admin tool, and a web admin tool. The web service should not be in the same binary as other bits though.

I realize there is precedent for this model in a lot of other tools, but I cringe every time I have to deploy or audit one, and it limits the platforms those services can be deployed on.

I already have innernet deployed on super low memory platforms (like 10 year old legacy Raspberry Pi's) where even a few megabytes of filesystem and runtime memory overhead is an issue, as is port management. Keeping the service binary lean is important. I don't need or want a web UI on all endpoints. I probably do want it at least one place that is an admin peer, but not everywhere.

Also having it embeded will greatly complicate builds for Android and other future platforms.

bschwind commented 2 years ago

I'm in agreement that the UI shouldn't be tightly coupled to the server or any of the binaries in particular. Also not a huge fan of the #[ts(export)] and #[derive(TS)] macros in the code. Having language-specific adjustments to struct fields feels a bit off as well. I would expect pretty vanilla Serialize and Deserialize derives on the structs, and the individual clients would adapt their deserialization logic to whatever serde spits out.

In summary, I don't have a perfect solution, but I think moving towards what @alerque suggested is probably the best move:

The Rust can probably be refactored so that there is a common library of functions shared by the interface service a CLI admin tool, and a web admin tool.

Then we can experiment with different frontends in completely separate packages and see what sticks.

tiphaineruy commented 2 years ago

Haha I did not expect this to be that polarizing.

But a lot of those concerns are innacurate.

where even a few megabytes of filesystem and runtime memory overhead is an issue, as is port management

The server's only internet-exposed port is its WireGuard listening port. The juicy HTTP API only listens on its internal IP address. Thus, the attacker would need to 1) find a way on to the WireGuard network by compromising an existing peer, or 2) find a vulnerability with WireGuard itself.

The Rust can probably be refactored so that there is a common library of functions shared by the interface service, a CLI admin tool, and a web admin tool. The web service should not be in the same binary as other bits though.

already have innernet deployed on super low memory platforms (like 10 year old legacy Raspberry Pi's) where even a few megabytes of filesystem and runtime memory overhead is an issue, as is port management

  1. The ui is only embeded in the innernet-server binary. No change to the client "cli" thus NO changes to the peers
  2. this is a static website. meaning there is NO runtime hit on the memory and the fs hit is 0.5mb on top of the 2mb innernet-server binary.
  3. innernet does litteraly zero heavy lifting performance wise, all is done by t wg. The impact of serving a static ui for innernet server is virtually none apart from the +0.5mb bin size.

Also having it embeded will greatly complicate builds for Android and other future platforms.

Again, only embeded in the innernet-server part.

  1. I do not expect people to run innernet-server on android
  2. If they do, embeding the ui in innernet-server is just sugar over the macro
    include_bytes 

    There is no build added complexity for other platform.

Also not a huge fan of the #[ts(export)] and #[derive(TS)] macros in the code. Having language-specific adjustments to struct fields feels a bit off as well

So yeah. I see only two real concerns:

  1. we don't want to couple the front with the binary
  2. we want to experiment with several frontends and see what sticks.

Reminder. The UI is definitely just a poc as is. it's not usable and I was planning for more time to get it to a MVP. Just testing the water with the binary coupling and repo owner.

But again, bottomline: The ball is now rolling, I's probably going to be the maintainer vision of how he wants this tool to be shaped. I'm fine with that.

mcginty commented 2 years ago

I'm so sorry that it took me so long to comment! Polarizing is open source's middle name ;). I'm really excited for all the thought and work you put in to this.

I'm also on the boat of "don't include the frontend in the binary," since I see the server as a minimalistic REST API that clients or frontends can consume, but the server itself is not concerned about - it should be easy and straightforward to package innernet-server without a frontend.

That said, I understand the logic behind not wanting to run a separate HTTP server when there's one already running, so perhaps there's also a middle ground: the server looks in a specific location for static files to serve up, and if they're there, it will serve them at a known URL (/ui for example). That way, package maintainers could opt to include the GUI or not, and those wanting a slimmer install would simply not package it with innernet-server. There would be no major bloat increase in the binary itself.

There are two "fronts" in the GUI realm: making it easier to connect to an innernet (clients), and making it easier to manage the network itself (server). In both cases, I think it makes sense to not include any concept of a GUI in the core binaries, for example with the clients I imagine a GUI project that packages the innernet binary and communicates with it, but the innernet binary itself does not include any graphical code. The parity between both client/server on this philosophy feels cleanest to me, personally.

Thoughts?