The last article talked about variables and the operation principle of Nginx, here is a main module to provide variables and modify the value of variables, that is, we want to talk about the anti-theft module: referer module.

Simple and effective means of preventing theft chain

scenario

If you have done a personal site of the students, may encounter other people steal their own site resources link, this is the chain. Referring to the HTTP header, the referer header. When another web site references your page through its URL and the user clicks on the URL in the browser, the HTTP request header takes the URL of the site’s current page with it through the referer header to tell the server who made the request.

For example, search for Nginx in Google and click on the link:

When you look at the request header on the new page that opens, you see that the request header contains the referer header with the value www.google.com/.

For example, Google is allowed, but when some other websites want to use our own resources, they need to do some control, otherwise everyone can get the link.

purpose

The purpose here is already very clear, is to refuse abnormal sites to visit our site resources.

Train of thought

  • Invalid_referer variable
    • Referer provides this variable that can be used to configure which referer headers are valid, that is, which sites you allow to reference your resources.

Referer module

To achieve the above purpose, the referer module can be counted as the first number, let’s see how the referer module is used.

  • Default to compile into Nginx, pass--without-http_referer_moduledisable

The Referer module has three directives, which we’ll look at below.

Syntax: valid_referers none | blocked | server_names | string ... ; Default: -- Context: server, location Syntax: referer_hash_bucket_size size; Default: referer_hash_bucket_size 64; Context: server, location Syntax: referer_hash_max_size size; Default: referer_hash_max_size 2048; Context: server, locationCopy the code
  • valid_referersDirective to configure whether or not the referer header is allowed and which referer access is allowed.
  • referer_hash_bucket_sizeThe values that represent these configurations are placed in the hash table, specifying the size of the hash table.
  • referer_hash_max_sizeRepresents the maximum size of the hash table.

The most important of these is the Valid_referers directive, which needs to be highlighted.

Valid_referers instruction

Multiple parameters can be carried at the same time, indicating that multiple referer headers are valid.

The parameter value

  • none
    • Allow access to requests missing the referer header
  • Block: Allows access to requests that have no corresponding value in the referer header. For example, it may pass through a reverse proxy or firewall
  • Server_names: If the site domain name in the referer matches one of the local domain names in the server_name field, the request is allowed
  • String: indicates the string of the domain name and URL. For a domain name, the prefix or suffix can contain * wildcard characters. If the value in the referer header matches the string, the access is allowed
  • Regular expression: Access is allowed if the value in the referer header matches the re

Invalid_referer variable

  • The allowed access time variable value is null
  • Deny access time variable value is 1

In actual combat

Let’s look at a configuration file.

server { server_name referer.ziyang.com; listen 80; error_log logs/myerror.log debug; root html; location /{ valid_referers none blocked server_names *.ziyang.com www.ziyang.org.cn/nginx/ ~\.google\.; if ($invalid_referer) { return 403; } return 200 'valid\n'; }}Copy the code

Which of the following requests will be rejected for this configuration file?

curl -H 'referer: http://www.ziyang.org.cn/ttt' referer.ziyang.com/
curl -H 'referer: http://www.ziyang.com/ttt' referer.ziyang.com/
curl -H 'referer: ' referer.ziyang.com/
curl referer.ziyang.com/
curl -H 'referer: http://www.ziyang.com' referer.ziyang.com/
curl -H 'referer: http://referer.ziyang.com' referer.ziyang.com/
curl -H 'referer: http://image.baidu.com/search/detail' referer.ziyang.com/
curl -H 'referer: http://image.google.com/search/detail' referer.ziyang.com/Copy the code

We need to parse the configuration file first. What values are configured with the valid_referers directive?

 valid_referers none blocked server_names
        *.ziyang.com www.ziyang.org.cn/nginx/
        ~\.google\.;Copy the code
  • None: Indicates that those without referer can be accessed
  • Blocked: Indicates that the referer can be accessed without a value
  • Server_names: Indicates that the local server server_name (referer.ziyang.com) can be accessed
  • *. Ziyang.com: matches the re can access
  • www.ziyang.org.cn/nginx/ : This page sends…
  • ~\.google\. : Both before and after Google are regular matches

Let’s actually look at the response:

