打工人张三最近换了新工作,原来的住房离公司的路程太远,于是乎想要重新找一个离工作地不那么远的住房,由于工作繁忙,没有时间看房。
房东王五名下有2套住房,一套自己住,另一套想租出去,难免会与形形色色的租客打交道,带他们实地看房,但是自己社恐,不喜欢与陌生人打交道。
打工人张三没时间找房,房东王五社恐不愿与陌生人打交道,于是乎,房屋中介应运而生。
张三委托房屋中介李四为自己寻找住房,房东王五授权房屋中介李四带看,两者的问题迎刃而解。
这里的房屋中介就是一种代理。
在代理中,分为3个角色,客户端、代理服务器和服务端。并且针对被代理的角色不同,又分为正向代理和反向代理。
正向代理:被代理的对象是客户端。张三发起看房需求,属于客户端。
反向代理:被代理的对象是服务端。王五提供住房资源,属于服务端。
是不是一脸懵逼?
我们来理理正向代理和反向代理的过程。
在正向代理过程中,代理服务器代理的是客户端,我们将客户端和代理服务器看作是一个整体,客户端知晓真实服务端地址,但是无法直接访问,因此通过代理服务器向服务端发送请求,服务端并不知晓真实客户端的信息。
正向代理使用场景:
可以看到,在反向代理过程中,代理服务器代理的服务端,我们将代理服务器和服务端看作是一个整体,客户端无法知晓真实服务端的地址,只能通过代理服务器进行访问,服务端通过代理服务器接收并响应请求。
反向代理使用场景:
Nginx作为代理服务器,提供了ngx_http_proxy_module模块来实现正向代理和反向代理。按照惯例,我们先来看看该模块提供的常用指令。
官方文档:https://nginx.org/en/docs/http/ngx_http_proxy_module.html
Nginx作为正向代理服务器常用的指令如下:
1)resolver指令
该指令配置域名解析服务器的地址,如果客户端通过域名访问服务端,需要配置该指令。
作用域:http, server, location
语法:resolver address … [valid=time] [ipv4=on|off] [ipv6=on|off [status_zone=zone];
2)proxy_pass指令
在正向代理中,该指令配置的地址从客户端的请求中获取。
作用域:location, if in location, limit_except
语法:proxy_pass URL;
示例:
proxy_pass http://$host$request_uri;
3)正向代理示例
服务端:192.168.110.98
代理服务器:192.168.110.101
代理服务器配置:
server {
listen 8080;
server_name localhost;
# 解析域名时需要配置
# resolver 8.8.8.8;
location / {
proxy_pass http://$host$request_uri;
}
}
服务端配置:
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html;
}
}
客户端配置:
访问http://192.168.110.98
查看服务端的access.log,可以看到访问者的IP是192.168.110.101,说明代理成功。
Nginx作为反向代理服务器常用的指令如下:
1)proxy_pass指令
在反向代理中,该指令配置被代理的服务端的URL地址。
作用域:location, if in location, limit_except
语法:proxy_pass URL;
示例:
# 访问的服务端地址为:http://192.168.110.98
location / {
proxy_pass http://192.168.110.98;
}
# 访问的服务端地址为:http://192.168.110.98,意味着URL的结尾加不加/都一样
location / {
proxy_pass http://192.168.110.98/;
}
# 访问的服务端地址为:http://192.168.110.98/proxy1
location /proxy1 {
proxy_pass http://192.168.110.98;
}
# 访问的服务端地址为:http://192.168.110.98
location /proxy2 {
proxy_pass http://192.168.110.98/;
}
🔔Tips:根据实际需要判断proxy_pass的URL值是否需要以/结尾。
2)proxy_set_header指令
该指令可以更改客户端请求的请求头信息或添加新的请求头信息,并将这些信息传递给被代理的服务端。
作用域:http, server, location
语法:proxy_set_header field value;
默认值:proxy_set_header Host $proxy_host;
proxy_set_header Connection close;
$proxy_host指的是被代理的服务端的IP名称和端口。
🔔Tips:在经过反向代理之后,被代理的服务器获取到的$remote_addr将是代理服务器的地址,因此在获取真实客户端的IP地址时需要注意。
如果要获取客户端的真实IP地址,我们可以使用通过proxy_set_header 指令添加新的header在反向代理服务器中进行设置。
proxy_set_header X-Real-IP $remote_addr;
然后在服务端就可以通过$http_X_Real_IP或者$http_x_real_ip来获取。
如果是代理websocket,则需要进行如下配置:
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
3)反向代理示例
服务端:192.168.110.98
代理服务器:192.168.110.101
代理服务器配置:
location /proxy {
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://192.168.110.98;
}
服务端配置:
location /proxy {
default_type text/plain;
return 200 $host===$remote_addr===$http_x_real_ip;
}
访问http://192.168.110.101/proxy
前面我们知道$remote_addr是用来获取客户端的IP地址,但是我们这里获取到的是代理服务器的IP地址,因此我们新定义一个X-Real-IP字段来传递发起请求的客户端的真实IP。
以上就是Nginx实现正向代理和反向代理,Nginx是多模块化的,还有很多高级功能,我们后面继续探索。