|
一.使用CDN自定义IP头来获取 假如说你的CDN厂商使用nginx,那么在nginx上将$remote_addr赋值给你指定的头,方法如下: | proxy_set_header remote-user-ip $remote_addr;, ? N" t6 I0 M9 C) q
1 W5 c8 S8 C1 W) {% r |
//如上,后端将会收到remote_user_ip的http头,有些人可能会挑错了,说我设置的头不是remote-user-ip吗,8 ~6 N& ~) p1 v% S1 u
怎么写成了remote_user_ip,是不是作者写错了.请参考文章:<nginx反向代理proxy_set_header自定义header头无效> 后端PHP代码getRemoteUserIP.php 1 6 b) m: E @ O* e ^
2
! `% ]9 a4 S, d: T( Y# q3
. Y5 b4 J1 ~" d( u4
2 c% X' J; k& h% U# f4 s9 t | <?php+ Y3 R$ g) h, ]$ i4 N
$ip = getenv("HTTP_REMOTE_USER_IP");4 d1 s) Z& e! @3 e' N* E9 @8 u
echo $ip; ! O0 f+ }/ _. n7 g1 H O" `
?>' X0 t7 M8 P. H1 H) j- ~
) {; Y. Y! U% E. Z | N |! ?: c' B% M
访问getRemoteUserIP.php,结果如下:
% G4 I' L' J1 o+ \ 120.22.11.11 //取到了真实的用户IP,如果CDN能给定义这个头的话,那这个方法最佳 ! x7 M2 G7 P+ p$ ~8 X. d/ y& I' a
' X# r/ ~4 F5 ?% L$ B/ f# X m
二.通过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
- y C5 W# p0 v+ i' H2 C M$ o2
5 u6 K( P/ _1 Y' ?/ ~! Q6 @3 # n! C% F2 i( w8 b" m) T1 ?4 ?; N
4 S9 n/ x+ q/ ^* m( ?$ I" X. n
5
2 |/ E, ~% Y g( R$ S4 k) F | getFor.php; t% k8 J" b9 i( o3 i' Q
<?php' j1 ^ y$ r: B% x. `, {8 {7 u
$ip = getenv("HTTP_X_FORWARDED_FOR");6 r2 j- M$ f J; h! l" [
echo $ip;3 M0 s. K0 w$ q9 T- |* `
?>
( J2 d( s) d' T' c9 D5 z1 w1 J; R) p e. y6 n3 U: s5 u& J2 D: t! t7 m
| . U7 q" R) F0 u0 ^5 S. ?
访问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 e4 z, v2 N- b4 y) m( G+ W" ]
6 f; l: y4 U; N4 T
三.使用nginx自带模块realip获取用户IP地址+ d; p* ]: V$ D* m5 y; U E; U
安装nginx之时加上realip模块,我的参数如下: ./configure –prefix=/usr/local/nginx-1.4.1 –with-http_realip_module
9 q) b% W& }: S6 U' r/ c3 x , P0 \8 v. p, A: [; f1 L
真实服务器nginx配置 1
4 @7 u0 ?! U; U& s* v7 n2
T- Y( b* S6 L' B+ e3
; n O9 X; M: w2 u* \2 o. u- p) @4
" n% |/ Q/ l5 N4 m! e5
; v, Q# S* ?* x, _7 F! E6 / v1 c2 d9 b: a3 \7 T
7 % p7 v& C4 |, O! c$ Y. A w
8 ! }! Y9 Z% I+ U8 j* k0 t6 g- P7 W; t! @
9 & q, P8 P( B4 k6 v% t: r9 R
10
9 V6 G( P K, t1 w2 X- z7 I% v9 q11
+ `% s4 m; W& `* D: @12
4 w5 \1 S' z2 i3 Q/ Q3 U7 g' z& G13 & k, R7 i$ R: O, Y0 R. O d2 ]
14 Q' Y" s7 q& P! T
15 / y9 q" k7 K [- l: Q
16 ) I' o& R, }! H- b
17 , D1 S4 L+ }/ \) Z
18 ( d0 A5 u* U1 J
19
/ a4 {, q& R7 @6 ?- y20
$ {, U3 p$ k# V8 N4 b21 & q5 ~' o: c% F) r
22
6 y w( j9 X7 x. a23
7 ]! `) z8 R; T24
+ {( |" c2 F. R+ J: V, x25
K" w% k ?/ Z( h26 * y+ ?* e7 c* G2 H3 v: s7 t+ n
27
6 i. a+ g' j$ k28
5 W$ V% S1 v: ~' v/ Q* t% [29 ( P+ x# R) J0 ^+ Z }
30
. p6 h& c8 P4 ~+ H6 j! w. y31 8 |. P: B5 k- I4 ?' h2 i+ |9 j
| server { # e% J# `, |/ Y( g' f
listen 80;
|: [3 L- Z6 S! _( D server_name www.ttlsa.com;
6 |6 ^# a a- c8 j! @ access_log /data/logs/nginx/www.ttlsa.com.access.log main; ! W0 [% L& J [/ K1 u5 U0 b
/ Y+ Z( k! {' d9 h, I
index index.php index.html index.html; + y4 Y8 q( g9 X1 x# F
root /data/site/www.ttlsa.com; ) }, v% N4 t' [
& F" ?7 v! M2 y1 d& l' K8 x8 ]. O3 L
location /
9 d2 w4 B' F' Y0 G { ( h, h- p! Q% b; B/ X! _
root /data/site/www.ttlsa.com; 8 O5 {1 @3 ~; ?( p9 m; }
}
$ O) s+ [8 {9 d# U$ L* @- s) x% P. \ location = /getRealip.php
8 Y" q7 ^+ g8 ?' Z/ B- n { 8 H- l" `1 ~: n4 y8 j, ?
set_real_ip_from 192.168.50.0/24;
; ?9 t" v3 z( z$ k/ c set_real_ip_from 61.22.22.22;
# R, q8 @: ~! ^& c4 F set_real_ip_from 121.207.33.33;
" T4 r! _! l% S, t8 R3 m set_real_ip_from 127.0.0.1;
3 E" i! w. f5 f% p, \3 V1 p( X9 s real_ip_header X-Forwarded-For;
& J0 u/ K, f+ t6 Y" W7 t4 R real_ip_recursive on;
) L, G/ ^" s; \3 a fastcgi_pass unix:/var/run/phpfpm.sock;
) {* R$ K6 [- Q0 Z; A* ? fastcgi_index index.php;
/ h9 f; |7 W( c' W: q/ a3 l H$ t include fastcgi.conf;
1 J9 E3 S9 j; b } " Q1 E8 L( T! a2 T, B% j
}
l9 _; c1 {0 V0 T( ] A
1 L% h" M- A0 D; ]& i4 ]getRealip.php内容
* |- {( N S0 `7 f+ q+ a <?php , D; |4 ]: l3 ~/ B; t! H1 m3 p
$ip = $_SERVER['REMOTE_ADDR'];
5 \9 z/ N+ ?" E" X& n echo $ip;
! ~1 Y& N% i+ ?" K$ R0 ^ ?>
, j! j: r4 e, y: f" `9 u0 [( ?! ]/ w" ]7 A
|
很不幸,获取到了中继的IP,real_ip_recursive的效果看明白了吧. set_real_ip_from:真实服务器上一级代理的IP地址或者IP段,可以写多行5 E- @ K3 F4 I3 N7 @7 r" J; n
real_ip_header:从哪个header头检索出要的IP地址: k3 F0 C% J* a" @+ F3 Z
real_ip_recursive:递归排除IP地址,ip串从右到左开始排除set_real_ip_from里面出现的IP,如果出现了未出现这些ip段的IP,那么这个IP将被认为是用户的IP。例如我这边的例子,真实服务器获取到的IP地址串如下:
; x) n0 U/ M" M& b$ S120.22.11.11,61.22.22.22,121.207.33.33,192.168.50.1219 E3 b' T, D% U. S6 c' M
在real_ip_recursive on的情况下
2 e3 w( b6 \. j9 T# M61.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或者不设置的情况下) X1 S. e- u ?: ]
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;
4 w7 A# V" N a M3 a9 z# V3 k" `访问结果如下: 121.207.33.33
" F( L0 _. N0 }: I- r# `( f/ k
0 ]0 o/ A1 s+ W8 F* w/ c四.三种在CDN环境下获取用户IP方法总结8 J, _& r, A! h' b
4.1 CDN自定义header头
: E+ T! |/ h2 A9 Y# j) Y% {: ]( R优点:获取到最真实的用户IP地址,用户绝对不可能伪装IP4 {/ z/ n U- x) z' R/ \
缺点:需要CDN厂商提供 7 n X5 W$ y% z. V
4.2 获取forwarded-for头' U/ q& \2 x" O+ T' C- o# g
优点:可以获取到用户的IP地址; ~1 [6 p) `/ h# h( a5 v$ ^) `
缺点:程序需要改动,以及用户IP有可能是伪装的
/ i# f1 G+ I: B( Z
4.3 使用realip获取) [, U B3 _/ F8 J/ j
优点:程序不需要改动,直接使用remote_addr即可获取IP地址
/ ^5 C0 p. r$ e6 c7 Y, V+ c& m0 Q缺点:ip地址有可能被伪装,而且需要知道所有CDN节点的ip地址或者ip段
5 h9 L G* G* y2 q9 h% B |