Connecting sms gateway to local CHT instance

@mozzy

This will be the case in the next major version 4.0. coming later this year.

1 Like

@mozzy - You are correct that the medic-os image on docker hub has not been updated recently. It ships with 3.9.1 However, you can follow these steps to update your instance to 3.13. Assuming your URL is https://192-168-0-103.my.local-ip.co/:

  1. Login as admin
  2. Go to the Admin menu in the upper right hamburger. You should be on https://192-168-0-103.my.local-ip.co/admin/
  3. Click the “Upgrades” link on the left so you’re on https://192-168-0-103.my.local-ip.co/admin/#/upgrade. At the top of the page it should say Version 3.9.1
  4. Find 3.13.0 from Sep 28, 2021 listed below and click the far right button “Install”
  5. Choose “Confirm” to start the upgrade. The upgrade may take some minutes -
  6. Wait for the upgrade to proceed
  7. Click “Reload application” when prompted
  8. It should now say “Version 3.13.0” at the top.

UPDATE - oops - step 3 had the wrong side of the screen - my apologies!

1 Like

@diana ,
i set up a CHT test instance on AWS , and installed some valid certificates .
This works fine on all browsers but the CHT-gateway Andorid app still throws SSL connection failed while the cht android app throws ‘Unable to contact server’

see Chrome validates the certificate

May be you could find these Nginix logs useful

  • error-ssl.log
2022/01/14 08:44:00 [error] 460#0: *7 connect() failed (111: Connection refused) while connecting to upstream, client: 41.210.146.124, server: _, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:5988/", host: "cht.openelis-global.org"
2022/01/14 08:44:00 [error] 460#0: *7 connect() failed (111: Connection refused) while connecting to upstream, client: 41.210.146.124, server: _, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:5988/", host: "cht.openelis-global.org"
2022/01/14 08:44:00 [error] 460#0: *7 open() "/srv/storage/medic-core/nginx/data/html/50x.html" failed (2: No such file or directory), client: 41.210.146.124, server: _, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:5988/", host: "cht.openelis-global.org"
2022/01/14 08:44:00 [error] 460#0: *7 no live upstreams while connecting to upstream, client: 41.210.146.124, server: _, request: "GET /favicon.ico HTTP/1.1", upstream: "http://medic-api/favicon.ico", host: "cht.openelis-global.org", referrer: "https://cht.openelis-global.org/"
2022/01/14 08:44:00 [error] 460#0: *7 open() "/srv/storage/medic-core/nginx/data/html/50x.html" failed (2: No such file or directory), client: 41.210.146.124, server: _, request: "GET /favicon.ico HTTP/1.1", upstream: "http://medic-api/favicon.ico", host: "cht.openelis-global.org", referrer: "https://cht.openelis-global.org/"

The other log files are empty

Thanks for reporting, @mozzy

I tried your host on my mobile device using CHT-Android and I’m getting the same error.
I’m also getting the an error when I try to access the URL on Firefox on my Android device, Chrome works however.

Pasting the whole Java error here for reference:

2022-01-14 14:31:50.430 18284-18398/org.medicmobile.webapp.mobile D/MedicMobile: Exception caught trying to verify url: https://cht.openelis-global.org
    javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
        at com.android.org.conscrypt.SSLUtils.toSSLHandshakeException(SSLUtils.java:363)
        at com.android.org.conscrypt.ConscryptEngine.convertException(ConscryptEngine.java:1134)
        at com.android.org.conscrypt.ConscryptEngine.readPlaintextData(ConscryptEngine.java:1089)
        at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:876)
        at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:747)
        at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:712)
        at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.processDataFromSocket(ConscryptEngineSocket.java:858)
        at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.access$100(ConscryptEngineSocket.java:731)
        at com.android.org.conscrypt.ConscryptEngineSocket.doHandshake(ConscryptEngineSocket.java:241)
        at com.android.org.conscrypt.ConscryptEngineSocket.startHandshake(ConscryptEngineSocket.java:220)
        at com.android.okhttp.internal.io.RealConnection.connectTls(RealConnection.java:196)
        at com.android.okhttp.internal.io.RealConnection.connectSocket(RealConnection.java:153)
        at com.android.okhttp.internal.io.RealConnection.connect(RealConnection.java:116)
        at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:186)
        at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:128)
        at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:97)
        at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:289)
        at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:232)
        at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:465)
        at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:411)
        at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:542)
        at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getResponseCode(DelegatingHttpsURLConnection.java:106)
        at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:30)
        at org.medicmobile.webapp.mobile.SimpleJsonClient2.get(SimpleJsonClient2.java:50)
        at org.medicmobile.webapp.mobile.SimpleJsonClient2.get(SimpleJsonClient2.java:38)
        at org.medicmobile.webapp.mobile.AppUrlVerifier.verify(AppUrlVerifier.java:23)
        at org.medicmobile.webapp.mobile.SettingsDialogActivity$AppUrlVerificationTask.doInBackground(SettingsDialogActivity.java:44)
        at org.medicmobile.webapp.mobile.SettingsDialogActivity$AppUrlVerificationTask.doInBackground(SettingsDialogActivity.java:37)
        at android.os.AsyncTask$3.call(AsyncTask.java:394)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:305)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:920)

