|
一.使用CDN自定义IP头来获取 假如说你的CDN厂商使用nginx,那么在nginx上将$remote_addr赋值给你指定的头,方法如下: | proxy_set_header remote-user-ip $remote_addr;
" j8 y F0 k& n9 |2 s, C
+ {9 q' a. Z( c1 ] |
//如上,后端将会收到remote_user_ip的http头,有些人可能会挑错了,说我设置的头不是remote-user-ip吗,
/ X: Z# I- G. a+ Z: i怎么写成了remote_user_ip,是不是作者写错了.请参考文章:<nginx反向代理proxy_set_header自定义header头无效> 后端PHP代码getRemoteUserIP.php 1
4 n* H: n% p1 S4 y1 ]2
5 i- p' \" s0 H0 W/ Y9 M* }# q. ~3 + f0 i; X% k( M+ L5 ~
4 2 v& `1 r9 k; L% \
| <?php6 u7 c! l9 D0 l6 J! @# Z1 Q; \
$ip = getenv("HTTP_REMOTE_USER_IP");
; w `! M4 X3 Q$ T echo $ip;
! ^* Z+ n7 i7 f% V$ p: a?>4 Q6 a$ |+ s( ]" r1 O9 W6 Z5 f
" U% f9 z( c: S' U L | 9 G# J; B2 h8 }; e
访问getRemoteUserIP.php,结果如下:, {; E: x- s7 J8 R* }+ B
120.22.11.11 //取到了真实的用户IP,如果CDN能给定义这个头的话,那这个方法最佳 q, \ R) C. O4 m) T: B% S+ v' _
+ ~, b4 T: w! a4 o5 H# J7 o
二.通过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
! r) p! ?/ k. `8 q" Y2
( _. u3 l6 G" H* \: t; |3
f% m: n/ _+ m' T4 % L( W3 w+ \& L; O. [8 B
5
( J% C, T0 ?- C5 J3 z | getFor.php# O5 q! \( ^' e' S& @+ o( D
<?php
5 |8 p' L% A, X7 z. W $ip = getenv("HTTP_X_FORWARDED_FOR");
$ E' a8 H+ f7 Z0 b% h echo $ip;
: g! P3 b: T, ]7 r9 B?>8 z( W$ s# X9 S/ z2 v& A( j
1 D, v) Q. H5 @8 N; o5 J/ u. c. o, ^ | k+ b) E G. 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. " W3 l' G; ]& w" f9 ?
* K# |6 B8 I+ Q$ j
三.使用nginx自带模块realip获取用户IP地址) C" a" }# V3 w8 M7 L7 \1 [
安装nginx之时加上realip模块,我的参数如下: ./configure –prefix=/usr/local/nginx-1.4.1 –with-http_realip_module
- L5 z z% W T. R7 C. w
# n5 U- P) F6 Z真实服务器nginx配置 1 ( M+ a3 \" Z; _ I- l
2 ) r. }, i. R3 y6 M ?7 d% ]
3 2 v. U8 x. F$ w$ m X
4 9 {, @7 r J8 s q# \0 L
5
8 L4 Q% N8 U; ^6
. Z3 ?. J9 c2 M" H3 |7
9 W5 Q5 ]$ [( b# a8 w9 i8 4 {' U, Y) k8 r& ~5 G+ d" r
9 $ m) |2 W7 @# p0 w' p: J/ }" \
10
: Y4 q l6 f6 r. }8 B5 s11 . H$ ~7 p8 ^/ w
12
. Z0 ?/ K/ m, U: {% g: e+ t13
1 X" E4 x$ l; R e' n! i14
' @% O9 V0 Z/ r; V15
/ \6 Q7 T1 ^4 H( o z3 a16
$ D; G6 V6 T0 U9 E3 l) F17 - x+ |& d! p/ ?$ m* f* a& U8 ]
18
' g* Z* d6 N' {19
3 u5 I) N6 @4 ^. G9 Y20 + B# E/ V4 P& I% ?
21 4 K0 q0 }1 {- h
22 + P" q N6 m8 X
23
% ^, }( k3 I- I24
; F, O' j G+ I5 M2 u m25
& }' c( K8 Y9 o7 W) M- j26
# E1 |0 v/ N/ I/ v; \$ K27
& O6 E/ R+ C& j, x28
: x- C; y' }7 [! X; G/ T29
7 E7 v1 J @/ i0 Z30
+ b5 U* q/ f. P0 z" G$ K* z+ P31
+ R n9 b) u0 A# H' {7 j, S | server {
' _" e1 i$ @0 D6 w' Q4 T listen 80; 6 a# ^" d& `/ S# F
server_name www.ttlsa.com; % A3 S- i. I% E' e: H$ `4 b4 G
access_log /data/logs/nginx/www.ttlsa.com.access.log main;
9 z/ v! i" i! s7 } : F4 d2 _" S6 u) J9 n/ l; a( R0 z
index index.php index.html index.html; 2 G4 ?) B- j6 E, _. _* v
root /data/site/www.ttlsa.com; 4 C5 I9 B6 N+ V _+ P
( S* ?+ a4 b: c' P' R: z7 K, u
location /
) v# ]3 O, o6 p6 R1 g- o: w { * o4 x7 T. t3 r+ f* V/ ~
root /data/site/www.ttlsa.com; ; P* L! p7 v7 K" @
} 7 [: T: L/ C" P2 ?) u
location = /getRealip.php
6 X) w8 a# t7 d0 [6 i {
/ v* n; e( d$ z6 H# C set_real_ip_from 192.168.50.0/24; , W% Z. W+ F, J5 @* [' R
set_real_ip_from 61.22.22.22;
( U& n! Y9 y& R set_real_ip_from 121.207.33.33;
( w$ M0 t2 y) T3 V set_real_ip_from 127.0.0.1; , G% o$ b$ `$ A+ `( G8 k
real_ip_header X-Forwarded-For;
) R( x$ `& X# m, j8 A real_ip_recursive on;
! _. G n7 ? A* A" y; g/ b fastcgi_pass unix:/var/run/phpfpm.sock;
% |; w2 N' A! A5 ~8 H; e fastcgi_index index.php; 3 B" h/ w; D. t; E O
include fastcgi.conf; 1 L- w$ Y0 x$ U5 |, v( y: C
} : [4 a' T8 {' l5 Z& S1 J: j: q' e1 K; K& d
}
8 c [: Y6 P# S
$ Q' s/ N, [* H, E& y3 V) I- S( MgetRealip.php内容
u7 q- b* q% }4 f <?php
, C1 `$ [0 v9 B8 N" k, } $ip = $_SERVER['REMOTE_ADDR'];
% `7 ~& d5 B7 J* A8 x, E echo $ip; # P" M+ e E$ X: T. ]2 s
?>
2 j9 k+ W1 ?3 ~3 B
: W+ Y2 c8 M/ N5 l. x1 W { |
很不幸,获取到了中继的IP,real_ip_recursive的效果看明白了吧. set_real_ip_from:真实服务器上一级代理的IP地址或者IP段,可以写多行8 l8 p5 h; ?% Z. `9 J; M( w
real_ip_header:从哪个header头检索出要的IP地址
3 w" h% U& K2 a# {real_ip_recursive:递归排除IP地址,ip串从右到左开始排除set_real_ip_from里面出现的IP,如果出现了未出现这些ip段的IP,那么这个IP将被认为是用户的IP。例如我这边的例子,真实服务器获取到的IP地址串如下:, _2 t* X4 b+ f
120.22.11.11,61.22.22.22,121.207.33.33,192.168.50.121
7 W' v6 W5 m1 R$ Z在real_ip_recursive on的情况下0 H1 X6 G* R; W& D; g
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或者不设置的情况下
4 g, ^3 w6 @ G/ k3 m8 f192.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; 8 h2 d) c" ?6 v% b" X
访问结果如下: 121.207.33.33
. f3 X* Q) v% n2 K9 s& H0 j9 ^
2 ?6 G1 d0 H& e3 q& O3 R; X9 I四.三种在CDN环境下获取用户IP方法总结6 h6 \& V; {3 |
4.1 CDN自定义header头: f( \) t, M( I2 I& ~& W% _) L& G
优点:获取到最真实的用户IP地址,用户绝对不可能伪装IP
7 a) ?% H% v! y' T. L缺点:需要CDN厂商提供
W+ [1 D3 w& E! R0 ^
4.2 获取forwarded-for头+ c; @0 H2 u1 n" n& b- L
优点:可以获取到用户的IP地址& ~0 N$ Q4 }! I% w/ v
缺点:程序需要改动,以及用户IP有可能是伪装的 + p8 G( c! J0 C W5 j1 b1 [% P) r* c
4.3 使用realip获取
0 u% m* b# h( e( j6 z; [/ D, B优点:程序不需要改动,直接使用remote_addr即可获取IP地址& N# s* ^/ F3 O: s" R% R
缺点:ip地址有可能被伪装,而且需要知道所有CDN节点的ip地址或者ip段
) n) G! j8 S. l. H R |