|
一.使用CDN自定义IP头来获取 假如说你的CDN厂商使用nginx,那么在nginx上将$remote_addr赋值给你指定的头,方法如下: | proxy_set_header remote-user-ip $remote_addr;3 y' Z: ]) H7 L
6 X% c5 k) s- I) y
|
//如上,后端将会收到remote_user_ip的http头,有些人可能会挑错了,说我设置的头不是remote-user-ip吗,
! p$ `, [4 f2 x% s. {5 H. }怎么写成了remote_user_ip,是不是作者写错了.请参考文章:<nginx反向代理proxy_set_header自定义header头无效> 后端PHP代码getRemoteUserIP.php 1 ! K: z- F! O) j9 b
2 8 ~+ }3 {% i, w
3 8 r0 a- k: Z7 _9 T9 ~
4
+ q( t1 q$ k& C3 X' N4 O2 G | <?php# O4 C2 @- R/ ?( Z
$ip = getenv("HTTP_REMOTE_USER_IP");
6 a/ y8 P5 G: r9 n& \ [ echo $ip;
! w O8 U* u! u! ~. j* s?>
% u& |$ i6 F6 F, `* n- g* h
/ ], M, ^! N; M2 l' k! x) c( l* W | : s8 {) ]3 m+ d' f% N
访问getRemoteUserIP.php,结果如下:
0 \. I U2 \8 e9 z- p1 m/ @( v 120.22.11.11 //取到了真实的用户IP,如果CDN能给定义这个头的话,那这个方法最佳
- n) v2 `4 V' [+ j
3 F" A1 T0 }6 C3 m2 e& i二.通过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 2 o9 `& C: N9 W& h& \
2
5 h0 s7 l' s6 a# P0 T3
- O9 b" q, h5 D% |) v( G4
* A: S. L! b6 q Z% v5 7 K& F- @4 t7 n0 T) `0 W
| getFor.php- Y) Z1 J. n! t
<?php
+ D8 d& F) f8 A+ C0 Z $ip = getenv("HTTP_X_FORWARDED_FOR");
7 }2 V- P0 V k5 y echo $ip;! K5 P) O' e, z( }% R
?>
2 I; _9 S* p: @! h. C- K& c& t9 l; V* {5 k+ E& w* N; Q
| 9 [' b, n1 q$ l+ l0 A
访问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.
1 E8 o S" W+ b: F- p6 `; _# [5 I" W
m; r% o" e! H* S
三.使用nginx自带模块realip获取用户IP地址
+ U8 z+ A* m: E2 G* {. H$ o8 w+ l安装nginx之时加上realip模块,我的参数如下: ./configure –prefix=/usr/local/nginx-1.4.1 –with-http_realip_module
( I: d+ c% U/ ` ) l2 x1 k: d2 v. I
真实服务器nginx配置 1 % L3 @7 w l1 F4 V' n9 {7 D3 J
2
8 h% I8 A( p! U3 ; x$ m' ]: A3 {- I5 A
4
1 e. K6 c6 ]6 _1 K5 8 r& z, i/ Q1 C2 ?$ `. d# }
6
& D" B4 D; s( t: q7 ( ]* b, P. D" B6 c9 i. A
8
" t, a3 g8 t$ w0 H h1 y9
/ i2 ~" c4 r* }5 f8 a P( f0 ?# {0 @10
4 q( L; L# k! H3 O( W% e1 p! Z11
- ]$ {7 x( A( j12 . S+ ?& N* r. \* A
13
' x' ^7 ^2 E2 z' {14
, J0 L# L( V* B9 C* p% a9 m; v7 |15 5 a/ a# O7 s0 o3 J' Y
16
& f* u* M6 d5 M17 ) e {1 U8 z6 }0 V, w7 n
18 6 T1 m7 }5 J/ k k% c
19
8 B) T; M5 m& U4 _! K" U20
v( a$ E! ^% g1 z9 p21
) P0 y: L# \' P1 J/ @22
3 @0 {% \: |+ `& c& m) _23
7 @, [* T% p+ x24 m# l$ z. n, M5 ?* @' p
25
6 [! k9 n( d) J& }0 _; z1 m* }' K8 D" A26
& B2 V. o% H/ ^/ P" r27 , D1 ]/ c! r' @% o2 h% V
28
7 D3 N: C' k+ v5 _" P& C5 T29
! P, m) s0 }* d; L30
) I; w. |8 I! v) _31
6 ]8 k- R1 g0 C- B8 ?% _3 f | server { e! F( F5 s" L; A
listen 80;
8 P' ^- L1 ? T& T# y. h$ G server_name www.ttlsa.com;
; u q3 O! g9 F9 \+ o access_log /data/logs/nginx/www.ttlsa.com.access.log main;
% K6 f- x3 b0 C6 W5 F' q7 S# v7 V % S% ^1 i' @4 J# i3 y# l1 @
index index.php index.html index.html; ) r% C9 @* l) i6 J$ h7 w# p
root /data/site/www.ttlsa.com; 9 r2 V- g2 p5 u
1 \, g; ]# R- h location /
: H- a/ c# {% n" _3 D {
- ?/ I0 V" L# r root /data/site/www.ttlsa.com;
" d1 r6 y6 n& N& M9 s! k0 i/ ` }
5 \' V) w$ z0 h" w- | location = /getRealip.php - v0 W5 }8 J' ?9 V1 Z. E
{
' H* {3 a; _5 _ set_real_ip_from 192.168.50.0/24; 1 g2 R2 Q1 o% j# Z2 U+ `& u! k
set_real_ip_from 61.22.22.22;
. y K1 Y6 z5 l% _+ q set_real_ip_from 121.207.33.33; 2 r$ e5 A) U, B2 ~- f5 B
set_real_ip_from 127.0.0.1;
+ ^. a, ^% h& s7 E real_ip_header X-Forwarded-For; 9 s- f8 q3 m {* M6 a6 Q6 r1 g
real_ip_recursive on; , d0 z2 z- j) ^2 s
fastcgi_pass unix:/var/run/phpfpm.sock;
" x. U, D! d7 y O4 r! o2 ] fastcgi_index index.php;
% L) j9 n \4 ~2 I" K include fastcgi.conf;
' g% j1 p0 ^+ y( N) x& j' w& s } 5 A/ P6 H- L8 j1 J& v2 ]
} 7 b6 n6 [3 P5 _3 j
* p; j0 p. g1 w0 {getRealip.php内容
$ N# g5 N8 ]- Q' A# |4 J9 | <?php . W, f# i& L, s" `' `! L" U1 k
$ip = $_SERVER['REMOTE_ADDR'];
$ @, ]! v$ |7 [1 B, u echo $ip; % |5 L& R$ }9 h! X5 ]" a. ^
?>
+ @% f1 d$ B% a. X' O; R/ y; c2 h. O4 a! Q
|
很不幸,获取到了中继的IP,real_ip_recursive的效果看明白了吧. set_real_ip_from:真实服务器上一级代理的IP地址或者IP段,可以写多行7 m- I0 t* E! ~4 D
real_ip_header:从哪个header头检索出要的IP地址 d7 b, o5 K' y
real_ip_recursive:递归排除IP地址,ip串从右到左开始排除set_real_ip_from里面出现的IP,如果出现了未出现这些ip段的IP,那么这个IP将被认为是用户的IP。例如我这边的例子,真实服务器获取到的IP地址串如下:
+ I8 |! \0 ]" X/ w120.22.11.11,61.22.22.22,121.207.33.33,192.168.50.1215 \& y- S0 X' u* T$ X2 `
在real_ip_recursive on的情况下
) Z( o8 T/ m, Y' E61.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或者不设置的情况下
) v6 q. _+ D1 d5 e* h6 ~& L3 O" p192.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;
2 ^+ D4 v+ G. s4 B- ?6 ]0 a) ]访问结果如下: 121.207.33.33
- t3 I" Q; u: P( n! w
* O8 \5 I/ n. E) {四.三种在CDN环境下获取用户IP方法总结: c( X2 D, F& E
4.1 CDN自定义header头
. k, K! s6 w8 ?( Z优点:获取到最真实的用户IP地址,用户绝对不可能伪装IP- E; @7 ]; z# ~) X$ W/ \
缺点:需要CDN厂商提供 4 K1 s( E% e- r9 t
4.2 获取forwarded-for头
D, ~& M& y" L优点:可以获取到用户的IP地址
% V0 g. m' C8 Y2 F8 s/ h缺点:程序需要改动,以及用户IP有可能是伪装的 ) d% Y! C* l4 b# K
4.3 使用realip获取
" ?5 ~ ?/ x( r, |( F优点:程序不需要改动,直接使用remote_addr即可获取IP地址! r0 }: J8 X, L8 U* O
缺点:ip地址有可能被伪装,而且需要知道所有CDN节点的ip地址或者ip段
7 r% P" q& E" G* A Q# ` |