Lets Encrypt across two ports

Hi,

Apologies in advance: I am new to servers and certificates.

I have two nodejs apps running on one server instance. The first is the client facing app (http://localhost:3000), and this makes calls to the second app (webservices http://localhost:3001).

This is my nginx sites available:

server {

        root /var/www/mydomain.com/html;
        index index.html index.htm index.nginx-debian.html;

        server_name mydomain.com www.mydomain.com;

        location / {
                proxy_pass http://localhost:3000;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection 'upgrade';
                proxy_set_header Host $host;
                proxy_cache_bypass $http_upgrade;
        }

    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/mydomain.com/fullchain.pem; # managed >
    ssl_certificate_key /etc/letsencrypt/live/mydomain.com/privkey.pem; # manage>
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot


}
server {
    if ($host = www.mydomain.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

Thanks to the LetsEncrypt certificate, the site is available at https://mydomain.com. This calls http://localhost:3001 to reach the webservices. The services are reached, but I need them to be HTTPS also.

Is this possible with one LetsEncrypt certificate? I’m trying to avoid spinning up another droplet and domain for my webservices.

1 Like

Why? If you’re afraid someone can Man-in-the-Middle your localhost connections, you’ve got a lot more to worry about :grin: IMO TLS doesn’t have any security benefit when connecting to localhost/127.0.0.1/::1

I have no experience with NodeJS, but in theory you could use one single certificate for as much services as possible.

1 Like

That’s a general thing.

More and more services / JavaScript commands etc. want https, not http.

Sample: Cookies SameSite = lax, if not defined. SameSite = none requires https.

Same with web services.

2 Likes

I think my services may need to be HTTPS in order to connect with my managed database server as sslmode=require is specified on the given connection string. I’m trying to figure out if changing to HTTPS on my webservices will allow the connection.

Well, that’s stupid then. 127.0.0.1/::1 should be treated as a potentially secure origin (same security level as HTTPS by the way according to that document). localhost seems to be a little bit nuanced, as that might hit DNS resolvers.

See also for example the following Chromium/Chrome proposal: https://www.chromium.org/Home/chromium-security/prefer-secure-origins-for-powerful-new-features

So you need to secure your database service, right? Or is that the same thing as your other “webservices” on port 3001?

1 Like

The webservices (3001) contain the database access code and connection strings.

The connection string used is the one provided by DigitalOcean in order to access the Managed Database.

postgresql://username:password@server:port/db?sslmode=require
1 Like

If server:port is 127.0.0.1:3001, can’t you just leave the "sslmode=require` out?

1 Like

Sorry, server:port in the connection string is for the remote managed database. The connection string above resides in the webservices on localhost:3001 on my app server.

1 Like

So what needs to be secured exactly? The remote managed database?

1 Like

I think I maybe have been getting confused, and if so, I’m sorry for wasting your time. I think I need to be specifying CA certificates in my connection string parameters. ie. nothing to do with my webservers being HTTPS.

1 Like

Personally, I’m not having any “overview” of what’s connecting to what, which connections are to localhost, which are to remote. Which are giving errors complaining about a lack of HTTPS, which are not. Et cetera. For me, the information now is too fragmented and possibly incomplete.

1 Like

First, let me restate some things with the typical terms:

  • You have a nginx server that is configured for “SSL Termination”.
  • Your nginx server proxies the decrypted HTTPS traffic to the local network (in this case, the same machine)
  • Your postgresql server is configured to use SSL authentication (https://www.postgresql.org/docs/current/libpq-ssl.html). This is a fairly esoteric authentication system. You don’t need to do this, and if you do use this - there is no need to use LetsEncrypt certificates, and I’m not even sure they are compatible. This system typically uses self-signed certificates, which you would install on the client (web application) and the database (postgresql).

You should be fine with the 3000 and 3001 applications running decrypted. As far as browsers are concerned, they are talking to a HTTPS server.

You can secure/lock-down postgresql in other ways. Using SSL Certificates is one of the least popular and most complex options to choose.

2 Likes

Yes, thank you - you are right. I’m in the process of trying to add certificates to the client web app now.

1 Like

I just want to clarify two points that I should have made better:

  1. you would install the root certificate onto the postgresql directory, and the client/leaf certificate into the home directory of the user the webapp runs on. So it’s more about installing on the machines, not an app.

  2. This may be worth reconsidering, since everything is on the same machine. SSL is usually used in clustered environments you do not trust, or when servers in different geographical regions and need to communicate over public networks. If you are prepping to do one of those things in the future, it is great to get it over with now… but if you don’t have definite plans to do that, you’re just encrypting traffic between two applications on the same machine and there is little benefit to this.

1 Like

Thanks again for your help.

I solved this by installing the client certificate to the app home directory, then specified this sslrootcert location in a connection string parameter. So the parameters looked like the following:

?sslmode=require&sslrootcert=Users/MyUserDirectory/Documents/GitHub/tester/certificate.crt
1 Like