大家好,欢迎来到IT知识分享网。
-
代理和获取规范
-
原则
- F5第一层代理,Nginx作为第二层代理,最终到web应用,如示例:F5->Nginx->Web
- 第一层代理需要把源IP设置到X-Real-IP,二级代理需把一级代理地址写入X-Forwarded-For
-
名词解释
- X-Real-IP: 自定义请求头中字段
- X-Forwarded-For:一个 HTTP 扩展头部,各大 HTTP 代理、负载均衡等转发服务广泛使用,并被写入 RFC 7239(Forwarded HTTP Extension)标准之中
-
定义规范的背景
- X-Real-IP和X-Forwarded-For都可以被客户端随意伪造,但是自定义X-Real-IP只能存在一个值,X-Forwarded-For字段可以存在多个以逗号分割,代理服务器只能追加,不能确定源IP地址写入的具体顺序
- Remote Address 无法伪造,因为建立 TCP 连接需要三次握手,如果伪造了源 IP,无法建立 TCP 连接,更不会有后面的 HTTP 请求
- 基于以上2点,需要一级代理服务器把源IP写入X-Real-IP,各级代理需把上级代理地址写入X-Forwarded-For中,追踪代理调用链
-
F5地址转换规范
- 在F5配置界面中,把源 IP写入参数: X-Real-IP
-
Nginx地址转换配置模板:
Nginx配置server {
# 监听端口
listen 7777;
server_name localhost;
charset utf-8;
location /{
# 转发地址
proxy_pass http://10.19.205.58:7777;
proxy_set_header Host $host;
# 只有一层代理时候开启,源地址放入X-Real-Ip
# proxy_set_header X-Real-IP $remote_addr;
# Nginx作为代理必须开启,源地址和代理服务器代理地址放入X-Forwarded-For字段
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
-
java代码获取源地址
public
String getRealIp(HttpServletRequest request){
// 1. 获取真实地址
String realIp = request.getHeader(
"X-Real-IP"
);
// 2. 非正常地址或者异常调用
if
(isIlegalHost(realIp)) {
// 2.1 获取X-Forwarded-For地址组
String forwardIps= request.getHeader(
"X-Forwarded-For"
);
if
(forwardIps !=
null
){
String[] forwardIpArray = forwardIps.split(
","
);
// 2.2 循环X-Forwarded-For 的地址,返回第一个正常的地址
for
(String forwardIp : forwardIpArray){
if
(!isIlegalHost(forwardIp)){
return
forwardIp;
}
}
}
//2.3 X-Forwarded-For不存在正常地址,则取远程地址
realIp = request.getRemoteAddr();
// 防止Nginx和web同一台无法获取地址
if
(
"127.0.0.1"
.equals(realIp)) {
try
{
// 2.4 如果是本机,则尝试获取网卡配置的IP
realIp = InetAddress.getLocalHost().getHostAddress();
}
catch
(UnknownHostException e) {}
}
}
return
realIp;
}
public
boolean
isIlegalHost(String ip){
if
(ip ==
null
|| ip.length() ==
0
||
"unknown"
.equalsIgnoreCase(ip)) {
return
true
;
}
return
false
;
}
-
2.场景分析
-
-
场景一:Nginx->Web;F5->Web
- F5只需界面操作,配置源地址写入:X-Real-IP
-
Nginx配置
server {
# 监听端口
listen 7777;
server_name localhost;
charset utf-8;
location /{
# 转发地址
proxy_pass http://10.19.205.58:7777;
proxy_set_header Host $host;
# 源地址放入X-Real-Ip
proxy_set_header X-Real-IP $remote_addr;
# 调用地址增加到X-Forwarded-For字段
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
-
实例结果:
# 访问路径:http:
//10.19.205.60:7777/express
# 客户端地址:
10.20
.
23.50
# Nginx地址:
10.19
.
205.60
# web应用地址:
10.19
.
205.58
# 代码:request.getRemoteAddr()+
"|"
+request.getHeader(
"X-Real-IP"
)+
"|"
+ request.getHeader(
"X-Forwarded-For"
)+
"|"
+getRealIp();
# 返回结果:Remote Addr:
10.19
.
205.60
X-Real-IP:
10.20
.
23.50
X-Forwarded-For:
10.20
.
23.50
getRealIp():
10.20
.
23.50
- 异常情况分析
-
异常情况:直接调用web地址,解决方法:java示例代码行注释2
# 返回结果:Remote Addr:10.20.23.50
X-Real-IP:null
X-Forwarded-For:null
getRealIp():10.20.23.50
-
-
场景二:F5->Nginx->Web
-
F5只需界面操作,配置源地址写入:X-Real-IP
- Nginx配置:
server {
# 监听端口
listen 7777;
server_name localhost;
charset utf-8;
location /{
# 转发web应用地址
proxy_pass http://10.19.205.58:7777;
proxy_set_header Host $host;
# F5调用地址增加到X-Forwarded-For字段
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
- 实例结果:
# 访问路径:http:
//10.19.18.51:7777/express
# 客户端地址:
10.20
.
23.50
# F5虚拟地址:
10.19
.
18.51
# Nginx地址:
10.19
.
205.59
# web应用地址:
10.19
.
205.58
# 代码:request.getRemoteAddr()+
"|"
+request.getHeader(
"X-Real-IP"
)+
"|"
+ request.getHeader(
"X-Forwarded-For"
)+
"|"
+getRealIp();
# 返回结果:Remote Addr:
10.19
.
205.59
X-Real-IP:
10.20
.
23.50
X-Forwarded-For:
10.19
.
18.254
(F5实际地址)
getRealIp():
10.20
.
23.50
-
异常情况分析
-
异常情况一:直接调用nginx地址,解决方案:java示例代码行注释2
# 返回结果:Remote Addr:
10.19
.
205.59
X-Real-IP:
null
X-Forwarded-For:
10.20
.
23.50
getRealIp():
10.20
.
23.50
-
异常情况二:直接调用web地址,解决方法:java示例代码行注释2.3
# 返回结果:Remote Addr:
10.20
.
23.50
X-Real-IP:
null
X-Forwarded-For:
null
getRealIp():
10.20
.
23.50
-
-
-
Nginx->Nginx->Web
-
第一层 Nginx配置:
server {
# 监听端口
listen
7777
;
server_name localhost;
charset utf-
8
;
location /{
# 转发web应用地址
proxy_pass http:
//10.19.205.58:7777;
proxy_set_header Host $host;
# 源地址放入X-Real-Ip
proxy_set_header X-Real-IP $remote_addr;
# 调用地址增加到X-Forwarded-For字段
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
-
第二层 Nginx配置:
server {
# 监听端口
listen
7777
;
server_name localhost;
charset utf-
8
;
location /{
# 转发web应用地址
proxy_pass http:
//10.19.205.58:7777;
proxy_set_header Host $host;
# 第一层调用地址增加到X-Forwarded-For字段
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
-
实例结果:
# 访问路径:http:
//10.19.205.69:7777/express
# 客户端地址:
10.20
.
23.50
# 第一层Nginx地址:
10.19
.
205.69
# 第二层Nginx地址:
10.19
.
205.59
# web应用地址:
10.19
.
205.58
# 代码:request.getRemoteAddr()+
"|"
+request.getHeader(
"X-Real-IP"
)+
"|"
+ request.getHeader(
"X-Forwarded-For"
)+
"|"
+getRealIp();
# 返回结果:Remote Addr:
10.19
.
205.59
X-Real-IP:
10.20
.
23.50
X-Forwarded-For:
10.20
.
23.50
,
10.19
.
205.69
getRealIp():
10.20
.
23.50
- 异常情况分析
-
异常情况一:直接调用第二层nginx地址,解决方案:java示例代码行注释2
# 返回结果:Remote Addr:
10.19
.
205.59
X-Real-IP:
null
X-Forwarded-For:
10.20
.
23.50
getRealIp():
10.20
.
23.50
-
异常情况二:直接调用web地址,解决方法:java示例代码行注释2.3
# 返回结果:Remote Addr:
10.20
.
23.50
X-Real-IP:
null
X-Forwarded-For:
null
getRealIp():
10.20
.
23.50
-
-
-
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/32276.html