➜ ~ curl -h 'referer: http://www.ziyang.org.cn/ttt' referer.ziyang.com/ <html> <head><title>403 Forbidden</title></head> <body> <center><h1>403 Forbidden</h1>< hr><center>nginx/1.17.8</center> </body> </ HTML > ➜ ~ curl -h 'referer: http://image.baidu.com/search/detail' referer.ziyang.com/ <html> <head><title>403 Forbidden</title></head> <body> <center><h1>403 Forbidden</h1>< hr><center>nginx/1.17.8</center> </body> </ HTML > # - H 'referer: http://www.ziyang.com/ttt' referer.ziyang.com/ valid ➜ ~ curl - H 'referer: http://www.ziyang.com' referer.ziyang.com/ valid # match server name ➜ ~ curl -h 'referer: http://referer.ziyang.com 'referer.ziyang.com/ valid # matches to the blocked ➜ ~ curl - H' referer: ➜ ~ curl ~ ziyang.com/ valid # match ~\.google\. ➜ ~ curl -h 'referer: http://image.google.com/search/detail' referer.ziyang.com/ validCopy the code

The Referer module is a simple anti-theft device that relies on the browser to initiate a request, which would not work if an attacker forged the referer header.

The secure_link module is another solution.

Its main principle is to prevent theft by verifying the hash value in the URL.

The basic process looks like this:

  • The server (either Nginx or some other Web server) generates an encrypted secure link URL and returns it to the client
  • The client accesses Nginx using a secure URL, which is verified by Nginx’s secure_link variable

The principle is as follows:

  • The hash algorithm is irreversible
  • Clients can only get hashed urls
  • Only the server that generates the URL, and Nginx, which verifies that the URL is secure, save the original string
  • A raw string usually consists of the following parts in order:
    • Resource location. For example, the URI specified in HTTP prevents an attacker from accessing any resource after obtaining a secure URI
    • User information. Such as the user’s IP address, prevent other users from stealing the URL
    • The time stamp. The secure URL expires in time
    • The key. Server-side only, making it harder for an attacker to guess the raw string

Module:

  • ngx_http_secure_link_module
    • –with-http_secure_link_module not compiled into Nginx
  • variable
    • secure_link
    • secure_link_expires
Syntax: secure_link expression; Default: - Context: HTTP, server, location Syntax: secure_link_MD5 expression; Default: -- Context: HTTP, server, location Syntax: secure_link_secret word; Default: - the Context: the locationCopy the code

Example configuration of variable values with expiration time

  • secure_link
    • If the value is empty string, the authentication fails
    • If the value is 0, the URL expires
    • If the value is 1, the authentication succeeds
  • secure_link_expires
    • Value of the timestamp

Command line generates secure links

  • To generate md5
Echo -n 'timestamp URL IP client key | openssl md5 - binary | openssl base64 | tr + / - | tr - d =Copy the code
  • Constructing the request URL
/test1.txt? Md5 = MD5 generated value & Expires = timestamp (e.g. 2147483647)Copy the code

Nginx configuration

  • secure_link $arg_md5,$arg_expires;
    • Secure_link must be followed by two values, md5 and timestamp
  • secure_link_md5 “$secure_link_expires$uri$remote_addr secret”;
    • In what order are raw strings constructed

In actual combat

Here is an actual configuration file. I won’t do the demo here, but you can do the experiment yourself if you are interested.

server { server_name securelink.ziyang.com; listen 80; error_log logs/myerror.log info; default_type text/plain; location /{ secure_link $arg_md5,$arg_expires; secure_link_md5 "$secure_link_expires$uri$remote_addr secret"; if ($secure_link = "") { return 403; } if ($secure_link = "0") { return 410; } return 200 '$secure_link:$secure_link_expires\n'; } location /p/ { secure_link_secret mysecret2; if ($secure_link = "") { return 403; } rewrite ^ /secure/$secure_link; } location /secure/ { alias html/; internal; }}Copy the code

An easy way to hash only urIs

In addition to this relatively complex way to prevent theft, there is a relatively simple way to prevent theft, which is to hash only the URI, so that when the URI is passed

  • Split the request URL into three parts: /prefix/hash/link
  • Hash generation mode: Md5 Hash is performed on the Link key
  • withsecure_link_secret secret;Configuration keys

Command line generates secure links

  • The original request
    • link
  • Generated security request
    • /prefix/md5/link
  • To generate md5
    • Echo -n 'linksecret | openssl md5 - hex

Nginx configuration

  • secure_link_secret secret;

This anti-theft chain method is relatively simple, so how to use it specifically? You’ve all downloaded resources from the web, whether it’s an ebook or a software application. When you click to download a website, you’ll get another page to download. This new page is actually a secure URL generated by the requested Nginx. If the URL is obtained, it is still usable, so you need to update the key frequently to ensure that the URL is not stolen.

Today, this article describes the specific usage of anti-theft chain in detail. The recent two articles are about the existing variable usage, and the next article will talk about how to generate new variables.


This article was first published on my personal blog: iziyang.github. IO. I have put all the configuration files in the Nginx configuration file, you can help yourself.