1

I have an application that's split into two servers: one is a React application running on port 8080 and the other is an Express server running on 3001. The machine running this application has to run a few other applications as well, so I set up an https reverse proxy using Nginx:

** I disabled some of the proxy options for testing, but please let me know if they should be enabled.

server {
server_name example.com ;
location / {
 proxy_pass http://example.com:8080;
#  proxy_set_header Host $host;
#  proxy_set_header X-SSL-CERT $ssl_client_escaped_cert;
#  proxy_set_header X-Real-IP $remote_addr;
#  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#  proxy_set_header X-Forwarded-Proto https;
}
listen 443 ssl; # managed by Certbot
   ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
   ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
   include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
   ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

This works as intended; I can reach the site and it is secured, however requests made to my backend server, which is running on http://localhost:3001, is blocked because it's attempting to load mixed active content. So I adjusted to client to make requests to https://localhost:3001, and then generated a self-signed certificate for the Express server and set it up to use https, and this is where I hit a wall. Because this certificate is self-signed, it won't be trusted unless explicitly done so by someone, which is unreasonable for the user audience. From searching around it seems that you can't use certbot for localhost(understandable) so I'm not quite sure where to go from here. My assumption about the proxy_pass field was that requests to the backend would come from http, but from error messages in the browser this doesn't seem to be the case. Is it really necessary that two servers running on the same machine need to use https to communicate?

This question: Proxy HTTPS requests to a HTTP backend with NGINX almost matches what I'm attempting to do, except that I'm only using Nginx to serve the client; requests to the backend are handled through a combination of Apollo Client/Server, so Nginx is ignorant of these requests. Is there anything obvious I'm missing here, or some other configuration options to try?

  • Express server should have a setting for root URL or similar, which tells what is the outside visible URL for your server. Set that URL to `www.example.com`. After that the application should use proper URLs for everything. – Tero Kilkanen Oct 28 '20 at 23:39

3 Answers3

0

So I managed to fix my issue after thinking about Tero Kilkanen's answer. Express allows you to set the hostname in app.listen(PORT, HOST), so I set HOST to example.com. My backend uses graphql, so now my backend url is: example.com:3001/graphql. Beforehand, my client's connection to the backend was defined as localhost:3001/graphql, so I modified it to connect to example.com/graphql, then in my Nginx configuration, created a new location for exmaple.com's server:

 location /graphql {
  proxy_pass http://130.245.12.107:3001/graphql;                                                                       $  proxy_set_header X-SSL-CERT $ssl_client_escaped_cert;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header X-Forwarded-Proto https;
 }

and now my requests to the backend have https.

0

For anyone else encountering this issue, you might be losing your mind. You do not want to send the requests to nginx on the hosted server port, you want them to go to port80 for http or 443 for https. So if your server is localhost:3001, that is in your nginx config, but postman or frontend API env variables should be using 80/443(not 3001) respectively, and nginx will handle the rest. I hope this saves some headaches.

If you're getting SSL errors or only getting a server response at :3001 as http and can't get https to work, you're possibly encountering this issue.

EOP
  • 1
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community May 18 '23 at 07:08
0

While the OPs subsequent answer explains how he fixed his issue, content generated by the origin may still contain references to http (rather than https) although arguably, if the response carries the scheme from the origin rather than the value rquested then there is a risk it will also contain the hostname/port of the origin.

OTOH, not all backend systems will honor the X-forwarded-proto header.

A more robust approach would be to use a certificate (valid or self signed or expired or ...) and set proxy_ssl_verify off on nginx.

symcbean
  • 21,009
  • 1
  • 31
  • 52