一.使用CDN自定义IP头来获取 假如说你的CDN厂商使用nginx,那么在nginx上将$remote_addr赋值给你指定的头,方法如下: 1
! d, ^: H6 a! I1 ]0 {' D4 m* X# O | proxy_set_header remote-user-ip $remote_addr;
3 V2 j- v' X& y* f2 n( y5 \. k6 y) G# X; E; x& r2 u G( M; M& ]
|
//如上,后端将会收到remote_user_ip的http头,有些人可能会挑错了,说我设置的头不是remote-user-ip吗,
( B9 d9 z1 n6 X+ s7 T6 c怎么写成了remote_user_ip,是不是作者写错了.请参考文章:<nginx反向代理proxy_set_header自定义header头无效> 后端PHP代码getRemoteUserIP.php 1 l" P* _, Z: M2 {# K% r: W
2 0 o9 V& G$ q6 k
3 " m. A: g& [. F. M
4
' d+ P: F2 |6 _5 l1 c. f8 } | <?php* b) a4 @7 Z' ~! n" A1 R1 G
$ip = getenv("HTTP_REMOTE_USER_IP");
( `' B& a2 Q% z: d0 u& {' i echo $ip;
' Y a4 n3 S/ H! M; k6 T$ _: N?>+ E: F* j- M3 `. x- S2 [/ a' r1 r
1 Q/ a1 `8 L7 r& @% n
|
. X k( V+ N. {# q) U: r0 U1 n' d访问getRemoteUserIP.php,结果如下:& @5 L3 | E7 w0 u d0 b
120.22.11.11 //取到了真实的用户IP,如果CDN能给定义这个头的话,那这个方法最佳
/ K' J) j4 [. t c" O7 v- _. C8 d9 k* G3 Y# w5 ]
二.通过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
, n2 j1 n1 F0 @% `- u2
$ {# N$ u% I! G) _3
- `7 S- s* d; D4 y8 y4 j4 $ o$ p3 S* q5 j9 h
5
# V1 o# n% b2 y( R7 _" d( f8 E U( z d | getFor.php
9 p& P0 l: z" i<?php6 d, q% v) F+ m
$ip = getenv("HTTP_X_FORWARDED_FOR");# Y9 `4 V t6 I; q( K2 O5 k, C; t; V' Y+ v
echo $ip;, K( O7 f: P- u+ \; M: e2 J/ y8 L2 `
?>
5 V, n5 L/ K# v$ c$ E1 b& V* K) H7 X5 b
| 0 K4 t. G+ b6 o( z5 |' X& _6 D
访问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# ?! U
/ n( W! Q+ h G
三.使用nginx自带模块realip获取用户IP地址
! r8 V3 Q5 n9 A安装nginx之时加上realip模块,我的参数如下: ./configure –prefix=/usr/local/nginx-1.4.1 –with-http_realip_module
1 U9 A3 _; z! }: U
: f9 v% W/ J4 W: ]. z真实服务器nginx配置 1
! j1 m ~, {( x7 J) b2 9 P# d: |( W; i0 B8 D# m1 F* ?
3 5 s- c' G) Z" F/ f* b1 w
4
! `0 P& ~. w8 J8 O3 E) I9 |5
2 B$ G8 X5 I' L6 ( n7 c7 D4 C8 b4 `$ ~+ u2 \
7 3 R' _7 S6 L% v! Z0 d
8 8 i+ R% E& _3 ?" O4 \7 }0 Y2 v
9
; Z. ]& W6 p4 C8 Q6 x) p10 9 ~# `( s% u, ]: [+ V7 H0 T
11
+ n( C% R# E: L' q* _5 {% H12
- S' o |7 z1 o% D0 P- i' C13 & B K, Q2 m' Q( ~3 L
14 ) i' M' B6 R& t' f9 @
15 - ]. A% }: D2 s( A5 H. ?! c! i
16
+ [/ y6 b, G$ u8 |17
$ {& W/ D6 I1 S4 N6 M18
8 s% m" u9 h) c8 z* m19
: K: W0 H2 w6 |% x, l1 c: Q* a20 $ {' x2 s# p# f1 L: s3 g' V
21 ) Y5 L( f. T6 j4 x5 y
22
+ z6 r; W: Q, c; z7 K& ^23
. T! e9 D# O2 m' e# K% o9 t2 |24
* F9 N' c: `9 A; `! `' r25
6 b4 N8 q% P4 a1 ]& F26
: G# b+ }0 _; X+ y: `2 ?27 3 E. D3 f+ z* i
28
; z9 h1 B9 m, V3 X3 \* {5 q! Z29
# O: C3 v2 w- _30
) L% X, x0 v% v/ k31 . u/ N0 b1 ? x4 [% \( z) W
| server { ; Z6 @, _! q0 R% }5 {2 U2 G
listen 80;
[* ~) k; i# w: }+ F server_name www.ttlsa.com;
2 ?, G; `8 j3 [8 N' i* z access_log /data/logs/nginx/www.ttlsa.com.access.log main; $ C# k* {6 V% y# S; I' J
' e# _" @; T0 T s4 f% t index index.php index.html index.html;
' A0 [ e" H9 \' x4 A' \ root /data/site/www.ttlsa.com;
: g4 o0 p/ X' A" _: p( e( T* G
: k3 V; n6 b0 \# u( d/ ] location / $ P" W0 |' m: d% c( ?3 D
{
$ |- K* Z! \# i% K$ g# p root /data/site/www.ttlsa.com; ( a% @! Q3 b5 `: ]5 o4 o
}
# J5 {/ ^+ g1 H5 E% v3 H @8 F location = /getRealip.php
& [8 c, p: o6 N! V { ; ]1 h* p4 `( ~+ l" `
set_real_ip_from 192.168.50.0/24;
6 P# m7 o i; \! K7 e4 d& h set_real_ip_from 61.22.22.22; ) W& _* n, |: | h4 b
set_real_ip_from 121.207.33.33; * H# y# n7 ^8 m: R# E+ `$ i
set_real_ip_from 127.0.0.1; . p( a$ a- Q; D, c; Q S/ k; s) n; O
real_ip_header X-Forwarded-For;
' a7 o7 e6 }. r. ? real_ip_recursive on;
" V$ e/ Y# K1 l" @. @ fastcgi_pass unix:/var/run/phpfpm.sock; 7 c8 a/ v' t4 @
fastcgi_index index.php;
1 I% Z3 N, h+ E8 H/ y8 \ include fastcgi.conf;
# ~/ T! |) d# `6 i% n* E }
- B1 m0 r/ Q8 `) n% L; i } ; n+ e8 I2 q1 X$ T
" @. j. s% i1 ]$ Y: v2 GgetRealip.php内容 . X& q% r: J* H
<?php * V3 }2 p" \$ w: j) M( V
$ip = $_SERVER['REMOTE_ADDR'];
8 S& M/ r) i: B ]% I" [ echo $ip;
: U# T, ~3 T+ d# j ?>
3 l9 C$ n8 H; @& i, o' J8 Q0 `& }
6 `, D, W$ n6 o3 S" q |
很不幸,获取到了中继的IP,real_ip_recursive的效果看明白了吧. set_real_ip_from:真实服务器上一级代理的IP地址或者IP段,可以写多行
2 O8 _3 N6 A) s$ Rreal_ip_header:从哪个header头检索出要的IP地址; v( D+ z" _% L
real_ip_recursive:递归排除IP地址,ip串从右到左开始排除set_real_ip_from里面出现的IP,如果出现了未出现这些ip段的IP,那么这个IP将被认为是用户的IP。例如我这边的例子,真实服务器获取到的IP地址串如下:
0 K8 D% l, _' }, @" @ S5 O120.22.11.11,61.22.22.22,121.207.33.33,192.168.50.121( X9 S6 X5 \* U: H* y$ h7 T
在real_ip_recursive on的情况下2 ], R( j S2 \2 w* W& Q+ K
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或者不设置的情况下
: m( n8 q5 }- L; i192.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;
5 S$ l' g! O% ]! |& a3 |访问结果如下: 121.207.33.33
6 ~* S) {0 l0 G9 t
( x/ a- P( a/ q# N V3 o; W四.三种在CDN环境下获取用户IP方法总结9 ^. N/ Q- B5 r
4.1 CDN自定义header头1 |: b2 @$ b! M: ^0 I" J |
优点:获取到最真实的用户IP地址,用户绝对不可能伪装IP
% U6 M2 r; W9 y缺点:需要CDN厂商提供 + u2 b* n4 P$ { I$ q4 {! [5 u% r
4.2 获取forwarded-for头7 j1 `! |" {! G- n* |- ]
优点:可以获取到用户的IP地址4 K! Z2 j6 y$ {, g: G. Y
缺点:程序需要改动,以及用户IP有可能是伪装的 ( @ ~& r# z: S0 n2 d5 n$ |. h
4.3 使用realip获取% q+ k. V/ O( L- q
优点:程序不需要改动,直接使用remote_addr即可获取IP地址
0 a8 z$ V( {0 I) j缺点:ip地址有可能被伪装,而且需要知道所有CDN节点的ip地址或者ip段 ! X3 U) S6 c5 l, I# L
|