|
一.使用CDN自定义IP头来获取 假如说你的CDN厂商使用nginx,那么在nginx上将$remote_addr赋值给你指定的头,方法如下: | proxy_set_header remote-user-ip $remote_addr;: g3 A+ a5 O$ R! i
$ \1 R5 j. b- f. x9 h" } |
//如上,后端将会收到remote_user_ip的http头,有些人可能会挑错了,说我设置的头不是remote-user-ip吗,4 J$ y% D& z' x4 E& |( s
怎么写成了remote_user_ip,是不是作者写错了.请参考文章:<nginx反向代理proxy_set_header自定义header头无效> 后端PHP代码getRemoteUserIP.php 1
( `! l/ S2 y' p2
; ]( G3 P0 ?4 a2 T* D( A3 3 R* b: s1 H! \* t, R# x9 d2 `
4 9 C1 K! Y9 }8 G! J8 u6 }0 @
| <?php
; ]! U: v; S$ d) h" g9 x% t& k4 M $ip = getenv("HTTP_REMOTE_USER_IP");
* y$ Q; l( ?3 ^0 P echo $ip; * E) t# ?8 x3 s( Y( \
?>
- o# O c& h3 n* R1 l6 A, k
+ L6 a @1 \) V |
& d9 r3 t6 o& d& s w- m# U访问getRemoteUserIP.php,结果如下:6 Y" A, p# w) y) n5 n
120.22.11.11 //取到了真实的用户IP,如果CDN能给定义这个头的话,那这个方法最佳
# p, Y( q/ I; {1 o7 H, o$ G. j( o( i: y" h! R/ K$ `" }
二.通过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
+ ?% n6 |5 P/ |2 K4 }+ Y! N2 1 J" e3 o2 |: F9 `+ D
3
- P/ F i# ~( Q4 2 p. u* E$ N7 B& |
5 % _& K3 ~1 ?& d# }) u) q" u
| getFor.php- d$ Y2 E8 D7 B2 l
<?php
9 w @ V; F. Q2 o; H( [/ K6 I% W $ip = getenv("HTTP_X_FORWARDED_FOR");
Y4 U+ O; K3 c8 l# K. U1 @ echo $ip;7 Q$ M* _* g+ ?" W* A! k! _
?>
8 u- |1 o8 t, W' G+ P$ w u# S9 y# _0 r) m
| W/ e, D+ b$ Z' S* C
访问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. % l& N" V; z' @# U# R) d
) `6 y8 Q9 A* f2 T, q
三.使用nginx自带模块realip获取用户IP地址
) o# B- J2 S0 u {: Q安装nginx之时加上realip模块,我的参数如下: ./configure –prefix=/usr/local/nginx-1.4.1 –with-http_realip_module( ~! H! u6 _) z2 ?9 Q4 D2 b: G
6 D1 K J- j1 A真实服务器nginx配置 1
1 ~7 O* e N1 u2 - i1 @: J, H9 p/ G
3
, B [3 ]5 ^) z- D p8 R0 {4 " ~: {3 u$ \2 r
5
3 X. v5 A, Z5 @/ o3 L7 q' S% T; Z% b6
# B) H0 a% n& M3 X7
: a; m) }1 o: ~, U8 & C& \ m) h/ v9 P7 b1 Z! @
9
/ P, T3 C; ^ v' k& \, |* h1 u10 9 G( K) w7 }# @
11
2 B' z* [) a8 c: e12 $ P- n- {( g" ~# \. q( r
13
% b8 f6 W P! i4 F9 \: j& u. L+ a* W14
- |: T- K+ p+ g) }15 5 k& _3 w5 s: `, Z( P% |& C4 x8 l
16
2 o* j! W0 y ?! q/ z# B- p17
* O8 ~ Y [. }( c( k" u* t4 {3 N18 % T) ~; X. @; O- {7 j5 C
19
@) R- E" n. ?6 i4 s20 $ d8 F( b1 Y1 I: z, N7 g$ W
21
8 K: c# \! M, L! C2 y) u% [9 I/ @22
: {% p r J0 C5 \1 p" o23 ' T3 |+ K5 K1 V# Z7 M0 P; Z8 W& q
24
: z( @2 s( v- T3 @' {, ^- b3 W- f25 . X) V* ]' Q6 P& m( D9 Z
26
+ f g) r8 O# L5 U: D27
9 b" H& \% c* U28
- ^7 G( S, L( d# A0 F3 U/ W! G29 g5 O5 M* s1 X; j; G" [
30
2 K( l5 _ L0 a) f8 [3 d31
; [) j. r$ Z M! {2 W | server { B1 j# {4 {& C8 M
listen 80;
8 d( o2 h, H4 e4 c2 w3 W server_name www.ttlsa.com;
' ~8 B/ Q0 M3 N/ P, v- _ access_log /data/logs/nginx/www.ttlsa.com.access.log main; ) e* w7 {% H! u* A3 `
+ d% I& w5 t, n% ^. Y+ a
index index.php index.html index.html; ( O! S: Y% v% k3 Y) k% \
root /data/site/www.ttlsa.com; ( V4 W% P# F' v2 `
/ b# \: w* O. B% ?% o7 V+ W
location / & o. }! |, s6 _/ b8 }
{
% ^! q5 S. G: x) n. H& p root /data/site/www.ttlsa.com;
3 P3 O8 i n. f& C }
0 ^; A+ h; ?& M/ ^; a location = /getRealip.php
" m+ q6 `" |$ _% s. o" {1 _, Z) Y {
- S+ [( f; d- M0 {) Z2 c& ? set_real_ip_from 192.168.50.0/24; & |& [- W( q. O9 F
set_real_ip_from 61.22.22.22; 7 r+ t* A( N$ ^5 u1 I) c
set_real_ip_from 121.207.33.33; % m' L/ h+ g$ g1 {$ g
set_real_ip_from 127.0.0.1; # \7 I- S+ p/ a% V$ _
real_ip_header X-Forwarded-For;
. N8 _6 K; H* P8 T. E real_ip_recursive on; 9 G+ J/ J+ B8 \& q
fastcgi_pass unix:/var/run/phpfpm.sock; & H R$ d7 p, J2 E. Y/ R
fastcgi_index index.php;
+ b |1 i/ l9 \! A* e7 S7 p include fastcgi.conf; * a3 j$ x: w N+ r, Z6 N
}
5 A+ J; k" [0 ]) Q; O3 @ }
" g7 p7 |8 E5 {- B2 ?4 m' o7 @6 t p0 K% v6 k# N( J+ z1 J% a
getRealip.php内容 + W, G% u, c3 J8 k" Q
<?php
6 m; T$ s8 ?9 b- G1 f) k4 E9 v8 O9 E ? $ip = $_SERVER['REMOTE_ADDR'];
4 E- }+ s- ~3 h echo $ip; . a6 A0 Z. Q" C+ e* t
?>
6 o1 c* t9 y1 l" \ b8 }
& X+ O1 D0 {; a0 S/ n6 q5 m |
很不幸,获取到了中继的IP,real_ip_recursive的效果看明白了吧. set_real_ip_from:真实服务器上一级代理的IP地址或者IP段,可以写多行1 ~4 E3 T. o$ ]5 ~+ i
real_ip_header:从哪个header头检索出要的IP地址* Z1 u: a& Q% ~- s, ?' {
real_ip_recursive:递归排除IP地址,ip串从右到左开始排除set_real_ip_from里面出现的IP,如果出现了未出现这些ip段的IP,那么这个IP将被认为是用户的IP。例如我这边的例子,真实服务器获取到的IP地址串如下:$ V2 \3 N9 T; ^0 H" z
120.22.11.11,61.22.22.22,121.207.33.33,192.168.50.121
" O! U) p: k7 s4 o! k+ F/ C在real_ip_recursive on的情况下) T* t! j9 E( a- b; S" X9 ?
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. t: U; H/ E7 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;
5 {; Q1 x7 s+ X) k访问结果如下: 121.207.33.33 " }, x. f J( }9 P' H g
, f' P$ O6 w, u+ ?0 k3 r" X
四.三种在CDN环境下获取用户IP方法总结1 }! W! p* s( I0 |6 a, L9 m
4.1 CDN自定义header头( f) q7 h2 k; k% b( ]* F. _! S
优点:获取到最真实的用户IP地址,用户绝对不可能伪装IP D& N' N! K6 X, I9 U1 L; i
缺点:需要CDN厂商提供 1 p% M' F* T. m1 p5 j4 N
4.2 获取forwarded-for头
2 n9 r3 Y- \( Q优点:可以获取到用户的IP地址
' q, W. a6 z% L- F* B5 N缺点:程序需要改动,以及用户IP有可能是伪装的 , N- C$ O4 s n- w# h
4.3 使用realip获取
; C l' k& t. |3 G4 j9 Q# X( r优点:程序不需要改动,直接使用remote_addr即可获取IP地址; x, L+ n/ p" h- z
缺点:ip地址有可能被伪装,而且需要知道所有CDN节点的ip地址或者ip段
2 n0 G3 j0 P$ {3 G( ~ |