有人刷登录、注册、短信等接口,而且量还比较大,需要根据 IP,进行访问次数的限制。在没有 CDN 的情况下,获取用户 IP 还比较好办,有了动态 CDN,获取到的就基本都是 CDN 统一出口的 IP 了。这时候根据 IP 进行访问次数限制,就非常容易造成误伤。
大部分情况下,以下两行代码就够用了:
request.ip
request.remote_ip
request.ip,这个很多情况下可能会取到内网 IP,要看服务器机房的网络架构,但 request.remote_ip 肯定就能取到外网 IP 了。内网 IP 和外网 IP,大家一眼就能看出来,各取所需就行。
这种情况最好办,request.ip 就拿到外网 IP 了;
如果拿不到,用 request.remote_ip,我就用这个
这种情况,你就安心的用 request.remote_ip 吧
这种情况,request.remote_ip 获取到的是 CDN 的 IP,不是用户的
我的 CDN 服务提供商,把用户真实 IP 放在下面这个请求头里:
Headers['Cdn-Src-Ip']
问一下自己的 CDN 服务提供商,或者用抓包工具抓一下,就可以确认了。请求头里没有的情况,我没遇到,暂时不知道如何解决,大家轻拍...
首先,我们要确认一下,nginx 里到底有没有这个东西?打印出来看看
sudo vi /etc/nginx/nginx.conf
在 log_format 里,添加以下变量:
$http_cdn_src_ip
然后,保存配置,重启 nginx,去 access.log 里面看看是否打印出来了
tail -100f /var/log/nginx/access.log |more
nginx 里,是有用户的真实 IP 了;但是,Rails 里是没有 headers['Cdn-Src-Ip'] 的,想办法传过去!
Google 出来的,基本都是用这个方法:
proxy_set_header
看了好多国内外文章,经历过了 N 次配置和重启,都无效,真是想死的心都有,在线上生产环境,每次都要配好多台服务器......
后来,在 Passenger 旧版的官方文档里,发现了相关的东西,然后又找到了新版的文档,终于解决!
Passenger 5 设置额外 headers 的方法
passenger_set_header
nginx 配置文件里,参考设置如下:
server {
listen 80;
server_name 192.168.0.xxx;
root /www/project-name/production/current/public;
rails_env production;
passenger_enabled on;
passenger_set_header X-Real-IP $http_cdn_src_ip;
}
保存设置,重启 nginx,去 Rails 里看看去!
因为我设置了:
passenger_set_header X-Real-IP $http_cdn_src_ip;
所以,我在 Rails 里是这么取的:
request.headers['X-Real-IP']
现在,总算是拿到用户的真实 IP 了!
这个问题,搞了挺久,分享出来,希望以后的人,少走弯路。有其他解决方法的,也欢迎分享出来!