VPN tunnel for apps
-
@robi That's a great idea. I've thought about it before, and I'm 99% sure it would work...I just can't wrap my head around it (it's roughly what I meant in my last post when I said " I'd still need to manually proxy their exposed port to their app.httpPort...somehow").
Tbh, I think I burnt myself out because I know you're right. I mean, putting another nginx reverse proxy behind the randomized
app.httpPort
(say 32344) toproxy_pass
to an exposed port (say 8080) would so work. My brain is just having trouble processing the concept rn (as in, where I'd need to put that code since I think it would still have to be created at thebox
level). -
So, your idea is my next attempt at making the OpenVPN client universal.
Oh, and I need to find a way to make Cloudron expose all of OpenVPN Client's internal ports. Or at least the common ones - because the second app inherits the exposed ports of OpenVPN Client app (so the two apps would need to match up their exposed ports somehow, and a wildcard, open all ports on the OpenVPN Client's side seems like the only way to do so).
-
@Lonk said in VPN tunnel for apps:
@robi That's a great idea. I've thought about it before, and I'm 99% sure it would work...I just can't wrap my head around it.
Take a break. Please A nap, walk, anything.
@Lonk said in VPN tunnel for apps:
So, your idea is my next attempt at making the OpenVPN client universal.
Right on!
Oh, and I need to find a way to make Cloudron expose all of OpenVPN Client's internal ports.
That means Nginx goes into the OpenVPN container, no?
Rules for reverse-proxying are something along the lines of:
if coming from internal IPs, do X
if coming from cloudron IP, do Y
if coming from elsewhere, do Z to the App. -
@robi said in VPN tunnel for apps:
That means Nginx goes into the OpenVPN container, no?
Rules for reverse-proxying are something along the lines of:
if coming from internal IPs, do X
if coming from cloudron IP, do Y
if coming from elsewhere, do Z to the App.I'm new to nginx, literally only using it's .conf files to try to get this working as a mere proof of concept. But so far I'm only familiar with
proxy_pass
for it taking incoming 80, 443 ports to pass it to the internal Docker port (and IP...I think but I don't *think this is an IP issue, though it might be). -
@robi But if I wanted to expose all of it's ports, it would actually be more of a
box
docker.js
thing with the "exposed ports" parameter being fed togContainer.createContainer
. I should be able to do that after I give my mind a lil break. -
Okay, after hardcode exposing ALL internal ports of the OpenVPN container, now the last thing is adding a second nginx reverse proxy which would mean this:
My exposedPort for the Gucamole app I'm installing to connect to the OpenVPN Client app exposes 8080. It gets a Docker internal
httpPort
of 32455. Nginx already correctly creates a nginx proxy config from web incoming port 80 and 443 to 32455 (somehow, presumably DNS TXT records, it even gets an SSL cert).So, I need to have nginx after that continue to proxy it to 8080. Which normally is Docker's job (with it's binding port) but when connecting two container's networks together, it doesn't do that job with the
dockerode
library for some Docker-y reason. I wonder...can I reverse proxy it in the same file as the original reserve proxy server. Or do I have to create a.conf
and an entirely new one? -
If I have the same nginx reverse proxy "listen" to it's own forwarded port (32455), then I could
proxy_pass
again to the real internal port and IP (8080) of Guacomole (the test app I'm now using to connect to the vpn client app)...or maybe I need another reverse proxy residing at Internal-IP-of-Guacomole:32455 to thenproxy_pass
again to 8080. -
The problem there is that the stuff in the container doesn't have access outside the container, so it's hard to drop updates to the host Nginx as another .conf file.
You could tell box to do it via how it already happens for new apps. Must be an API for it.
-
@robi I keep trying to experiment on how to shoehorn a second Ngnix proxy into this to get it all up and running 100% with no success.
Inter-communication between the two containers would be nice, but tbh I could hardcode that if I knew how to setup the second reverse nginx inside of
reverseproxy.js
. Which, honestly, I can't figure out how. -
I know the answer lies here:
https://git.cloudron.io/cloudron/box/-/blob/master/src/reverseproxy.js#L463
I can configure a second file for a second nginx server to proxy
app.httpPort
toapp.manifest.httpPort
- but, like, I don't know how to change that it's hardcoded to listen only on 80 and 443. Plus, I don't know how to actually get this hypothetical second nginx reverse proxy running to "take" the new config within the container that's connecting to the VPN. But that's the last step here on how to make this work. -
@mehdi said in VPN tunnel for apps:
(Disclaimer: I am no expert on docker networking magic)
I think instead of trying to find a way to expose the ports from the OpenVPN container, you should instead try and find a way to make it work directly from the app container itself.
Even if you do make it work for the exposedPort (which, I think, refers to the main web port exposed by the app, the one which is behind the reverse proxy, to expose its web interface and such, that's why there's only one: there's only one web interface), you're gonna have trouble with the extra ports (the ones defined in the manifest here https://docs.cloudron.io/custom-apps/manifest/#tcpports ) for apps that use these.
I really think this. You should try finding a way to make the app container's default route be through the OpenVPN network, but still be connected to cloudron's regular network so it can interact with nginx and stuff. There is no good reason to make all the traffic, even the local one, be through OpenVPN.
@Lonk is there a repo with your box changes ? Maybe I'll have time to take a look this WE
-
@mehdi You only have to change one file (docker.js) so Iβll send that to you today!
But the app has no other issues. It is on the Cloudron network. It has everything network-wise that the OpenVPN container has which means there are no issues anywhere. The only issue is that Nginx doesnβt take that into account because it inherits all network ports and modes from the OVPN Client itβs connected to.
I actually have an idea though to prove that everything works except the web interface using the app terminal.
I will also be sending you my OVPN client in chat so you can see how it works.
-
@mehdi Oh, and just to make it clear, the app is running fine even in the terminal. If I install the LAMP app for instance and connect it to the OpenVPN Client. I can go to LAMP's terminal and type
curl 127.0.0.1:80
and it will give me the LAMP Welcome page, but from the IP address of the OpenVPN Client. It'll just never get past the "Starting..." stage without a 200 response and Nginx is routing it to the wrong location. Maybe I could try hardcoding it to the right port after it installs it's config.Like, this works. But I don't know how to get NGINX to route it to the port I need it to route to. Docker is supposed to
bind
theapp.httpPort
(say 34567) to theexposedPort
(say 80). But that Docker binding command has to be removed to connect the containers so NGINX has to bind them manually somehow and I don't know how to work with Nginx. -
I'm near positive the way to route NGINX properly is to to add another reverse proxy which leads from the Docker randomized
app.http
port to theexposedPort
(AKAapp.manifest.httpPort
). I'm not sure how though. But I can clearly access the exposedPort's data from either terminal.In the terminal of either of the two network-bonded apps (the LAMP or the VPN Client) - I can curl (localhost) the exposed ports of either app (the VPN Client or the LAMP) and get back the correct HTML pages.
It's just that the reverse proxy is forwarding it to a port that Docker wasn't allowed to bind. So with no binding, that means no NGINX web page.
-
For people just joining and for me to read this in the future:
Cloudron has a user-defined network
cloudron
that it uses for all of it's apps and services. I'm connecting my OpenVPN Client app directly to another app (LAMP for testing) usingNetworkMode
which is the official way to do this. When doing so, both apps share the exact same network space (including both being connected to thecloudron
network) and can, in fact, even talk to each other directly (I need to set the OpenVPN Client's exposed port to something ridiculous like in the 50000s so it doesn't conflict with any regular app's commonly exposed ports - but in the end the OpenVPN Client will expose all of it's internal network ports-P
for compatibility with all other apps connecting to it - but for now, this will do since I'm just testing).Now, the NGINX Reverse Proxy resides on the main
box
level of Cloudron and routes to the randomized Docker binding port of the app which forwards it to it's "real" port (I honestly don't know where the IP translation takes place...I can't find it).So, solution, place a second NGINX proxy at the randomized Docker
app.http
port and have that nginx server be inside of the internal network of the LAMP testing app so it can then internally forward the web request to it'sexposedPort
which is, also, port 80 (for LAMP anyway). -
@mehdi said in VPN tunnel for apps:
There is no good reason to make all the traffic, even the local one, be through OpenVPN.
All local traffic is local, it doesn't go through the VPN. All of the connected-to-the-vpn-client apps run indefinitely. Eventually after Cloudron says "Starting..." it switches the message to "Not Responding" but the app will continue indefinitely because there's nothing actually wrong with it. It's connecting to all the local services it needs, it's just, this feature was designed without consideration of Cloudron's network. That's why from within the app's terminal, I can access everything locally and everything externally (the open web) from Cloudron and the web sees my VPN Client's IP Address instead of Cloudrons. This is a perfectly running app. Except...I can't expose it's internal IP:ExposedPort to NGINX to have it actually pass the health check (meaning the web app isn't being routed to the right place and I think I need a second NGINX reverse proxy to get me routed to the app's exposed port). It gets as far as
app.httpPort
and then because there is no binding for theapp.mainfest.httpPort
(AKA:ExposedPort
), it just gets stuck on the web side of things.I can
curl
all I want into it the LAMP welcome. But can't access it from outside the container itself.