|
一.使用CDN自定义IP头来获取 假如说你的CDN厂商使用nginx,那么在nginx上将$remote_addr赋值给你指定的头,方法如下: 1 $ B! y& E+ P# x& N9 {! _
| proxy_set_header remote-user-ip $remote_addr;+ z! S h9 L7 T. ^1 w
( q; d! Q8 z9 U0 s
|
//如上,后端将会收到remote_user_ip的http头,有些人可能会挑错了,说我设置的头不是remote-user-ip吗,2 k8 z+ e5 C8 p% ]1 U
怎么写成了remote_user_ip,是不是作者写错了.请参考文章:<nginx反向代理proxy_set_header自定义header头无效> 后端PHP代码getRemoteUserIP.php 1
. }' O+ ^* Z2 S2 X. C% g3 y' a3 @, ^5 i, \# J
3 # j9 A% H! C5 r4 N* }
4 , P U4 I$ i* K$ p0 C' x
| <?php
6 w# m L/ A) e/ U+ r $ip = getenv("HTTP_REMOTE_USER_IP");
3 U+ Q3 G& j8 t echo $ip; 8 B8 A7 c' M- G% {1 M5 | s) z
?>
9 N" M# N6 P# ~+ o0 R8 d( r( |0 P# w: c$ E; p. m7 d- E
|
' ^' C* n8 _! R; k( ^% t( O7 T访问getRemoteUserIP.php,结果如下:
: ^/ g1 S" P8 S! [/ `4 C+ v) O 120.22.11.11 //取到了真实的用户IP,如果CDN能给定义这个头的话,那这个方法最佳
4 B s' @2 [ u& j( o1 F: V4 j! x
二.通过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
9 r+ G1 E) @+ |" e/ x* h2
( o, ?* ?: d* }+ D3 $ X7 S! _- X5 o' _/ \
4 8 K- e d! i, L9 c9 [3 V
5
3 f4 z9 u8 E+ f | getFor.php
* n, x X5 R/ T2 O+ x<?php$ y# X0 A% }* t
$ip = getenv("HTTP_X_FORWARDED_FOR");
* k- l" W: {& u echo $ip;
: ?4 N% b# y) e& V2 s& U7 u?>
+ b1 ~+ p( A/ X, T( H# n# C
! u" u/ |: J8 z2 N( M. @ | . c% f" N& `4 ?
访问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. ' v3 ~+ d) T- i# c, g$ y! c
/ i7 r' T6 C) w% F9 r 三.使用nginx自带模块realip获取用户IP地址: M- z# {! A4 x* H& N& y
安装nginx之时加上realip模块,我的参数如下: ./configure –prefix=/usr/local/nginx-1.4.1 –with-http_realip_module6 B+ O9 U5 A; b. d
2 J- m. h& F- q3 ~- h; m# |# D3 T
真实服务器nginx配置 1
8 f; K s# H1 \, g. z2
/ u" l) X; o n* z3
9 Q7 P- K! n* {4
& m6 h* Q7 _; e0 ^) V' y5
6 r, l8 l1 M* C; k; x% ^9 `' M( [% W6 ( T5 `+ Y/ d/ i" `
7 ' B# X, y* `- u/ \
8
" J" w1 L* H, L1 V0 x F5 d+ z9
3 h6 |/ ~) w. I! E0 h10 8 }6 [+ u6 u4 I! w6 Q+ r4 q
11
7 c! K: l8 c, ?1 M6 [12 5 P1 ]" J# E& X8 c: r6 g' k# V% m( ^
13 # H, [& k" x j5 X6 j
14
# i" V* J7 R& @* p" |15
" d; ^) [) i$ o, `; ?9 L. e16 ) A' m0 t5 e( r1 y" n @
17
0 V9 M! @4 }. [+ G# t) ~18
& c$ F& N0 M/ W# y9 H" I% G- [19 : D3 ~- X2 Q$ d8 p& c1 V
20
2 @ x1 L r) S- ^: w21 6 B8 ^3 K$ [6 j& p% Z
22 . Q; A& u x. y& X
23
3 g# X6 r' H8 z- _# C! R# F24
o3 T+ X- y! A3 T4 R/ K$ H4 e25 8 ` N* Z# b; L- a8 P
26
' [; [* R+ Q- G27 + }8 m2 U# j% w1 F, J+ v* l
28 ! M+ z8 I; W" J- v4 ?
29 8 E: r+ H: U9 [
30
) J& |* U, z2 ~& k31
1 [0 m; d7 `$ X9 u6 `0 b4 v | server { # W. h9 _5 n0 N, E- E
listen 80;
+ i8 i3 V* V& c* c server_name www.ttlsa.com; + ~4 ?, Q1 v+ F+ ?3 u/ [% Y: `" k
access_log /data/logs/nginx/www.ttlsa.com.access.log main; 0 J9 a# ^. X+ I. B, ]
7 O( G# ]0 m' t4 _( x
index index.php index.html index.html;
7 ~, [& P: p. q1 C( O+ M root /data/site/www.ttlsa.com; / ~) r+ P5 k1 R. ?: h8 M7 i
) y* p) C; H+ P location / $ }6 e ?- \ M
{ $ _8 {% @. B2 }/ b
root /data/site/www.ttlsa.com;
4 D0 `7 t& X2 Y }
: H( Z+ i% L- X location = /getRealip.php 8 }/ A7 R! l" a6 I7 P% I: C' Y) ~
{ , [/ O. P- w: R& y/ l9 S* i! g
set_real_ip_from 192.168.50.0/24; 0 t& a$ T, a3 J
set_real_ip_from 61.22.22.22;
) {% G. M; t4 l K set_real_ip_from 121.207.33.33; ) u, V$ r' X8 | U/ b! P5 l4 P
set_real_ip_from 127.0.0.1; . B M$ o- @" J2 @% N0 F
real_ip_header X-Forwarded-For; / i5 c. l* p- I Z+ i
real_ip_recursive on;
6 u' h: B; i6 p" n* t1 ]9 X fastcgi_pass unix:/var/run/phpfpm.sock; 8 `) I/ C, S4 B/ y7 H
fastcgi_index index.php; ( @5 ^2 \$ Z5 y2 n( I
include fastcgi.conf; * w9 J1 D: q( o; ~- T$ o
}
- E2 V# l; g+ L) G5 U9 n } : R0 X) c5 W! w8 v9 Z
" P/ U# f0 z$ e* wgetRealip.php内容
9 n1 g6 I1 ?2 F6 f2 G. Z <?php
; f0 T1 Y( V9 |9 A8 P6 _ $ip = $_SERVER['REMOTE_ADDR']; 0 S) L1 n, v4 B3 X9 H! a0 B
echo $ip;
. |( o3 j4 {, w$ }3 C/ c& K& ^% u ?>
+ t* i5 J3 e: x; A; D/ _; S
2 R: W# J' p, ?2 k& | |
很不幸,获取到了中继的IP,real_ip_recursive的效果看明白了吧. set_real_ip_from:真实服务器上一级代理的IP地址或者IP段,可以写多行; ^/ j9 g7 R8 b0 }4 p$ f
real_ip_header:从哪个header头检索出要的IP地址8 @ R$ W! Q; o: x
real_ip_recursive:递归排除IP地址,ip串从右到左开始排除set_real_ip_from里面出现的IP,如果出现了未出现这些ip段的IP,那么这个IP将被认为是用户的IP。例如我这边的例子,真实服务器获取到的IP地址串如下:5 X7 w8 _% R. A7 W! E
120.22.11.11,61.22.22.22,121.207.33.33,192.168.50.1214 L+ p8 K& N O& v
在real_ip_recursive on的情况下
3 A6 a: R$ {2 D) \/ d61.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或者不设置的情况下7 g$ ~% V7 I0 b$ _% I
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; 0 f' H" O& M( E" b; p
访问结果如下: 121.207.33.33 ! L, v) T2 u. H8 A! f
+ h% C, u9 C9 Y3 K四.三种在CDN环境下获取用户IP方法总结1 ]9 Y( f& f2 v$ R$ a
4.1 CDN自定义header头
! ?) ~ O# @" K3 g* i: W+ A优点:获取到最真实的用户IP地址,用户绝对不可能伪装IP
/ B) Y) |* ?3 ~# e% N缺点:需要CDN厂商提供 $ f) }/ t: a' Z$ r3 l% @( G
4.2 获取forwarded-for头
4 i0 {* @4 ~ N1 m; \2 m优点:可以获取到用户的IP地址
+ M' h) k) _" C8 V6 u缺点:程序需要改动,以及用户IP有可能是伪装的
' n1 I S" {" O
4.3 使用realip获取( O p. ]4 T: H! _9 h- f# u) U
优点:程序不需要改动,直接使用remote_addr即可获取IP地址
% q# g, t3 h( X) T2 g缺点:ip地址有可能被伪装,而且需要知道所有CDN节点的ip地址或者ip段 * \, h+ K0 S, |$ F# u
|