跳到主要内容

[toc]

nginx代理

nginx反向代理官方文档

1.代理分类

nginx代理分为正向代理和反向代理

  • 正向代理代理的对象是客户端

  • 反向代理代理的对象是服务端

正向代理

概念

在如今的网络环境下,我们如果由于技术需要要去访问国外的某些网站,此时你会发现位于国外的某网站我们通过浏览器是没有办法访问的,此时大家可能都会用一个操作FQ进行访问,FQ的方式主要是找到一个可以访问国外网站的代理服务器,我们将请求发送给代理服务器,代理服务器去访问国外的网站,然后将访问到的数据传递给我们!

上述这样的代理模式称为正向代理,正向代理最大的特点是客户端非常明确要访问的服务器地址;服务器只清楚请求来自哪个代理服务器,而不清楚来自哪个具体的客户端;正向代理模式屏蔽或者隐藏了真实客户端信息。

示意图

iShot2020-06-1620.45.14

反向代理

概念

多个客户端给nginx服务器发送请求,nginx服务器接收到请求之后,按照一定的规则分发给了后端的业务处理服务器进行处理。此时请求的来源也就是客户端是明确的,但是请求具体由哪台服务器处理的就不明确了,nginx扮演的就是一个反向代理角色

反向代理,主要用于服务器集群分布式部署的情况下,反向代理隐藏了服务器的信息!

示意图

iShot2020-06-1620.36.29

项目场景

通常情况下,我们在实际项目操作时,正向代理和反向代理很有可能会存在在一个应用场景中,正向代理代理客户端的请求去访问目标服务器,目标服务器是一个反向代理服务器,反向代理了多台真实的业务处理服务器。公司的生产环境就是如下图所示,公司的核心业务SASS平台是这样的流程

域名解析到了阿里云的SLB,通过SLB把请求分发到公司公共nginx(两台ECS),然后又在公共nginx上配置了具体的转发规则(location的匹配,upstream等),最后把请求的流量转发到ECS中,下图中的正向代理就相当于我们的SLB,反向代理就相当于我们的公共nginx,业务服务器就相当于后端的真实web服务ECS

具体的拓扑图如下

iShot2020-06-1620.39.01

2.nginx代理配置相关

语法

字段说明
Syntax:proxy_pass URL;
Default:
Context:location, if in location, limit_except

2.1 将请求传递到代理服务器

当NGINX代理请求时,它将请求发送到指定的代理服务器,获取响应,然后将其发送回客户端。可以使用指定协议将请求代理到HTTP服务器(另一个NGINX服务器或任何其他服务器)或非HTTP服务器(可以运行使用特定框架开发的应用程序,例如PHP或Python)。支持的协议包括FastCGIuwsgiSCGImemcached

要将请求传递到HTTP代理服务器,请在proxy_pass中指定指令location。例如:

location /some/path/ {
proxy_pass http://www.example.com/link/;
}

此示例配置结果将在此位置处理的所有请求传递到指定地址的代理服务器。此地址可以指定为域名或IP地址。地址还可以包括一个端口:

location ~ \.php {
proxy_pass http://127.0.0.1:8000;
}

注意,在上面的第一个示例中,代理服务器的地址后跟URI /link/。如果URI与地址一起指定,它将替换与位置参数匹配的请求URI部分。例如,这里带有/some/path/page.html URI的请求将被代理到http://www.example.com/link/page.html。如果指定的地址没有URI,或者无法确定要替换的URI部分,则传递(可能是修改)完整的请求URI。

要将请求传递到非HTTP代理服务器,**_pass应使用适当的指令

请注意,在这些情况下,用于指定地址的规则可能会有所不同。您可能还需要将其他参数传递给服务器(有关更多详细信息,请参见参考文档)。

proxy_pass指令还可以指向服务器的命名组。在这种情况下,将根据指定的方法在组中的服务器之间分配请求。

代理到后端的TCP连接、响应、返回等超时时间

# nginx代理与后端服务器连接超时时间(代理连接超时)
Syntax: proxy_connect_timeout time;
Default: proxy_connect_timeout 60s;
Context: http, server, location

# nginx代理等待后端服务器的响应时间
Syntax: proxy_read_timeout time;
Default: proxy_read_timeout 60s;
Context: http, server, location

# 后端服务器数据回传给nginx代理超时时间
Syntax: proxy_send_timeout time;
Default: proxy_send_timeout 60s;
Context: http, server, location

2.2 传递请求头

默认情况下,NGINX在代理请求中重新定义两个头字段“ Host”和“ Connection”,并消除其值为空字符串的标头字段。“主机”设置为$proxy_host变量,“连接”设置为close

要更改这些设置以及修改其他标题字段,请使用proxy_set_header伪指令。可以在location或更高版本中指定此指令。也可以在特定server上下文或http块中指定。例如:

location /some/path/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://localhost:8000;
}

在此配置中,“主机”字段设置为$host变量。

为了防止将头字段传递给代理服务器,请按以下步骤将其设置为空字符串:

location /some/path/ {
proxy_set_header Accept-Encoding "";
proxy_pass http://localhost:8000;
}

添加发往后端服务器的请求头信息

# 用户请求的时候HOST的值是www.abc.com, 那么代理服务会像后端传递请求的还是www.abc.com
proxy_set_header Host $http_host;

# 将$remote_addr的值放进变量X-Real-IP中,$remote_addr的值为客户端的ip
proxy_set_header X-Real-IP $remote_addr;

