|
一.使用CDN自定义IP头来获取 假如说你的CDN厂商使用nginx,那么在nginx上将$remote_addr赋值给你指定的头,方法如下: 1 % p* u# A2 c7 T0 w+ X4 j: k
| proxy_set_header remote-user-ip $remote_addr;
9 s$ R E( T9 d. e/ G" O
/ n& i8 Y$ _' V: z7 u" K |
//如上,后端将会收到remote_user_ip的http头,有些人可能会挑错了,说我设置的头不是remote-user-ip吗,
n: R, t0 v# \# U怎么写成了remote_user_ip,是不是作者写错了.请参考文章:<nginx反向代理proxy_set_header自定义header头无效> 后端PHP代码getRemoteUserIP.php 1 8 ~$ o j b$ U" U* K
2
3 G0 ]# H6 y* A4 M; j* J1 v9 ~3
. @% j: T# p9 ?. Z% T4
* Y' h+ \0 K- P" z4 n: w | <?php$ I. i5 c4 a6 K7 v/ i8 l6 ~0 T
$ip = getenv("HTTP_REMOTE_USER_IP");
6 a D1 c% m% W8 h9 p+ k$ ` echo $ip;
( J7 S6 o3 [) W( v?>
- J8 w! }3 u9 H2 e3 P0 ]2 ?' t- l
, C% f" b9 l |' L | : n7 {$ X5 R. z
访问getRemoteUserIP.php,结果如下:
6 f. H# {0 y% W: M4 G! k4 j 120.22.11.11 //取到了真实的用户IP,如果CDN能给定义这个头的话,那这个方法最佳 ) @6 s% Y8 [+ r0 p8 O# i$ |
$ X2 B! ^- C1 h8 D+ J
二.通过HTTP_X_FORWARDED_FOR获取IP地址 一般情况下CDN服务器都会传送HTTP_X_FORWARDED_FOR头,这是一个ip串,后端的真实服务器获取HTTP_X_FORWARDED_FOR头,截取字符串第一个不为unkown的IP作为用户真实IP地址, 例如: 120.22.11.11,61.22.22.22,121.207.33.33,192.168.50.121(用户IP,CDN前端IP,CDN中转,公司NGINX代理) 1 ( x1 Z6 \$ V3 A
2
" S) Q3 X8 E2 o, G3 " W! T4 F. j- N4 u+ |! N3 E- `+ h+ ?
4 @: K/ q: S; L
5 % `" P3 l8 J$ h& a6 Z# x3 N
| getFor.php
- `, u; `& i- F& `1 G `<?php; r) n; U _8 g9 N
$ip = getenv("HTTP_X_FORWARDED_FOR");
. I/ T& {& J- d) Y9 ? echo $ip;
! N0 f, A) |. U' h6 S?># b- R* x; B6 }
2 p/ i) _ V) T! l% K7 V
| : V. F" p- { B
访问getFor.php结果如下:120.22.11.11,61.22.22.22,121.207.33.33,192.168.50.121 如果你是php程序员,你获取第一个不为unknow的ip地址,这边就是120.22.11.11.
5 X @# k7 v+ }$ O0 ]1 [; c: p
2 J- `& T- S [/ z3 @' q* B8 e 三.使用nginx自带模块realip获取用户IP地址$ E7 @- J# a, [/ g
安装nginx之时加上realip模块,我的参数如下: ./configure –prefix=/usr/local/nginx-1.4.1 –with-http_realip_module
$ |+ f) ]: ~$ L; A
8 K8 b) ~5 N" W9 |/ P1 Z: D真实服务器nginx配置 1
+ u4 p, w9 f+ L* M. b( D2
+ [1 N( I, I' ~! k/ v5 v3 _1 J( U, N" R7 X, W0 v- L# c
4 $ a+ M- X) [: o8 D8 k
5
0 G5 a, t. v- v6 h. s6 5 t9 y4 c% @6 g2 z7 P
7
! @# F5 h+ G m+ a8 ! N' z) A6 R' N' [9 b
9 ! F4 h* O# e' m. L. q8 l2 v8 C
10
c. i0 K- G% M- C11
9 _ b4 O& L. f' r12
" {4 O. C8 t! r( e" u13
c0 K/ `/ W" C1 h* g2 @# \3 [% \7 K14 7 l+ @- j1 D* Z9 q5 ^2 W* _0 u1 A
15
+ l' d. e1 ^$ ?/ |' `16 , b; T" J7 n& F. ?0 H& V" s
17
i( G d8 f$ b3 b18
2 G! b' X4 m$ ]4 k* Q$ T19 ' n; x! j; a5 j
20 , S: N2 |. N( ~7 W; O# q) z b
21
- M5 J% [" P% R7 v22 . Y: {8 i, ?2 t0 w
23
1 x% i* t5 n, F9 A* e( C& ?) C( U- ^24 5 Y$ w9 p Y8 c) j0 ?
25
3 b$ V% P8 E/ ?4 ~4 \- s26
! W& m4 H; ], a6 J" }27
: x& p% s4 \4 a# s- j- C28 . S0 V5 `( W6 g ?& J
29
9 A8 t7 T9 H; d) W- K4 R30
% t J7 e, |1 M ~31
6 v4 O- t- A, T5 O' _5 F | server { * U- U0 n% S6 e
listen 80;
# _: o+ P4 j9 a1 `8 g server_name www.ttlsa.com;
1 q: ^" ~9 n* Q% e5 v access_log /data/logs/nginx/www.ttlsa.com.access.log main;
, F, x; c! I/ a+ D6 ]8 @* u
- L7 [4 s- B1 A' K9 _ index index.php index.html index.html;
/ y" A8 O' c7 y. G root /data/site/www.ttlsa.com;
1 w& H" I6 H$ [8 C% f0 t; i5 e $ }: C# S7 _& `
location /
: n5 P; G5 R% w( T- R9 h6 K# Z8 s { ) s+ R8 Q# ^7 Y5 M/ D
root /data/site/www.ttlsa.com;
) P$ L/ r: f' B# l; F* F } 8 n+ q" T7 a4 |& B; j' e
location = /getRealip.php * O! L$ ]2 E( }! }, m
{
# u2 n0 Q0 B+ `) T2 r) e set_real_ip_from 192.168.50.0/24;
& B Y+ m4 Z; B N# K. n) [2 d set_real_ip_from 61.22.22.22; " ]; X% b. Z* m: U
set_real_ip_from 121.207.33.33; 0 N- ?( l& b6 _7 Y) [5 B* B" {% Q
set_real_ip_from 127.0.0.1; # `8 _0 M- j/ T% X! ^
real_ip_header X-Forwarded-For; ( p2 T( z9 p+ j* \. Q
real_ip_recursive on; ' m( J/ e" K/ _# D
fastcgi_pass unix:/var/run/phpfpm.sock; % z- {& J: L5 o
fastcgi_index index.php; b/ Q6 t0 d5 Q* i, H4 _
include fastcgi.conf;
|" ?9 J+ }4 k# i# [ }
! H3 Q; L/ t. H% v1 ? } ( u! Q# m7 q. o
. j' e2 _3 B3 @2 s( M4 R- bgetRealip.php内容 / `5 a6 p* ~ K) s
<?php " f6 j* [! U) J, e" D
$ip = $_SERVER['REMOTE_ADDR']; 1 F' ]# D9 R \. c# ^: `
echo $ip; ) h3 j2 z9 a# V
?>
* u" q" C3 g2 U; r+ p9 }( Q+ l) Y: l
|
很不幸,获取到了中继的IP,real_ip_recursive的效果看明白了吧. set_real_ip_from:真实服务器上一级代理的IP地址或者IP段,可以写多行
* Y" z6 e! B( }real_ip_header:从哪个header头检索出要的IP地址
+ f$ n4 k- A# }5 wreal_ip_recursive:递归排除IP地址,ip串从右到左开始排除set_real_ip_from里面出现的IP,如果出现了未出现这些ip段的IP,那么这个IP将被认为是用户的IP。例如我这边的例子,真实服务器获取到的IP地址串如下:
( {8 m. g! R/ b$ Y1 I' g120.22.11.11,61.22.22.22,121.207.33.33,192.168.50.121$ g0 Q8 E. A" l; G2 G2 g
在real_ip_recursive on的情况下
) x% y6 h% C+ V) ?4 Y61.22.22.22,121.207.33.33,192.168.50.121都出现在set_real_ip_from中,仅仅120.22.11.11没出现,那么他就被认为是用户的ip地址,并且赋值到remote_addr变量 在real_ip_recursive off或者不设置的情况下6 O1 W3 M/ h" S1 D
192.168.50.121出现在set_real_ip_from中,排除掉,接下来的ip地址便认为是用户的ip地址 如果仅仅如下配置: set_real_ip_from 192.168.50.0/24; set_real_ip_from 127.0.0.1; real_ip_header X-Forwarded-For; real_ip_recursive on; + q$ }4 x5 L; L: _! t7 ]
访问结果如下: 121.207.33.33 , z7 D% x, B5 O
+ J4 B$ ]" o5 H' f* Z/ h; _
四.三种在CDN环境下获取用户IP方法总结3 E7 h# H" S& S" Y* o9 k
4.1 CDN自定义header头 ^/ R6 a' K1 T* ]# m$ x) U% t
优点:获取到最真实的用户IP地址,用户绝对不可能伪装IP
/ m* G8 X$ X( C5 k+ }缺点:需要CDN厂商提供
1 w' _0 b3 n2 j& {8 ~+ P: q4 V
4.2 获取forwarded-for头1 I% _$ D _0 I. z4 b$ W
优点:可以获取到用户的IP地址
- a6 ~" s9 Z0 x' _3 B' B# [4 m缺点:程序需要改动,以及用户IP有可能是伪装的
( B2 `5 R v4 t+ F
4.3 使用realip获取
p5 V* u! l/ d0 D优点:程序不需要改动,直接使用remote_addr即可获取IP地址
& T- U: x' e4 ^) Q; Z9 _缺点:ip地址有可能被伪装,而且需要知道所有CDN节点的ip地址或者ip段
P7 k: u0 f! K' o+ v; @/ t: G |