Hi @mozzy. I noticed you’ve switched out the certificate on cht.openelis-global.org to be the local-ip.co one:

echo |openssl s_client -connect cht.openelis-global.org:443 | openssl x509 -noout -dates           
depth=2 C = US, O = Internet Security Research Group, CN = ISRG Root X1
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = R3
verify return:1
depth=0 CN = *.my.local-ip.co
verify return:1
DONE
notBefore=Oct 26 07:27:54 2021 GMT
notAfter=Jan 24 07:27:53 2022 GMT

If this is the case, then to remove the TLS errors, you can use https://44-228-97-26.my.local-ip.com as your URL. Note that you should consider this as effectively not having TLS enabled because the private key is intentionally shared.

Otherwise, if you want to go back to the wild card *.openelis-global.org cert issued by InCommon where you had the error - I strongly suspect an issue with your certificate chaining. The Java error that @diana gives me this page discussing the issue, and only #3 " The server configuration is missing an intermediate CA" applies to you as you’re using a valid CA and it isn’t self signed. Another relevant search result was this one, which also points to a chaining issue.

To verify your chain is correct in your container, these are the steps to try:

  1. Get a copy of your wildcard certificate in server.pem, a copy of your intermediate chain cert in chain.pem and a copy of your private key in server.key
  2. Add the server and chain .pem to the same file: cat server.pem chain.pem > default.crt
  3. Copy the newly created .crt into your medic-os container to /srv/settings/medic-core/nginx/private/default.crt
  4. Copy the private .key to /srv/settings/medic-core/nginx/private/default.key
  5. Restart nginx with: docker exec -it medic-os /boot/svc-restart medic-core nginx

Let us know if that fixes the issue!

CC @craig

1 Like

Thanks @mrjones .

Yeah. i did that as a quick work round for the mean time ,as i was trying to debug why my certs fail to validate on Android.
so temporalily we use https://44-228-97-26.my.local-ip.co/ and it works fine .

Let me try out the steps above and let you know.

1 Like

@mrjones ,
Thats true , when i install back the *. openelis-global.org cert and i try to verify it
i get

depth=0 C = US, postalCode = 98195, ST = Washington, L = Seattle, street = 4545 15th Ave NE, O = University of Washington, OU = UW-IT, CN = *.openelis-global.org
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 C = US, postalCode = 98195, ST = Washington, L = Seattle, street = 4545 15th Ave NE, O = University of Washington, OU = UW-IT, CN = *.openelis-global.org
verify error:num=21:unable to verify the first certificate
verify return:1

meaning OPenSSL was unable to verify the certificate’s issuer or the topmost certificate of a provided chain

@mozzy - Thanks for the update and the confirmation that the error is in the chain. Did you double check that you you added the intermediate cert before copying the default.crt file to the container? Is there another nginix, or any other web server, with this *.openelis-global.org cert that you can compare against?

As well, since this is a server with access to the internet and a DNS entry, you may want to set up Let’s Encrypt certificates for just cht.openelis-global.org - this would bypass any issues you have with the InCommon CA wildcard cert.

hello @diana

Am trying to integrate rapidpro with cht however am getting

{
    "code": 400,
    "error": "Message was not saved"
}

Hi @cliff

Please share API logs to see more details about what is going on.
Alternatively, please share the contents of your POST body.

thanks @diana

{
    "content":"cht","from":"+256783243994","id":"355fce73-2ce1-428d-aa9a-8123f7eac886"
}

though it keeps on hanging when sending the request

i have also upgraded my CHT instance

Hi @cliff
Could you have a look at API logs to see if there are any errors logged?

1 Like

I had forgoten to reply back , adding the intermediate certs to the certificate solved the issues. Our testing server https://cht.openelis-global.org/ now works fine wtih the Android App

Great news - thanks for sharing the update @mozzy !

hello @diana

Am attempting to connect to CHT using the webhook in rapidpro
however the posting works fine via postman

But when i try via the simulator i get a failure


Am using

> @(json(object(
>   "id":"1f0c6157-1747-44a1-8138-c26ad3d82e20",
>   "from":"+256 783 243991",
>   "content":"hello cliff"
> )))

Hi @cliff

Instances that use the local-ip.co reverse proxy are only accessible in your local network, it’s expected for the textit RapidPro server to not be able to access it.
To make your local instance accessible outside of your local network, you’d need to use a service like ngrok.

1 Like

hello @diana
i have hosted the CHT Instance on ngrok https://255a-41-210-159-84.ngrok.io/#/messages/contact:89a7aa7c-4240-4016-8982-36e23e26fd1c as you recommended above … When i POST to CHT from rapidpro i get {"code":400,"error":"Message was not saved"}

this is coming from cht-core/api/src/controllers/rapidpro.js at 8f328d40b21dd95a6f24606e19c607c75e8dc41d · medic/cht-core · GitHub though not sure why the message is not being saved

Hi @cliff

Can you please check API logs to see if any errors are logged?
From the screenshot you shared, it’s concerning that the content-length header is 0.
I also see an error in the background about invalid json.

1 Like

A post was split to a new topic: CHT Android gives “Unable to contact server" Error