YOLO813

Web服务器测试: Nginx的反向代理、限速、url重写

Nginx反向代理

    反向代理,隐藏服务器信息,可以保证内网的安全,通常将反向代理作为公网访问地址,web服务器是内网。直接上示例,Nginx反向代理只需要在server中配置一个proxy_pass即可。

location / {
  #真正主机IP8080端口所存放的页面
  proxy_pass http://217.**.*.***:8080;
}

    看起来和页面重定向有些相似,但实际完全不同,这种方法,访问的还是原本的公网IP,只不过从真正的主机8080端口取来了数据。

     从谷歌调试工具中(下图),可以看到远程地址为反向代理的IP及端口,真实的主机地址被隐藏了。

    再来看看反向代理中nginx的日志

    真实主机上的nginx的日志

    看上面的日志信息,发现会有一个问题,真实主机上获取到的IP永远都是反向代理的服务器IP地址,如何获取真实客户端IP呢?优化建议如下:

location / {
    proxy_pass ****;
    
    proxy_set_header Host $host;
    #在web服务器端获得用户的真实ip【 $remote_addr值 = 用户ip 】
    proxy_set_header X-Real-IP $remote_addr;
    #在web服务器端获得用户的真实ip
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    
    client_max_body_size 10m;#允许客户端请求的最大单文件字节数
    client_body_buffer_size 128k;#缓冲区代理缓冲用户端请求的最大字节数,
    proxy_connect_timeout 90;#nginx跟后端服务器连接超时时间\(代理连接超时\)
    proxy_send_timeout 90;#后端服务器数据回传时间\(代理发送超时\)
    proxy_read_timeout 90;#连接成功后,后端服务器响应时间\(代理接收超时\)
    proxy_buffer_size 4k;#设置代理服务器(nginx)保存用户头信息的缓冲区大小
    proxy_buffers 4 32k;#proxy_buffers缓冲区,网页平均在32k以下的话,这样设置
    proxy_busy_buffers_size 64k;#高负荷下缓冲大小(proxy_buffers*2)
    proxy_temp_file_write_size 64k;#设定缓存文件夹大小,大于这个值,将从upstream服务器传
}

    隐藏主机上成功获取真实客户端IP,下图


Nginx限速

    通过Nginx限速,防止DDos攻击,防止磁盘卡死,具体有以下两种限速场景,第一种:下载限速。限制下载速度及并发连接数,应用在下载服务器中,保护带宽及服务器的IO资源。第二种:请求限速。限制单位时间内用户访问请求,防止恶意攻击,保护服务器及资源安全。

    原理:漏桶原理。

    Nginx官方版本限制IP的连接和并发分别有两个模块:

    limit_req_zone 用来限制单位时间内的请求数,即速率限制,采用的漏桶算法 “leaky bucket”。

    limit_conn_zone 用来限制同一时间连接数,即并发限制。

    先来测试第一种limit_req_zone,在html新建abc目录,没有设限之前,可以使用elinks无限访问(建议不要用浏览器测试,会有缓存)

    配置nginx.conf文件,重启以生效

http{
  #设置漏桶
  #基于IP对下载速度进行限制,限制每秒处理一个请求,对突发超过5个以上的丢入缓存区
  #第一个参数:$binary_remote_addr 表示通过remote_addr这个标识来做限制,“binary_”的目的是缩写内存占用量,是限制同一客户端ip地址。
  #第二个参数:zone=zhangxiaofei:10m表示生成一个大小为10M,名字为zone的内存区域,用来存储访问的频次信息。
  #第三个参数:rate=1r/s表示允许相同标识的客户端的访问频次每秒1次
  limit_req_zone $binary_remote_addr zone=zhangxiaofei:10m rate=1r/s;
  server{
    #第一个参数:zone=zhangxiaofei 设置使用哪个配置区域来做限制,与上面limit_req_zone 里的name对应。
    #第二个参数:burst=5,这个配置的意思是设置一个大小为5的缓冲区,当有大量请求(爆发)过来时,超过了访问频次限制的请求可以先放到这个缓冲区内。
    #第三个参数:nodelay,如果设置,超过访问频次而且缓冲区也满了的时候就会直接返回503,如果没有设置,则所有请求会等待排队。
    location /abc {
           limit_req zone=zhangxiaofei burst=5 nodelay;
       }
  }
}

    再次使用elinks测试,成功拦截,返回503页面

    可以使用netstat -antpl查看IP访问情况,可以看到均在TIME_WAIT状态,如下图:

    再来进行第二种并发测试。

#创建200M测试文件
dd if=/dev/zero of=testfile bs=1M count=200

  未做限制前,我开几个连接下载都OK(由于带宽只有1M,下载速度确实只有125K这个速度。。。)

    配置文件更改之后

http{
  limit_conn_zone $binary_remote_addr zone=speed_down:10m;
  server{
    location /abc {
           #1个连接
           limit_conn speed_down 1;
           limit_rate 10k;
           # 包下载到多大时开始限速
           limit_rate_after 100m;
       }
  }
}

再次开启多个连接下载,返回503,并且下载速度也降低到10K限速,如下:


Nginx重写url

    模块名:ngx_http_rewrite_module。一般用于网址的重定向或者制作伪静态页面便于CDN缓存,重定向rewrite依赖PCRE库(Perl Compatible Regular Expressions)。

    URL模块语法,主要有以下5种

    set,设置变量

    if,条件判断

    return,返回状态码或者url

    break,终止后续rewrite规则

    rewrite,重定向url

    set介绍

set $variable value;
Context:
# 可以用于以下三种作用域
server, location, if

配置文件加入以下代码测试,成功跳转

location / {
  set $name zhangxiaofei;
  rewrite ^(.*)$ http://112.126.88.219/$name;
 }

    if简介

if (condition) { … }
Context:
server, location

    让谷歌浏览器访问首页返回403

location / {
 #http_user_agent内置nginx变量
 # ~模糊匹配 ~*不区分大小写的匹配
 # =精确匹配
  if ($http_user_agent ~* 'Chrome'){
      return 403;
  }
 }


    return简介

return code URL;
Context:    
server, location, if


    break简介,停止执行当前虚拟主机的后续rewrite指令集

Context:server, location, if


    rewrite指令,重写url。语法如下

rewrite <regex> <replacement> [flag];

    flag有以下四种

    last,本条规则匹配完成后,以重写后的url继续向下匹配新的location URI规则,以最后匹配的规则为准,最多匹配10次,超过10次返回500错误。

    break,本条规则匹配完成即终止,不再匹配后面的任何规则,类似临时重定向,状态码返回302。

    redirect,302。

    permanent,301。

    last用法示例,目标:访问112.126.88.219/hello访问跳转至112.126.88.219/chrome//hello/,先创建相对应文件夹,否则会报404错误:

cd html/;mkdir chrome;cd chrome/;mkdir hello;echo chrome > index.html

    nginx.conf配置文件

location / {
  if ($http_user_agent ~* 'chrome'){
    rewrite ^(.*)$ /chrome/$1 last;
  }
  location /chrome {
    root html;
    index index.html;
  }
}