Nginx常用变量和应用案例

Nginx/Web服务器
230
0
0
2024-02-06
标签   Nginx基础

1. $args

$args变量包含请求行中的参数。例如,请求URL为/index.html?page=2,那么$args的值就是page=2。
1.假设你想根据请求参数是否包含debug来决定是否开启debug模式,你可以这样配置:
location / {
  if ($args \~* "debug") {
    error_log /var/log/nginx/debug.log debug;
  }
  try_files $uri $uri/ =404;
}
​
#在这个配置中,如果请求的URL包含debug参数,Nginx将在/var/log/nginx/debug.log文件中记录debug日志。
2.添加或修改查询参数:
if ($args \~ "^(.*)param1=(.*)$") {
  set $args "$1param1=newvalue&$2";
}
​
#查询字符串中包含 param1,则将其值修改为 newvalue。
​
原请求URL:www.example.com?param1=value1&param2=value2
经过配置后修改为:www.example.com?param1=newvalue&param2=value2 
3.根据查询参数重定向请求:
if ($args \~ "^lang=(en|es|fr)$") {
  rewrite ^ /$1$request_uri? last;
}
​
#如果查询字符串中的 lang 参数为 en,es 或 fr,则重定向到对应语言的页面。
​
lang=en,重定向到英语页面,如www.example.com/en/
lang=es,重定向到西班牙语页面,如www.example.com/es/
lang=fr,重定向到法语页面,如www.example.com/fr
4.删除查询参数:
if ($args \~* "^(.*)(^|&)param_to_remove($|&)(.*)") {
  set $args $1$4;
}
​
如果查询字符串中包含 param_to_remove,则将其从查询字符串中删除。
​
一个请求URL:www.example.com?param1=value1&param_to_remove=value2&param3=value3
这里查询字符串包含了参数名为"param_to_remove"的参数。
那么根据这个配置,nginx会删除这个参数:
改写后的URL:www.example.com?param1=value1&param3=value3
5.基于查询参数阻止请求:
if ($arg_param1 = "badvalue") {
  return 403;
}
​
#如果查询字符串中的 param1 参数值为 badvalue,则返回 403 状态码,拒绝请求。
​
一个请求URL:www.example.com?param1=badvalue
返回状态码为403

2. $arg_PARAMETER

$arg_PARAMETER 变量可以用来直接访问查询字符串中的特定参数。PARAMETER 部分应该被替换为你想要获取的参数名。
1.假设你想根据请求的page参数来重定向用户,你可以这样配置:
location / {
  if ($arg_page = 2) {
    rewrite ^ /page2.html last;
  }
  try_files $uri $uri/ =404;
}
​
#在这个配置中,如果请求的URL包含page=2参数,Nginx将会重定向用户到/page2.html。
​
用户请求 URL 为:www.example.com/?page=2
返回 301 状态码,地址栏变成www.example.com/page2.html
用户就被重定向到了 /page2.html 页面
2.根据具体查询参数重定向请求:
if ($arg_lang \~* "(en|es|fr)") {
  rewrite ^ /$arg_lang$request_uri? last;
}
​
#如果查询字符串中的 lang 参数为 en,es 或 fr,则重定向到对应语言的页面。
​
用户请求URL如:www.example.com/?lang=en
所以重写目标为:/en/?lang=en
用户被永久重定向到英语页面
3.基于查询参数值阻止请求:
if ($arg_token = "badvalue") {
  return 403;
}
​
#查询字符串中的 token 参数值为 badvalue,则返回 403 状态码,拒绝请求。
​
用户请求URL:www.example.com?token=badvalue
nginx匹配if条件:if ($arg_token = "badvalue")
执行return 403返回403状态码
页面返回403禁止访问信息
4.基于查询参数值进行缓存控制:
proxy_cache_bypass $arg_nocache;
​
#查询字符串中的 nocache 参数存在(不论其值为何),那么 Nginx 将不会从缓存中提供内容,而是从后端服务器获取新的内容。
​
用户请求 URL 为www.example.com?nocache
Nginx匹配此请求发现$arg_nocache参数存在
由于proxy_cache_bypass $arg_nocache,如果参数存在就跳过缓存
Nginx不会从缓存中读取页面,而是直接向后端服务器请求新内容
用户能获取最新不经缓存的页面
5.基于查询参数值进行日志记录:
log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
          '$status $body_bytes_sent "$http_referer" '
          '"$http_user_agent" "lang=$arg_lang"';
