Site is secure only on "/", ssl invalidates on inner urls

Hello there,

I’m using Nginx as a proxy for my NodeJS app. When I enter http://staging.app.zulutek.com it is secure. Now the problem is, when this app loads, first action on Angular is to redirect to a path /discoverer. When it redirects the app is not secure anymore - red https sign on Chrome.

I tested the app url via SSLLabs (both ‘/’ and ‘/discoverer’) and everything seems to be working fine.

Inside ‘/discoverer’ and other urls, whatever external resources I’m loading, they’re loaded over HTTPS - some of them are self-signed. No HTTP errors, everything loads just fine.

The resources, which are loaded over self-signed HTTPS, are loaded from a device, REST’ing on an IP.

To test, I disabled every single external request on ‘/discoverer’ , except css files, yet problem still persisted.

How can I debug the problem? Where to look? Has anyone had this kind of problem?

Here is my Nginx config:

upstream app {
        server 127.0.0.1:9090;
}
server {
        listen 80;
        server_name staging.app.zulutek.com;
        access_log /var/log/nginx/app.log;
        add_header Strict-Transport-Security max-age=63072000;
        add_header X-Frame-Options DENY;
        add_header X-Content-Type-Options nosniff;
        location / {
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $http_host;
                proxy_set_header X-NginX-Proxy true;
                proxy_cache_bypass $http_upgrade;
                proxy_pass http://app;
                proxy_redirect off;
        }

        listen 443 ssl; # managed by Certbot
        ssl_certificate /etc/letsencrypt/live/staging.api.zulutek.com/fullchain.pem; # managed by Certbot
        ssl_certificate_key /etc/letsencrypt/live/staging.api.zulutek.com/privkey.pem; # managed by Certbot
        include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot


        if ($scheme != "https") {
                return 301 https://$host$request_uri;
        } # managed by Certbot
}

Thank you very much.

I cannot reproduce this in Chrome. However, I noticed that your site issues a request to https://192.168.42.1:8445/api/. This IP doesn’t exist in my LAN, but if it does in yours and you use a self-signed certificate that’s not trusted by your browser (which I would assume to be the case, since this an IP address in a reserved IP range), I think Chrome would downgrade the connection indicator to “insecure” because of that.

I’m not sure about your use-case, but you’d probably want to use a domain name and a publicly-trusted certificate for that resource.

Thanks for the reply Patrick.

Yes, that resource is in that device I talked about. It should be in the
same network as you. It is self-certified, and unfortunately that resource
has to be private.

And also, using it in browser is not a problem, it continues to work. But
unfortunately, when try to use in a mobile app web view (iOS) it shows “TLS
error” error and closes the application.

So the question here is how can I add a certificate to a private device in
LAN, is it doable? And is it the root of the problem?

Publicly-trusted CAs are not allowed to issue certificates for IP addresses in reserved ranges or for domain names that are not under an ICANN TLD.

Your options are roughly:

  • Run an internal CA, use it to sign that certificate and deploy the root certificate on all clients that will use your service, including mobile devices. There are some limitations on this with newer versions of Android. I’m not sure what the situation is on iOS.
  • Don’t use the IP address when requesting the resource, but rather use a “real” (sub)domain under an ICANN TLD and make it resolve to your internal IP. This could be something like internaldevice.example.com, where example.com is a real domain that you own. The device itself does not need to be publicly routable and does not have to exist in the public DNS, but in order to obtain a certificate from Let’s Encrypt, you will need the ability to dynamically publish (every 2-3 months, in order to renew your certificate) a DNS record under _acme-challenge.internaldevice.example.com. Certbot supports this option via the manual plugin - for other clients, what you’re looking for is support for the dns-01 challenge (sometimes just called “dns challenge”).
1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.