|
一.使用CDN自定义IP头来获取 假如说你的CDN厂商使用nginx,那么在nginx上将$remote_addr赋值给你指定的头,方法如下: | proxy_set_header remote-user-ip $remote_addr;
& R/ u! w/ N( f' d3 A
# R& d5 O* `2 W5 S) _# ^; k- @ |
//如上,后端将会收到remote_user_ip的http头,有些人可能会挑错了,说我设置的头不是remote-user-ip吗,! Z+ l- q% Q( {/ {
怎么写成了remote_user_ip,是不是作者写错了.请参考文章:<nginx反向代理proxy_set_header自定义header头无效> 后端PHP代码getRemoteUserIP.php 1 8 v3 Q, B& H& M: G0 G3 M' \: s
2 ; }( A) o N) b8 t [; v
3
1 m/ o& Y$ W& n* D8 Y: j4
0 d9 r+ [5 H3 r# y+ T | <?php+ H/ e6 j, C: |. {$ g: x
$ip = getenv("HTTP_REMOTE_USER_IP");
7 i* X( }( T9 _* H% Q- b' k echo $ip;
# P" Q/ n) D% S0 e?>3 |2 I% X S% ?8 z+ n
: \2 \' r' Z6 K; o
|
! k7 h& q, w0 \+ @6 s: I访问getRemoteUserIP.php,结果如下:+ c8 L% P8 m5 [4 q1 S0 W, \
120.22.11.11 //取到了真实的用户IP,如果CDN能给定义这个头的话,那这个方法最佳 " W3 L/ k1 p2 ^4 a; D& R
. u- u# l. B; i' y/ n二.通过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
( G9 L# o, {0 x+ Z8 \* s. s2 $ ?+ d2 }% u" s2 Z
3
+ }2 @" a8 s. O- _& ^2 [2 v; f$ R4
% q7 I. \- `4 K( U5
# P& W& G E' Z | getFor.php: v7 U! v6 [ w. e2 |
<?php/ K) g4 f/ A: g0 @6 K' @1 q( t1 H
$ip = getenv("HTTP_X_FORWARDED_FOR");( W$ O _% @# v5 P8 G9 h7 T0 s
echo $ip;
$ Q! |. C+ R' c/ G2 g?>! R \4 j7 F, k1 J
& v+ L+ j/ L/ x4 s! j& m7 w
| $ d. S+ [0 `5 r1 b3 K# n! G8 ?& n
访问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.
% s5 s1 l! \- H. G- q4 G
3 u, J) x/ L4 {9 L2 u! d 三.使用nginx自带模块realip获取用户IP地址8 C3 p$ {) |. h" q6 M2 Z7 `: u
安装nginx之时加上realip模块,我的参数如下: ./configure –prefix=/usr/local/nginx-1.4.1 –with-http_realip_module6 J9 a8 ~3 H# N9 f) Q% R; l4 N, a
8 ^3 C! K+ }. A* f3 h真实服务器nginx配置 1 8 }2 E6 }6 x j; g' Z
2 - v% |; ?' P6 }/ V5 E" R
3 5 r3 `( U; p! a7 R. F
4
+ J; d: E* e: e& i5
' D8 L0 s2 y- p1 h6 5 z, T4 v$ i) p' M6 g/ `9 G
7
4 r9 h" f2 W6 t. _8
( E7 Y3 S! p9 a; K9
/ L- ]9 x# _' p$ D3 u( V9 w10
" I, u5 N5 m* U# {' `9 m k' | [% g) I11 7 l: u: K5 ?/ m# P
12 . g- H2 f5 W% Q9 `4 K6 e9 I! m7 G
13 / a1 C7 t9 j3 R1 `' s3 q
14 * x0 I8 T! H* s& R) w
15
4 D! ]0 p: l$ P H9 D3 w+ ~* A9 k16 3 ?7 l. F1 ?% c2 w( u# @4 H* W
17 " @/ }( z: c) R3 j% C
18
3 o, q9 V, }" ?19 2 i+ ~; j$ S! O2 C5 O. h. g3 i4 c
20 5 y$ y9 H% R2 G4 w9 t
21 1 b- S# q" A) ^' @( w$ R& |
22
! p4 ^' ]' A* z6 T2 h23
5 p' m: m' G- N% B9 o5 e: x24
+ g& n& ?9 ~ W: p25
, |# K3 F! I! @/ ?26
) V, C0 W9 S$ e$ c27
9 u: i7 b1 Y( C5 d: E28 $ O4 M8 F' O9 \, Z0 N
29
8 P6 |- Q9 n% G30
) d. Y) J* m& l31 & @2 V3 y# z$ S+ J J8 t
| server { Z: i8 p3 y* E7 @- _/ N" Y
listen 80; . K# z. x: \& H- b
server_name www.ttlsa.com;
- }) v0 n7 U3 y a( i8 K access_log /data/logs/nginx/www.ttlsa.com.access.log main;
5 N. }' L- l/ h" B% m: ~
9 i1 ^7 [5 g) ?! o- A8 _- L- c& F index index.php index.html index.html;
) G' a' I2 \' `% y" v0 d4 o6 Y S2 } root /data/site/www.ttlsa.com;
( H0 z9 k. `1 L5 `
/ D8 ?# z! ~5 }% f location / + s' w: f: J/ P, m
{ + {3 `, J+ @: `- O
root /data/site/www.ttlsa.com; / w r" i% U- L& o$ b b
} % \& ^% n7 {$ j; X7 C
location = /getRealip.php
) n2 U, B6 l( _ |0 k( H7 ?1 } {
1 M* J" j0 S3 O4 j- |% r set_real_ip_from 192.168.50.0/24; - B V- Z/ n2 Y& {0 }$ d/ }4 i
set_real_ip_from 61.22.22.22; / `! r2 q! R9 ]& [. V0 j5 O) |
set_real_ip_from 121.207.33.33;
: o. }& d, \5 s set_real_ip_from 127.0.0.1;
~* w: [2 [+ e1 g) E3 \/ r/ @+ m$ ~ real_ip_header X-Forwarded-For; + i/ ]* W9 g2 n; c% B7 ?1 v; T9 [
real_ip_recursive on; & e1 n, ]; X7 b& T6 [7 m
fastcgi_pass unix:/var/run/phpfpm.sock; 6 }# L8 b3 Z9 ~( {1 E
fastcgi_index index.php; 2 _( A0 s* C: P: i
include fastcgi.conf;
% U! a9 Z/ J1 A2 s1 L: U0 i7 H" K } + `- E0 g+ E$ r! ^
} : p4 p* b& l1 {+ P% n$ m
" m2 T! ]3 x0 Y6 Y) @getRealip.php内容 " m) e( G) |) W. p- p
<?php : k0 h: @7 y: m- X
$ip = $_SERVER['REMOTE_ADDR'];
; g! i* Z% }+ n$ l O( S0 f echo $ip;
- A5 [! z7 o! L ?> ' ]8 B. U5 M4 G8 Y# E g
$ A- f2 r7 Y& ?' m1 t, L |
很不幸,获取到了中继的IP,real_ip_recursive的效果看明白了吧. set_real_ip_from:真实服务器上一级代理的IP地址或者IP段,可以写多行
! E7 E( S; i. W! ^& zreal_ip_header:从哪个header头检索出要的IP地址
& n4 J3 v! P& F2 G4 x# F, rreal_ip_recursive:递归排除IP地址,ip串从右到左开始排除set_real_ip_from里面出现的IP,如果出现了未出现这些ip段的IP,那么这个IP将被认为是用户的IP。例如我这边的例子,真实服务器获取到的IP地址串如下:
, b9 ?; p# _: E9 l* `120.22.11.11,61.22.22.22,121.207.33.33,192.168.50.1212 [, _- @6 M n! ]
在real_ip_recursive on的情况下
" Z& v4 r0 k/ U3 T3 B9 U61.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或者不设置的情况下
0 k, M% Z; z+ x: k2 _- C5 Q* c192.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;
* ]1 J! ^$ Z7 B4 h9 q/ L访问结果如下: 121.207.33.33 / l0 V1 s4 M* Y' n
) y9 `. h4 O: @. Y! _" ~7 Z2 }四.三种在CDN环境下获取用户IP方法总结- z! O" x* @* ]- @$ z- ?/ s" ~
4.1 CDN自定义header头
) a- Q. G/ V' p+ T6 \优点:获取到最真实的用户IP地址,用户绝对不可能伪装IP6 H9 u1 {+ ?* t1 x3 o4 y
缺点:需要CDN厂商提供 4 d- u! i% b* n+ a, Z4 ~
4.2 获取forwarded-for头
/ F- W/ Q; Q1 V8 Y+ p优点:可以获取到用户的IP地址
+ ]4 f5 O' c9 L缺点:程序需要改动,以及用户IP有可能是伪装的 * }3 Z% u0 @" t
4.3 使用realip获取) b! x5 c( @: b, `2 }" _
优点:程序不需要改动,直接使用remote_addr即可获取IP地址! A' _8 }* R8 c6 V
缺点:ip地址有可能被伪装,而且需要知道所有CDN节点的ip地址或者ip段
, s! r( r0 x% D0 {+ w% ?- h |