access_log  /var/log/nginx/access.log  main;
​
#每个访问日志条目将包含查询字符串中 lang 参数的值
​
假设我们有一个网址 http://example.com?page=home&lang=en,用户通过 IP 地址 123.45.67.89 访问了这个网址。在这种情况下,日志条目可能会是这样的:
123.45.67.89 - - [12/Sep/2023:14:50:30 +0000] "GET /?page=home&lang=en HTTP/1.1" 200 2326 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36" "lang=en"
在这条日志中,"lang=en" 就是查询字符串中 lang 参数的值,这个值被添加到了日志条目的末尾这样,就可以知道每个请求的 lang 参数是什么,这对于分析网站的国际化使用情况非常有用

3. $http_HEADER

`$http_HEADER`变量可用于获取名为`HEADER`的HTTP请求头的值。例如,`$http_user_agent`可以获取`User-Agent`请求头的值。
1.如果你想根据User-Agent头来决定是否重定向,你可以使用以下配置:
if ($http_user_agent \~* "(Mobile|Android|iPhone|Windows Phone)") {
  rewrite ^ /mobile$uri last;
}
​
#当一个使用移动设备(如 Android、iPhone 或 Windows Phone 等)的用户访问网站时,他们会被重定向到对应的移动版网页。
​
用户使用移动设备(如Android手机)访问网站
请求头中带有用户代理信息 $http_user_agent
nginx匹配if条件,使用正则表达式匹配用户代理字符串是否包含"Mobile|Android|iPhone|Windows Phone"等移动设备关键词
匹配成功,表示用户使用移动设备访问
执行rewrite规则:rewrite ^ /mobile$uri last
将请求永久重定向到/mobile目录下的页面
实现了移动端优先访问效果
2.根据特定的用户代理(User-Agent)进行重定向:
if ($http_user_agent \~* "(iPhone|Android)") {
  rewrite ^ /mobile$uri last;
}
​
#如果用户代理是 iPhone 或 Android,请求将被重定向到对应的移动版页面。
​
用户使用iPhone手机访问网站,请求URL为:
www.example.com
nginx检查用户代理信息:$http_user_agent
匹配if条件:\~* "(iPhone|Android)"
发现用户代理包含"iPhone",匹配成功
执行rewrite规则:rewrite ^ /mobile$uri last
将请求永久重定向到/mobile目录
所以用户实际访问的是www.example.com/mobile
显示的是为移动设备优化的页面
3.根据特定的引用源(Referer)阻止请求:
if ($http_referer \~* "badwebsite.com") {
  return 403;
}
​
#如果引用源头部字段的值包含 "badwebsite.com",则返回 403 状态码,拒绝请求。
​
Bob 访问了 http://badwebsite.com 这个网站。
在 badwebsite.com 的某个页面中,有一个链接指向你的网站 http://mywebsite.com。
Bob 点击了这个链接,浏览器向 http://mywebsite.com 发起了一个请求。
这个请求的 HTTP Referer 头部字段的值是 http://badwebsite.com,因为这是请求的来源。
你的 Nginx 服务器收到了这个请求,并检查了 Referer 头部字段的值。
由于 Referer 包含 "badwebsite.com",因此 Nginx 返回 403 状态码,拒绝了这个请求。
Bob 的浏览器接收到 403 状态码,显示一个错误页面,表示他无法访问 http://mywebsite.com。
4.根据特定的头部字段控制缓存:
proxy_no_cache $http_cache_control;
​
#如果 HTTP 请求头中的 Cache-Control 字段存在,那么 Nginx 将不会对该请求进行缓存
​
你可能不希望某些请求被缓存,例如,你有一个动态生成内容的页面,每次访问都需要显示最新的信息。在这种情况下,你可以让客户端在 HTTP 请求头中加入 Cache-Control 字段,Nginx 就会根据这个配置,不对这个请求进行缓存
5.根据特定的头部字段进行日志记录:
log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
          '$status $body_bytes_sent "$http_referer" '
          '"$http_user_agent" "cookie=$http_cookie"';
