Nginx:负载均衡、动静分离、目录穿越漏洞

admin 2024年12月3日14:13:44评论8 views字数 5536阅读18分27秒阅读模式

声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由用户承担全部法律及连带责任,文章作者不承担任何法律及连带责任!

Nginx负载均衡

什么是Nginx负载均衡

Nginx 把请求均匀的分摊给上游的应用服务器,这样即使某一个服务器宕机也不会影响请求的处理,或者当应用服务器扛不住了,可以随时进行扩容。 

为什么需要负载均衡

现在高流量网站必须以快速可靠的方式处理来自用户或客户端大量的并发请求并且返回正确的数据。为了经济高效地扩展以满足这些高容量,我们往往需要添加更多的服务器。

Nginx负载均衡器解决了什么

负载均衡器充当坐在服务器前面的交通警察,并在所有能够以最大化速度和容量利用率的方式满足这些请求的所有服务器之间路由客户端请求,并确保没有任何服务器过度工作,保证服务器集群的性能。如果在服务器集群中某个服务器出现故障,负载均衡器会将流量重定向到其余正常工作的服务器。当一个新的服务器添加到服务器集组时,负载均衡器会自动开始向他发送请求。

总结:负载平衡器执行以下功能

  • 跨多个服务器有效地分配客户端请求或网络负载

  • 通过仅向在线服务器发送请求来确保高可用性和 可靠性

  • 提供根据需求添加或减少服务器的灵活性

Nginx:负载均衡、动静分离、目录穿越漏洞

负载均衡算法

  • Round Robin -- 轮询为负载均衡中较为基础的算法,不需要配置额外参数。假设配置文件中共有M台服务器,该算法遍历服务器节点列表,并按节点次序选择一台服务器处理请求。当所有节点均被调用过一次后,该算法将从第一个节点开始重新一遍遍历。由于该算法中每个请求按时间顺序逐一分配到不同的服务器处理,因此适用于服务器性能相近的集群情况,其中每个服务器承载相同的负载。但对于服务器性能不同的集群而言,该算法容易引发资源分配不合理等问题。

    upstream bakend {  
      server 192.168.0.1;    
      server 192.168.0.2;  
    }
  • Weight -- 加权轮询,为了避免基础的轮询算法带来的弊端,加权轮询应运而生。在加权轮询中,每个服务器会有各自的weight。一般情况下,weight的值越大,承载的请求数越多,尽量为性能高的服务器配置较大的权重。

    upstream bakend {  
      server 192.168.0.1 weight=10;  
      server 192.168.0.2 weight=10;  
    }
  • url Hash -- url_hash是根据请求的URL的hash值来分配服务器,相同的URL请求会被分配给固定的服务器,当存在缓存的时,效率会很高,很好的解决了session共享问题。然而Nginx默认不支持该负载均衡算法,需要依赖第三方库。

    upstream backend {  
      server 192.168.0.1:88;  
      server 192.168.0.2:80;  
      hash $request_uri;  
      hash_method crc32;  
    }
  • IP Hash -- IP hash是根据请求的客户端地址来分配服务器,其效果与上者相同(仅限HTTP)。

    upstream bakend {  
      ip_hash;  
      server 192.168.0.1:88;  
      server 192.168.0.2:80;  
    }
  • fair -- 可以依据页面大小和加载时间长短进行负载均衡,即根据后端服务器的响应时间来分配请求,响应时间短的优先分配,Nginx本身不支持fair。若需要使用该算法,须下载Nginx的upstream_fair模块。

    upstream backend {  
      server 192.168.0.1:88;  
      server 192.168.0.2:80;  
      fair;  
    }
  • Least Connections -- 一个新的请求会被发送到与客户端当前连接最少的服务器。每台服务器的相对计算能力是确定哪台服务器连接最少的因素。

  • Least Time -- 将基于响应时间和活跃连接数进行综合计算,将请求转发到负载最小的服务器 —— 这是只有 NGINX Plus 可以提供的独有功能。

  • Random with Two Choices -- 随机选择两台服务器并将请求转发到活动连接数较少的服务器(即,上方提到的“最少连接”算法)。通过使用 NGINX Plus,还可以通过“最少时间”算法优化使用效果。

负载均衡的配置

以加权轮询为例,展示简要步骤

  1. 搭载一台nginx服务器

    mkdir /soft/nginx -p
    wget https://nginx.org/download/nginx-1.21.6.tar.gz
    tar -xvzf nginx-1.21.6.tar.gz
    yum install --downloadonly --downloaddir=/soft/nginx/ gcc-c++
    yum install --downloadonly --downloaddir=/soft/nginx/ pcre pcre-devel4
    yum install --downloadonly --downloaddir=/soft/nginx/ zlib zlib-devel
    yum install --downloadonly --downloaddir=/soft/nginx/ openssl openssl-devel
    yum install --downloadonly --downloaddir=/soft/nginx/ gcc
    cd /soft/nginx && rpm -ivh --nodeps *.rpm
    cd /root/nginx-1.21.6 && ./configure --prefix=/soft/nginx/
    make && make install
    systemctl start firewalld
    firewall-cmd --zone=public --add-port=80/tcp --permanent && firewall-cmd --reload
  2. 更改配置文件

    worker_processes  1;

    events {
      worker_connections  1024;
    }

    http {
      include       mime.types;
      default_type application/octet-stream;
      sendfile       on;
      keepalive_timeout  65;
       #gzip on;    

      upstream nginx_boot {
          server 192.168.218.132:82 weight=100;
          server 192.168.218.132:81 weight=200;
                      }

      server {
    location / {
    root html;
    index index.html index.htm index.jsp index.ftl;
    proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://nginx_boot;
              }
            }
        }
  3. 使用docker增加两个节点,也可以再创建两个虚拟机

    docker pull nginx
    docker run -d --name web1 -p 81:80 nginx:latest
    docker run -d --name web2 -p 82:80 nginx:latest
    docker exec -it web1 /bin/bash
    echo this is 81 > /usr/share/nginx/html/index.html
    exit
    docker exec -it web2 /bin/bash
    echo this is 82 > /usr/share/nginx/html/index.html
    exit
    /soft/nginx/sbin/nginx -c /soft/nginx/conf/nginx.conf

