VPN tunnel for apps
I still think the solution lies in this function:
But that function is setting NGINX config listening on the server's public IP port. I need NGINX inside of the container to forward to the
app.manifest.httpPort(in LAMP's case it's port 80).
Or maybe it doesn't need to be inside of the container...since if I SSH into the VPS and do
curl ip-address-of-lamp:80then it returns the HTML just fine.
I'm so close. I can manually edit the NGINX configuration of the LAMP-test app and get it's web app working using it's local IP (not 127.0.0.1:
app.httpPort, but 172.18.0.3:80 - the port 80 is what LAMP uses). Both web pages come up for their each individual domain names. WOOOO!
It still doesn't make it past the "starting..." step though. That might be because I'm editing the NGINX file and then restarting the app to make it's web interface work. If the NGINX file was properly created from the beginning the check might pass.
@Lonk said in VPN tunnel for apps:
@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.
Sorry, I meant: There is no good reason to make all the traffic, even the local one, be through the OpenVPN client container.
What you should try to achieve is making only the app's outgoing traffic go through OpenVPN, and the connexion between it and Nginx and stuff stay exactly the same as it currently is
That is currently the case as far as I can tell. All incoming traffic bypasses the VPN entirely. Outgoing traffic uses the VPN's connection. But the NGINX needs an incredibly minor change. There's no way around that.
But the bigger deal is that it works now!
Okay, I know it says not responding but it actually is fully working (web page and everything). The "not responding" status is something I think will fix itself when I get the Nginx IP
proxy_passworking. Because it's sort of a race condition as to when I start the app and when I manually rewrite the Nginx IP. And I'll never go fast enough to beat the "Not responding message".
I just need a function like
getAppByManifestId(manifestID)- and this will be a fully functioning proof of concept. And then another function for
Oh, and I need to change some slight NGINX config, make it more dynamic (Cloudron hardcodes it's
proxy_passto 127.0.0.1 rn and it needs to be dynamic).
You can't getAppByManifestId since there can be many apps for a given manifest id. I think you have to store whatever you want in the database in the apps table. Then when you get the app, you can get that information (like say the network id). Sorry, if my answer is totally off since I didn't read the full thread completely.
@girish I had actually nailed that issue out actually as a matter of fact. The only thing I have left is
getLocalIPAddressByApp(app)- but maybe the
appobject already stores its internal IP (I didn’t think it did, but it stores a lot)?
@girish As for the first function, it was mainly due to me needing to find a way to identify the VPN client app by the only unique identifier I knew. I’ve hardcoded it for my use case rn...but that won’t work for the production version now that I think about it - so I’ll still need to get app data using the manifest.id (com.joelstickney.openvpn-client-cloudron). So when the app that needs to connect to it starts, it attaches to the container ID of the Open VPN client on
Maybe right now I’ll store the things I need in ENV variables and find a way to use the “apps” object to parse through all of them till I find the VPN client.
@girish I think you’re right about using the app table. I’ll try to RE how you use it to populate the
And no worries not following along with this thread. It’s been really difficult for me to get this working so I used this as kind of note-taking. Now that I’m nearly finished, people won’t get as bugged by my posting here every time I discover something new about the way
I guess the proper function name then would be
getAppsByManifestId- the point is to get the possibly multiple VPN Clients installed to populated the drop down box in other app’s configs asking which VPN Client app they would like to share a network with. So this is a needed function and I can parse through the app DB to collect the data.
I found your function to
getIDByIPAddressand I’m basically using it as a reference to write the opposite function now
getIPAddressById. Would you like me to make this a function or would you like me to just put the code in the
NginxAppConfigfunction the singular time I need to use it? It’s needed to make all of this work.
I need you to know of the singular limitation of the VPN Client app though:
• Multiple apps can connect to a singular VPN Client app unless two apps exposed
httpPortsare the same. So you couldn’t connect two of the same app or different apps that use the same web port. I cannot find a way around this except to install a second VPN Client. Which I don’t think is a bad solution given how small my app is. But that will have to be enforced in the drop down box via a new function. I don’t plan on touching dashboard code tho so I’ll leave that up to you. But when you get to that step, tell me and I’ll write you a function to only show you the VPN clients whose connected
app.manifest.httpPortsdon’t conflict with the app being configured in the dashboard to protect users from port conflicts.
@girish (or @nebulon) I'm finished with the OpenVPN Client app, and with the
reverseproxy.jschanges needed to make it work. Right now, it's hardcoded so that if any app being installed with a domain name containing "vpnconnect" it will connect to the OpenVPN Client if there is one (you'd need to change this hardcoded
ifconditional to be the dropdown box value where you choose which VPN Client to connect on the Cloudron Dashboard that @girish suggested - since you can install as many as you want and thus connect as many as you want to them, a dropdown will be needed).
Everything is working perfectly now. But, my code to get the IP Address and the container name of the OpenVPN Client is...not great.
Ideally, on starting the VPN Client app, it would (if I could have figured it out) add it's IP Address and container name somewhere easy for other apps to retrieve those two pieces of data and connect to the client since those are the only two values needed. But instead I changed the
createSubcontainer()function and also when writing the Nginx
writeAppNginxConfig()- I parse the DB for those VPNClient values and get them - but it's messy code. Could I send you those files for you to look over? I don't know another way to write the code - but my original goal was to load
VPNClientContainerNameinto every app object on initialization if an app exists on Cloudron who's
manifest.idincudes "vpnclient". I'm sure that's possible, but I couldn't find where you load the
appobjects values. I could RE some more and find it, but this works so I'm just gonna use it.
So now that this is working with no issues, where should I go from here to:
- Make this an official app on the App Store?
- Work with you guys to make the
boxchanges that are needed to make the app work?
Note: I'm still working on a simple web interface to change the
.ovpnfile rather than having to replace the file in the Cloudron File Manager (the web interface will do it for you). When the file is changed in the web interface, the container / app will restart via a Cloudron API call meaning the user would have to provide their Cloudron token unless there's another way to restart the container from within it (but I plan on just disconnecting and reconnecting to the new file with no container restart - but for an MVP that will work). Right now, you have to change the file in the Cloudron File Manager and restart the app yourself.
Quick Ideas for the web interface I wanted to jot down:
• Easy access to common VPN providers
• Attaching VPN app to other app's from within the app itself (using the Cloudron API)
• Saving previous connections for later use
• Not having to restart itself (the app) every connection change (there's no avoiding needing to restart an app that's connecting to it though, that's a limitation of docker unless
docker network connect --link vpnclientcontainername cloudron container2would work to mitigate this - it did not in my testing but I know more now, I'll test this again at some point).
@Lonk I am not sure changes to the reverse proxy code are required at all. Maybe I didn't get a full grasp of your feature request, so let's take a step back.
The reverse proxy is only for inbound traffic. It's not used for outbound traffic. It's just a demuxer for incoming http requests to the app containers. My understanding of the feature you suggested was that we want say TTRSS, to use the tunnel for outbound traffic like say when fetching RSS feeds. This means that https://reader.domain.com itself still points to Cloudron but any outbound traffic originating from the container goes via this tunnel.
You shouldn't filter by app id etc in docker. Instead, we have to first create a networkId entry in the apps table. Then, app.networkId is then simply the network id to be used in docker.js when creating the container. We don't even have to filter by openvpnclient app etc. The filtering will be done by the dashboard code (i.e in the UI).
I can help out a bit more but I want to first double check if we are in sync about this reverse proxy stuff.