一.使用CDN自定义IP头来获取 假如说你的CDN厂商使用nginx,那么在nginx上将$remote_addr赋值给你指定的头,方法如下: 1 1 x8 B0 T; X1 r0 _: q: v" @7 G
| proxy_set_header remote-user-ip $remote_addr;% f6 g8 |) d6 g: L6 Y3 L2 N
" H6 z0 n! O( r
|
//如上,后端将会收到remote_user_ip的http头,有些人可能会挑错了,说我设置的头不是remote-user-ip吗,9 w/ |3 T6 s5 c! v, _" H% A4 B
怎么写成了remote_user_ip,是不是作者写错了.请参考文章:<nginx反向代理proxy_set_header自定义header头无效> 后端PHP代码getRemoteUserIP.php 1 % L" c: u6 u/ J( w% K9 U
2
+ @5 O* C( k6 y1 J) ]1 y3 " z) D1 L- S5 _% Z3 q, B! W7 R
4
% g, L: @) z: \% @! ~ | <?php* ]$ U/ d1 \9 Z3 K6 j
$ip = getenv("HTTP_REMOTE_USER_IP");% K- }1 R# ], x6 Y Z+ X
echo $ip; 0 V0 S+ d$ h$ G5 ?, J4 R
?>! ^8 v+ O7 }' z, r9 N
6 k; \7 H% `0 U* A
|
' j$ c0 S2 ?1 C5 m+ G5 e访问getRemoteUserIP.php,结果如下:
6 \& b3 R" D( b) ? 120.22.11.11 //取到了真实的用户IP,如果CDN能给定义这个头的话,那这个方法最佳 0 J: x( Q" C/ d7 S/ Y
4 _) |# V. I' |% o二.通过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
/ g6 y1 @5 t* a1 o2 1 P6 Y" U- y" }1 |/ j
3 / d3 ~: D; i( _( G9 i: @/ _4 s) m2 [
4 - ]' B% k' H$ I6 W) Z4 j Q: \
5
! |8 Q4 ^8 J. B& S' Q! F3 k | getFor.php
* g7 v" c4 h4 P6 J+ D9 l<?php& E3 g# y, w0 _! g
$ip = getenv("HTTP_X_FORWARDED_FOR");5 |8 c# s& i4 Q* ]/ A
echo $ip;
0 B ?3 |+ m) m! ?7 `- \+ u3 C?>2 e6 r3 A- O+ j: E; r! X, Q6 ^
4 p) R4 \9 r2 @" O9 E K
| " m% z( g: Z0 a/ J$ f; m3 D
访问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 f' k5 S$ c3 S* t
9 I9 @$ w/ N. Z: ~
三.使用nginx自带模块realip获取用户IP地址; Q% Z% D# m* j# O' _, B* L
安装nginx之时加上realip模块,我的参数如下: ./configure –prefix=/usr/local/nginx-1.4.1 –with-http_realip_module
. n. I1 p4 T/ K* i( f U; j
t" _7 ?4 l7 b E% W" O' r5 Q真实服务器nginx配置 1
9 {3 f- T* m8 j2 B, [1 B9 u" l2 ' ?' I. z( y R2 w
3 0 c% I- S0 u: {3 L* P3 \0 N
4
' e, B6 q7 p" a5 9 l& H1 }$ D: \4 j
6 # J' K" W' H! s4 o# Y
7
( |7 M5 |8 p( F) G4 m" W0 C& g8 7 P1 m$ c4 x$ J) R5 O/ H
9
3 _6 n O9 |( ?4 f5 w+ J5 X10 + _5 L* n% g. X7 y4 X6 k5 D; R
11
: w4 c+ F0 Z7 ~4 _12 $ ?- r% Y) t6 V2 z. X
13
# \, v) u, e; P7 M3 _14
1 H, B# g) Q, w; Q) r- G. q15 % l8 D2 s3 g8 S8 T( n
16
7 }+ M6 C* L& B E7 P- W# p17
5 T; j( F: \5 m9 ~( g" i18
: T: U2 x5 h8 _/ ]: y3 J' c) y19
" I3 e* V$ ~3 k6 E" T0 V20
5 n& R+ z A0 W6 { y/ p# r21 5 v* T: [( i/ k9 Q
22
* M- @9 ]. g- a6 o# U23 ! `9 E- e; x3 D5 _, k s
24 9 z2 m" E* p9 Y& \5 @- z% u& ~) K: ?
25 5 P [( `' I( }9 A% _
26 + w$ W) D: y$ ]2 ^0 F$ |
27
9 _/ i" x. q, c7 X28
3 k4 R/ s7 e$ V" t3 M29 + p2 i; ?" t. R G# }
30
% \- |! d* x5 V31
: F# b& a3 f5 F7 X3 }( e2 a | server { / [: d0 \9 w) ~- \ f3 c G
listen 80; " r" M" K: f. V6 H& g% q. U
server_name www.ttlsa.com;
q1 F* o0 R( a; x- C access_log /data/logs/nginx/www.ttlsa.com.access.log main;
: v" }. t4 p$ A3 n : O) r! W2 ]$ i$ h
index index.php index.html index.html; & ~" a8 U6 \7 G' u" G' \
root /data/site/www.ttlsa.com; 9 Q0 n; j- L. G/ _' G2 i
0 D8 x* k7 v) W! m
location / ' I5 X* m8 k$ u
{ 5 m# d/ m+ U7 @* u+ w( ]$ E9 b, `3 {
root /data/site/www.ttlsa.com; $ K5 y* r# N: e! r; m
}
0 m* K2 L/ \$ ~' \ location = /getRealip.php " h0 G, h9 P2 ~4 s
{ 2 r/ `3 l" r0 \4 z3 Z, q
set_real_ip_from 192.168.50.0/24;
* F& t0 u+ ~. | O: k+ {$ ?; A set_real_ip_from 61.22.22.22; # B+ |9 r( {# o r$ t
set_real_ip_from 121.207.33.33; % l0 W3 D+ g- n- M; f9 @; r* t8 e
set_real_ip_from 127.0.0.1;
+ e5 P, \) @6 t real_ip_header X-Forwarded-For;
, J/ k5 d4 N" B6 w% e- k9 a# ^ real_ip_recursive on;
, {9 C" h; F$ F/ B( m fastcgi_pass unix:/var/run/phpfpm.sock;
* N, S S& d, p7 Y8 P fastcgi_index index.php; ! z8 r2 T* |6 E! ]0 t, u& H6 o
include fastcgi.conf;
/ T. z, W, ?( o6 n" g& c } m- U. I0 M8 q. X }$ C7 u: O
}
8 S$ G- }4 k, B& U. ^4 m* Y# z& o
$ P$ R* l }( x/ i2 i- l/ S6 UgetRealip.php内容 % `9 g9 ?* X; u7 W; w9 x( I' ?7 R6 F
<?php
4 p3 |* x3 ^9 q, N# A$ Z R) m $ip = $_SERVER['REMOTE_ADDR']; 9 r x/ j f+ p, |
echo $ip; $ ^6 W$ \) L; |( r2 R s" }
?>
6 r# i- y- {1 D$ U% Z$ s2 W& N S3 ?) ^% l+ F# ?
|
很不幸,获取到了中继的IP,real_ip_recursive的效果看明白了吧. set_real_ip_from:真实服务器上一级代理的IP地址或者IP段,可以写多行3 u4 a# D$ }9 f% b( e) X1 o# n: i
real_ip_header:从哪个header头检索出要的IP地址
% s5 [% P( Q2 B1 J1 ^/ Rreal_ip_recursive:递归排除IP地址,ip串从右到左开始排除set_real_ip_from里面出现的IP,如果出现了未出现这些ip段的IP,那么这个IP将被认为是用户的IP。例如我这边的例子,真实服务器获取到的IP地址串如下:0 i! Y! N# o' y7 q9 b# K! Y7 ~
120.22.11.11,61.22.22.22,121.207.33.33,192.168.50.121
2 n6 | b2 ~/ z g' X3 N! h3 q在real_ip_recursive on的情况下
' ?0 L$ P6 q- {% X7 {5 k4 c' G61.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或者不设置的情况下
* b. n$ x8 X. Z* X2 Q8 a192.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; : o( S! D* I7 E+ |5 S
访问结果如下: 121.207.33.33 2 H: k6 O3 E0 X- i$ p
, O, e) Z1 X3 v
四.三种在CDN环境下获取用户IP方法总结
5 q7 M ]8 i* j8 c# y4.1 CDN自定义header头
& N8 N- t: C0 Z优点:获取到最真实的用户IP地址,用户绝对不可能伪装IP& G9 ]* A3 Q* a* X& y
缺点:需要CDN厂商提供 8 \4 a, Z# h! f6 Q5 P- P
4.2 获取forwarded-for头
: L$ B* K/ O- F+ A优点:可以获取到用户的IP地址6 d* A0 \+ v' Z' k8 O
缺点:程序需要改动,以及用户IP有可能是伪装的
6 {+ e, u: u3 A0 [. b" b
4.3 使用realip获取
$ y4 L2 I% }) ~$ ?1 {& H; m1 O# O优点:程序不需要改动,直接使用remote_addr即可获取IP地址
" B f+ m! A o! q! W; F缺点:ip地址有可能被伪装,而且需要知道所有CDN节点的ip地址或者ip段
2 W# W& O ?! G, v' { |