access_log  /var/log/nginx/access.log  main;
​
#每个访问日志条目将包含 HTTP 请求头中 Cookie 字段的值
​
假设用户 Bob 通过他的 iPhone 设备访问你的网站 htxxp://mywebsite.com,并且在他的浏览器中有一个名为 session_id 的 Cookie,其值为 "123456"。他首次访问的页面是首页,然后他点击了一个链接,跳转到了 htxxp://mywebsite.com/about 页面。
在这种情况下,Nginx 会在 /var/log/nginx/access.log 文件中添加两行日志,大致如下:
192.0.2.1 - - [12/Sep/2023:08:50:30 +0000] "GET / HTTP/1.1" 200 5126 "http://mywebsite.com/" "Mozilla/5.0 (iPhone; CPU iPhone OS 13_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.5 Mobile/15E148 Safari/604.1" "cookie=session_id=123456"
192.0.2.1 - - [12/Sep/2023:08:52:17 +0000] "GET /about HTTP/1.1" 200 3148 "http://mywebsite.com/" "Mozilla/5.0 (iPhone; CPU iPhone OS 13_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.5 Mobile/15E148 Safari/604.1" "cookie=session_id=123456"
从这两行日志中,你可以明确地看到 BobIP 地址 (192.0.2.1),他的请求时间,他的请求内容 (首次访问首页,然后跳转到关于页面),服务器对请求的响应状态 (200 表示成功),发送到 Bob 的字节数,他的引用页,他的用户代理信息 (表明他使用的是 iPhone 设备) 以及他的 Cookie 信息 (session_id=123456)

4.$sent_http_HEADER

$sent_http_HEADER 变量表示 Nginx 发送给客户端的 HTTP 头部信息。它可以用于查看或修改 Nginx 发送的头部字段。
1.假设你想记录发送给客户端的Content-Type,你可以这样配置:
location / {
  add_header X-Sent-Content-Type $sent_http_content_type;
  try_files $uri $uri/ =404;
}
​
#在这个配置中,Nginx会在响应头中添加一个X-Sent-Content-Type字段,其值就是发送给客户端的Content-Type。
2.$sent_http_Content_Type(发送的内容类型)
`Content-Type` 头部字段通知客户端响应的主体是什么类型的数据。这是一个标准的 MIME 类型,如 `text/html``application/json``image/jpeg` 等。此外,还可以指定字符编码,如 `charset=utf-8`
例如,假设你有一个端点,该端点返回 JSON 数据。在这种情况下,你可能会在 Nginx 配置中设置 Content-Type,如下所示:
location /api/data {
  proxy_pass http://backend;
  proxy_set_header Content-Type application/json; charset=utf-8;
}
​
#当客户端访问 /api/data 端点时,Nginx 会将请求转发到后端服务器,并在响应头中设置 Content-Type 为 application/json; charset=utf-8。这样,客户端知道返回的数据是 JSON 格式,并使用 UTF-8 字符编码。
​
用户通过浏览器向网站地址/api/data发出JSON数据请求
Nginx根据location规则,将请求转发到后端服务器backend
但在转发前,设置proxy_set_header
将响应头Content-Type设置为application/json; charset=utf-8
表示响应内容的数据类型是JSON,字符编码是UTF-8
后端服务器处理请求,返回JSON数据
Nginx将响应返回给客户端
客户端根据Content-Type知道:
    返回的数据格式是JSON
    使用了UTF-8字符编码
可以正确解析和显示响应内容
3.$sent_http_Cache_Control(缓存控制)
`Cache-Control` 头部字段是一种机制,它允许网站指定响应是否可以被缓存,以及在何种情况下可以被缓存。这对于控制网页的性能和一致性非常重要。
例如,你可能想要对静态资源(如 CSS、JavaScript、图像文件等)设置长时间的缓存,以减少返回同一资源的请求次数。你可以在 Nginx 配置中这样设置:


