medic / cht-core

The CHT Core Framework makes it faster to build responsive, offline-first digital health apps that equip health workers to provide better care in their communities. It is a central resource of the Community Health Toolkit.
https://communityhealthtoolkit.org
GNU Affero General Public License v3.0
441 stars 211 forks source link

Inability to remotely access a running Medic Mobile Instance with #6884

Closed andrineM closed 3 years ago

andrineM commented 3 years ago

We currently have installed the docker Instance on a local facilities but encountered some setbacks.

NB: The facilities do not have public ip addresses neither do they have a registered domains for acquiring needed to a a valid SSL Certificate. The machine from where we are running the Medic mobile are stand alone desktop with static ip addresses. When deploying the app we used the ports mappings as below: ports:

  1. The app on the Play Store cannot access the Server via https://ServerIP:7200 port-It brings the error-Invalid server address, it only allows accesses if I use http://ServerIP:5988.
  2. On the phone (with the server URL as http://ServerIP:5988), it does not allow users to log in, even the admin medic account, it just reverts back to login page:
  3. All phones available on site are on Android 8.* & above up to Ver.11 This would mean one has to be in the office to access it, via a Firefox browser, since the app option which will allow offline mode does not work – users cannot log in. Below is ther error on the mobile device. image

Am attaching the docker compose file in use. docker-compose.docx

Hareet commented 3 years ago

Hi @andrineM !

You have an interesting setup scenario. Thanks for setting it up.

For desktop users, you can bypass the SSL warning at https://ServerAddress:7200 by typing in thisisunsafe at the warning page using Chrome. Android users won't be able to use this workaround. Unfortunately, this effects most of your questions.

If you can obtain a public IP address, there is a way of using a Free DNS provider and Free SSL certs to secure the application. We would recommend registering a subdomain with duckdns.org and generating an SSL cert with letsencrypt.org.

Since it's an internal private network (192.168..), with no public access, I don't think we can use ngrok here either. @mrjones-plip Any ideas here?

mrjones-plip commented 3 years ago

Hey @andrineM ! Happy to help if I can - thanks for tagging me @Hareet.

I didn't catch if this is a production or development instance. If it's a development instance, we recommend using either a tool like ngrok or pagekite to expose your instance to the internet. These services give you a public URL which does SSL termination. These are ephemeral though - the external URL to access the instance will change.

We've also JUST published a guide I wrote about a self hosted solution to share your dev instance. This would give you a persistent URL and SSL termination, but does have a possibly harder and more expensive requirement of a publicly accessible linux server.

If you did go the self hosted solution route, and you wanted to make this more production-like, you could set up a persistent SSH tunnel using something like autossh. That said, there are a TON of ways to solve this "expose an internal host to the internet in a production way" problem. Wireguard is another solution that comes to mind. This, again, is still dependent on an external linux server.

As an aside, I believe you could simplify the demands on your users by mapping external docker host port 443 to internal port 5988. This would allow https://ServerIP to Just Work™, no explicit port needed. @Hareet - keep me honest though: Maybe the docker set up we tell people deploy has the HA Proxy running on 443 which is already pointing at CHT's 5988 port internally?

Any which way you go, keep us posted. We'd love to help, improve our docs and empower our self hosting users!

andrineM commented 3 years ago

Thanks all so much for the response. Just to clarify that the setup is for use in production with multiple users accessing mostly in offline mode. Again the setup is to be replicated in multiple isolated facilities (over 1,000). By isolated meaning each facility has an independent setup. Users on the ground are to access the setup that is in their facility.

makombe commented 3 years ago

We are supporting facility based setups with just LAN addresses. Getting SSL certificates for such is not possible (at least from our research) and we are looking at having a setup that can work with just HTTP. This way, any workstation within the facility is able to reach the CHT server through a local address for first time access, and have CHT setup on the browser even for offline data capture. We also look to support the use of mobile devices outside of the facility and this should also connect to the CHT server for first time access, and subsequently use the devices in offline mode

garethbowen commented 3 years ago

Hi @makombe and @andrineM - This sounds like a really exciting project! Do you have any more information I can read about what's being planned?

Having a local server replicate the data from the primary installation is something we've given quite a lot of thought to. There are some potential challenges to this approach.

  1. There are certain actions in API and Sentinel services that should be only performed once per dataset and with this concept they will be executed on every facility device. This will cause performance issues and Document Update Conflicts in the database. We have this issue tracking an idea for "secondary" or "satellite" servers which would work to resolve this problem.
  2. If the power goes out at a facility then the secondary server will be unavailable. This can be made more resilient with a UPS system for the server and WiFi router so phones will still have access. Another possibility is implementing a feature in CHT so the devices can fall back to replicating directly to the cloud server if the local server is unavailable.
  3. Securing the 1000s of secondary servers is a difficult challenge. To protect the health information stored in couchdb each server would need to be stored in a locked room with an encrypted device which is operationally very difficult to implement.
  4. Offline storage requires an HTTPS connection so to use the devices in offline mode you'll need to solve the certificate challenge. This is a browser limitation and not something we can easily get around. This could be solved with a self-signed certificate which is manually added to each device, or perhaps a wildcard certificate so each facility can have its own subdomain.
andrineM commented 3 years ago

Thanks @garethbowen for this detailed response. Its all getting clear on the root cause of some of the issues we are experiencing. Just to clarify. In our case we are only having one installation per facility. This holds data for that facility and doesn't link to a primary server. In our case each facility manages the data independently. Users are intended to access the setup installed at their facility r via mobile devices. Kindly expound on point number one, does the Document Update Conflict occur when several facility devices are simultaneously syncing data?

garethbowen commented 3 years ago

@andrineM Thanks for clarifying - I misinterpreted one of your comments and thought the data was going to be replicated centrally. You can ignore point number one - that only occurs when two or more server instances are replicating to each other. I think the other points 2-4 remain relevant.

ojwanganto commented 3 years ago

Thanks @garethbowen for the detailed explanation. Just to give you a brief description of the project.

  1. We implement KenyaEMR, a flavor of OpenMRS, and is mainly used to support the provision of care in HIV clinics. As @andrineM had pointed out, every facility manages their instance of KenyaEMR at the facility with a bunch of workstations to access the EMR through the LAN.
  2. Most facility servers are not connected to the internet, and accessing the EMR is solely through the LAN
  3. We have been exploring CHT to support HIV testing services, a feature that requires providers to go to the community and test/follow-up clients in the community. Providers are required to synchronize data once they get to the facilty and connect their devices to the facility LAN. We have developed a data exchange module between CHT and KenyaEMR and this works as intended. This work was originally used in the integration of CHT and KenyaEMR for COVID-19 tracking in Kenya.

I hope this provides an insight into how we intend to use CHT at the facility level.

Kindly help me understand the following based on your responses above:

  1. Is there a way to generate SSL certificates for LAN addresses? I have researched but I can't seem to get any leads. Any guidance will really be appreciated.
garethbowen commented 3 years ago

Thanks @ojwanganto , that answers a lot of my questions - it sounds like a great project!

I'll hand over to @mrjones-plip to help out with your certificate questions.

ojwanganto commented 3 years ago

Thanks, @garethbowen.

mrjones-plip commented 3 years ago

Yes, @ojwanganto - your project sounds really fascinating! We're all excited to see how it turns out.

Is there a way to generate SSL certificates for LAN addresses? I have researched but I can't seem to get any leads. Any guidance will really be appreciated.

@ojwanganto @andrineM @makombe: Inherently, there is nothing that ties an SSL certificate to a specific IP address. That is, if you generate a certificate on a server with a public IP address, you can use this certificate on any server with any IP address. The one thing that must be true, is that the HTTP request's hostname must match the certificate's common name (CN).

The way we tie an IP to a hostname is, of course, through DNS. There is no rule against having a domain resolve to different IP addresses in different locations. This is called split horizon DNS.

When we take all this in to considerations, one way (of many!) to solve your problem might look like this:

  1. Purchase a certificate for https://your-deployment-site.com . This should expire in 1 year. You will need to prove you own the domain via the domain-validation process.
  2. Taking care to protect the private key, copy the certificate and private key for https://your-deployment-site.com to each of your 1000 locations.
  3. At each location, run a simple DNS server that resolves https://your-deployment-site.com to which ever static, private IP you CHT server is on. While this can be different in each location, there's no reason you can't make these all the same (eg 192.168.1.100) at all locations.
  4. When any client connects to the LAN, either desktop via ethernet or mobile devices via WiFI, have your DHCP server tell network clients to use your local DNS server.
  5. When these clients request https://your-deployment-site.com, your local DNS server will resolve it to the local IP at that physical location (again eg 192.168.1.100).
  6. Given the HTTP request's host matches the CN in the certification, the https:// connection will be valid and enabled

This will allow the same SSL certificate exist in many locations and be used by many web servers. You could also use a wildcard cert to enable each location to have a different name. This might come in handy if you ever expect a device from location A to keep from syncing when at location B (eg https;//locaitonA.your-deployment-site.com vs https;//locaitonB.your-deployment-site.com)

Note - 1 year is the longest a cert may exist and this may get shorter! We strongly recommend designing an automated process to keep your 1000 locations updated.

You're likely already working on a prototype to prove this can all work in a custom, non automated way offline. For the local, offline DNS server, something like Pi-Hole or dnsgui (vs a more heavy solution) with a GUI can be used to create your custom domain entry on the offline LAN. You will need a public DNS entry to create the cert so, as @Hareet suggested, you can use Duck DNS. If you don't have a public server to point your DNS entry to, I recommend provisioning a cheap $5 USD/month server and using a Let's Encrypt free certificate, also as @Hareet suggested. I see Digital Ocean also offers free DNS if you're paying for something like a droplet already.

Once Let's Encrypt generates the certificate and private key, you can copy this down to your offline LAN CHT test server. With your offline DNS server in place resolving your test domain to a local IP on the LAN where CHT is installed, it should work!

andrineM commented 3 years ago

@mrjones-plip Thanks for the response. Please allow me to give more input on this. We did purchase a wild certificate and experimented the use of the same at our facilities by changing HTTP request's hostname to must match the certificate's common name (CN). The result of this was that the app could only be accessed on older versions of browser but still not be accessed on more recent browsers and devices running on android 8 and above. Most of our clients have the devices on android 8 and above.

mrjones-plip commented 3 years ago

@andrineM - Ah - thanks for the details. Congratulations on getting the wildcard certificate and setting up a test for it - that's great! This means you solved the DNS problem as well so that the hostname matches the CN, as you said.

It's hard to say exactly why the different devices don't work, but I have some theories:

  1. You have a CN/hostname mismatch that some clients don't like. Some tools that are helpufl test are curl and openssl. See this post and this post respectively with some examples.
  2. You're using a sub-sub-domain. Not likely, but be sure you using just subdomain (*.domain.com). You can't use a sub-subdomain ( *.*.domain.com) with a wildcard certificate.
  3. You don't have the full certificate chain set up correctly. Often certifcates come with 3 files: the public certificate, the private key and the intermediate certificate. In nginx for example, they specify you need cat them together. See their documentation about chains.
  4. While most modern CA's will give you a widely compatible certificate, you may have one that does not work with all devices. This SE post has some good info on this.

Can you provide your environment details? This may help debug in case anything stands out as problematic:

andrineM commented 3 years ago

@mrjones-plip

Please see below the responses. Server OS where CHT is hosted? ubuntu 16.04 Desktop browser versions? Tested on chrome, firefox and safari Android versions? version 10 CA provider where you bought the certificate from? Godaddy DNS server for the local, offline resolution? Facilities run on a LAN on static ip. We mapped the local ip to resolve to the the certificate's common name (CN). LAN Network address range? _192.168.x.x__** Anything else you feel would be helpful ;) Curl of the endpoint remotely on a different machine within the network worked fine. As well as access the the Application via Mozilla Firefox browser (remote machine). However access of the application on mobile was unsuccessful as well as accessing via the phone browsers. A similar setup with same certificate installed and public ip/domain name works as expected.

mrjones-plip commented 3 years ago

@andrineM - thanks so much for all the details. That all looks good except one point: CHT does not work in Safari.

The remote users cannot log in to the web access, {"error":"forbidden","reason":Insufficient privileges"} is the error when we try the created users (Per your first comment)

I'm so sorry! I overlooked this detail! This is a bug in CHT that causes this and there's an easy work around. This is caused when you're logged in as an admin, you logout, and then try to login as a normal user. The fix is after you log out as an admin, go to https://yourserver.com/medic/login. See the ticket for more info.

A similar setup with same certificate installed and public ip/domain name works as expected.

This is great news! That means you just need to figure out the difference between the public set up and your offline set up.

Some general tips that might be helpful:

chesterosoronyas commented 3 years ago

Kindly note we used pihole as the dns server and this is what we found out:

Challenges -One has to configure the hosts in both machines in order to access the domain name on the browser -One cannot access the domain name in the mobile phone within the same network since it issues Error of resolving the domain name

mrjones-plip commented 3 years ago

@chesterosoronyas - Thanks very much for the update!

It sounds like you're close! Because you're needing to update the /etc/hosts file, it sounds like the issue is that your LAN clients are not seeing the Pi-hole DNS server or that the Pi-hole is not working correctly. I would:

If you get DHCP set up correct, confirm all this with dig, you should not only be able to remove all /etc/hosts entries, but all devices on the LAN, including phones, should just work with no further configuration.

NB - be sure to remove /etc/hosts entries! These can override DNS settings and cause a lot of confusion when configuring DNS.

antonykhaemba commented 3 years ago

@mrjones-plip, @Hareet and @nomulex Is there any walkaround for this concern raised by @chesterosoronyas

I have a concern since this require one to access the router configuration and make changes on the DHCP/DNS settings. My concern is what about a scenario where the internet connection is based on use of modem or one does not have any access to any router configuration in the network how will you enable the server accessible in such scenarios

cc @derickl

mrjones-plip commented 3 years ago

@antonykhaemba - thanks for passing along the @chesterosoronyas's concerns!

Generally speaking, an ideal situation would be where every deployment is identical in its configuration and hardware. This would make trouble shooting easier as you could document the single way every site is configured and anyone with the documentation could know how it works. This would include how you resolve DNS at each location. This is good to keep in mind while we work to resolve this!

However, the real world often isn't an ideal situation, so let me try and address your concerns:

My concern is what about a scenario where the internet connection is based on use of modem

I'm not quite sure what this means. Maybe it means that the there is no router such that the cable or DSL modem from the ISP in the facility is directly connected to only one computer?

If this one computer is the ubuntu box with your CHT instance on it, you need to figure a way to get other devices to talk to the CHT instance. That might look like:

If the CHT server is not directly connected to the modem, the solution below may work.

or one does not have any access to any router configuration in the network how will you enable the server accessible in such scenarios

Pi-Hole actually comes with it's own DHCP server. Given you said you had a computer running Pi-hole already, one solution might be to turn off the DHCP server on the router and turn it on Pi-hole. The Pi-Hole DHCP server will of course tell clients to use Pi-Hole for DNS.

However, turning off the DHCP server on the router does mean you're actually making a change to the router configuration. You said you you might not have any access to the router configuration. Another solution, which does mean re-using hardware or possibly purchasing new hardware, would be to set up a new LAN that has:

To reduce the need to purchase or gather additional hardware, you could actually run Pi-Hole in another docker container on the same Ubuntu box where the CHT is running. To further minimize the extra hardware needed, you could even run the WiFi access point on the CHT instance as well, using built in features to 16.04.

This last solution could done intentionally at every location to standardize your deployment where the CHT server has as much of the software all in one place (docker, CHT, Pi-Hole, and WiFI AP).

mrjones-plip commented 3 years ago

@andrineM @ojwanganto @makombe @chesterosoronyas @andrineM @antonykhaemba @garethbowen @SMurithi - Per our call yesterday, I've created a new ticket to document how to deploy the CHT server offline. Can you please review it to ensure it captures all of your requirements?

Once we have confirmed it has everything needed, we'll work to prioritize this to publish updated document on our site.

mrjones-plip commented 3 years ago

I see there's now a forum post where @andrineM is commenting, but also a new docs ticket. I'm going to close both this ticket and the docs ticket so we can focus giving help in the forum.