Nginx动静分离

场景

我们请求一个网站时,我们可以发现往往需要100+的请求数。

Nginx:负载均衡、动静分离、目录穿越漏洞

仔细地观察可以发现,这里面大多数文件都是.js、.css、.jpg……这类的静态文件。假如这100+个并发请求都交给后端服务器去处理,无疑后端服务器的压力是巨大的。在我们这里虽然只有100+个文件,但是此时此刻又有成千上万的人在发起类似请求,这一定是一个庞大的数据量。那么我们如何解决这样的情况?答案是Nginx动静分离!

Nginx动静分离如何实现

我们已经知道,在这100+的请求中,大部分都是在请求静态资源。正常情况下,这种静态资源一般不会出现变动。我们要时刻明确我们的根本目的是减轻后端服务器的并发压力,所以我们就可以将这些静态资源放在前端服务器上面。这样做了以后,至少可以减少后端服务器一半以上的并发量。

在我们正常项目开发时,我们可以将静态资源放到resources/static/目录下:

Nginx:负载均衡、动静分离、目录穿越漏洞

在项目上线部署时,我们需要将这些静态资源一起打包放到Nginx服务器上。

具体步骤:

静态资源:192.168.218.132

动态资源:192.168.218.133

方法一:

  1. 在部署好的nginx目录下创建一个专门存放静态文件的目录static

    mkdir /soft/nginx/html/static
  2. 将打包好的静态资源文件拷贝到该目录下并解包。(文件style.css内容如下)

    p {color:red}
  3. 配置后端服务器(文件index.html内容如下)

    <!DOCTYPE html>
    <html lang="en">
    <head>
       <meta charset="UTF-8">
       <meta http-equiv="X-UA-Compatible" content="IE=edge">
       <meta name="viewport" content="width=device-width, initial-scale=1.0">
       <title>Document</title>
       <link rel="stylesheet" href="style.css">
    </head>
    <body>
       <p>I am an ikun!</p>
    </body>
    </html>
  4. 修改一下nginx.conf配置文件,在server里面增加以下规则:

    upstream nginx_boot{
    server 192.168.218.133;
    # 这里的IP配置成后端服务所在的机器IP
    }

    server {
    listen 80;
    server_name 192.168.218.132;

    location / {
    root html;
    # 配置一下index的地址,最后加上index.ftl。
    index index.html index.htm index.jsp index.ftl;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    # 请求交给名为nginx_boot的upstream上
    proxy_pass http://nginx_boot;
    }

    location ~ .*.(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css) {
    root html/static;
    expires 7d;
    }
    }

    # ~代表匹配时区分大小写;.*代表不限制资源名;括号内代表静态资源类型;root后面是静态文件的所在的目录;expires代表缓存天数
  5. 刷新一下nginx服务并重启

    /soft/nginx/sbin/nginx -s reload -c /soft/nginx/conf/nginx.conf
  6. 效果

    Nginx:负载均衡、动静分离、目录穿越漏洞

方法二:

将静态资源上传到文件服务器,然后location中配置一个新的upstream指向。

目录穿越漏洞(CVE-2020-17519)

场景

常见于Nginx做了反向代理的情况,动态资源文件被proxy_pass传递给后端端口,而Nginx服务器来处理静态资源文件。

而一些静态文件存储在/home/目录下,而该目录在url中的名字为files,那么就需要用alias设置目录别名。

其实根本原因还是我们设置目录别名时配置不规范导致,因此我们可以模拟一个最简单的环境。

server {
      listen 80;
      server_name 192.168.218.132;


      location / {
      root html;
      index index.html;
              }
      location /files {
              alias /home/;
              autoindex on;
                }
}

漏洞原理

我们发现,location上的files后面是没有/的,而alias设置的/home/是有后缀/的。这个/就是导致漏洞穿越的罪魁祸首。因为我们在访问files时,由于后面没有闭合,我们仍可以在后面添加指令,比如files..,此时files代表/home/,然后我们再执行..指令就会回到根目录下,此时我们将得到一个任意文件读取的漏洞。

示例

Nginx:负载均衡、动静分离、目录穿越漏洞

解决方案

我们只需要保证/files和/home后面都有/后缀或者都没有即可。

参考链接

https://blog.csdn.net/apple9005/article/details/79961391

https://www.nginx-cn.net/products/nginx/load-balancing/

原文始发于微信公众号(鱼板安全):Nginx:负载均衡、动静分离、目录穿越漏洞

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年12月3日14:13:44
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Nginx:负载均衡、动静分离、目录穿越漏洞https://cn-sec.com/archives/2492604.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息