【Nginx】反向代理原理

一、正向代理

说到反向代理,那也不得不提一下正向代理。

什么是正向代理?

正向代理是一种代理模式,它通常位于客户端,允许客户端通过它来发起请求到真正的目标服务器,从而隐藏客户端的身份或改善性能。

举个栗子,企业或学校网络中的代理服务器。

内部网络的用户必须通过这台代理服务器来访问互联网上的资源。

这样做的目的可能是为了实现上网内容过滤、缓存以加速访问和减少带宽消耗,或者是为了达到监控和控制用户上网行为的目的。

用户在浏览器或其他网络应用中配置代理服务器的地址和端口,所有对外的 HTTP 或 HTTPS 请求都会先发送到这个代理服务器,再由代理服务器转发到互联网上的目标服务器。 

“梯子”的原理也是正向代理 

二、反向代理

什么是反向代理?

反向代理是一种服务器端技术,它拦截来自客户端的请求,并作为客户端的代理向后端服务器发出请求,然后将结果返回给客户端。 

举个栗子,使用如 Nginx 或 HAProxy 这样的软件来管理进入网站的流量。

在这种设置下,当用户尝试访问一个网站(比如 www.example.com)时,他们的请求实际上首先到达反向代理服务器。这个代理服务器根据一定的规则决定如何将请求路由到后台的多个实际服务器之一。

这种架构可以帮助负载均衡、提高安全性(因为外部世界只直接与代理服务器交互,而不是直接与后端服务器),并且可以提供 SSL 终止、压缩响应等附加服务。

 

三、总结

一句话总结,正向代理就是代理客户端,用户可以感受到;反向代理就是代理服务端,用户感受不到。

四、基础配置 

使用 Nginx 做反向代理并不复杂,只需要简单的配置即可:

