一.使用CDN自定义IP头来获取 假如说你的CDN厂商使用nginx,那么在nginx上将$remote_addr赋值给你指定的头,方法如下: 1 & k4 x# M8 M- x9 ~8 x8 X
| proxy_set_header remote-user-ip $remote_addr;: N; \2 ` ?, m( Z
# f, h. X3 L! E+ s# ? |
//如上,后端将会收到remote_user_ip的http头,有些人可能会挑错了,说我设置的头不是remote-user-ip吗,- C1 d9 }8 L: d9 h
怎么写成了remote_user_ip,是不是作者写错了.请参考文章:<nginx反向代理proxy_set_header自定义header头无效> 后端PHP代码getRemoteUserIP.php 1 ' p( K6 K3 Z) N/ T$ s
2 " U" q3 L$ o/ E& d( F& S8 Q( e
3
! `! l% d+ p$ `/ ]4 ' x, C1 a1 x8 w, Z; Z$ v, E
| <?php- R9 q5 z7 ?8 l) X
$ip = getenv("HTTP_REMOTE_USER_IP");( E) n% i; P6 q9 }7 Z7 I
echo $ip; ' U- d* S" E" C% X0 q
?>
$ U) Z! N! M4 m7 _6 J1 \+ C1 q- L
7 _# H, c, ~3 V$ C9 \ |
4 w9 g, w/ H( n. c% k# W访问getRemoteUserIP.php,结果如下:) d6 W( T! \& Y, e
120.22.11.11 //取到了真实的用户IP,如果CDN能给定义这个头的话,那这个方法最佳 8 ?0 F" Z+ X/ N: p3 ]5 N3 n
. B) \4 r. K- F0 h6 l二.通过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 / E! I2 m, o( Q
2 6 `& k) h# k0 u; B8 ?6 y
3
# Y! R% Z8 B0 R# I9 R. K. A4 ! e3 X& B3 \! b( l, {% b# z
5 0 U; R4 H% j' o+ ]/ Z% d6 v
| getFor.php# d6 e$ H2 B7 v# @6 j% `
<?php
! S3 |5 _4 H% X6 m6 |4 J $ip = getenv("HTTP_X_FORWARDED_FOR");
* }5 j) \3 F6 c echo $ip;4 p2 ]0 o9 _" w1 y7 F( ]3 Z+ p p
?># n, h. B3 E$ b
0 a( E2 x! C6 Z3 z; b |
+ a3 w1 E" Z m# r访问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.
) K* D A/ X# s: L" w% ^& r8 R
9 K! n2 U. @1 [5 g* Z! G$ x! K 三.使用nginx自带模块realip获取用户IP地址
' M/ c8 s8 Q% ]+ N8 k安装nginx之时加上realip模块,我的参数如下: ./configure –prefix=/usr/local/nginx-1.4.1 –with-http_realip_module4 b, z; ]2 N1 n# J4 A+ g* O4 K
; t5 W- m# z5 i
真实服务器nginx配置 1
1 T. C- w* B$ q* I2
% y6 ~$ m3 j) T, U$ Z( i3
* ^& h/ R. o! X* L N4
( w# T( `* I" b% ^. O5 % M2 K" s- y( }. I- D' @- M# O
6 K+ f9 k b) @; y, H# y
7
J6 U: X' @6 G% |% w- f# `8 & c' Y( ]+ W8 G2 k9 ?
9 1 E& S& g7 k4 C: l1 d, i. \: W6 p
10 - o5 a; ]$ T& |2 K
11
8 {3 C Q9 K$ @7 P4 y1 T. h12
* l0 i* Z/ E, k* h; O/ L9 q13
. M$ V) ~+ @# z1 w: i7 `14 " }7 x0 Y. D$ q1 B, c% E2 @8 C
15 8 q; x9 {- F4 ~$ l6 r" d
16
9 X r- c0 }' U- b17
. U0 E- c, _! {/ K% I% s4 C' X18 7 D( o, D9 m& w3 A; f
19 ) j- b+ m; A+ k( y
20
% ?& ~; c' ?$ Z* m21 5 S3 o8 `5 ^. ?
22
: s0 I$ N' W5 `5 I \9 G( @23 % [& e5 B+ m5 p0 p$ X* o1 r2 E2 Q% Z
24
) T) T# c% n3 c$ j: N5 \# Q, q( d25
$ a4 b' \7 y5 i26 $ T1 |0 u+ p0 M
27
3 z( @' i4 E- G0 o4 z! Y28 7 V- [; w% ?# N* [- ~' n; P: p/ e
29
4 H1 T4 k' r5 R, j30 / N7 A- H% F1 F, f* O2 ^2 y) q7 C
31 * i! c! s: p0 q
| server {
! J/ R# H! z7 r8 m$ y listen 80;
6 d, V. ~" L# k1 W) x) N server_name www.ttlsa.com; % z6 M, ^# t+ y2 W3 [' |
access_log /data/logs/nginx/www.ttlsa.com.access.log main;
. i" [9 \, {* }5 H. U1 \" A; S' r $ N0 w1 n0 ~) [4 L- }7 D3 Y- c
index index.php index.html index.html;
9 \+ `" e) _/ H5 H( G1 a* A' i root /data/site/www.ttlsa.com;
* }9 ?% E% {# }/ y
8 T# |, [- t3 U/ f% A+ T t# Q/ N location /
3 d- {' S2 y" y0 X) @! n( b { , a' B, Y( \; j% \( C3 {5 ]' y
root /data/site/www.ttlsa.com; & D7 @2 [1 `/ g6 F
} : m C' k) `* H7 E
location = /getRealip.php
2 l! v( @) M/ h: p: Q+ w5 T$ S { , N0 `' r/ \+ C0 _& a- \
set_real_ip_from 192.168.50.0/24; $ d7 ]/ a1 p" k5 y4 k
set_real_ip_from 61.22.22.22; 8 h6 G! ~. |, f9 R7 L! }
set_real_ip_from 121.207.33.33;
1 [7 B4 S2 C4 h$ R set_real_ip_from 127.0.0.1;
) G y6 O* f. Q8 f' l8 \8 F! N real_ip_header X-Forwarded-For;
. _% N) g6 a3 v# K3 [ real_ip_recursive on;
' c' {( u: _! M$ z* A fastcgi_pass unix:/var/run/phpfpm.sock; 2 G$ {6 V. J6 ^2 g/ {% F0 y
fastcgi_index index.php; u) k, L8 g% Z7 Q4 w, H8 P/ @
include fastcgi.conf;
7 U" ?& L5 a2 x% q0 q N }
7 t+ J( o9 v2 z } 0 m0 D/ w, Q. I2 D7 ?- \4 o! L
& s' `+ a! o! v! I E' ggetRealip.php内容 : l! Y9 z8 Z1 H
<?php , s4 a. I+ i7 a
$ip = $_SERVER['REMOTE_ADDR']; & u4 \7 ~9 g' t
echo $ip; # i D' g3 ~3 d2 ?
?>
* a0 {/ A& C+ y+ X6 a2 w( N# e% `9 {4 s1 }) D- j' a
|
很不幸,获取到了中继的IP,real_ip_recursive的效果看明白了吧. set_real_ip_from:真实服务器上一级代理的IP地址或者IP段,可以写多行
' W' R8 V+ y( ?& X% @# L$ creal_ip_header:从哪个header头检索出要的IP地址
% A" s* I8 I3 e' G. {real_ip_recursive:递归排除IP地址,ip串从右到左开始排除set_real_ip_from里面出现的IP,如果出现了未出现这些ip段的IP,那么这个IP将被认为是用户的IP。例如我这边的例子,真实服务器获取到的IP地址串如下:7 a( D ?1 s" K# \
120.22.11.11,61.22.22.22,121.207.33.33,192.168.50.121) B6 H, ~0 n+ c4 i1 G2 F
在real_ip_recursive on的情况下: T8 j+ ~# e) n, I0 {
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或者不设置的情况下: P U% g- k0 {% {# `) f
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;
2 L; o6 ?" T- R1 z+ E访问结果如下: 121.207.33.33 # X7 ?- c4 _. l6 |& g( A
* d" M7 L& h! ^, Y& c四.三种在CDN环境下获取用户IP方法总结 r! S; m* @; i, z0 v; t/ Y5 y8 p! U
4.1 CDN自定义header头5 l, A2 X9 [6 ~& W( i1 w, I' |
优点:获取到最真实的用户IP地址,用户绝对不可能伪装IP
) R0 r- H" |2 j `- ]缺点:需要CDN厂商提供
: y6 `& c; ^+ w. I" a
4.2 获取forwarded-for头
+ J* L. U5 q% e* c# Y1 _! e优点:可以获取到用户的IP地址
8 }! f: u2 L- A' ?* p( }缺点:程序需要改动,以及用户IP有可能是伪装的 8 B% M1 S `! j! R
4.3 使用realip获取( `* @% O4 A: G% ]% p% ~
优点:程序不需要改动,直接使用remote_addr即可获取IP地址
7 ^+ m1 ~: E# K" x& A5 x缺点:ip地址有可能被伪装,而且需要知道所有CDN节点的ip地址或者ip段 7 n. d. R9 T- [9 C% V- A" a
|