一.使用CDN自定义IP头来获取 假如说你的CDN厂商使用nginx,那么在nginx上将$remote_addr赋值给你指定的头,方法如下: 1
/ u+ n' W$ d3 \7 w+ b- M | proxy_set_header remote-user-ip $remote_addr;% a( I' c6 l9 @" n$ l' y
& g9 F# o7 T' P2 ]! _; w F
|
//如上,后端将会收到remote_user_ip的http头,有些人可能会挑错了,说我设置的头不是remote-user-ip吗,& |5 D6 p: L; O7 S2 G& J
怎么写成了remote_user_ip,是不是作者写错了.请参考文章:<nginx反向代理proxy_set_header自定义header头无效> 后端PHP代码getRemoteUserIP.php 1 6 U0 f4 e6 V" D6 d) {) F
2
! A( X4 w0 |. S4 _, I* r% U3
u: `& G: ?9 N/ T+ O% d4
q) T# Y. R W' |: A y- ?! [& z | <?php2 h2 C9 b" H v8 m" ]$ t8 Y
$ip = getenv("HTTP_REMOTE_USER_IP");
$ B- T5 [ W* M& r( V5 I3 e d. U echo $ip;
; Z( I* J3 d/ K, v?>
9 g. t8 r) g3 s" d! v2 b( \- O) c
6 D+ L; V/ L7 W0 k$ Y' w; a | ' L. w$ J$ R& F6 ~
访问getRemoteUserIP.php,结果如下:
7 e, ]: [" O: { u) G 120.22.11.11 //取到了真实的用户IP,如果CDN能给定义这个头的话,那这个方法最佳
3 ?6 h4 k5 E0 U; b6 x/ E
2 K% J8 a. h6 L! i- C% W二.通过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 z6 B1 ^$ }# w0 x; ^3 L
2 1 X! `$ w" }, h7 Q5 o5 O. j8 r
3
1 g: x- _4 w4 O6 `# W( f4 $ m4 l/ s! l" v2 G! }- X' U
5
, n; q2 C0 X( J7 T0 n5 K | getFor.php
8 e6 L, j3 a$ V0 v<?php
* D* s/ _$ Q! l7 i/ X $ip = getenv("HTTP_X_FORWARDED_FOR");* l7 C9 y2 Z. s
echo $ip;6 T% o% W8 Q3 ^# A% u, T
?>& }3 t) C( B7 u+ ]2 |; d( T' q
5 k% S+ S: h) m
| 3 N: Y) S4 }+ H" t
访问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.
! ^# c7 J: O0 i/ ]* ~
* k8 w# r7 _6 c, t
三.使用nginx自带模块realip获取用户IP地址- D9 K5 X! b; ^+ \1 V4 x
安装nginx之时加上realip模块,我的参数如下: ./configure –prefix=/usr/local/nginx-1.4.1 –with-http_realip_module& s; b% m, M7 P
8 l' Q0 a, y, }8 U
真实服务器nginx配置 1
& {! j2 i J- S1 d8 n/ }. H% g" a2 , B! a2 @+ O9 e1 u# |$ j+ W" j. z
3 ) p2 G. d9 Y& x# [# Q4 F
4 + }6 o9 c' P+ s
5 4 L3 E: {1 \1 _) r& G' V' b/ X6 O2 N, v
6 # X! z9 |* [7 u, P1 O8 J8 c/ v
7
1 h) t$ f2 C q0 D, g) I* o8 9 u R, n7 c7 v9 ?* R/ a
9 7 ~, p2 ^8 i9 @5 U4 x1 \ a+ {
10
# p* U( \9 L. F l4 z5 u11 ' u) k! D$ s) O, N( H6 u v
12 " O% a' s5 \' F2 z5 y0 k
13 - _7 d- h; n9 t2 ?
14 6 P6 ], b3 t* f. B, H5 o, k/ u
15
' }0 b/ O; ^5 o1 @, s16
" k3 C E6 q9 T9 ?6 f2 L5 U17
* H5 j) O" o; F9 F: r5 z18
; b1 K4 F4 J$ Z9 I0 x- z19 6 X' q9 A0 u, {: h0 c: {
20 3 p0 T0 f1 ~: F% |
21 0 e4 A0 P3 E4 j5 @( _9 Q4 ^
22
9 k$ t' w8 i v7 T, U8 _9 {- L0 D7 T0 {23
" e% ^9 ?6 \8 h24
9 @- W( G& r$ F# J25
% C( v3 n0 I+ H; b: U, {26
. T+ l6 u& ?; \& e# P27 9 Z" p- e1 l; `3 q. U2 |* ~: F( h
28 1 f1 s2 |1 A2 Y/ u+ h J
29 2 S v9 Q6 G8 F1 _) w* a
30
% t! l5 Q/ A! c) I- d9 ]& A1 t$ e1 t3 d31
% S4 H& C5 J0 c# P | server { M. B: L$ H9 I
listen 80;
0 H( f5 X9 R% Q$ Q. Y! Y2 s, j! Q2 X! J server_name www.ttlsa.com;
! F4 U' [7 [0 r access_log /data/logs/nginx/www.ttlsa.com.access.log main; s# b } C) q& ?
2 I" W1 E8 i& ?2 @* n0 e) q* i7 l index index.php index.html index.html; Y6 a- E0 s8 w+ w
root /data/site/www.ttlsa.com;
+ ?( B7 c$ I( A% r: W5 ]2 B- J# ]
" F9 M G! K; J. i0 u2 y location / 4 c$ P3 d# L/ A. T+ U! \: m0 M
{
" H' j+ {; V+ |6 M. S1 @ root /data/site/www.ttlsa.com;
( g! }, A; A# V. y+ U+ ?' x }
! e$ K& x P1 F" q+ e location = /getRealip.php 5 L& {7 _' A6 ~& }3 g; |5 l2 y6 W
{ @, W# A8 V7 c$ {- ^& W
set_real_ip_from 192.168.50.0/24; 6 X2 m1 O+ C* y2 V( T' H3 A. V$ d
set_real_ip_from 61.22.22.22; 2 E% H6 B7 h8 j9 g' F, t1 `
set_real_ip_from 121.207.33.33; 0 x; L: o' d/ w0 \" T, W1 n
set_real_ip_from 127.0.0.1;
% d0 d8 Q& `0 u- \9 K, b real_ip_header X-Forwarded-For; 6 O4 S) V. y+ }
real_ip_recursive on; 6 G# k! M0 {# f3 k& L% M
fastcgi_pass unix:/var/run/phpfpm.sock;
8 E" Z; p6 C- [1 G& D fastcgi_index index.php;
9 C; V! |7 o9 ~6 }8 w; o$ o include fastcgi.conf; % k0 u {- B# [- M% Z8 o) N
}
1 c* C& I1 M# G( m }
5 ?( r& N: z4 G6 s" }7 {0 g9 Z. R' k m W; q0 _0 {! N
getRealip.php内容 1 c4 I7 V) M/ K/ @
<?php # y$ M/ }/ N! ~
$ip = $_SERVER['REMOTE_ADDR']; 1 X0 w( o7 G* U" |& f* V, X
echo $ip;
* J& Z- V% s" z' l" O' k! I ?> ) N; L5 W l b. E) Q9 ]$ N0 c
5 X5 T" C: C( y) _/ {( K |
很不幸,获取到了中继的IP,real_ip_recursive的效果看明白了吧. set_real_ip_from:真实服务器上一级代理的IP地址或者IP段,可以写多行7 S( U6 h) g) I, N4 [
real_ip_header:从哪个header头检索出要的IP地址( ~; z6 _( l' S$ [1 k% G4 b- _
real_ip_recursive:递归排除IP地址,ip串从右到左开始排除set_real_ip_from里面出现的IP,如果出现了未出现这些ip段的IP,那么这个IP将被认为是用户的IP。例如我这边的例子,真实服务器获取到的IP地址串如下:. j2 @, M, A2 |; N+ i
120.22.11.11,61.22.22.22,121.207.33.33,192.168.50.121
; S5 K: k' s7 ^' T在real_ip_recursive on的情况下
, V& t8 U! D" Q61.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或者不设置的情况下
. a/ W) q* g" W0 f) f192.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;
# u0 H# i0 ~" e a3 G* \访问结果如下: 121.207.33.33 " V" W5 g& g4 _& \. L( f
3 x$ O( i/ K1 b* z+ Q四.三种在CDN环境下获取用户IP方法总结4 i) O m* [$ [! ?2 e* V3 C
4.1 CDN自定义header头
8 Q( i7 i" h( W2 `, d优点:获取到最真实的用户IP地址,用户绝对不可能伪装IP
J" U# N, i0 g, T ?) ?! v* S缺点:需要CDN厂商提供 * B0 `# L" S( E/ g t% d
4.2 获取forwarded-for头
$ k: ]& M+ p& s# y" C9 F优点:可以获取到用户的IP地址! t& o/ @" v; E P4 W
缺点:程序需要改动,以及用户IP有可能是伪装的 ' x: x& K0 i$ p# w4 }4 i: d
4.3 使用realip获取
2 u% _" E+ K! \, B/ v5 z' l' ]优点:程序不需要改动,直接使用remote_addr即可获取IP地址
/ X: p: q) o" g+ e; S缺点:ip地址有可能被伪装,而且需要知道所有CDN节点的ip地址或者ip段
6 @" H6 c2 t- _4 j; }+ h |