正向代理和反向代理

正向代理和反向代理

正向代理

​ 正向代理是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。

正向代理,其实是”代理服务器”代理了”客户端”,去和”目标服务器”进行交互;客户端必须要进行一些特别的设置才能使用正向代理

​ 举个栗子:一个国内用户访问不了Google,但是他能访问到一个代理服务器,这个代理服务器能够访问Google,于是该用户需要先连上代理服务器,然后告诉代理服务器需要访问哪个网站的内容,代理服务器去将网站内容取回来,然后返回给用户。从网站的角度,只在代理服务器来取内容的时候有一次记录,有时候并不知道是用户的请求,也隐藏了用户的资料,这取决于代理告不告诉访问的网站

正向代理的用途

  1. 突破访问限制

    ​ 通过代理服务器,可以突破自身IP访问限制,访问国外网站等

  2. 提高访问速度

    ​ 通常代理服务器都设置一个较大的硬盘缓冲区,会将部分请求的响应保存到缓冲区中,当其他用户再访问相同的信息时, 则直接由缓冲区中取出信息,传给用户,以提高访问速度

  3. 隐藏客户端真实IP

    ​ 上网者也可以通过这种方法隐藏自己的IP,免受攻击

反向代理

​ 反向代理(Reverse Proxy)是指以代理服务器来接受Internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给Internet上请求连接的客户端,此时代理服务器对外就表现为一个服务器

反向代理,其实是”代理服务器”代理了”目标服务器”,去和”客户端”进行交互;通过反向代理服务器访问目标服务器时,客户端是不知道真正的目标服务器是谁的,甚至不知道自己访问的是一个代理

反向代理的用途

  1. 隐藏服务器真实IP

    ​ 使用反向代理,可以对客户端隐藏服务器的IP地址

  2. 负载均衡

    ​ 反向代理服务器可以做负载均衡

    ​ 根据所有真实服务器的负载情况,将客户端请求分发到不同的真实服务器上

  3. 提高访问速度

    反向代理服务器可以对于静态内容及短时间内有大量访问请求的动态内容提供缓存服务,提高访问速度

  4. 提供安全保障

    ​ 反向代理服务器可以作为应用层防火墙,为网站提供对基于Web的攻击行为(例如DoS/DDoS)的防护,更容易排查恶意软件等

    ​ 还可以为后端服务器统一提供加密和SSL加速(如SSL终端代理),提供HTTP访问认证等

正向代理和反向代理的区别

  1. 正向代理其实是客户端的代理,帮助客户端访问其无法访问的服务器资源

    反向代理则是服务器的代理,帮助服务器做负载均衡,安全防护等

  1. 正向代理一般是客户端架设的,比如在自己的机器上安装一个代理软件

    反向代理一般是服务器架设的,比如在自己的机器集群中部署一个反向代理服务器

  1. 正向代理中,服务器不知道真正的客户端到底是谁,以为访问自己的就是真实的客户端

    反向代理中,客户端不知道真正的服务器是谁,以为自己访问的就是真实的服务器

  1. 正向代理主要是用来解决访问限制问题

    反向代理则是提供负载均衡、安全防护等作用

图片来源:https://www.zhihu.com/question/24723688

代理

Java获取用户的IP地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/**
* 获取请求的真实ip地址
* @param request
* @return
*/
public String getRealIpAdrress(HttpServletRequest request) {
String ipAdrress = "";
String forwardFor = request.getHeader("X-Forwarded-For");
if (!T.isBlank(forwardFor) && !"unKnown".equalsIgnoreCase(forwardFor)) {
//多次反向代理后会有多个ip值,第一个ip才是真实ip
int index = forwardFor.indexOf(",");
if(index != -1){
ipAdrress = forwardFor.substring(0,index);
}else{
ipAdrress = forwardFor;
}
}
if (T.isBlank(ipAdrress) || "unKnown".equalsIgnoreCase(forwardFor)) {
ipAdrress = request.getHeader("Proxy-Client-IP");
}
if (T.isBlank(ipAdrress) || "unKnown".equalsIgnoreCase(forwardFor)) {
ipAdrress = request.getHeader("WL-Proxy-Client-IP");
}
if (T.isBlank(ipAdrress)) {
ipAdrress = request.getHeader("X-Real-IP");
}
if (T.isBlank(ipAdrress) || "unKnown".equalsIgnoreCase(forwardFor)) {
ipAdrress = request.getHeader("HTTP_CLIENT_IP");
}
if (T.isBlank(ipAdrress) || "unKnown".equalsIgnoreCase(forwardFor)) {
ipAdrress = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (T.isBlank(ipAdrress) || "unKnown".equalsIgnoreCase(forwardFor)) {
ipAdrress = request.getRemoteAddr();
}
return ipAdrress;
}

getRemoteAddr

request.getRemoteAddr()获取客户端的ip地址

​ 但是如果使用了反向代理软件,例如Nginx,用request.getRemoteAddr()方法获取的IP地址都会是反向代理服务器的ip,而并不是客户端的真实IP。
​ 经过代理以后,由于在客户端和服务之间增加了中间层,因此服务器无法直接拿到客户端的IP,服务器端应用也无法直接通过转发请求的地址返回给客户端。但是在转发请求的HTTP头信息中,增加了X-Forwarded-For信息。用以跟踪原有的客户端IP地址和原来客户端请求的服务器地址

X-Forwarded-For

​ X-Forwarded-For是用来识别通过HTTP代理或负载均衡方式连接到Web服务器的客户端最原始的IP地址的HTTP请求头字段

​ 如果有配置X-Forwarded-For设置的话,每次经过proxy转发都会有记录,格式就是:

(client1, proxy1, proxy2) 以逗号隔开各个地址(client指客户端IP,proxy指反向代理服务器的IP)

即设置了X-Forwarded-For,取逗号分隔的第一项即为客户端的IP

在代理转发及反向代理中经常使用X-Forwarded-For 字段

  1. 代理转发(正向代理)

    ​ 在代理转发的场景中,你可以通过内部代理链以及记录在网关设备上的IP地址追踪到网络中客户端的IP地址

    ​ 处于安全考虑,网关设备在把请求发送到外网(因特网)前,应该去除 X-Forwarded-For 字段里的所有信息

    ​ 这种情况下所有的信息都是在你的内部网络内生成,因此X-Forwarded-For字段中的信息应该是可靠的

  2. 反向代理

    ​ 在反向代理的情况下,你可以追踪到互联网上连接到你的服务器的客户端的IP地址,即使你的网络服务器和互联网在路由上是不可达的

    ​ 这种情况下你不应该信任所有X-Forwarded-For信息,其中有部分可能是伪造的。因此需要建立一个信任白名单来确保X-Forwarded-For中哪些IP地址对你是可信的

    ​ 最后一次代理服务器的地址并没有记录在代理链中,因此只记录 X-Forwarded-For 字段是不够的。完整起见,Web服务器应该记录请求来源的IP地址以及X-Forwarded-For 字段信息

X-Forwarded-ForX-Real-IP** 区别

​ X-Real-IP如果经过多级代理的情况下,其记录的IP不一定是真实的客户端IP;如果有多级代理,x-forwarded-for效果是大于x-real-ip的,可以记录完整的代理链路