location \~* \.(css|js|png|jpg)$ {
  expires 30d;
  add_header Cache-Control "public, max-age=2592000";
}
​
#在这个配置中,任何扩展名为 .css、.js、.png 或 .jpg 的文件都将被设置为 30 天后过期,并且在 Cache-Control 头部中设置 max-age 为 2592000 秒(即 30 天)。这意味着,如果客户端已经请求过这些文件,那么在 30 天内,它们可以从客户端的本地缓存中直接获取,而不需要再向服务器发送请求。
4.$sent_http_Expires(过期时间)
Expires 头部字段提供了一个日期/时间,之后响应被认为是过时的。这个字段与 Cache-Control 一起使用,可以更精细地控制缓存行为。
例如,你可能希望某个特定的文件在一年后过期。在这种情况下,你可以在 Nginx 配置中这样设置:
location = /special/file {
  expires 1y;
  add_header Cache-Control "public";
}
​
#在这个配置中,当客户端请求 /special/file 时,Nginx 会在响应头中设置 Expires 字段为当前时间加一年,并设置 Cache-Control 为 public。这样,客户端就知道它可以将这个响应缓存一年,并在这一年内,如果有对同样的文件的请求,它可以直接从本地缓存中获取。
5.$sent_http_Location(重定向位置)
Location 头部字段用于重定向客户端到新的 URL。这在你需要将客户端从旧的 URL 重定向到新的 URL,或者从 HTTP 重定向到 HTTPS 时非常有用。
例如,你可能有一个旧的端点,现在已经不再使用,而是使用一个新的端点。在这种情况下,你可以在 Nginx 配置中设置一个重定向,如下所示:
location = /old/endpoint {
  return 301 /new/endpoint;
}
​
#在这个配置中,当客户端尝试访问 /old/endpoint 时,Nginx 会返回一个 301 重定向响应,并在 Location 头部字段中设置新的 URL /new/endpoint。这样,客户端知道它需要向新的 URL 发出请求,而不是旧的 URL。
6.$sent_http_Set_Cookie(设置 Cookie)
Set-Cookie 头部字段用于服务器向客户端发送 cookie。这在需要保持用户会话,或者跟踪用户行为等情况下非常有用。
例如,你可能有一个登录系统,需要在用户登录后设置一个会话 cookie。在这种情况下,你可以在 Nginx 配置中设置 Set-Cookie,如下所示:


location = /login {
  add_header Set-Cookie "session=abcd1234; Path=/; HttpOnly";
  proxy_pass http://backend;
}
​
#在这个配置中,当客户端访问 /login 端点并成功登录后,Nginx 会在响应头中设置 Set-Cookie 为 session=abcd1234; Path=/; HttpOnly。这样,客户端知道它需要保存这个 cookie,并在后续的请求中将其发送回服务器。

5. $upstream_http_HEADER

`$upstream_http_HEADER`变量可以获取上游服务器发送的名为`HEADER`的HTTP响应头的值。例如,如果你的Nginx服务器配置了反向代理,那么`$upstream_http_content_type`可以获取到后端服务器发送的`Content-Type`响应头的值。
1.假设你想记录后端服务器发送的Content-Type,你可以这样配置:
location / {
  proxy_pass http://backend;
  add_header X-Upstream-Content-Type $upstream_http_content_type;
}
​
#在这个配置中,Nginx会在响应头中添加一个`X-Upstream-Content-Type`字段,其值就是后端服务器发送的`Content-Type`。
2.$upstream_http_Content_Type(上游的内容类型)
Content-Type 是一个 HTTP 头部字段,它告诉客户端响应的主体是什么类型的数据。例如,它可能是 text/html、application/json、image/jpeg 等。在 Nginx 中,你可以使用 $upstream_http_Content_Type 变量来访问这个字段
例如,你可能有一个上游服务器返回 JSON 数据,但你希望将其转换为 HTML。你可以使用 $upstream_http_Content_Type 变量来检测响应的 Content-Type,并据此做出决策,如下所示:
location /api/data {
  proxy_pass http://backend;
  proxy_intercept_errors on;
  error_page 415 = @handle_json;
}
​
location @handle_json {
  if ($upstream_http_Content_Type \~* application/json) {
    # 将 JSON 转换为 HTML...
  }
}
​
#这个配置中,当客户端访问 /api/data 端点时,Nginx 会将请求转发到后端服务器。如果后端服务器返回的 Content-Type 是 application/json,那么 Nginx 会将响应转发到 @handle_json 位置,然后在那里将 JSON 转换为 HTML。
3.$upstream_http_Set_Cookie(上游的设置 Cookie)
Set-Cookie 是一个 HTTP 头部字段,它允许服务器向客户端发送 cookie。在 Nginx 中,你可以使用 $upstream_http_Set_Cookie 变量来访问这个字段。
例如,你可能有一个上游服务器设置了一个会话 cookie,但你希望修改这个 cookie 的值。你可以使用 $upstream_http_Set_Cookie 变量来检测和修改响应的 Set-Cookie,如下所示:
location / {
  proxy_pass http://backend;
  proxy_ignore_headers Set-Cookie;
  add_header Set-Cookie "session=abcd1234; Path=/; HttpOnly";
}
​
#在这个配置中,Nginx 会忽略来自后端服务器的 Set-Cookie 头部字段,并设置自己的 Set-Cookie 头部字段。这意味着,无论后端服务器设置的会话 cookie 是什么,Nginx 都会告诉客户端设置 `session=abcd12344. $upstream_http_Location(上游的位置)
​
用户通过浏览器请求网站首页"/"
Nginx根据location规则,将请求转发到后端服务器backend
后端可能在响应中设置了自己的会话cookie,如"JSESSIONID=1234"
Nginx通过proxy_ignore_headers忽略后端Set-Cookie头
自己设置一个统一的会话cookie
    add_header Set-Cookie "session=abcd1234; Path=/; HttpOnly"
