|
一.使用CDN自定义IP头来获取 假如说你的CDN厂商使用nginx,那么在nginx上将$remote_addr赋值给你指定的头,方法如下: | proxy_set_header remote-user-ip $remote_addr;
+ O6 r) ]9 l" _0 X
# H6 Y3 G/ F$ L. W/ d |
//如上,后端将会收到remote_user_ip的http头,有些人可能会挑错了,说我设置的头不是remote-user-ip吗,8 c, ] L/ g" y! @* e
怎么写成了remote_user_ip,是不是作者写错了.请参考文章:<nginx反向代理proxy_set_header自定义header头无效> 后端PHP代码getRemoteUserIP.php 1 % @) G& n4 r# ~9 s x- |! A8 M
2
+ h& I4 A" A: G3 \8 H: x; ?3 , x- V. Q6 M- _7 V ^0 }
4
, j/ b' W& a3 v2 N, I% a+ r | <?php
2 u) t3 `3 q6 r3 Q" k1 D $ip = getenv("HTTP_REMOTE_USER_IP");) ^$ {: r) h d3 _( }, n8 e
echo $ip; 8 @2 B9 @# v7 X* e# H
?>
1 L- N, h4 M- b
% O7 k& {0 _* E | 1 C/ }8 h: v% o4 T% |
访问getRemoteUserIP.php,结果如下:
# v, v# C& p9 n" ^ 120.22.11.11 //取到了真实的用户IP,如果CDN能给定义这个头的话,那这个方法最佳 % M+ }" ^+ H8 R& Q5 q+ x, z2 ]
9 D$ D0 t4 J! |+ n8 ?& |二.通过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 # g2 H: |' c/ s/ b1 w
2
0 S0 b D4 I1 C1 z) L; p& Q% }3
5 L0 @' x1 ]; c% j. h7 n4
& Z: s1 M" P6 `5
# ~; s4 K5 D& x4 C | getFor.php
1 R7 z# g6 W; `) j$ y<?php
/ x% V7 d) ~5 \) W% Q) A: Q6 B2 f $ip = getenv("HTTP_X_FORWARDED_FOR");- N1 e, u! D3 H0 z
echo $ip;+ x9 o8 c/ k# v: X* {* q! t3 L
?>. [# j& G; x0 g$ c9 R# u
7 w9 g3 T6 O$ J! N B
| ) l2 S8 S: x$ t4 `# `3 M' [! c4 k# y
访问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# l# D$ ~* A/ l9 i0 l! z" E; ~
+ L' B9 o, {) [. C! C5 B" v& k
三.使用nginx自带模块realip获取用户IP地址
2 t& S0 ?2 s, K+ u8 Y) c( h+ |0 a8 U安装nginx之时加上realip模块,我的参数如下: ./configure –prefix=/usr/local/nginx-1.4.1 –with-http_realip_module
) J, Z3 X2 E$ d& e
9 q" N" \; z- w7 ^真实服务器nginx配置 1 4 a" t% a d! Y
2 7 H/ P9 j+ X. O) b
3 " }7 D# h: \4 F3 ^
4
8 k$ |" w4 `- C5 : L" ]7 V; k- n
6 , p3 z& Q' k: D0 r) `8 N
7 ; W R1 V( I7 T. E" d
8
% C @9 J+ R8 \ c3 a8 P9 3 f/ k+ ^8 e4 w2 b0 ?
10
: W2 b: b" S5 X, A11 & ~$ d4 A$ g$ a* k% d1 ~5 m+ F7 Z
12
& e0 Y( K5 t1 f5 B4 L13
- | a, |4 I. I; k* @0 X8 C14 4 D$ q" J; [8 T- y+ X
15
/ N7 e0 w0 S ]# x' u8 f16
6 r; |' H5 l# p, d3 s8 I4 C) C17 ! M3 I4 |1 a2 ]# L1 v1 j1 p
18 + U9 J& h1 w- L) u# Q
19 6 p# X9 P% N# K9 M3 y. b+ Y
20 / a7 F3 q4 q2 l( k
21
: _* W; z0 n; m b! O9 w22
: z! X" K& s% W4 D23 * ?/ g" [- {8 p" ]: C, ?5 j
24
) q$ J5 o8 ^, c, s25
: E, S& V4 u/ X4 n26 2 O: m5 K/ x9 J- [% k
27 ' }$ O+ B2 m) j( i
28 4 t# n+ v. ? F. Z
29 4 F* M* k1 l9 T' S+ z
30
. X$ s$ U& H O+ I6 i31
! x$ W/ @2 B* j | server { : Z1 F# J: A/ B5 f" Q
listen 80;
* l/ b9 s0 r1 ^3 ~( {/ n server_name www.ttlsa.com;
) a! N7 Z8 [7 i- M1 K( O access_log /data/logs/nginx/www.ttlsa.com.access.log main; ( ]; y2 V& U5 Y$ B& L
( Z0 @, w: z, O index index.php index.html index.html; ' I! \ P. @+ Y" J
root /data/site/www.ttlsa.com;
2 r# i+ x; v& {: Q' f' s6 y 4 {! |) k7 c! ]3 Q
location /
, O0 F! I7 O) `% w$ ^ {
& N. @0 M! X) p0 r root /data/site/www.ttlsa.com; ; Y. j% [: p$ ^7 y9 _8 j4 ^" i
} 3 y2 D, m/ F Z# {& E$ s
location = /getRealip.php 2 [' d7 r6 U+ ^* Z9 S
{ 0 `- t+ e& }) f* H5 B; p' O
set_real_ip_from 192.168.50.0/24; ; A5 Z6 b$ g5 U3 J- x7 f0 [
set_real_ip_from 61.22.22.22; . h& _8 h6 r. Z4 d% @& q2 I% A; \
set_real_ip_from 121.207.33.33; g* w+ B6 [; y+ m
set_real_ip_from 127.0.0.1; + X9 ]& A1 f9 \ ?. a1 E. E0 G
real_ip_header X-Forwarded-For;
$ m6 |3 [3 U( z real_ip_recursive on; x2 E( j# n* Y6 v% Y0 B
fastcgi_pass unix:/var/run/phpfpm.sock;
) ?/ N, ?# f# y$ c" e# w$ _; E7 M fastcgi_index index.php; * d* L* l( U1 Y
include fastcgi.conf; 1 ^: r0 y, d' c
} / b( k3 r2 E% F3 q$ H
}
' D3 x$ Z/ B9 m" W, h8 p% j4 Y
! ~% ~5 X, l& |5 agetRealip.php内容
2 S2 m5 X: }3 E <?php 4 b8 v4 Q: G: s5 Y
$ip = $_SERVER['REMOTE_ADDR']; : G* s. \& ^7 ~$ I
echo $ip;
! M6 v* c( P8 Q' j ?>
% X7 j: H2 G# w1 a* E
4 u8 A* R8 \# \ |
很不幸,获取到了中继的IP,real_ip_recursive的效果看明白了吧. set_real_ip_from:真实服务器上一级代理的IP地址或者IP段,可以写多行
- q6 C0 F. h; H8 l/ Z8 Xreal_ip_header:从哪个header头检索出要的IP地址
+ T3 E0 l8 g: u# m) Ereal_ip_recursive:递归排除IP地址,ip串从右到左开始排除set_real_ip_from里面出现的IP,如果出现了未出现这些ip段的IP,那么这个IP将被认为是用户的IP。例如我这边的例子,真实服务器获取到的IP地址串如下:5 T) Z& q9 G& b. ]0 s0 [
120.22.11.11,61.22.22.22,121.207.33.33,192.168.50.121
, Y$ V& O5 G% `& B# q8 U( M在real_ip_recursive on的情况下* o9 Q5 f) u' Q/ h- `
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或者不设置的情况下
( v8 n& T0 r: D5 k, `6 M192.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;
$ `' d& K B; \, r4 r2 F访问结果如下: 121.207.33.33
* Y$ |$ {0 G t Q) W * f: u! V! e6 A! N' I% h
四.三种在CDN环境下获取用户IP方法总结 l( S$ Y6 a3 U- G) h2 Q4 [
4.1 CDN自定义header头
9 d& |1 [5 R# i& ^5 k/ ^优点:获取到最真实的用户IP地址,用户绝对不可能伪装IP
, u* w7 r& B% y4 d( Z缺点:需要CDN厂商提供
4 _; ?' [( d( B% K% p
4.2 获取forwarded-for头! y4 e- x9 v9 B
优点:可以获取到用户的IP地址
. @ D1 ~ W- A) U+ B1 @. P3 j0 F缺点:程序需要改动,以及用户IP有可能是伪装的
7 i- l$ X! n1 J8 v% K% E. ~4 O1 m
4.3 使用realip获取& N2 s8 F* D0 ?+ m6 S n* Z
优点:程序不需要改动,直接使用remote_addr即可获取IP地址5 O+ Q) z2 ?( M
缺点:ip地址有可能被伪装,而且需要知道所有CDN节点的ip地址或者ip段
! B5 w7 {; }9 U' }2 Y |