Cloudron makes it easy to run web apps like WordPress, Nextcloud, GitLab on your server. Find out more or install now.


Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Bookmarks
  • Search
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo

Cloudron Forum

Apps | Demo | Docs | Install
  1. Cloudron Forum
  2. Feature Requests
  3. VPN tunnel for apps

VPN tunnel for apps

Scheduled Pinned Locked Moved Feature Requests
openvpnnetworking
137 Posts 9 Posters 39.2k Views 11 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • LonkleL Offline
    LonkleL Offline
    Lonkle
    wrote on last edited by Lonkle
    #103

    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) using NetworkMode which is the official way to do this. When doing so, both apps share the exact same network space (including both being connected to the cloudron 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's exposedPort which is, also, port 80 (for LAMP anyway).

    1 Reply Last reply
    0
    • LonkleL Offline
      LonkleL Offline
      Lonkle
      wrote on last edited by
      #104

      ^^^^ -- Does anyone know how to do this?

      1 Reply Last reply
      0
      • mehdiM mehdi

        @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

        LonkleL Offline
        LonkleL Offline
        Lonkle
        wrote on last edited by Lonkle
        #105

        @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 the app.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.

        mehdiM 1 Reply Last reply
        0
        • LonkleL Offline
          LonkleL Offline
          Lonkle
          wrote on last edited by Lonkle
          #106

          Quick example of all local processes running for the second container:

          Oct 02 12:05:28 2020-10-02 16:05:28,718 INFO success: redis entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
          Oct 02 12:05:28 2020-10-02 16:05:28,719 INFO success: redis-service entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
          Oct 02 12:05:40 [GET] /healthcheck

          It just gets stuck at the health check because NGINX is giving it a 502 Bad Gateway since port 80 is not bound to port app.httpPort. That's what I still need to figure out and I think what's best is @robi's double nginx server suggestion. I just don't know how to set up NGINX inside of the LAMP container from box code though I'm sure it's possible.

          1 Reply Last reply
          0
          • LonkleL Offline
            LonkleL Offline
            Lonkle
            wrote on last edited by Lonkle
            #107

            I still think the solution lies in this function:

            https://git.cloudron.io/cloudron/box/-/blob/master/src/reverseproxy.js#L463

            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:80 then it returns the HTML just fine.

            1 Reply Last reply
            0
            • LonkleL Offline
              LonkleL Offline
              Lonkle
              wrote on last edited by
              #108

              SUCCESS!!!

              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.

              1 Reply Last reply
              0
              • LonkleL Offline
                LonkleL Offline
                Lonkle
                wrote on last edited by
                #109

                Which...now I need to find the function to get the IP address of the VPN container (the app connected to it share's it's IP address).

                1 Reply Last reply
                0
                • LonkleL Lonkle

                  @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 the app.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.

                  mehdiM Offline
                  mehdiM Offline
                  mehdi
                  App Dev
                  wrote on last edited by
                  #110

                  @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.

                  1 Reply Last reply
                  0
                  • mehdiM Offline
                    mehdiM Offline
                    mehdi
                    App Dev
                    wrote on last edited by
                    #111

                    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

                    LonkleL 1 Reply Last reply
                    0
                    • mehdiM mehdi

                      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

                      LonkleL Offline
                      LonkleL Offline
                      Lonkle
                      wrote on last edited by Lonkle
                      #112

                      @mehdi said in VPN tunnel for apps:

                      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.

                      girishG 1 Reply Last reply
                      0
                      • LonkleL Offline
                        LonkleL Offline
                        Lonkle
                        wrote on last edited by Lonkle
                        #113

                        But the bigger deal is that it works now!

                        Screen Shot 2020-10-02 at 6.18.06 PM.png

                        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_pass working. 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". 😂

                        1 Reply Last reply
                        1
                        • LonkleL Offline
                          LonkleL Offline
                          Lonkle
                          wrote on last edited by Lonkle
                          #114

                          I just need a function like getAppByManifestId(manifestID) - and this will be a fully functioning proof of concept. And then another function for getLocalIPAddressByApp(app).

                          Oh, and I need to change some slight NGINX config, make it more dynamic (Cloudron hardcodes it's proxy_pass to 127.0.0.1 rn and it needs to be dynamic).

                          1 Reply Last reply
                          0
                          • LonkleL Offline
                            LonkleL Offline
                            Lonkle
                            wrote on last edited by
                            #115

                            @girish The post above this one, do you know off the top of your head how to get those values?

                            1 Reply Last reply
                            0
                            • girishG Offline
                              girishG Offline
                              girish
                              Staff
                              wrote on last edited by
                              #116

                              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.

                              LonkleL 4 Replies Last reply
                              0
                              • girishG girish

                                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.

                                LonkleL Offline
                                LonkleL Offline
                                Lonkle
                                wrote on last edited by Lonkle
                                #117

                                @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 app object already stores its internal IP (I didn’t think it did, but it stores a lot)?

                                1 Reply Last reply
                                0
                                • girishG girish

                                  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.

                                  LonkleL Offline
                                  LonkleL Offline
                                  Lonkle
                                  wrote on last edited by
                                  #118

                                  @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 containerCreate.

                                  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. 🤔

                                  1 Reply Last reply
                                  0
                                  • girishG girish

                                    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.

                                    LonkleL Offline
                                    LonkleL Offline
                                    Lonkle
                                    wrote on last edited by
                                    #119

                                    @girish I think you’re right about using the app table. I’ll try to RE how you use it to populate the apps variable.

                                    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 box works. 😂

                                    1 Reply Last reply
                                    0
                                    • LonkleL Offline
                                      LonkleL Offline
                                      Lonkle
                                      wrote on last edited by
                                      #120

                                      Oh wait, the container object, would contain the IP and the container ID. I could intercept that right after it’s created. 🧐

                                      1 Reply Last reply
                                      0
                                      • girishG girish

                                        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.

                                        LonkleL Offline
                                        LonkleL Offline
                                        Lonkle
                                        wrote on last edited by Lonkle
                                        #121

                                        @girish said in VPN tunnel for apps:

                                        getAppByManifestId

                                        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 NginxAppConfig function 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 httpPorts are 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.httpPorts don’t conflict with the app being configured in the dashboard to protect users from port conflicts.

                                        1 Reply Last reply
                                        0
                                        • LonkleL Offline
                                          LonkleL Offline
                                          Lonkle
                                          wrote on last edited by Lonkle
                                          #122

                                          @girish (or @nebulon) I'm finished with the OpenVPN Client app, and with the docker.js and reverseproxy.js changes 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 if conditional 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 docker.js - createSubcontainer() function and also when writing the Nginx .conf in reverseproxy.js - 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 VPNClientIPAddress and VPNClientContainerName into every app object on initialization if an app exists on Cloudron who's manifest.id incudes "vpnclient". I'm sure that's possible, but I couldn't find where you load the app objects 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:

                                          1. Make this an official app on the App Store?
                                          2. Work with you guys to make the box changes that are needed to make the app work?
                                          1 Reply Last reply
                                          0
                                          Reply
                                          • Reply as topic
                                          Log in to reply
                                          • Oldest to Newest
                                          • Newest to Oldest
                                          • Most Votes


                                          • Login

                                          • Don't have an account? Register

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • Bookmarks
                                          • Search