// 定义了一个新的服务器块(server block),用于处理特定域名或 IP 地址的请求
server {
    // 指定这个服务器块监听标准的 HTTP 端口 80
    listen 80;

    // 指定了这个服务器块负责处理域名为 example.com 的请求
    server_name example.com;

    // 定义了一个位置块(location block),这里设置的是对根路径/的所有请求都将被代理到另一个服务器
    location / {
        // 配置了代理的行为,告诉 Nginx 将所有针对/的请求转发到本地主机的 8000 端口上
        // 这里的localhost指的是运行 Nginx 服务器的机器本身
        proxy_pass http://localhost:8000;

        // 设置了代理传递给后端服务器的 Host 头部信息
        // 这使得后端服务器知道原始请求的目标主机名
        proxy_set_header Host $host;

        // 设置了 X-Real-IP 头部,让后端服务器知道原始客户端的真实 IP 地址
        proxy_set_header X-Real-IP $remote_addr;

        // 这个指令用于添加或修改 X-Forwarded-For 头部
        // 该头部包含了客户端和代理之间的完整 IP 地址列表
        // 如果请求经过了多个代理,这些代理会依次追加它们的信息到这个头部字段中
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

这段配置的作用是:当有请求到达 example.com 且目标路径为 / 时,Nginx 将会把请求转发到localhost:8000,同时会向后端服务器提供必要的头部信息,以便后端服务器能够正确识别请求的来源

关于 Nginx 的其他配置,这里就不详细展开了 

 

五、使用场景

下来罗列一下 Nginx 的使用场景:

1、负载均衡: Nginx可以作为负载均衡器,将请求分发到多个后端服务器,从而提高系统的吞吐量和可用性。这可以通过使用 upstream 指令和 proxy_pass 指令来实现。

http {
    upstream backend {
        # 定义一个名为backend的上游服务器组
        server backend1.example.com:80;
        server backend2.example.com:80;
    }

    server {
        listen 80;
        server_name example.com;

        location / {
            proxy_pass http://backend;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
}

2、SSL/TLS终止: Nginx 可以在反向代理服务器上终止 SSL/TLS 连接,从而释放后端服务器处理加密通信的开销。客户端与 Nginx 之间的通信是加密的,但 Nginx 与后端服务器之间的通信可以是明文的,这简化了后端服务器的配置和管理。

http {
    upstream backend {
        server localhost:8000;  # 假设后端服务器监听在8000端口
    }

    # SSL证书和密钥所在的位置
    ssl_certificate /etc/nginx/ssl/example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;

    # SSL相关设置
    ssl_protocols TLSv1.2 TLSv1.3;  # 使用最新的协议版本
    ssl_ciphers HIGH:!aNULL:!MD5;   # 加密套件选择
    ssl_prefer_server_ciphers on;   # 优先使用服务器加密套件

    server {
        listen 443 ssl;             # 监听443端口,并启用SSL
        server_name example.com www.example.com;  # 处理example.com和其子域的请求

        location / {
            proxy_pass http://backend;
            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_set_header X-Forwarded-Proto $scheme;  # 告诉后端请求是通过HTTPS来的
        }
    }

    # 可选:重定向所有HTTP请求到HTTPS
    server {
        listen 80;
        server_name example.com www.example.com;
        return 301 https://$host$request_uri;
    }
}

3、缓存: Nginx 可以配置为缓存来自后端服务器的响应。当相同的请求再次到达时,Nginx 可以直接从缓存中提供响应,而无需再次请求后端服务器。这可以大大减少后端服务器的负载并提高响应速度。

http {
    # 定义缓存区
    proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m inactive=60m;

    # 缓存相关的默认设置
    proxy_cache_key "$scheme$request_method$host$request_uri";
    proxy_cache_valid 200 60m;
    proxy_cache_valid 404 1m;
    proxy_cache_use_stale error timeout invalid_header updating http_500;

    server {
        listen 80;
        server_name example.com;

        location /static/ {  # 指定缓存规则应用于/static/目录下的请求
            proxy_pass http://backend;
            proxy_cache my_cache;  # 使用前面定义的缓存区
            proxy_cache_bypass $http_pragma;  # 如果请求包含'Pragma: no-cache',则绕过缓存
            add_header X-Cache-Status $upstream_cache_status;  # 添加X-Cache-Status头显示缓存状态

            # 设置缓存控制
            proxy_cache_revalidate on;
            proxy_cache_min_uses 1;
            proxy_cache_lock on;
            proxy_cache_methods GET HEAD;
            proxy_ignore_headers Cache-Control Expires;

            # 设置缓存刷新
            proxy_cache_min_data 1k;
            proxy_cache_background_update on;
            proxy_cache_remove_headers Set-Cookie;
            proxy_hide_header Vary;
        }

        # 如果缓存未命中,则直接请求后端
        location = /favicon.ico { access_log off; log_not_found off; }
        location = /robots.txt { access_log off; log_not_found off; }

        # 其他location块...
    }
}

4、访问控制和安全: 通过 Nginx 反向代理,您可以实施各种访问控制和安全措施,例如限制特定IP地址的访问、过滤恶意请求、实施 CORS 策略等。这有助于保护您的后端服务器免受未经授权的访问和攻击。

http {
    # 定义一个变量来保存客户端的IP地址
    geo $allowed {
        default 0;
        192.168.1.0/24 1;  # 允许特定的子网访问
        10.0.0.0/8 1;      # 允许私有IP地址范围内的访问
    }

    # 定义一个map来检查请求频率
    map $remote_addr $limit_req_status {
        default 0;
        ~^(127\.0\.0\.1|::1)$ 0;  # 不限制本地回环地址
        default 1;
    }

    # 定义限制请求速率的配置
    limit_req_zone $binary_remote_addr zone=one:10m rate=5r/s;

    server {
        listen 80;
        server_name example.com;

        # 配置限制特定IP地址的访问
        if ($allowed = 0) {
            return 403;
        }

        # 过滤恶意请求
        set $bad_request 0;
        if ($request_uri ~* "(sql|script|<script>|<iframe>)") {
            set $bad_request 1;
        }
        if ($bad_request = 1) {
            return 403;
        }

        # 实施CORS策略
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';

        if ($request_method = 'OPTIONS') {
            add_header 'Content-Type' 'text/plain charset=UTF-8';
            add_header 'Content-Length' 0;
            return 204;
        }

        location / {
            proxy_pass http://backend;
            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_set_header X-Forwarded-Proto $scheme;

            # 限制请求速率
            limit_req zone=one burst=5 nodelay;
        }
    }
}

5、静态文件服务: Nginx 可以高效地处理静态文件请求,如 HTML、CSS、JavaScript 和图片等。通过配置 Nginx 来提供静态文件服务,可以减轻后端服务器的负担并提高整体性能。您可以使用 root 指令或 alias 指令来指定静态文件的位置。

http {
    server {
        listen 80;
        server_name example.com;

        root /var/www/html;  # 指定静态文件的根目录

        # 设置索引文件
        index index.html index.htm;

        # 静态文件的处理
        location / {
            try_files $uri $uri/ =404;  # 尝试直接提供请求的文件,如果不存在则返回404
        }

        # 配置静态资源的缓存
        location ~* \.(jpg|jpeg|gif|png|css|js|ico|xml|webp|svg)$ {
            expires max;  # 设置这些文件的缓存过期时间为最大值
            log_not_found off;  # 请求日志中忽略404错误
            access_log off;  # 关闭访问日志记录
        }

        # 配置压缩
        gzip on;
        gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

        # 错误页面处理
        error_page 404 /404.html;
        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
            root /usr/share/nginx/html;  # 指定错误页面的位置
        }
    }
}

6、日志记录和监控: Nginx 提供了强大的日志记录功能,可以记录请求的详细信息,如请求时间、来源 IP、请求的 URL 等。这些日志可以用于监控和分析系统的行为,以便及时发现和解决问题。您可以使用内置的日志格式或自定义日志格式来满足特定的需求。

http {
    # 自定义日志格式
    log_format custom_format '$remote_addr - [$time_local] "$request" '
                             '$status $body_bytes_sent "$http_referer" '
                             '"$http_user_agent" "$http_x_forwarded_for"';

    # 启用gzip压缩
    gzip on;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

    server {
        listen 80;
        server_name example.com;

        # 访问日志
        access_log /var/log/nginx/access.log custom_format;

        # 错误日志
        error_log /var/log/nginx/error.log;

        location / {
            root /var/www/html;
            index index.html index.htm;

            # 尝试直接提供请求的文件,如果文件不存在,则尝试提供一个目录
            try_files $uri $uri/ =404;
        }

        # 静态文件的处理
        location ~* \.(jpg|jpeg|gif|png|css|js|ico|xml|webp|svg)$ {
            expires max;
            log_not_found off;
            access_log off;
        }

        # 错误页面处理
        error_page 404 /404.html;
        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
            root /usr/share/nginx/html;
        }
    }
}

7、高可用性: 通过将多个 Nginx 实例配置为高可用性集群,您可以确保即使某个实例发生故障,其他实例仍然可以继续提供服务。这可以通过使用第三方工具如 Keepalived 或 HAProxy 来实现。

在主节点(Master)上的 /etc/keepalived/keepalived.conf 配置文件如下:

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.1.100
    }
}

