kalyan chakravarthy
kalyan chakravarthy

Reputation: 653

Configure Nginx to reverse proxy requests to backend server based on port number

I have have four web applications running in one ec2-instance with hostname "ip-10-176-225-83.us-west-2.compute.internal" on the ports 8888, 8088, 8042 and 8890. All those web application are on HTTP.

Our security team doesn't allow to open http port from onpremise to AWS. The suggest to setup a reverse proxy in same VPC subent which takes HTTPS requests and forward the same to back end webservers using HTTP.

I have created a new instance in same subnet with hostname "ip-10-176-225-84.us-west-2.compute.internal" and installed Niginx Server.

How can i configure Nginx so that it does as below

https://ip-10-176-225-84.us-west-2.compute.internal:8080 call http://ip-10-176-225-83.us-west-2.compute.internal:8080 and responds back

same for other ports

Upvotes: 5

Views: 10576

Answers (1)

AfroThundr
AfroThundr

Reputation: 1225

TL;DR: There are several methods of accomplishing what you're looking for here.

Adhering to the principle of reducing attack surface where possible, it's usually best to not expose ports to the public internet unless absolutely necessary. A reverse proxy is an excellent way to accomplish this. Generally, you'd want all of the backend web apps to be reverse proxied over HTTPS on port 443, and you would access each service either:

  • with different host names, such as app1.example.com and app2.example.com, or
  • with different subdirectories, such as example.com/app1 and example.com/app2

Depending on the method you choose, the configuration may vary significantly, either with multiple server blocks for the former scenario, or location blocks for the latter. In either case, we'll be making use of the upstream and proxy_pass directives. I'll give an example of both scenarios.


Multiple Hosts

If you're using multiple hostnames (or multiple ports) for the frontend, you'll need to create multiple server blocks for them:

# Nginx reverse-proxy configuration
upstream app1 {
    server 10.176.225.83:8888;
}

upstream app2 {
    server 10.176.225.83:8088;
}

upstream app3 {
    server 10.176.225.83:8042;
}

upstream app4 {
    server 10.176.225.83:8890;
}

server {
    listen 443 ssl;
    server_name app1.example.com;

    ssl_certificate_key /path/to/your/ssl-key.pem;
    ssl_certificate /path/to/your/ssl-cert.pem;

    location / {
        proxy_pass http://app1;
    }
}

server {
    listen 443 ssl;
    server_name app2.example.com;

    ssl_certificate_key /path/to/your/ssl-key.pem;
    ssl_certificate /path/to/your/ssl-cert.pem;

    location / {
        proxy_pass http://app2;
    }
}

server {
    listen 443 ssl;
    server_name app3.example.com;

    ssl_certificate_key /path/to/your/ssl-key.pem;
    ssl_certificate /path/to/your/ssl-cert.pem;

    location / {
        proxy_pass http://app3;
    }
}

server {
    listen 443 ssl;
    server_name app4.example.com;

    ssl_certificate_key /path/to/your/ssl-key.pem;
    ssl_certificate /path/to/your/ssl-cert.pem;

    location / {
        proxy_pass http://app4;
    }
}

Several things to note here:

  • All of the backends have been defined at the top, using the upstream directive, and can now be referenced by name.
    • If you don't want to do it this way, you can omit the upstream blocks, and the proxy_pass lines would look like this: proxy_pass http://10.176.225.83:8888;
  • Because each app is being served on a different hostname, each gets its own server block. This would also be the case if they were each being served on different ports.
  • The ssl_certificate and ssl_certificate_key in each server block can point to different certificates, or even the same certificate, if you defined multiple SANs in the certificate.
  • Each app will be available from its own hostname, which all point to the frontend server:
    • App 1: https://app1.example.com
    • App 2: https://app2.example.com
    • App 3: https://app3.example.com
    • App 4: https://app4.example.com

Multiple Directories

For a configuration using a single host and port, serving the backend apps from subdirectories, you'll be using a single server block with multiple location blocks:

# Nginx reverse-proxy configuration
upstream app1 {
    server 10.176.225.83:8888;
}

upstream app2 {
    server 10.176.225.83:8088;
}

upstream app3 {
    server 10.176.225.83:8042;
}

upstream app4 {
    server 10.176.225.83:8890;
}

server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate_key /path/to/your/ssl-key.pem;
    ssl_certificate /path/to/your/ssl-cert.pem;

    location /app1 {
        proxy_pass http://app1;
    }

    location /app2 {
        proxy_pass http://app2;
    }

    location /app3 {
        proxy_pass http://app3;
    }

    location /app4 {
        proxy_pass http://app4;
    }
}

A few more things to note with this one:

  • We still define all four upstream services, as before. And you can still omit them if you prefer the direct route. This directive is more useful in complex configurations.
  • Because all the apps are being served from the same hostname, they share a server block, but have separate location blocks for their respective subdirectories.
  • Since they all share the same hostname, multiple SANs aren't necessary for the server certificate in this case.
  • Each backend app will be available from a subdirectory on the frontend server:
    • App 1: https://example.com/app1
    • App 2: https://example.com/app2
    • App 3: https://example.com/app3
    • App 4: https://example.com/app4

TLS Configuration

In either scenario, you'll need to configure SSL certificates, either signed by a public CA, or your internal PKI, if applicable. If your apps are to be public facing, you will need to use public certificates. Then you'd add their location to the above Nginx config.

Further Reading

For a real world example, you can check out the Nginx configuration I'm using for a Genieacs TR-069 server, which implements SSL and reverse proxies several other services, albeit on their original ports, not to 443. This may be useful if you wanted to keep them on their original ports.

The Nginx site also has a decent primer on reverse proxy basic configuration.

Upvotes: 6

Related Questions