|
一.使用CDN自定义IP头来获取 假如说你的CDN厂商使用nginx,那么在nginx上将$remote_addr赋值给你指定的头,方法如下: | proxy_set_header remote-user-ip $remote_addr;( y3 q5 v3 p7 w8 ~- b
+ ~% N4 s7 I" ?! h) Q, R0 l |
//如上,后端将会收到remote_user_ip的http头,有些人可能会挑错了,说我设置的头不是remote-user-ip吗,
5 g5 D2 p3 {- K, j i* H怎么写成了remote_user_ip,是不是作者写错了.请参考文章:<nginx反向代理proxy_set_header自定义header头无效> 后端PHP代码getRemoteUserIP.php 1 : ?0 H0 S& z4 q' ]; K
2 5 w2 X7 m- C- G4 ?) p& K, i, W
3 8 w% b1 B9 l: [% @" h
4
+ O. J+ r \ j | <?php1 H1 m' e$ U9 q/ r. @/ x. d: J
$ip = getenv("HTTP_REMOTE_USER_IP");
# e9 L" c6 ^9 g* c" |5 ~ echo $ip; 3 y; {) i& l: S* }; R# D2 k h# H0 S4 b
?>( {7 J( d0 U- m& g4 z7 J6 Y
, |$ x3 A. F+ F; f! q0 Q( v0 z4 j |
' ^- H, {3 y: u9 B4 Z* r; [$ {访问getRemoteUserIP.php,结果如下:' _; f' O( G, s
120.22.11.11 //取到了真实的用户IP,如果CDN能给定义这个头的话,那这个方法最佳 $ {/ H' H- x6 p% H0 i! f
D& n! K& N9 r. j, U' F二.通过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 1 t3 K. V# i) G; n/ y
2
/ o4 e5 t- i. u& @$ j3 e3 * w4 v& o5 T+ e% e
4 ) X7 g P$ r, M; D4 c- K
5 4 p! j0 M: t3 y9 S4 b
| getFor.php
" Z9 k0 ? [2 F4 T V<?php3 M/ B0 U P2 v. k/ @# d1 q* u
$ip = getenv("HTTP_X_FORWARDED_FOR");, a& N- N( o7 o( W& m& e
echo $ip;' Y" ]/ ~9 r3 w% s
?>
/ N8 ?0 a( {: Z% i3 k) e1 w, L1 k. o9 ^9 m7 X
| . g+ [3 k1 F! l3 z' _( }
访问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. 8 N( F7 ?; \3 g
' P) H$ n8 A) P2 A8 l
三.使用nginx自带模块realip获取用户IP地址
$ G+ y2 b) A8 j. j- r安装nginx之时加上realip模块,我的参数如下: ./configure –prefix=/usr/local/nginx-1.4.1 –with-http_realip_module
7 i; J$ c2 i: `: } O $ _! |* A& z, O J% Q- C
真实服务器nginx配置 1 3 y; Z; L' `% i1 v7 |: T
2
& G& k6 M! I( H7 A3 `/ p3 2 I1 X! O \1 p& X! W7 P1 B# I
4 : `' ~' m- D. a% [- x9 D
5
/ a' z8 d0 H& D$ D6
; c9 s- v! ]" `! w( H+ b& ~4 k6 ]7
V, S+ P* V- J( W+ m8
) x( P5 z. K) T% }9
: q+ A6 C( U2 r' E10
! h: s6 u* n' m8 q) |5 @* S11 # E S1 A( w$ R( J+ |
12
c9 w8 j+ f% R, F/ ?9 e13 ( j7 e7 L/ _8 U2 @
14
9 P$ s) T& G0 r5 B! O! s15 : G+ D: b i0 |$ f9 E) v$ n
16 : P2 A( {* ^* H$ ^
17
: \$ H4 R& {6 t2 k7 p18
# J9 L9 S9 G* ~) G0 ]1 f5 |19 * P0 D Q n, O' O! G
20 0 @- Z% e! [) S. P9 ` a
21 , e8 { N9 o S* e; z
22 * e8 P# G0 F+ @1 K+ M4 T
23 4 a4 m- J4 g& W4 U
24
, O3 Z. Q) @! L1 G+ f! K% d9 P25
$ B4 l) ~: y$ P: f2 _' i1 d) l+ J26
% @: F& ~7 ~6 [" v27 2 d3 E: n) H% z$ ~" J6 m+ J; N+ t
28
; ^ i' n, E1 ^( g( R29
# f8 f0 {" |+ `+ { G2 O30
" m2 j$ _" Z+ k! T. w# U31 / H% w V/ g; ]0 R Q& ^/ Y
| server { / t' q3 E7 y/ ^! x0 s0 X, v
listen 80;
% O/ w& ?/ ^: B- \! Q. Y5 s3 b server_name www.ttlsa.com; ! e8 `! T; t) K7 v4 c
access_log /data/logs/nginx/www.ttlsa.com.access.log main; ' r/ T2 }3 O$ E a9 t) u
0 I4 p, C V3 |8 u6 e, U index index.php index.html index.html; 2 p/ N F+ V) t1 t1 @- r' ?
root /data/site/www.ttlsa.com; 5 O* R: Y2 c: z. ?7 t0 ]
. |) A2 |# u5 I* h9 g: y. l2 R- ] location / / o8 B& Y8 U1 K
{ , S6 ]5 Q. e4 V/ i
root /data/site/www.ttlsa.com; 7 @8 \( m' M8 R1 O+ D
}
j8 y' T0 S6 y n location = /getRealip.php * i! G2 u9 T9 j; B
{
7 l. w; v1 T9 ^ set_real_ip_from 192.168.50.0/24; 1 I6 q9 v, \) H8 m
set_real_ip_from 61.22.22.22;
" \. f8 ?+ \* w, c- ^7 h' W- O set_real_ip_from 121.207.33.33;
7 k. e9 J1 ]7 F: d r8 ~5 w set_real_ip_from 127.0.0.1; + H, `# x4 X% a, p3 v8 E
real_ip_header X-Forwarded-For; , |5 R4 U# @7 N# [! I* O* I5 b6 E7 l1 X
real_ip_recursive on;
! a$ z1 |/ L* N5 F: W fastcgi_pass unix:/var/run/phpfpm.sock; + {5 c: l& P5 B* i& q8 y
fastcgi_index index.php;
% k! }6 q- S, M ~8 h; S include fastcgi.conf; 6 _* H8 N$ z* I$ w$ ~5 J* T
} 0 t2 R$ _8 T2 x# g1 L* u
} / [8 c k4 R+ u; e& n; d+ D
4 G5 A$ h" S# p3 q" {, }
getRealip.php内容
3 t0 P6 @6 F- B <?php
$ V. w, M' t7 v $ip = $_SERVER['REMOTE_ADDR']; / x$ A, @# Q) K$ p& W. m) v0 f# P
echo $ip; 0 y2 a) g& U1 Q7 ~* K' x
?>
2 l$ t3 C3 ~2 _( F/ T& }$ {, D( i9 m" ] C
|
很不幸,获取到了中继的IP,real_ip_recursive的效果看明白了吧. set_real_ip_from:真实服务器上一级代理的IP地址或者IP段,可以写多行
0 C! H% Z, N' ~( A& u" a/ Y6 N( _8 _real_ip_header:从哪个header头检索出要的IP地址# E% c( |% r$ X: Z
real_ip_recursive:递归排除IP地址,ip串从右到左开始排除set_real_ip_from里面出现的IP,如果出现了未出现这些ip段的IP,那么这个IP将被认为是用户的IP。例如我这边的例子,真实服务器获取到的IP地址串如下:
" g" {9 H2 d2 Y4 e; z# _: ~( d120.22.11.11,61.22.22.22,121.207.33.33,192.168.50.121" y$ o. Q, D5 V& x% |8 ~! W2 ]6 b
在real_ip_recursive on的情况下, z w6 V/ p! d# ]6 E
61.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或者不设置的情况下
* F( X0 ?6 ~1 E2 S" e$ C* l1 O192.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; & E2 X+ c. Q8 Y& a- ?: Q
访问结果如下: 121.207.33.33
; t* g( P9 [ s0 X
" a% \1 o, d' \四.三种在CDN环境下获取用户IP方法总结
. N, t7 Q+ g3 @4.1 CDN自定义header头
2 b' }3 i7 j& Q3 S8 o: d* t6 I优点:获取到最真实的用户IP地址,用户绝对不可能伪装IP& n) V, h( i. B9 U: z+ C
缺点:需要CDN厂商提供 8 Y/ r7 {$ A, q; ?
4.2 获取forwarded-for头
% P2 _2 D7 ] C2 O5 ?- x优点:可以获取到用户的IP地址
4 u: {* d* t% i缺点:程序需要改动,以及用户IP有可能是伪装的
( {. Q9 T+ d# v/ Q' \* k
4.3 使用realip获取7 o* I5 `. g; g0 U1 h4 y
优点:程序不需要改动,直接使用remote_addr即可获取IP地址- L, _$ w9 K. N0 y# [4 B
缺点:ip地址有可能被伪装,而且需要知道所有CDN节点的ip地址或者ip段
: U1 \4 l! y( l" k |