vrrp_script chk_http {
    script "/usr/local/bin/check_nginx.sh"
    interval 2
    weight -2
}

track_script {
    chk_http
}

 在备用节点(Backup)上的 /etc/keepalived/keepalived.conf 配置文件如下:

vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 51
    priority 99
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.1.100
    }
}

vrrp_script chk_http {
    script "/usr/local/bin/check_nginx.sh"
    interval 2
    weight -2
}

track_script {
    chk_http
}

创建一个简单的脚本来检查 Nginx 的状态: 

#!/bin/bash
nginx_pid=$(pgrep nginx)
if [ -z "$nginx_pid" ]; then
    echo "Nginx is not running."
    exit 1
else
    echo "Nginx is running with PID: $nginx_pid"
fi

将上述脚本保存为 /usr/local/bin/check_nginx.sh,并赋予执行权限: 

chmod +x /usr/local/bin/check_nginx.sh

8、动态内容压缩: Nginx 支持在传输过程中对动态内容进行压缩,以减小传输的大小并提高响应速度。您可以使用 gzip 模块来启用压缩功能,并指定需要压缩的文件类型和压缩级别。

http {
    # 开启gzip压缩功能
    gzip on;

    # 设置压缩级别,数值从1到9,数值越大压缩效果越好,但是CPU消耗也越大
    gzip_comp_level 6;

    # 设置压缩最小文件大小,只有超过这个大小的文件才会被压缩
    gzip_min_length 1024;

    # 设置压缩类型,这里列出了常见的文本和脚本文件类型
    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

    # 是否压缩已有的压缩文件,如gzipped文件
    gzip_vary on;

    # 设置缓存压缩后的数据,以便重复利用
    gzip_proxied any;

    # 设置过期时间,压缩后的数据多久可以被认为是有效的
    gzip_buffers 16 8k;

    # 设置HTTP响应头,告诉浏览器如何处理过期的压缩数据
    gzip_http_version 1.1;

    server {
        listen 80;
        server_name example.com;

        location / {
            root /var/www/html;
            index index.html index.htm;

            # 尝试直接提供请求的文件,如果文件不存在,则尝试提供一个目录
            try_files $uri $uri/ =404;
        }
    }
}

