When configuring a server for a website, you may need to perform some common conditional operations. For example, some files may be cached by the user’s browser longer than others, or some parts of the website should only allow secure connections (such as anything that requires a user’s password), while other parts of the website should not .
Another simple common example is to ensure that when a new page is published instead of an old page, all old addresses will be redirected to the correct location. This is useful because it means that old links and bookmarks will not stop working, and it will also keep Google's cache.
Nginx's map module allows you to create variables in Nginx's configuration files whose values are conditional-that is, they depend on the values of other variables. In this guide, we will learn how to use Nginx's map module to implement two examples: how to set up a redirect list from an old website URL to a new website, and how to create a whitelist of countries/regions to control the traffic of your website.
To follow this tutorial, you need:
First, we will create a test file that represents the newly published website. We will use this file to test our configuration.
Let's create a simple page index.html
in the default Nginx website directory. This file has only a simple text description: the home page.
sudo sh -c 'echo "Home" > /var/www/html/index.html'
With this test file, next we will use curl
to check whether it is used correctly. We don't need index.html
to specify for this command, because if the exact file name is not provided, it will be provided by default.
curl http://localhost/
In response, you should see a word saying 家 is like the following:
Home
Now let us try to access a file that does not exist in /var/www/html/
, such as old.html
.
curl -L http://localhost/old.html
The response will be a system error message, 404 Not Found, indicating that the page does not exist.
< html><head><title>404 Not Found</title></head><body bgcolor="white"><center><h1>404 Not Found</h1></center><hr><center>nginx/1.10.0(Ubuntu)</center></body></html>
We are only using a virtual website in this tutorial, but if old.html
is a page that once existed and was deleted on the real website, returning 404 will mean that all links on that page are broken. This is not ideal, because these links may have been indexed by Google, printed or recorded, or shared by any other means.
In the next step, we will use the map module to ensure that this old address works again by automatically redirecting the viewer to the new replacement.
For small sites with only a few pages, simple if
conditional statements can be used for redirects and similar things. However, as the condition list becomes longer, this configuration is not easy to maintain or expand in the long run.
The map module is a more elegant and concise solution. It allows you to compare Nginx variable values with a list of conditions, and then associate the new value with the variable based on the match. In this example, we will compare the requested URL with the list of old pages we want to redirect to. For each old address, we will associate the new address.
The mapping module is the core Nginx module, which means it can be used without a separate installation. To create the necessary mapping and redirection configuration, please open the default server block Nginx configuration file with nano
or your favorite text editor.
sudo nano /etc/nginx/sites-available/default
Find the server
configuration block as shown below:
...
# Default server configuration
#
server {
listen 80 default_server;
listen [::]:80 default_server;
...
We will add two new parts: one before the server
block and one in it.
The part before the server
block is a new map
block, which uses the map module to define the mapping between the old URL and the new URL. The part inside the server
block is redirection.
...
# Default server configuration
#
# Old website redirect map
#
map $uri $new_uri {/old.html /index.html;}
server {
listen 80 default_server;
listen [::]:80 default_server;
# Old website redirect
if($new_uri){
rewrite ^ $new_uri permanent;}...
The map $uri $new_uri
command gets the contents of the system $uri
variable, which contains the URL address of the requested page, and compares it with the condition list in braces. Each item in the condition list has two parts: the value to match, and if it matches, the new value assigned to the variable.
The line
/old.html /index.html in the map
block means that if the value of $uri
is /old.html
, $new_uri
will be changed to /index.html
. If it does not match, it will not be changed. Here, we only define one condition, but you can define any number of conditions in the map.
Then, use another if
conditional statement in the server
block to check whether the value of the $new_uri
variable is set. If it is, it means that the conditions in the map are met and we should redirect to the new website using the rewrite
command. The permanent
keyword ensures that the redirect will be a 301 Moved Permanently HTTP redirect, which means that the old address is no longer valid and will not be back online.
Save and close the file to exit.
To enable the new configuration, restart Nginx.
sudo systemctl restart nginx
To test the new configuration, perform the same request as before:
curl -L http://localhost/old.html
There will be no 404 Not Found errors in the output this time. Instead, you will see the simple home page we created in step 1.
Home
This means that the map is properly configured and you can use it to redirect the URL by adding more entries to the map.
Redirect URL is a useful application of the map module. Another, we will explore in the next step, filtering traffic based on the geographic location of visitors.
Sometimes, the server may receive too many automated malicious requests. This may be a DDoS attack, an attempt to force a password on the website management panel, or an attempt to exploit a known vulnerability in the software to attack the website and use it to send spam or modify the content of the website.
Such automated attacks can come from many different distributed servers in many different countries, so it is difficult to stop. One solution to mitigate the impact of such attacks is to create a whitelist of countries/regions where the website can be accessed.
This is not a perfect solution, but when restricting access to the website based on the visitor's geographic location is a wise choice and does not limit the audience of the website, this solution has the advantage of being fast and not prone to errors.
Filtering at the server level is faster than filtering at the website level and also covers all requests (including static files such as images). This filtering also prevents requests from reaching the website software, which makes vulnerabilities more difficult to exploit.
To use geographic filtering, we first create a new profile.
sudo nano /etc/nginx/conf.d/geoip.conf
Paste the following content into the file. This tells Nginx where to find the GeoIP database containing the mapping between the visitor's IP address and their respective country/region. This database is pre-installed with Ubuntu 16.04.
...
# GeoIP database path
#
geoip_country /usr/share/GeoIP/GeoIP.dat;
The next step is to create the necessary mapping and restriction configurations. Open the default server block Nginx configuration.
sudo nano /etc/nginx/sites-available/default
Find the server
configuration block, after the modification in steps 1 and 2, as shown below:
...
# Default server configuration
#
# Old website redirect map
#
map $uri $new_uri {/old.html /index.html;}
server {
listen 80 default_server;
listen [::]:80 default_server;
# Old website redirect
if($new_uri){
rewrite ^ $new_uri permanent;}...
We will add two new parts: one before the server
block and one in it.
The part in front of the server
block is a new map
block, which defines the default operation (no access allowed) and a list of country/region codes that are allowed to access the website. If the result of map
is so, the part inside the server
block refuses to access the website.
...
# Default server configuration
#
# Allowed countries
#
map $geoip_country_code $allowed_country {default no;
country_code_1 yes;
country_code_2 yes;}
# Old website redirect map
#
map $uri $new_uri {/old.html /index.html;}
server {
listen 80 default_server;
listen [::]:80 default_server;
# Disallow access based on GeoIP
if($allowed_country = no){return444;}
# Old website redirect
if($new_uri){
rewrite ^ $new_uri permanent;}...
Save and close the file to exit.
Here, we use country_code_1
and country_code_2
as placeholders. Replace these variables with the two-character country code of the country you want to whitelist. You can use [ISO's complete, searchable list of all country/region codes] (https://www.iso.org/obp/ui/#search) to find it. For example, the two-character code for the United States is US
.
Unlike the first example, in this map
block, the $allowed_country
variable will always be set to a certain value. By default, it is set to no
; if the $geoip_country_code
variable matches a certain country code in the block, it is set to yes
. If the $allowed_country
variable is no
, we will return 444 Connection Closed Without Response instead of serving the actual website.
To enable the new configuration, restart Nginx.
sudo systemctl restart nginx
If you did not add the country/region to the whitelist, when you try to access http://your_server_ip
, you will see an error message such as The page is invalid or The page does not send any data . If you do add the country to the whitelist, you will see Home as before.
Although it may be a very simple example of how to use the map module, it shows the mechanism that can be used in many other different ways. The map module not only allows simple comparisons, but also supports regular expressions that allow more complex matching. If multiple conditions must be evaluated, this is a good way to make the profile clearer.
Another very popular use case for the map module is to conditionally redirect the secure part of a website in a non-SSL environment. Setting a mandatory SSL connection only for forms that require password input is a good example. How to apply the map module in a real world scenario, I encourage you to try such a setting.
More detailed information can be found in the official map module documentation of Nginx](http://nginx.org/en/docs/http/ngx_http_map_module.html).
To learn more about the related tutorials about using the map module of Nginx, please go to [Tencent Cloud + Community] (https://cloud.tencent.com/developer?from=10680) to learn more.
Reference: "How to Use Nginx's map Module on Ubuntu 16.04"
Recommended Posts