响应返回给客户端
客户端只获取并存储Nginx设置的cookie"session=abcd1234"
例如,你可能有一个上游服务器返回了一个重定向响应,但你希望修改 Location 头部以更改重定向的目标。你可以使用 $upstream_http_Location 变量来检测和修改响应的 Location,如下所示:
location / {
  proxy_pass http://backend;
  proxy_intercept_errors on;
  error_page 301 302 307 308 = @handle_redirect;
}
​
location @handle_redirect {
  if ($upstream_http_Location \~* /old-path) {
    set $new_location $upstream_http_Location;
    rewrite ^/old-path(.*)$ /new-path$1 break;
    add_header Location $new_location;
  }
​
  proxy_pass $upstream_http_Location;
}
​
#在这个配置中,当客户端访问 / 端点时,Nginx 会将请求转发到后端服务器。如果后端服务器返回了一个 301、302、307 或 308 响应,那么 Nginx 会将响应转发到 @handle_redirect 位置。在那里,如果 Location 头部包含 /old-path,Nginx 会修改 Location 头部,将 /old-path 替换为 /new-path。然后,Nginx 会将修改后的 Location 头部添加到响应中,并将响应返回给客户端。

当你询问商场的工作人员(location /),你想去 "旧店",他们会告诉你去哪里(proxy_pass http://backend;),这个 "旧店" 就是名为 "backend" 的地方。

如果 "旧店" 进行了重新装修或搬迁(返回了一个 301、302、307 或 308 响应),商场的工作人员会有特定的处理方法(error_page 301 302 307 308 = @handle_redirect;)。他们会告诉一个专门处理这种情况的工作人员(location @handle_redirect)。

这个专门的工作人员会检查 "旧店" 是否已经搬到 "旧地址"if ($upstream_http_Location \~* /old-path))。如果是这样,他们会在地图上(set $new_location $upstream_http_Location;)把 "旧地址" 改为 "新地址"(rewrite ^/old-path(.*)$ /new-path$1 break;)。

然后,他们会在你的地图上标注这个新地址(add_header Location $new_location;),这样你就可以直接去 "新地址",而不是 "旧地址"

最后,他们会告诉你这个新地址(proxy_pass $upstream_http_Location;),你就可以顺利地找到 "新店"

6. $uri

`$uri`变量包含了请求行中的URI(不包括参数)。例如,请求URL为`/index.html?page=2`,那么`$uri`的值就是`/index.html`。
1.假设你想针对某些特定的URI实施重定向,你可以这样配置:
location / {
  if ($uri = "/oldpage.html") {
    rewrite ^ /newpage.html permanent;
  }
  try_files $uri $uri/ =404;
}
​
#在这个配置中,如果请求的URI为`/oldpage.html`,Nginx将会永久重定向用户到`/newpage.html`。
2.重写和重定向:
location / {
  rewrite ^(/user/.*)$ $1/last/ permanent;
}
​
#在上述配置中,如果请求的 URI 是 `/user/<any-value>`,那么它将被重定向到 `/user/<any-value>/last/`。`$1` 是 `rewrite` 指令中的第一个捕获组,当匹配到 `/user/<any-value>` 时,`$1` 将存储 `/user/<any-value>` 的值。
3.请求日志记录:
access_log /var/log/nginx/access.log combined;
#在上述配置中,每个请求的 URI 都会记录在 `/var/log/nginx/access.log` 文件中。
4.条件处理:
location / {
  if ($uri = /healthcheck) {
    return 200 'Healthy';
  }
}
​
#在上述配置中,如果请求的 URI 是 `/healthcheck`,那么 Nginx 将返回 HTTP 200 状态码,以及 'Healthy' 的响应正文。
5.负载均衡和反向代理:
location /app1/ {
  proxy_pass http://backend1$request_uri;
}
​
location /app2/ {
  proxy_pass http://backend2$request_uri;
}
​
#在上述配置中,如果请求的 URI 是 `/app1/<any-value>`,那么请求将被转发到 `http://backend1/app1/<any-value>`。如果请求的 URI 是 `/app2/<any-value>`,那么请求将被转发到 `http://backend2/app2/<any-value>`。

