Sunday, April 4, 2021

Setup NGINX Proxy

Once in a while there are applications that needs to run in unprivileged port
(ports above 1024). What can you do to protect its identity from attacks? Aha!
Use HTTPS.. But how? We can setup another host in front of it (proxy server) to
accept incoming requests via encrypted channel (HTTPS, port 443/tcp) and
redirect that to the backend server (or proxied host) via an uncrypted channel.
In this post, we will use Nginx to have that setup.

1. First, let's say we have VM01 that runs an application on port 8081.







2. Now, let's spin up another host, VM02 (Centos 7.3 w/ SELinux in enforcing
mode), and install Nginx. First, be sure that the nginx repo is enabled.

[root@vm02 ~]# cat /etc/yum.repos.d/nginx.repo
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/7/x86_64/
gpgcheck=0
enabled=1
[root@vm02 ~]#

3. Install nginx package.

[root@vm02 ~]# yum install -y nginx

4. Start and enable nginx at boot

[root@vm02 ~]# systemctl start nginx
[root@vm02 ~]# systemctl enable nginx
Created symlink from /etc/systemd/system/multi-user.target.wants/nginx.service to /usr/lib/systemd/system/nginx.service.
[root@vm02 ~]#

5. Create selfsigned certificates. In this part, you may use `genkey` or
`openssl`. I always wanted the openssl way because its faster. BTW, don't
memorize the command below. Just be familiar with it because you can always see
it inside `/etc/pki/tls/certs/make-dummy-cert`

[root@vm02 ~]# /usr/bin/openssl req -newkey rsa:2048 -keyout vm02.key -nodes -x509 -days 365 -out vm02.crt
Generating a 2048 bit RSA private key
.........+++
..........................................................................................+++
writing new private key to 'vm02.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:US
State or Province Name (full name) []:California
Locality Name (eg, city) [Default City]:Los Angeles
Organization Name (eg, company) [Default Company Ltd]:dummy
Organizational Unit Name (eg, section) []:dummy
Common Name (eg, your name or your server's hostname) []:vm02
Email Address []:dummy@nxdomain.com
[root@vm02 ~]#

6. Move the certificates to the correct paths and run `restorecon` to make sure
SELinux contexts are correct.

[root@vm02 ~]# mv *crt /etc/pki/tls/certs
[root@vm02 ~]# mv *key /etc/pki/tls/private/                                                                                                                                                                [root@vm02 ~]# restorecon -Rv /etc/pki/tls/
restorecon reset /etc/pki/tls/certs/vm02.crt context unconfined_u:object_r:admin_home_t:s0->unconfined_u:object_r:cert_t:s0
restorecon reset /etc/pki/tls/private/vm02.key context unconfined_u:object_r:admin_home_t:s0->unconfined_u:object_r:cert_t:s0
[root@vm02 ~]#

7. Update nginx configuration to use SSL, point to the correct certificates
(ssl_certificate_*), and activate reverse proxy (proxy_pass). We will just use
the default config and use the minimal directives needed for simplicity.

[root@vm02 ~]# cat /etc/nginx/conf.d/default.conf
server {
    listen       443;
    server_name  vm02;
    ssl on;
    ssl_certificate /etc/pki/tls/certs/vm02.crt;
    ssl_certificate_key /etc/pki/tls/private/vm02.key;

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    location / {
        proxy_pass   http://vm01:8081;
    }
}
[root@vm02 ~]#

8. Open up port 443/tcp on the firewall to allow incoming connections. You may
use firewall-cmd's "--add-service" or "--add-port". Let's use "--add-service"
since there is already an existing service defined for HTTPS.

[root@vm02 ~]# firewall-cmd --add-service=https --permanent
success
[root@vm02 ~]# firewall-cmd --reload
success
[root@vm02 ~]#

9. Activate this SELinux boolean to allow HTTP to forward requests to our
upstream server (VM01).

[root@vm02 ~]# setsebool -P httpd_can_network_connect on
[root@vm02 ~]#

10. Now, our proxy server is ready. Let's try connecting. It must display the
data from the upstream like in #1.







So that are the basics steps in hiding your application via a proxy server.
This is very important if your application accepts user details like username
and passwords. You never want your credentials to be sent in cleartext!

Hope you learned something from this post :)

No comments:

Post a Comment