loading

Restricting Access and Enhancing Security with password in NGINX

Updated at
16/12/2023
Views
1202

Introduction: In this tutorial, you will learn how to enhance the security of your website by configuring NGINX server blocks and location directives. You will discover how to block specific client IP addresses, restrict access based on geographical locations (geo-based restriction), and implement password-based authentication using HTTP Basic Authentication. These measures can provide additional protection for your web server while allowing you to control access to specific web pages.

Prerequisites:

  • An Ubuntu server with sudo privileges
  • NGINX installed on your server 
  • Basic understanding of NGINX and its configuration

Note: For password-based restriction, it's recommended to have HTTPS enabled for your server. You can follow this tutorial to set up HTTPS.

Formatting Conventions:

  • In some configuration examples, ellipsis (...) may be used to indicate omitted parts.
  • The term "server" refers to your Ubuntu server with NGINX installed, while "server block" refers to the NGINX configuration block that looks like this:
server { ... }

Configuration Places: You should be aware of where NGINX stores its configuration files:

  • /etc/nginx is the NGINX configuration directory where all configuration files are placed.
  • /etc/nginx/nginx.conf is the main NGINX configuration file, where NGINX starts reading its configuration.
  • /etc/nginx/sites-enabled is where you can place your HTTP(S) server configuration files. After NGINX is started or reloaded, all files from this directory are loaded by NGINX.
  • /etc/nginx/sites-available is where you can place your HTTP(S) server configuration files, but they won't be loaded by NGINX unless you create a symbolic link in the /etc/nginx/sites-enabled directory.

Log Files: NGINX generates two default log files:

  • /var/log/nginx/access.log: Logs all requests.
  • /var/log/nginx/error.log: Logs error conditions and status information.

Error on Reload: If you encounter an error when reloading your NGINX configuration with sudo systemctl reload nginx, you can view the specific error by running sudo nginx -t.

Step 1 - Locating the Server Block File

To configure restrictions, you need to find the server block file that corresponds to your domain. Use the following command to list server block files:

ls -al /etc/nginx/sites-available/

Assuming you want to add restrictions to a server block that responds to example.com, locate the server block with the line server_name example.com;. For example:

server { ... server_name example.com; ... }

Ensure that the listen directive matches the port you intend to restrict (e.g., listen 80; for HTTP).

Step 2 - Using IP Addresses to Allow or Deny Access

NGINX provides allow and deny directives to control access based on client IP addresses. You can block access to specific IP addresses, including your own for testing.

Step 2.1 - Finding Your Public IP Address To block your own IP address, you first need to determine your public IP address. Run the following command:

curl -4 https://2ip.io

You'll receive your public IP address as output (e.g., 15.1.1.1). If the command fails, you can find your IP address through a Google search.

Step 2.2 - Blocking Access To block your IP address, add the following line to the appropriate location context in your server block, replacing 15.1.1.1) with your public IP:

deny 15.1.1.1);

Here's an example configuration snippet:

server { listen 80; server_name example.com; location / { deny 15.1.1.1) } }

After making this change, reload NGINX to apply the configuration:

sudo systemctl reload nginx

Now, if you run the same command to access your website from your IP:

curl -4 --head http://example.com

You should receive an HTTP 403 Forbidden error, indicating that access has been denied.

Note: You can specify multiple allow and deny directives. The first directive that matches will be applied. For instance:

allow 15.1.1.1; allow 15.1.1.2; deny all;

In this example, access is allowed for 15.1.1.1 and 15.1.1.2, while all other IP addresses are denied.

Step 3 - Using the Geo Module to Allow or Deny Access

NGINX's geo module offers a flexible way to control access based on geographical locations using IP databases. To enable this feature:

  1. Install the libnginx-mod-http-geoip2 package:
sudo apt update && sudo apt install libnginx-mod-http-geoip2
  1. Ensure that /etc/nginx/nginx.conf contains the following line:
include /etc/nginx/modules-enabled/*.conf;
  1. Download a GeoIP2-compatible IP database. You can use the provided command or create an account on the MaxMind website and download the GeoLite2 Country database:
cd /etc/nginx && sudo curl --fail -LO https://github.com/P3TERX/GeoLite.mmdb/releases/latest/download/GeoLite2-Country.mmdb
  1. Edit your NGINX configuration to include the GeoIP2 directives:
geoip2 /etc/nginx/GeoLite2-Country.mmdb { $user_country country iso_code; } map $user_country $not_allowed { CA 1; # Canada US 1; # United States default 0; # Allow all other countries } server { listen 80; server_name example.com; location / { if ($not_allowed) { return 403 "You're not allowed to access."; } } }

In this example, access is denied for users from Canada (CA) and the United States (US), while all other countries are allowed.

Reload NGINX to apply the changes:

sudo systemctl reload nginx

Step 4 - Password-Based Authentication (HTTP Basic Authentication)

To restrict access based on username and password, you can use HTTP Basic Authentication. Ensure you have HTTPS enabled for your server.

  1. Create a file to store usernames and hashed passwords:
sudo touch /etc/nginx/users
  1. Add users using the following command (replace user and password with your desired username and password):
python3 -c 'from subprocess import *; import sys; print("Username: ", end="", file=sys.stderr); user = input(); passwd = run(["openssl", "passwd", "-6"], encoding="utf-8", stdout=PIPE).stdout.strip(); print("Username or password is empty. Try again!", file=sys.stderr) if user == "" or passwd == "" else print(user + ":" + passwd)' | sudo tee -a /etc/nginx/users

This command adds a user to the /etc/nginx/users file and outputs the username and hashed password as user:password pairs. The password is not stored in plain text on the server.

  1. Modify your server block configuration to include HTTP Basic Authentication:
server { server_name example.com; location / { } auth_basic "Protected area!"; auth_basic_user_file /etc/nginx/users; 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 }

Make sure to replace example.com with your actual domain.

  1. Reload NGINX to apply the configuration:
sudo systemctl reload nginx

You can test the new configuration with curl. Accessing the site without a username and password should result in an HTTP 401 Unauthorized error, while providing valid credentials should grant access.

Restricting Access to a Single URL

To restrict access to a specific URL, add the auth_basic and auth_basic_user_file directives directly to a location context within your server block. For example:

server { server_name example.com; location / { } location /admin { auth_basic "Protected area!"; auth_basic_user_file /etc/nginx/users; } 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 }

In this example, the /admin URL is protected by HTTP Basic Authentication.

Logging Wrong Access Details

NGINX logs incorrect access attempts to the /var/log/nginx/error.log file. This includes incorrect passwords and non-existent usernames, providing additional visibility into unauthorized access attempts.

Example Log Entries:

  • Incorrect password:
2023/03/28 12:06:49 [error] 1865#1865: *14 user "root": password mismatch, client: 15.1.1.1, server: example.com, request: "GET / HTTP/1.1", host: "example.com"
  • Non-existent username:
2023/03/28/12:08:21 [error] 1865#1865: *16 user "root" was not found in "/etc/nginx/users", client: 15.1.1.1, server: example.com, request: "GET / HTTP/1.1", host: "example.com"

Conclusion: This tutorial has equipped you with the knowledge to enhance the security of your website using NGINX. By configuring server blocks, controlling access based on IP addresses, implementing geographical restrictions, and setting up password-based authentication, you can better protect your web server and control access to specific resources. NGINX's flexibility and powerful features make it a valuable tool for securing your web applications. For further guidance, refer to the official NGINX documentation and mailing list archives.

YottaSrc footer

why choose us?

Better Pricing, Fast SSD Storage and Real 24/7
Technical Support.

control panel icon
cPanel

Managing Your Site Through CPanel With The Latest Version

security icon
FAST, RELIABLE & SECURE

99.8% Uptime Guarantee.
So Focus On Your Work!

support icon
24/7/365 Support

Day or night, rain or shine,
our team is here for you!

cloud backup icon
Daily Backup

Daily & Weekly Backup.
Your Files Are Safe!