7. $request_uri

request_uri 是 Nginx 的一个内置变量,它包含了原始请求的完整 URI,包括任何查询参数。这个变量在许多场景下都非常有用,比如重定向,日志记录,或者将请求转发到后端服务器。
1.假设你想记录完整的请求URI,你可以这样配置:
location / {
  access_log /var/log/nginx/access.log combined;
  try_files $uri $uri/ =404;
}
​
#在这个配置中,Nginx会在`/var/log/nginx/access.log`文件中记录完整的请求URI。
2.重定向
$request_uri 可以用于重定向请求到新的 URL。这在你需要改变网站结构,或者迁移到新的域名时非常有用。
案例
server {
  listen 80;
  server_name example.com;
  location / {
    return 301 https://$host$request_uri;
  }
}
​
#将所有 HTTP 请求重定向到 HTTPS
​
我们使用 $request_uri 保留原始请求的路径和查询字符串,以便在重定向后的 URL 中使用。
3.日志记录
使用 $request_uri 变量在 Nginx 日志中记录完整的请求 URI。这对于追踪和调试问题非常有用。
案例
http {
  log_format myformat '$remote_addr - $remote_user [$time_local] "$request_uri"';
  access_log /var/log/nginx/access.log myformat;
}
​
#这会在日志文件中记录如下格式的信息:192.0.2.1 - - [12/Sep/2023:00:00:00 +0000] "/path?arg=value"
4.缓存建
在使用 Nginx 作为反向代理服务器并启用缓存时,我们经常使用 $request_uri 作为缓存键的一部分。这是因为 $request_uri 包含了完整的请求路径和查询参数,这对于区分不同的请求非常有用。
案例
proxy_cache_key "$scheme$request_method$host$request_uri";
#这个配置会将请求的协议,请求方法,主机名和完整的请求 URI 综合起来作为缓存键。
5.请求限速
Nginx 提供了 limit_req 模块,允许我们基于客户端的 IP 地址或者其他变量对请求进行限速。我们可以使用 $request_uri 作为限速的关键因素之一。
案例
limit_req_zone $binary_remote_addr$request_uri zone=mylimit:10m rate=10r/s;
​
server {
  location / {
    limit_req zone=mylimit burst=20;
  }
}
​
#我们将客户端的 IP 地址和请求的 URI 一起作为限速的关键因素。这意味着对于同一 IP 地址,不同的请求 URI 将被视为不同的请求进行限速。

8. $remote_addr

`$remote_addr`变量包含了客户端的IP地址。
1.假设你想根据客户端的IP地址进行访问控制,你可以这样配置:
location / {
  if ($remote_addr = "192.168.1.1") {
    return 403;
  }
  try_files $uri $uri/ =404;
}
​
#在这个配置中,如果客户端的IP地址为`192.168.1.1`,Nginx将会返回403禁止访问的错误。
2.访问限制
你可能需要限制特定 IP 地址的访问,例如阻止恶意请求或者仅允许特定的 IP 地址访问某个资源。你可以使用 $remote_addr 和 deny 指令实现这个功能。
案例
location /sensitive-data/ {
  allow 192.0.2.1;
  deny all;
}
​
#我们只允许 IP 地址为 192.0.2.1 的客户端访问 /sensitive-data/ 路径下的资源,所有其他的请求都会被拒绝。
3.日志记录
使用 $remote_addr 变量在 Nginx 的日志中记录客户端的 IP 地址。这对于分析访问模式和调查问题非常有用。
案例
log_format myformat '$remote_addr - $remote_user [$time_local] "$request" "$status" "$body_bytes_sent" "$http_referer" "$http_user_agent"';
access_log /var/log/nginx/access.log myformat;
​
#我们在日志中记录了客户端的 IP 地址用户请求时间请求状态发送的字节数referer 和 user-agent
4.限速
Nginx 的 limit_req 模块可以让我们基于 $remote_addr 变量对请求的速率进行限制。这主要用于防止恶意请求或者过于频繁的请求。
案例
limit_req_zone $remote_addr zone=mylimit:10m rate=1r/s;
​
server {
  location / {
    limit_req zone=mylimit burst=5;
  }
}
#同一个IP在10分钟内,最多允许1个请求每秒通过,同时每10分钟内允许5个并发请求。
5.统计访问量
记录不同IP的访问次数,实现简单的访问统计:
案例
log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
          '$status $body_bytes_sent "$http_referer" '
          '"$http_user_agent"';
