一.使用CDN自定义IP头来获取 假如说你的CDN厂商使用nginx,那么在nginx上将$remote_addr赋值给你指定的头,方法如下: | proxy_set_header remote-user-ip $remote_addr;7 k% W. k9 M3 T: g3 _! k6 v
- k- s4 G5 \6 B; i' j* p) o5 j |
//如上,后端将会收到remote_user_ip的http头,有些人可能会挑错了,说我设置的头不是remote-user-ip吗,. p# U8 G) |: a y7 d9 s% H' y0 }
怎么写成了remote_user_ip,是不是作者写错了.请参考文章:<nginx反向代理proxy_set_header自定义header头无效> 后端PHP代码getRemoteUserIP.php 1
4 A8 o7 l9 Z- Z2 K8 y' ^2
/ O$ B- U% a8 L* B; G- v7 N3 9 u% J H# N# M9 o" ^
4
; E$ u& Q) Q' r* O | <?php
+ f' ~1 O" |3 v2 I5 l- P $ip = getenv("HTTP_REMOTE_USER_IP");
" o5 a) `- i$ y echo $ip; 9 i/ [$ Z! h6 r
?>' N. M& Z- w) ^) ^
& k" `2 m" G" i8 ^; z | 3 ~* ^4 {# R' c) S: f! x9 y+ C* {
访问getRemoteUserIP.php,结果如下:/ a! q1 n/ Y/ a$ U) B
120.22.11.11 //取到了真实的用户IP,如果CDN能给定义这个头的话,那这个方法最佳
% |1 |3 m5 {# H; t8 k0 C6 W/ i% \' H8 {4 D, F5 n4 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 & t! Y3 ~: [# B( H" K% _
2 # M- |( T$ ~% u# A% b
3
& o8 x4 @ [# ^5 a4 X$ a4 + L8 P" X* @' i+ @9 M
5
* r* ~4 n1 y; \' a# u5 Z7 A+ Y | getFor.php
6 z1 G' H, ?% g<?php* v( y# }2 F" t+ N* C2 W
$ip = getenv("HTTP_X_FORWARDED_FOR");8 Q7 h8 w( F* ~* k P7 s. k
echo $ip;
1 p& I/ v/ D1 D+ p4 S?>
1 o1 C# O5 _+ h. m$ }( i+ q% j1 e- o) i6 K
| ; H! t3 ?/ H9 \) n; E2 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.
& X) P) \1 r( D
4 E; E3 O+ s+ ^. ~0 ]
三.使用nginx自带模块realip获取用户IP地址
6 O7 l! [( A4 J4 [安装nginx之时加上realip模块,我的参数如下: ./configure –prefix=/usr/local/nginx-1.4.1 –with-http_realip_module
' u- O" q* w+ d% U4 [2 @ : Q4 l+ m* A/ b
真实服务器nginx配置 1 % `2 ^- f: z% q+ f) o
2
; q. Y- D3 i1 v, _# f3
; j* e' B. \7 r( a7 D# ~4 & M( X j+ V* W: r. l
5
4 x2 ~) n" {6 S0 M0 _2 \6 ( p9 r1 @2 h1 b2 T% K! x
7
2 Y1 w D0 e7 g8 G1 S8 % W9 S0 F4 A8 X* Z+ g" `
9 ( Q" b- |9 D5 v* [6 F
10
+ S: V3 n6 O, b$ _4 y7 W11 - w3 e9 Q" q9 e& N2 `! i' c, b% Y
12
/ w. q9 o; C& m2 |' v13
6 I+ W6 ^5 J4 B% r R$ ?* z' R1 k14 $ k k" b, M6 p$ j- v) B
15 0 S, C* s/ H! i8 I+ C8 ^! ]
16
+ G5 Z$ W2 ^; J7 x9 U/ G$ D17 2 i5 o3 o0 K' N& ~+ |
18
t5 O$ e( Z8 m# ]19
, U1 e4 k' M0 c* ?0 R# z% S20
! v K: b, B. H' C" m21 / ^) F# R9 n% P {$ c6 Q
22
, ^+ i% ?0 U* o# y7 B; E8 i23
# p* T k" h: x$ r$ t24
& k& O$ ?; }' e) r3 D9 q+ T25 # R6 B" W5 s. s
26
# y$ {/ f/ w) a/ {# d27 # T- {2 o: A+ D, t8 k
28
# Y; n) b$ W2 n- y29 : N# C& h3 t: b% V& L3 M# A8 y
30 $ B P! o" z$ m
31 4 O% T6 }$ e5 W+ m
| server { - d; z# Q8 c% d; j+ x4 f
listen 80; 8 `0 q' w# G; m& N$ H
server_name www.ttlsa.com;
4 f( J# f5 r2 c0 c access_log /data/logs/nginx/www.ttlsa.com.access.log main; $ [7 ?& ]5 X6 z/ y/ |, n2 k. X
- }4 }7 ^; e/ G' k& v index index.php index.html index.html;
( T7 W( D, B, c- V+ B" c root /data/site/www.ttlsa.com;
+ f0 |& X6 _, a9 t$ g / n* }7 d& \# N3 ]5 }7 z
location /
1 M% a& C) I2 I( p! f {
! u) F6 [" o0 [3 F root /data/site/www.ttlsa.com; # K" @; N. J$ E5 }
} ' d0 E5 [0 _# P1 q6 g
location = /getRealip.php
+ ~7 N- C. S \! u& [8 N9 ?; J$ o! R {
0 l% C3 R& q8 }6 O- k set_real_ip_from 192.168.50.0/24;
- X8 d$ s$ b; Z$ m1 N set_real_ip_from 61.22.22.22; # P( T* D9 r6 V3 V. L2 D& }' P% L1 |6 f
set_real_ip_from 121.207.33.33;
, b( s$ ?- z$ G% P: ^ set_real_ip_from 127.0.0.1;
% X( V( R5 V' g2 C2 i* t b# X real_ip_header X-Forwarded-For;
2 d5 I9 @& A* G real_ip_recursive on;
5 d& i' {8 Z; h6 i( m% F3 G7 T fastcgi_pass unix:/var/run/phpfpm.sock; & N# C+ V( i3 P+ K N
fastcgi_index index.php;
" Q4 D. T. M* G7 K/ R- }* A% `0 j include fastcgi.conf;
0 D- C$ z( _: \. C( r# S } 6 Z) N, W9 J4 K' i( l1 T. i
} 0 d+ B. n A z0 z- U- h& S
, p: @0 r: ?0 h( |' X) m. i
getRealip.php内容 ! B- ]* X' \% y
<?php
& F: d' \8 \/ x5 `. ]( K; _ $ip = $_SERVER['REMOTE_ADDR']; 7 x6 l: f- L* U& N2 r+ `% l$ ]
echo $ip;
7 d* Y7 {# q0 N/ L) T. C( B ?>
& m' L/ Z9 @- i8 n; w9 y
3 |) W. ~/ l' F2 d; O |
很不幸,获取到了中继的IP,real_ip_recursive的效果看明白了吧. set_real_ip_from:真实服务器上一级代理的IP地址或者IP段,可以写多行7 O. ]0 {+ N( ?
real_ip_header:从哪个header头检索出要的IP地址
3 }# u. T; y8 r B' f0 lreal_ip_recursive:递归排除IP地址,ip串从右到左开始排除set_real_ip_from里面出现的IP,如果出现了未出现这些ip段的IP,那么这个IP将被认为是用户的IP。例如我这边的例子,真实服务器获取到的IP地址串如下:5 M4 m3 P4 t1 n9 n( M9 q( Y9 W! ^
120.22.11.11,61.22.22.22,121.207.33.33,192.168.50.121
4 N i1 ~. h5 p8 Q9 w3 a [, b- B在real_ip_recursive on的情况下3 E$ l4 b: k+ A* @
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或者不设置的情况下8 ~1 m( h2 b# g4 F4 U+ w, Y# N1 W
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;
E& o- W. q _2 k5 m' I, U& {9 g; D6 _访问结果如下: 121.207.33.33 9 Y/ A: R+ E5 i( D' m; s- n0 G
, u! v; H. H/ v4 s" r四.三种在CDN环境下获取用户IP方法总结; O* c& b2 c3 [! t4 R) W6 b' d
4.1 CDN自定义header头5 u- Y- f) ~. [8 y0 N
优点:获取到最真实的用户IP地址,用户绝对不可能伪装IP& h$ p; b. {2 O4 a' h
缺点:需要CDN厂商提供 . A; K4 h- O( j7 y6 y
4.2 获取forwarded-for头+ Q/ C! A6 j5 d" u$ W
优点:可以获取到用户的IP地址
- A; r. c6 ]! [+ i缺点:程序需要改动,以及用户IP有可能是伪装的
, `. e% F8 a9 ?* Q$ u
4.3 使用realip获取6 t' h! g. j( j: C( I/ B7 L$ @
优点:程序不需要改动,直接使用remote_addr即可获取IP地址( H" H- U4 T! e6 {9 v
缺点:ip地址有可能被伪装,而且需要知道所有CDN节点的ip地址或者ip段 ) c8 Q9 D2 g& q8 q: }: f; K
|