一.使用CDN自定义IP头来获取 假如说你的CDN厂商使用nginx,那么在nginx上将$remote_addr赋值给你指定的头,方法如下: 1 9 V7 T* D! X2 F4 `: P& j {4 x
| proxy_set_header remote-user-ip $remote_addr;' a2 A2 W" V0 r5 I) j
' o% v' l) s! {! w9 f# y# f9 P
|
//如上,后端将会收到remote_user_ip的http头,有些人可能会挑错了,说我设置的头不是remote-user-ip吗,$ e! r* f+ m' [9 v
怎么写成了remote_user_ip,是不是作者写错了.请参考文章:<nginx反向代理proxy_set_header自定义header头无效> 后端PHP代码getRemoteUserIP.php 1 ; B; [/ X* ^: A+ Q9 d
2 5 h: a* d3 Y$ @' H7 r0 w
3
& \# m) Q4 R' G# T4 0 q( l2 X; \" o' a6 W. q3 p, ?
| <?php
2 q: @- t3 {; m+ Z& z' T $ip = getenv("HTTP_REMOTE_USER_IP");& M) D4 @7 p( _- V
echo $ip;
9 ?- P G* b. @' Y' M. A9 k6 m$ d; f?>: U" Y4 t( Q, G, R& k4 D7 f& q
2 g( u( C: b. X& f7 n& n | 3 l9 e: R- D* x, t' I$ A
访问getRemoteUserIP.php,结果如下:% h3 [: ^& F! L2 b9 ?( ~
120.22.11.11 //取到了真实的用户IP,如果CDN能给定义这个头的话,那这个方法最佳
" M; [ s6 X9 G6 j8 e1 [; Q. R4 S6 b* h. M9 Q! a% ?
二.通过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 8 p" { y9 V- f, B6 q
2 $ W0 k: f$ \. L) \9 k, K% U8 K3 @
3 8 O" H7 K) X. r# Y. O
4
) J( M! J- v7 ?- N5 W, r! i' x5
. W+ v% h( i9 B d: u | getFor.php
+ x2 G. ~7 I/ ^. q+ B0 m1 b, g<?php
; I# c5 W' B% A" J* g3 B $ip = getenv("HTTP_X_FORWARDED_FOR");) u0 |9 U9 {* b
echo $ip;
& h; B' h+ x% d?>& m; I- w! F' |$ M
; d- Q' G6 Q1 v' D R9 U | + ^& a1 C' Z- Y4 O7 d; U5 O
访问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. " j P- O& g( ?8 S+ Y! H
/ X( l( p+ ~- y9 D: w- [
三.使用nginx自带模块realip获取用户IP地址 Q2 R( h& s) y" }: U
安装nginx之时加上realip模块,我的参数如下: ./configure –prefix=/usr/local/nginx-1.4.1 –with-http_realip_module
5 T: ]) p" N1 ?9 Y7 b$ \* C% j
8 N @. |) H& _+ \5 T' {+ G# e0 u$ z真实服务器nginx配置 1
% g. _0 O1 } F' h2 * H% Z) V. M% Y- W$ k, a N, E8 f
3 $ F0 _+ L; f% G& _& z0 d+ q! _
4 . C2 \, k. d+ A+ n1 z. V3 d
5 8 L( j1 }+ b1 T# e. A$ c. e
6
% P! o. D; a; V/ k' V$ X7 9 X" K& V2 B X- w$ o5 P
8
8 D' j& j5 n2 q" s9 J9 , |4 [8 _/ @7 x5 z$ U. l' O8 h6 M W
10 + j7 R) ?$ f/ }1 F. L8 }: O4 b
11 6 |* U7 z9 d/ J/ W% r! \
12
+ j- O. m2 p; Z8 y8 p13 + z+ G5 ~$ |& u
14 % _" L5 q7 A$ u: |+ {0 e! T
15 . F6 g3 b5 h/ \
16 ! o* k: A- [- J1 F
17
: [9 v- Y/ T2 k6 K9 ]+ X18 ( d7 ~7 P- ]. w7 \0 F
19 / E& K% O+ y. u: g
20 ' J( m _" \ ^7 f" Y$ ?6 x2 N- m
21
2 z5 F! p2 b, i" @1 M22 ) m3 e4 ~ c/ A. S3 N
23 $ ]/ t( d+ r& u. n
24
1 P5 e, j: f/ e! L) W$ p& r, L! b25
; l& U6 d9 Z1 |/ b$ @26
7 k% e! e" g H; c" X27 W8 V( g8 X! t9 o* Z7 }3 R7 s
28 0 M4 A# R; b9 T
29
% S& U0 x* ~6 B/ i7 @* A5 \! o30
7 s3 x, p4 y: O3 [2 i, m$ i31 ! x' Q% f/ f. h* K, r
| server { ) ` H5 t& s, m# U
listen 80;
* E, \, ]8 H# v0 e$ c' F% {( Q server_name www.ttlsa.com; 1 b7 _: a$ h: q( S
access_log /data/logs/nginx/www.ttlsa.com.access.log main;
& o; Z/ n1 E, v$ K) H7 W
' D8 Y5 H8 x1 g, Q; H1 \ index index.php index.html index.html; , S. g7 }) x/ A% A: e6 f
root /data/site/www.ttlsa.com; 4 v' i- H% r; f3 y0 \5 y9 p0 j; ~
- E7 r# u. S# X, F5 q5 Z! ]' C location / & {& v* G( \1 B u) t
{ $ b$ R9 D, |9 {! n
root /data/site/www.ttlsa.com;
: o i. b* M' N3 n } + L0 I* e" m. }# x, H( i1 R
location = /getRealip.php ; K- h7 |; [" q3 O8 }4 e) Z
{
) B& i- X1 ]2 D2 d set_real_ip_from 192.168.50.0/24; ! z8 f3 h* q5 j* C
set_real_ip_from 61.22.22.22;
) F" M4 F# k' h' G9 a: V6 |2 ]- { set_real_ip_from 121.207.33.33;
. r7 u: K( V, ] set_real_ip_from 127.0.0.1;
( W |; I7 e0 `7 z/ b9 r real_ip_header X-Forwarded-For; 5 n5 j o, o+ U
real_ip_recursive on;
+ E5 m" s7 q% T2 u' j2 [ fastcgi_pass unix:/var/run/phpfpm.sock; 4 q# t" i0 }% Z7 p' J
fastcgi_index index.php;
" r3 _, C1 t$ |! k$ k include fastcgi.conf;
+ d7 T, x* _! g. K. \ P- R }
6 S G0 v$ h9 p' u2 I# J+ R } c2 P* a; V0 {1 C L
, z* c0 T0 m1 }4 F+ s6 ~" A3 Q- ]getRealip.php内容 , d% ~% R4 \2 I) M5 i% L) c, j
<?php 6 i- q: H3 P( h( M: C2 q) B
$ip = $_SERVER['REMOTE_ADDR']; ! e& k1 Y- _5 ]/ [, N8 q% o
echo $ip;
( y0 e; }; A$ K# W ?> 9 m" C0 H& ]+ K9 `
. x# o+ L) t9 l0 D |
很不幸,获取到了中继的IP,real_ip_recursive的效果看明白了吧. set_real_ip_from:真实服务器上一级代理的IP地址或者IP段,可以写多行% S- F7 y; x7 W* I- o4 ~0 d) W
real_ip_header:从哪个header头检索出要的IP地址
& l- N J0 F* p3 g1 x- zreal_ip_recursive:递归排除IP地址,ip串从右到左开始排除set_real_ip_from里面出现的IP,如果出现了未出现这些ip段的IP,那么这个IP将被认为是用户的IP。例如我这边的例子,真实服务器获取到的IP地址串如下:% p/ V, l" `5 H* W! K6 }; n
120.22.11.11,61.22.22.22,121.207.33.33,192.168.50.121
# ~ j0 U" U8 u z, U在real_ip_recursive on的情况下 J, Q" |/ w0 a2 _% c" a5 j1 ~: i
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或者不设置的情况下
" e. N) @% a7 ^+ {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; 8 U( l$ f* n; W" S6 @% R
访问结果如下: 121.207.33.33
! r! `7 y( j& d2 g% h7 b ) o) c* J" ]& v+ D; j& ?5 k4 b, ?" W
四.三种在CDN环境下获取用户IP方法总结
8 j4 P% I$ ^/ z! n6 j4.1 CDN自定义header头
, p; C) q0 _0 U& ~4 v0 G优点:获取到最真实的用户IP地址,用户绝对不可能伪装IP
. @5 R* U7 f% I& z缺点:需要CDN厂商提供 6 S3 c3 b+ p% `$ d7 C' M
4.2 获取forwarded-for头
# a8 T; b( E e0 H4 @优点:可以获取到用户的IP地址) N" K; O8 a' w+ e7 b5 k- b
缺点:程序需要改动,以及用户IP有可能是伪装的
6 ~ _% i+ q' z$ J: t
4.3 使用realip获取, q- [% V" H/ K, t6 C2 x
优点:程序不需要改动,直接使用remote_addr即可获取IP地址. P+ M, K$ b2 b; q$ C# l
缺点:ip地址有可能被伪装,而且需要知道所有CDN节点的ip地址或者ip段
$ g4 [7 x7 J! G' n4 y+ [5 ? |