VPN tunnel for apps
-
Still sifting through our 5.6 release bucket list, so I am trying to wrap my head around this a bit.
@Lonk IIUC, the feature requested here is to pipe the network traffic of some apps via a VPN connection. I love the idea! I can see use cases like the ttrss one but also for any of the "pulling" apps like emby metadata download, torrent, searx, scapers etc.
I think this involves two steps (which you already figured). Step 1 is to package the openvpn client app for Cloudron. I think you only need
net_admin
for this but we can easily add new caps depending on what is needed.Step 2 is to then have some configuration to let apps use this container as the networking layer. If you ignore the UI/UX, this is really just a one-line change: https://git.cloudron.io/cloudron/box/-/blob/master/src/docker.js#L311 will be changed to the VPN client app's container. If we had a way to identify vpn clients, we can just have a dropdown of vpn clients as the available 'networks' in the app's configuration UI. And that should be it.
(I hope I understand your requirements correctly.)
-
@girish You understand the use case perfectly, Iâm genuinely grateful you took the time to read and understand my posts on this thread (I know they were long). ď¸ Iâm actually almost done with Step 1. Using the
net_admin
capability was key so I should be finished with that tonight. Step 2 would be a slight change in Cloudronâs manifest so as to identify an app as a ânetwork clientâ and then you could easily have a drop down at the app in Cloudron to list all other Cloudron apps flagged as a ânetwork clientâ (of which the OpenVPN Client Iâm making would be the first) to choose from. The Cloudron app switching itâs network connection would need to be restarted for the change to take effect I believe (but am not on that).Again, Iâm kind of blown away by you guys being so engaging with us (your users) so if thereâs anything else I can do aside from finishing building my fork of the VPN Client for Cloudron, let me know!
-
@Lonk Thanks for the encouragement and let us know if you need help finishing up the client part.
Do you know how docker behaves when it comes to routing? There is a
docker network attach
that lets us attach the container to multiple networks. This is required on Cloudron because the addons like databases are in a network namedcloudron
. With your app, we will attach the app to the vpn client andcloudron
network. I wonder how we can "route" all internet traffic via the vpn client. I can't find any obvious docs for this. -
I think automatically detecting and proposing "network providers" apps in a dropdown would not be very easy... Plus, I think a lot of other apps would benefit from "providing" services to other apps, like a minio instance could provide object storage for other apps.
But this is a big undertaking in my opinion.
In the meantime, simply providing an UI to add custom docker options manually would do the job I think. It would not be as easy to use, but with a little bit of doc it should be doable even for someone who doesn't know docker inside and out. Plus, it would obviously allow a lot of other customizations.
-
I think maybe adding fields to manifest etc to identify network client might be an overkill right now. What I was thinking is just to have an API to set an existing app id as the container's network. This is easy for the backend to do, we have to simply issue
docker network attach
. For the frontend dropdown, it can simply filter out network providers based on the manifest appstore id for now (hardcoded to openvpn client). Should be fine.But I think the bigger thing to be figured out is how the routing works.
-
@girish Would
docker connect
work better in this regard? And also, I agree with the hardcoded dropdown to "openvpn-client" (manifest appstore id).This is how I do it locally with just Docker:
docker run -it --cap-add=NET_ADMIN --device /dev/net/tun --dns 8.8.8.8 --name openvpn-client -e "CONNECTION_TIMEOUT=-1" -p 3000:3000 lonk/openvpn-client:latest
That starts the OpenVPN Client Docker and connects it to vpn.conf (a hardcoded VPN server). I set the DNS because the VPN can't seem to get the DNS otherwise for some reason, and I set the port because the other container needs that port to be open.
So then I connect my next Docker container to the VPN Client container at runtime:
docker run --name chrome -"CONNECTION_TIMEOUT=-1" --net=container:openvpn-client viridiancloud/chrome:latest
This works perfectly locally, the
chrome
container runs everything through the VPN if I pass the--net=container:openvpn-client
on runtime. I'm trying to get thepuppeteer
container to use thenetwork
of theopenvpn-client
while it's still running now. Experimenting withdocker network connect
now on my localhost.I may need to create a network somehow and assign the OpenVPN Client Docker to that. Looking into it now so we can further understand how to get this working in the cloudron network context (or in addition to it since containers can connect to multiple networks at once).
-
@Lonk said in Better documentation for the API:
Would docker connect work better in this regard
Is this a new command? Atleast, I don't have this in my docker 19.03.12.
$ docker connect docker: 'connect' is not a docker command. See 'docker --help'
edit: don't mind me, I guess they are just typos.
docker network connect
anddocker network attach
, I guess. I wasn't aware of this connect subcommand.edit2: there is no,
docker network attach
I meantdocker network connect
all the time. -
@girish said in VPN tunnel for apps:
there is no, docker network attach I meant docker network connect all the time.
Okay, that makes a lot of sense, when you mentioned the "network" attach command, I figured I had some reading up to do.
I edited my post to fix my typo and remove mentions of "docker attach".
-
@girish I have finished converting the app into a Cloudron app and have pushed it to the Docker Hub, there appears to be one issue with these two lines in the
start.sh
file:mkdir -p /dev/net
[[ -c /dev/net/tun ]] || mknod -m 0666 /dev/net/tun c 10 200
There seems to be an issue with this part of the starting script. Likely related to this
docker run
argument that I run locally--device /dev/net/tun
. This is the exact error I get when attempting to run it on Cloudron (despite it successfully running locally with strictly Docker).ERROR: Cannot ioctl TUNSETIFF tun: Operation not permitted (errno=1)
What do you think on the Cloudron side of things there?
-
@Lonk Note: I submitted the DockerHub link for you here (https://www.cloudron.io/app-developer.html) to pull and test yourself locally via
docker run -it --cap-add=NET_ADMIN --device /dev/net/tun --dns 8.8.8.8 image/name
(which will succeed, just trycurl icanhazip.com
in the Docker container and it will see a different IP address). Then check the logs on cloudron when trying to install to it and you'll see the issues with/net/tun
that don't exist locally. -
@Lonk Have you pushed the package source code somewhere?
-
For the tun device stuff, @mehdi solved it by creating the device in Dockerfile - https://git.cloudron.io/cloudron/openvpn-app/-/blob/master/Dockerfile#L30 (
RUN mknod /app/code/net-tun c 10 200
) and then usingdev-node /app/code/net-tun
option in openvpn.conf -
It's quite a long time ago now that I wrote the openvpn-server app, but I remember that this ton device stuff was hell (Plus, Cloudron did not have support for capabilities like NET_ADMIN back then, so I had to implement that in the server itself^^)
@Lonk in your command line, you forward the host's
/dev/net/tun
device to the container, which cloudron does not do, so the problem probably comes from there.If @girish's suggestion of using the same trick as the openvpn-server app does not work, I'd be happy to take a look.
-
I worked on this for a few more hours tonight and after editing the starting script and DOCKERFILE (and a dumb mess up with CloudronManifest.json), I now have it 100% working within Cloudron.
Thank you so much for your help @girish / @mehdi!
There's a bunch of polish now that needs to be made. Proper healthcheck since this doesn't have a web admin exposed yet. I'll be making a custom web admin to change out VPN files (.ovpn) and credentials to make this a proper web app for Cloudron. For now, I'm just going to fake the healthcheck in testing just to see if we can connect containers using @girish Cloudron's code edit idea to make another container use my OpenVPN Client's Container's Network (akin to
docker run
's--net=container:vpn-client
command).PS. @girish, I haven't published the code on Github yet because I've hardcoded my home's VPN credentials in there since this is just a proof of concept. I gave you guy's the DockerHub link through this form: https://www.cloudron.io/app-developer.html - so that only you guys would know the link to
pull
it to Cloudron. Once I make the VPN configurable, I'll be releasing the source. I'll fix the health check in the morning with v0.3. Until then, feel free to pull the image to Cloudron to install for your own testing purposes (the idea you had to make it connect to other Cloudron apps). If you don't have time to, or are unable, I can take a stab at editing the Cloudron code directly. Let me know! ď¸ -
Alright, v0.3 release notes:
⢠Uses
cloudron:2.0
base image now.
⢠Added apache to start the process of configuring a web interface (it'll need to do a few things like adddev-node /app/code/net-tun
to the openvpn-server.ovpn files and convert them into vpn.conf files (which is stored inapp/data
so it's persistent and can change at anytime through an API endpoint I'm going to write...for now, you can change the file yourself and add it in the Cloudron File Manager and then restart the app).
⢠Fixed thehealthcheck
so that Cloudron now runs it as a full fledged appThis is at the point where I'm ready to upload it to Github tonight and I'll post the link. I just need to revoke my personal OVPN Server certificate first before I do that and I have some more testing when it comes to the web interface and modifying files.
@girish Do you have any questions from me in order to make your side of things (Cloudron's base code) connect to this container's network to other apps on Cloudron? Were you able to find and pull my testing image from the DockerHub through the form I submitted - which I did get a response, as I'm now in the contributor program and I'm happy to be because developing with Cloudron is just getting more and more fun. I have some ideas for Wordpress which is where my real expertise is. I'll finish this project and then move onto that after you guys release 6.0 (since I know it's coming with Wordpress changes).
-
@Lonk Thanks! It might be easier for me to test with the package source. On Cloudron, you will need the manifest file to install and not just the docker image anyway.
I am happy to look into the Cloudron side of things whenever the package is semi-ready. Thanks for all the work!
-
@girish My DockerHub link you can pull to Cloudron and install comes with the Cloudron manifest So, rn, itâs working perfectly as an app in Cloudron now, fully operational (just doesnât have a web interface to change the OVPN file yet but contains everything you need to test it, directly connects to my homes VPN until I revoke the cert which I didnât want to do until you were done testing). Iâll post the source on GitLab today minus the hardcoded
.ovpn
file. But can I send you that specific file personally so you can use it for testing. You just place it in the/app/data
folder and restart the OpenVPN Client app and your IP for that container will magically change. So you can then test connecting another app to it network-wise (a la a cloudron eqivalent todocker run
's--net=container:vpn-client
runtime argument) and thencurl icanhazip.com
the âconnected-to-the-vpn-clientâ app to see if it gets the same IP address as the OpenVPN Client Cloudron app.Does all of that make sense?
-
@girish I removed the pre-configured
.ovpn
file that is in the DockerHub version of 0.3 and added the full source code to Github. I tried adding it to Cloudron's Gitlab but it didn't let me create a repository for some reason so I just used Github.https://github.com/lonkle/openvpn-client-cloudron
If you need my preconfigured
.ovpn
file for testing instead of creating your own (you can add your converted.ovpn
file and rename it tovpn.conf
to the root directory before you install or after the install with the Cloudron File Manager, but if you do that you have to restart the app for it to take effect), then let me know so I can send it to you privately. I'll revoke my pre-configured one when you're done testing if you want to go that route (pun intended ). -
Goals for v0.5.0:
⢠Add an HTTP API endpoint to change and convert any
.ovpn
file a user supplies viaPOST
into the container and disconnect from current to connect to the newly added.ovpn
Goals for v1.0.0 (I'd consider it ready to upload to the official Cloudron Appstore at this point):
⢠Add a full web interface at the base URL of the app which uses the API endpoint in v0.5 to allow a user to submit any
.ovpn
file and convert it to what Cloudron needs to straight from a web interface (so they don't have to use the API or manually add it in the terminal / file manager, which would be confusing to new users using Cloudron).@girish Neither of these final features will be needed for you to do your testing whenever you'd like to connect one or multiple containers networks to the the "OpenVPN Client v0.3" app's network. So let me know a good way to send you my preconfigured
vpn.conf
file for you to use to test the feature. In the end, the API backend will automatically convert any.ovpn
files supplied by a user via the API or web interface into a format Cloudron needs; mine is just pre-configured for ya so you don't have to make your own just to test networking between the containers. -
@p44 I built the OpenVPN Client you can use to change your IP for your app. @girish offered to add a custom feature to Cloudron specifically to allow Cloudron apps to
network connect
to my OpenVPN Client app. So, not much longer now! I might try to dive into the network code myself but I'll admit, Cloudron's base code intimidates me.