多级nginx代理,获取客户端真实ip

今天服务里的微信公众号支付业务突然不能用了,报错为网络环境未能通过安全验证,请稍后再试。检查后端日志,没有任何问题,看来是成功创建支付订单,但是调起支付时出现了问题。上网查了一下,这个报错的直接原因是传入的客户端ip与调起支付的ip不符。但是印象中我在代码中获取的是X-Forwarded-For,就是请求来源的客户端IP,就查看日志发现传给微信的ip为172.17.0.1,也就是宿主机ip,这是才恍然大悟,在升级线上环境时我们将所有服务放进了docker,并且在docker里装了nginx来分发请求给对应的服务,也就是说我们是两级nginx代理,我们的服务是没法拿到最外层客户端ip的。只好改进nginx将每级代理的ip都记录起来,而不是直接覆盖。

改进方法:

对第一级nginx代理

location ~ ^/test {
  proxy_pass http://127.0.0.1:8888;
  proxy_set_header Host $host;
  proxy_set_header X-real-ip $remote_addr;
  proxy_set_header X-Forwarded-For $remote_addr;
}

第一级nginx代理不需要改动,直接将原始客户端ip记录到X-Forwarded-For即可

 

对于第二级,以及之后可能存在的更多级代理

location ~ ^/test {
  proxy_pass http://127.0.0.1:12000;
  proxy_set_header Host $host;
  proxy_set_header X-real-ip $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

这样就将新一级代理的ip接到X-Forwarded-For的尾部,并用逗号分割。也就是说X-Forwarded-For是一个逗号拼接的ip字符串,想拿到原始ip只需要按逗号分割,取第一位ip即可。

 

Golang业务中读取原始客户端ip代码

 

	real_ip := r.Header.Get("X-Forwarded-For")
	ip_list := strings.Split(real_ip, ",")
	if len(ip_list) > 1 {
		real_ip = ip_list[0]
	}

 

 

就是这么简单啦,希望对大家有所帮助~

 

转载于:https://www.cnblogs.com/baiyb/p/9657233.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值