# 客户端通过代理服务访问后端服务, 后端服务通过该变量会记录真实客户端地址
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

2.3 配置缓冲区

默认情况下,NGINX缓冲来自代理服务器的响应。响应存储在内部缓冲区中,直到接收到整个响应后才发送给客户端。缓冲有助于优化慢速客户端的性能,如果响应从NGINX同步传递到客户端,则这可能会浪费代理服务器的时间。但是,启用缓冲后,NGINX允许代理服务器快速处理响应,而NGINX将响应存储的时间与客户端下载响应所需的时间一样长。

负责启用和禁用缓冲的指令是proxy_buffering。默认情况下将其设置为on并启用缓冲。

proxy_buffers指令控制规模和分配的请求缓冲区的数目。来自代理服务器的响应的第一部分存储在单独的缓冲区中,缓冲区的大小由proxy_buffer_size伪指令设置。这部分通常包含一个相对较小的响应头,并且可以使其小于其余响应的缓冲区。

在以下示例中,增加了默认缓冲区数,并使响应第一部分的缓冲区大小小于默认值。

location /some/path/ {
proxy_buffers 16 4k;
proxy_buffer_size 2k;
proxy_pass http://localhost:8000;
}

如果禁用了缓冲,则响应将从客户端服务器接收到的响应同步发送到客户端。对于需要尽快开始接收响应的快速交互客户端,此行为可能是理想的。

要在特定位置禁用缓冲,请将proxy_buffering伪指令locationoff参数一起放置在中,如下所示:

location /some/path/ {
proxy_buffering off;
proxy_pass http://localhost:8000;
}

在这种情况下,NGINX仅使用配置的缓冲区proxy_buffer_size来存储响应的当前部分。

反向代理的常见用法是提供负载平衡。在免费的《选择软件负载平衡器的五个理由》电子书中,了解如何提高性能,性能并通过快速部署专注于您的应用程序。

proxy_buffer代理缓冲区

# nignx会把后端返回的内容先放到缓冲区当中,然后再返回给客户端,边收边传, 不是全部接收完再传给客户端
Syntax: proxy_buffering on | off;
Default: proxy_buffering on;
Context: http, server, location

# 设置nginx代理保存用户头信息的缓冲区大小
Syntax: proxy_buffer_size size;
Default: proxy_buffer_size 4k|8k;
Context: http, server, location

# proxy_buffers 缓冲区
Syntax: proxy_buffers number size;
Default: proxy_buffers 8 4k|8k;
Context: http, server, location

2.4 选择转发IP地址

如果代理服务器具有多个网络接口,有时您可能需要选择特定的源IP地址以连接到代理服务器或上游服务器。如果将NGINX之后的代理服务器配置为接受来自特定IP网络或IP地址范围的连接,这可能很有用。

指定proxy_bind指令和必要的网络接口的IP地址:

location /app1/ {
proxy_bind 127.0.0.1;
proxy_pass http://example.com/app1/;
}

location /app2/ {
proxy_bind 127.0.0.2;
proxy_pass http://example.com/app2/;
}

IP地址也可以用变量指定。例如,$server_addr变量传递接受请求的网络接口的IP地址:

location /app3/ {
proxy_bind $server_addr;
proxy_pass http://example.com/app3/;
}

3.配置nginx反向代理

在代理服务器和后端真实web中的nginx头文件proxy_params中加上参数X-Forwarded-For以获取客户端真实IP,然后模拟访问过程如下

客户端10.0.0.10-->通过代理服务器10.0.0.51-->访问后端真实web 10.0.0.52

代理服务器10.0.0.51 nginx配置

# 编辑nginx反向代理配置文件
cat > /etc/nginx/conf.d/www.abc.com.conf <<EOF
server {
listen 80;
server_name www.abc.com;
index index.html index.htm;

location / {
proxy_pass http://10.0.0.52;
include proxy_params;
}
}
EOF

# 编辑nginx头文件,加上参数X-Forwarded-For
cat > /etc/nginx/proxy_params <<'EOF'
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_connect_timeout 30;
proxy_send_timeout 60;
proxy_read_timeout 60;

proxy_buffering on;
proxy_buffer_size 32k;
proxy_buffers 4 128k;
EOF

后端真实web 10.0.0.52操作

# 编辑nginx配置文件
cat > /etc/nginx/conf.d/www.abc.com.conf <<EOF
server {
listen 80;
server_name www.abc.com;

location / {
root /website;
index index.html index.htm;
include proxy_params;
}
}
EOF

# 编辑nginx头文件,加上参数X-Forwarded-For
cat > /etc/nginx/proxy_params <<'EOF'
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_connect_timeout 30;
proxy_send_timeout 60;
proxy_read_timeout 60;

proxy_buffering on;
proxy_buffer_size 32k;
proxy_buffers 4 128k;
EOF

# 创建网站根目录
mkdir /website && echo '10.0.0.52' >/website/index.html

客户端10.0.0.10做本地hosts解析

10.0.0.51 www.abc.com

客户端10.0.0.10访问www.abc.com,经过nginx代理服务器10.0.0.51将请求转发至后端真实web 10.0.0.52,最终访问到的内容如下

$ curl www.abc.com
10.0.0.52

加上X-Forwarded-For 参数后,nginx的访问日志(真实web服务器10.0.0.52查看)中就可以获取到客户端的真实IP地址了

10.0.0.51 - - [16/Jun/2020:10:35:12 +0800] "GET / HTTP/1.0" 200 10 "-" "curl/7.29.0" "10.0.0.10"