​
access_log  /var/log/nginx/access.log  main;
​
定义了一个名为main的访问日志格式
格式包含客户端IP时间请求信息状态码等详细日志字段
将采用该格式的访问日志记录到access.log文件中
6.静态IP缓存
根据$remote_addr给指定IP开启缓存,提高静态IP用户体验:
案例
map $remote_addr $static_ip {
  default   0;
  192.168.1.1 1;
}
​
location / {
  if ($static_ip) {
  add_header Cache-Control "public, max-age=3600";
  }
}
​
#实现了对192.168.1.1这个IP地址的资源设置了更长的缓存时间,其他IP地址资源缓存时间使用Nginx默认设置
7.区域访问限制
通过$remote_addr判断客户端IP所在区域,实现区域访问限制:
案例(放在nginx作为负载均衡器或代理服务器的配置文件)
map $remote_addr $restricted_area {
  default 0;
  # 中国大陆IP段
  \~^\d{1,3}\.\d{1,3}\. 1;  
}
​
location / {
  if ($restricted_area) {
  return 403;
  }
}
​
识别客户端来源区域,区分限制区域和非限制区域
对来自限制区域(如中国大陆)的请求返回403错误,实现区域访问控制
其他非限制区域请求不受影响,继续正常处理
8.日志数据统计
通过日志分析工具如ELK,结合$remote_addr变量统计不同区域、设备类型的访问数据,了解用户行为:
案例(nginx主配置文件或其包含文件中配置。)
log_format elasticsearch '{{remote_addr}} {{request_time}}' ;
​
access_log /var/log/nginx/access.log elasticsearch;
​
log_format定义了一个名为elasticsearch的日志格式。
这个格式只记录客户端IP地址remote_addr和请求时间request_time两个变量的值。
access_log指令使用定义的elasticsearch格式来记录访问日志。
访问日志将记录到文件/var/log/nginx/access.log中。
9.域名访问限制
通过$remote_addr映射域名,实现按域名限制访问:
案例
map $remote_addr $domain {
  default none;
  # IP映射域名
  192.168.1.0/24 company.com;
}
​
server {
  server_name $domain;
  # ...
}
​
map指令定义了一个名为$domain的变量,根据客户端IP地址范围192.168.1.0/24映射为company.com域名。
server块使用$domain作为server_name值。
这样,当客户端IP地址在192.168.1.0/24范围内时,Nginx会使用company.com作为域名处理请求。
其他IP地址下,server_name会使用默认none值。

9. $request_method

`$request_method`变量包含了HTTP请求方法,例如`GET``POST`等。
1.假设你想针对POST请求进行特殊处理,你可以这样配置:
location / {
  if ($request_method = POST) {
    # do something for POST requests
  }
  try_files $uri $uri/ =404;
}
​
如果是POST请求,则会执行if块内定义的操作:
    可以设置特定的header、变量等
    可以返回不同的响应
    可以重写URI或调用不同的后端等
    执行完if块内操作后,还会继续执行后面的try_files指令:
    尝试找到真实文件
    如果没有找到,返回404错误
2.限制请求方法
if ($request_method !\~ ^(GET|POST)$ ) {
  return 403;
}
​
#只允许GET和POST请求,其他方法返回403:
3.路由分发
根据请求方法分发到不同的后端服务器
案例
upstream backend {
  server 192.168.1.100:80 weight=5;
  server 192.168.1.101:80 weight=5;
}
​
location / {
  if ($request_method = POST) {
  proxy_pass http://backend; 
  }
​
  if ($request_method = GET) {
  proxy_pass http://other_backend;
  }
}
​
POST请求会转发到192.168.1.100和192.168.1.101两个后端服务器上负载。
GET请求会转发到其他后端,可能是另一组服务器。
4.缓存策略
根据请求方法动态控制缓存行为。
案例
map $request_method $no_cache {
  default 1;
  GET   0;
}
​
location / {
  if ($no_cache) {
  add_header Cache-Control no-cache;
  }
}
​
GET请求不会添加Cache-Control头,浏览器可以缓存响应。
其他请求(POST等)会添加Cache-Control: no-cache头,不允许缓存
5.访问日志记录
区分记录GET和POST访问日志
案例
log_format get '$remote_addr - $remote_user [$time_local] ' 
        '"$request" $status $body_bytes_sent';