注意:这里压缩级别建议 6 即可,在保证压缩效果的同时对于 CPU 的消耗也不会过大(实际呀u送效果跟 9 差别不会特别大) 

9、重定向和重写: Nginx 提供了强大的重定向和重写功能,可以根据请求的 URL 或其他条件将请求重定向到其他位置或重写 URL。这对于实现 URL 重写规则、处理旧版本应用的重定向或实现特定的业务逻辑非常有用。您可以使用 rewrite 指令和 return 指令来实现重定向和重写功能。

将所有来自http://example.com/oldpath/*的请求永久重定向到https://newsite.com/newpath/*

server {
    listen 80;
    server_name example.com;

    # 永久重定向
    return 301 https://newsite.com$request_uri;
}

 10、集成第三方模块: Nginx 支持通过加载第三方模块来扩展其功能。这些模块可以为您提供额外的功能如身份验证、限流、WAF(Web 应用防火墙)等。通过集成这些模块,您可以增强 Nginx 的安全性和功能性以满足特定的需求。 

ngx_http_limit_conn_module 是一个常用的模块,用于限制并发连接数。下面是一个示例,演示如何限制对特定资源的访问。

http {
    # 配置用于限流的key
    limit_conn_zone $binary_remote_addr zone=perip:10m;
    limit_conn_zone $http_cookie zone=peruser:10m;

    server {
        listen 80;
        server_name example.com;

        # 限制对特定路径的访问
        location /api/ {
            # 每个IP每秒最多5个请求
            limit_req zone=perip burst=5 nodelay;
            # 每个用户每秒最多10个请求
            limit_req zone=peruser burst=10 nodelay;
            proxy_pass http://app_backend;
        }
    }
}

ModSecurity 是一个流行的开源Web应用防火墙,它可以集成到Nginx中以保护Web应用免受常见攻击。

http {
    # 加载ModSecurity模块
    include /etc/nginx/conf.d/modsecurity.conf;

    server {
        listen 80;
        server_name example.com;

        # 启用ModSecurity
        modsecurity on;

        # 配置规则集
        modsecurity_rules_file /etc/nginx/modsecurity/crs/rules/*.conf;

        location / {
            proxy_pass http://app_backend;
        }
    }
}

参考文章:

深入解析NGINX反向代理

一文带你彻底搞懂Nginx反向代理-阿里云开发者社区 (aliyun.com) 

Nginx保姆级入门——什么是反向代理?Nginx能实现哪些功能? 

nginx反向代理原理和配置讲解 

nginx反向代理原理 

 

一  叶  知  秋,奥  妙  玄  心

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qx_java_1024

祝老板生意兴隆,财源广进!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值