|
一.使用CDN自定义IP头来获取 假如说你的CDN厂商使用nginx,那么在nginx上将$remote_addr赋值给你指定的头,方法如下: 1 4 h5 W+ N# K, \, u: R4 t. I4 _
| proxy_set_header remote-user-ip $remote_addr;
' d1 [; `: Z2 T0 P2 k
* C9 @! J# R; O T |
//如上,后端将会收到remote_user_ip的http头,有些人可能会挑错了,说我设置的头不是remote-user-ip吗,
2 l' c- b5 w _+ A- P怎么写成了remote_user_ip,是不是作者写错了.请参考文章:<nginx反向代理proxy_set_header自定义header头无效> 后端PHP代码getRemoteUserIP.php 1
# i. }! U& b# @2
8 m6 [& f$ C2 H- C9 y; Z, ]6 ?3
+ N" k9 ]/ g, ~% [9 _4 5 M: D6 m. [: Q: |5 [
| <?php, Z" ]* o2 `) u6 E# j3 p- _
$ip = getenv("HTTP_REMOTE_USER_IP");& W6 R7 W! \( ~- m. @& Y$ B. X: w
echo $ip; ; L& S+ t, m4 A( Z
?>
1 k& m# v) v+ n1 b* G3 q+ @
0 `2 Z+ t- S5 j4 |5 T5 V | % H- z0 r" u) N n' `9 P
访问getRemoteUserIP.php,结果如下:. P2 ? A/ e' A/ j4 _* R" c
120.22.11.11 //取到了真实的用户IP,如果CDN能给定义这个头的话,那这个方法最佳 $ |9 N: r& n! m) d' F1 I% J- M: @
4 ?4 S* Q6 p1 {, 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
9 n2 f, N& D N2 B) o# C2
& d, C4 S& l7 z. `, V1 l$ ^- Q3 3 I: t0 g& v+ f& s
4 8 n, U. v1 f3 o/ K! C% V4 G8 e
5
. s3 J" y# q; a9 N | getFor.php; v& N; h/ P2 }5 M9 J3 {3 o
<?php
& g1 j* b6 ]( ? $ip = getenv("HTTP_X_FORWARDED_FOR");- ^" D1 E: D7 a7 a7 w9 A
echo $ip;
) L3 y' W4 s: s0 I! f4 e?>1 P) h' [: y9 ?/ R. \ r/ @/ ?- v0 P
. Q1 N S9 q {: z! R$ m1 j% b! @ |
5 N' |% ~8 @0 F" Q0 ^. ]. S k访问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. - c" C+ ~9 o! D4 A( I
1 [$ Q5 r- v+ A- j( v/ x0 V
三.使用nginx自带模块realip获取用户IP地址- P4 D- A$ N. p: G
安装nginx之时加上realip模块,我的参数如下: ./configure –prefix=/usr/local/nginx-1.4.1 –with-http_realip_module
8 r3 u$ E- S4 l( y4 @7 ` o! I; ^ # B% H j+ q# t( V& q! p
真实服务器nginx配置 1
0 M; l+ `1 p( H! ^% y4 Z2
/ L- U# X9 f* T7 K e3 7 T I* e& C( B
4
. U4 r+ {8 K, W+ w* ^- l! Z5
' ]# N6 L+ `* j* a# N6
) ]- B7 M' t- f) h7
3 ~5 c1 u+ m# g( F4 z8
. l0 S2 o! \3 ]5 z" |9
7 ~( P6 Y% r3 w# Z/ O10 2 t f# Y" }6 |9 N- Z+ [/ t! _8 m
11 1 f: c" U" o! T* I- E3 n
12
. @0 R9 _( J3 S( F! g0 S13 1 c2 M& O3 N. [/ P; g: n7 M
14
% M) ]3 {9 D& N& @; A" G2 k9 \15 4 L2 I' @( ?8 g) Y3 C
16 # H- S% A* |. y2 h3 n" R
17 1 o, l! `. G p: S
18
6 w" P$ Q2 }. N+ [$ ?! W/ x1 [- ?. t19 ! s* w- F# q" s6 O
20 ' y: O( }# ~4 A1 U: {
21 & o Q0 K4 K6 \
22 , y D2 ^% [/ f7 U7 N, V# O
23 " F5 Y; f& Z, `# Q9 c4 G1 s' {9 g
24 ' v* ]; @5 _3 ]8 f* k" H
25
5 N) a/ M9 Z2 e' C26
" E2 ?4 [# B" N$ z5 b0 q27
$ h. f3 P( [% u7 J, `28 ) Z- f( }3 @: `' Q. m
29 & W8 {! y8 |5 P
30
. V* k3 J, l8 h' D31
4 q/ G9 T* }7 O0 _5 d Q, r8 R# W | server {
; R* c- c) N1 ]2 R5 ^# R listen 80;
5 t- i# ~, h$ h1 i& d" H, R$ O0 ^' i server_name www.ttlsa.com;
( Z+ a# v! [& t/ T access_log /data/logs/nginx/www.ttlsa.com.access.log main; 2 q$ G/ I2 m2 E; c
& D; X9 [$ E6 C
index index.php index.html index.html;
6 c# M* ]; a/ D9 U root /data/site/www.ttlsa.com; & ^+ k* K+ K9 R2 }& q& _+ P
2 F2 w6 y' R5 Q8 C
location / $ e0 x# E2 T7 L) ?& R
{
" X- ?) e. \. w root /data/site/www.ttlsa.com;
; \, C: y7 T7 t: C0 _7 x } $ {# U4 p& ^; w( N% [( a& [+ c7 g
location = /getRealip.php 0 J9 }0 W8 J% ?
{
& i: B9 k+ O9 r' B" Q set_real_ip_from 192.168.50.0/24;
. Q& y/ F- |- d& z# N6 A4 o set_real_ip_from 61.22.22.22;
& X k4 g5 Z2 }6 R+ X \ set_real_ip_from 121.207.33.33; / G& |. X$ h9 y" m# M
set_real_ip_from 127.0.0.1; " X/ k: P( C+ m1 [2 f
real_ip_header X-Forwarded-For; 6 _$ g9 C; A1 u; P' \$ `0 N
real_ip_recursive on;
+ t% G5 b, S4 m. \+ o2 V fastcgi_pass unix:/var/run/phpfpm.sock; . S7 y' n1 f0 d( A+ x9 V
fastcgi_index index.php;
# n; E& @9 T( _, @ include fastcgi.conf; ; T/ h, H+ _ M! `: M8 K( R
}
' I5 j0 T0 C9 q5 H9 W }
# F8 `9 p3 e/ F* P1 W9 Y# @- X6 [$ k* i- Y) e3 H: B
getRealip.php内容 8 h2 e2 s: w4 ^$ s
<?php
! G- i; h' f& e- D( | $ip = $_SERVER['REMOTE_ADDR'];
9 u* k& h. w7 t5 [: R echo $ip;
1 f8 i7 M% W# p( C ?> 2 N4 P; J3 M9 ^% ] a4 }& n0 C
* J K+ H2 \' s2 u9 d1 X |
很不幸,获取到了中继的IP,real_ip_recursive的效果看明白了吧. set_real_ip_from:真实服务器上一级代理的IP地址或者IP段,可以写多行' z( I% I: p* x3 F) j# G( p( D
real_ip_header:从哪个header头检索出要的IP地址1 \& ~4 g( O0 z' b4 |
real_ip_recursive:递归排除IP地址,ip串从右到左开始排除set_real_ip_from里面出现的IP,如果出现了未出现这些ip段的IP,那么这个IP将被认为是用户的IP。例如我这边的例子,真实服务器获取到的IP地址串如下:
8 {; d! W Z7 P' ^120.22.11.11,61.22.22.22,121.207.33.33,192.168.50.121: |' w) `9 o5 H% Q# ~$ d
在real_ip_recursive on的情况下
2 Q! n' _. A$ O' s* ?* x! Z61.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或者不设置的情况下
% g" v6 R/ j4 R! [/ Y i8 {; z. m: u192.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; : Y8 K$ Y! m* N# m
访问结果如下: 121.207.33.33 . x0 ~$ `. `* A2 M6 ^: e
/ F1 c& w1 U2 Z
四.三种在CDN环境下获取用户IP方法总结1 [8 }! w8 z6 |6 H0 k2 v% N4 D! Y9 o
4.1 CDN自定义header头5 Q( V2 W) n# e, w
优点:获取到最真实的用户IP地址,用户绝对不可能伪装IP5 R2 g- M+ j2 d- V6 `' G
缺点:需要CDN厂商提供 . Q) [; f* o2 H' Y+ ?
4.2 获取forwarded-for头5 o. C3 h/ V! ?" d, v7 d& s
优点:可以获取到用户的IP地址6 P, i" f; m9 z# b
缺点:程序需要改动,以及用户IP有可能是伪装的 " I: y( m. c4 p: \5 y7 L/ p
4.3 使用realip获取
, U8 l+ R0 ?! ^优点:程序不需要改动,直接使用remote_addr即可获取IP地址7 b* [+ b r" L' n& i0 L" y
缺点:ip地址有可能被伪装,而且需要知道所有CDN节点的ip地址或者ip段
, T c* f6 ~) a) [+ h |