​
log_format post '$remote_addr - $remote_user [$time_local] '
         '"$request" $status $body_bytes_sent ' 
         '"$http_referer" "$http_user_agent"';
           
access_log /var/log/nginx/access-get.log get;
access_log /var/log/nginx/access-post.log post;
​
定义了两个日志格式get和post
get格式只记录基本信息如IP,时间,请求,状态码等
post格式除了基本信息外,还记录http_referer和http_user_agent信息
分别使用get和post格式记录访问日志
get请求记录到access-get.log文件
post请求记录到access-post.log文件
6.限流控制
根据请求方法设置不同的限流策略
案例
limit_req_zone $request_method zone=req_method:10m rate=1r/s;
​
location / {
  limit_req zone=req_method burst=10 nodelay;
  
  if ($request_method = POST) {
  limit_req zone=req_method burst=1;
  }
}
​
GET/其他方法:每秒1个请求,同时最多10个并发请求。
POST方法:每秒1个请求,同时只允许1个并发请求。
7.错误页面定制
不同方法设置自定义错误页面
案例


error_page 405 = @405;
​
location @405 {
  if ($request_method = GET) {
  return 405 "$uri Method Not Allowed (GET)";
  }
  return 405 "$uri Method Not Allowed";
}
​
如果是GET,返回405错误,并定制错误页面内容为"$uri Method Not Allowed (GET)"
如果不是GET,返回405错误,错误页面内容为"$uri Method Not Allowed"
这样就为GET方法和非GET方法定制了不同的405错误页面显示内容。
当请求的资源或方法不允许时,会返回405错误。
根据请求方法的不同,显示上面定制的不同错误页面内容。

10. $scheme

`$scheme`变量包含了请求使用的协议,通常是`http``https`
1.假设你想强制所有的HTTP请求重定向到HTTPS,你可以这样配置:
server {
  listen 80;
  server_name example.com;
  location / {
    return 301 https://$host$request_uri;
  }
}
​
server {
  listen 443 ssl;
  server_name example.com;
  # SSL configuration goes here
  # ...
}
​
#在这个配置中,所有到example.com的HTTP请求都会被永久重定向到HTTPS。
2.根据协议设置缓存策略
map $scheme $no_cache {
  default 1;
  https 0;
}
​
server {
  if ($no_cache) {
  add_header Cache-Control no-cache;
  }
}
​
#HTTPS请求不设置Cache-Control,允许缓存;HTTP请求设置Cache-Control: no-cache不缓存页面。
3.设置安全相关头部
map $scheme $hsts {
  default off;
  https on; 
}
​
server {
  add_header Strict-Transport-Security $hsts;
}
​
#只为HTTPS请求添加HSTS头,提高HTTPS站点的安全性。
4.日志记录格式区分
通过$scheme在访问日志中记录请求是否为HTTPS。
案例
log_format ssl '[$time_local] ' '$scheme://$host$request_uri'; 
​
access_log logs/ssl.access.log ssl;

区分记录HTTPS请求的访问日志

通过$scheme字段可以明确区分请求是否为HTTPS

为后期统计、分析HTTPS访问提供详细数据

方便监控和优化HTTPS服务的性能

与普通HTTP访问日志进行区分和管理

5.后端服务器配置区分

根据协议动态代理请求到不同的后端服务器处理。

案例
upstream http_backend {
  server 192.168.1.101;
  server 192.168.1.102;
}
​
upstream https_backend {
  server 192.168.1.103;
  server 192.168.1.104;  
}
​
server {
  listen 80;
​
  location / {
  proxy_pass http://http_backend;
  }
}
​
server {
  listen 443 ssl;
​
  ssl_certificate /path/to/ssl/cert;
  ssl_certificate_key /path/to/ssl/key;
​
  location / {
  proxy_pass https://https_backend;
  }
}

HTTP请求转发给专门的HTTP后端服务器处理

HTTPS请求转发给专门的HTTPS后端服务器处理

6.自定义错误页面

设置不同的404错误页面,区分HTTP和HTTPS请求。

案例

​如果是HTTP请求,会返回error.http错误页面

如果是HTTPS请求,会返回error.https错误页面

8.配置SSL参数
server {
  listen 443 ssl;
​
  ssl_certificate certificate.pem;
  ssl_certificate_key private.key;
​
  #其他SSL配置
}
​

处理HTTPS请求,提供SSL加密支持

验证客户端证书的合法性

提高传输层安全性,保护数据安全

符合网站安全最佳实践