大洲的小偷程序非常让人眼馋,无奈本diao丝程序员,一无RMB,二无论坛币,只能望洋兴叹,所幸我有web程序开发的经验,对于这个小偷程序的基本原理能猜到不少,本着自力更生,服务大众的精神,我自己实现了一个简易版,在此开源给大家,希望能赚点论坛币,早日进入email版见见世面。4 ~& `- E p. k
: X. W( U, R/ @9 P& t一、原理: f( S) K5 N$ ?6 T
1.用户访问流程:
- K' }/ n- v- \3 E b3 r0 `7 D(1)用户访问我们的冒牌站(A.com)7 r; H) a( R4 O. J# H" Y9 Z" [& ]# p/ }
(2)网站后台程序根据用户的query参数(包括get/post/cookie)构造原始网站B.com的url,用后台程序去访问该url,此时可以拿到原始网站的html和header输出。这里有一点需要注意的是原始网站输出的头也不可以忽略,里面的set-cookie信息也可以转发给用户的,这样就可以实现注册和登陆原网站啦。" _; M+ \# K' d. j& g
(3)对原始网站的html输出和header输出按某些规则做替换,比如把某些广告去掉啦,把B.com的地址替换成A.com啦,其实这一步是最关键的,也是玩法最多最好玩的部分
$ g% I ]0 B! Q" G+ n(4)将替换后的html和header输出给用户。. ^' b1 X/ i4 n
2 p. ~! R" O7 ^* C/ _9 j8 E$ w7 `
2.规则替换的几种玩法:& s" Z. c& F7 T( A. _/ V! m
(1)最简单的当然是字符串和正则表达式了,这就不多说了, T e8 P9 u+ q- ?. t# R
(2)用html解析库对html的dom节点做操作,然后重新生成html,比如可以把页面中的text node翻译成另一种语言,或者做文章重写,这样比较容易逃过搜索引擎的法眼。4 e& \* ~3 C. {
据我所知每种语言都由若干个html库,比如php的有DOM、phpQuery等,java的有htmlcleaner等# m }/ q9 w/ u) O
(3)在原始html代码的后面加入一些javascript代码,用来隐藏一些页面元素,或加入一些广告代码等
* ^% o) u1 `* `& F
% P8 x) g; I H* @3.关于速度和性能:
# _; E2 |4 {" c$ v' {$ f(1)提到性能第一个想到的当然是缓存啦,我觉得最适合加缓存的地方就是上文1.1.2中提到的生成原始网站url后,这里可以对原始url做md5编码,访问一次改url后就把它的内容和头存到硬盘上,这样就不用每次都去原网站拉取了。做缓存的另一个好处是不用担心被原网站屏蔽。& X* |& H; J/ Z
+ P9 {4 x Q& |(2)对于css,图片,js等静态文件,其实不用每个文件都让php访问原网站拉取,可以直接返回个302,让浏览器直接去原网站拉取。
, n3 P" H z. E- z3 L7 \
8 U( G$ z4 n' }+ [5 S8 E W: @9 u# `0 y) {
二、实现
* Z$ n! Z) m! ~! E% G1.程序语言:! K7 F+ i ?* y# s- ^4 ]: l4 b/ J. L
其实这个东西哪种语言都能搞定,也都不麻烦,我对php比较熟,就选了php。
7 X# e, [$ ^ O# ~2.一些准备工作:2 U! n! T* r7 Z" j6 ^
(1)修改apache的rewrite规则,因为我们的程序只有一个文件,我们必须把所有接收到的请求都重定向到这个文件,这里我假设重定向到index.php,在apache的<VirtualHost>中加入这几句,如果是虚拟主机的话就修改.htaccess吧,不过我没试过,所以不知道怎么写re它的write规则
H, b1 ?4 q( m; z$ Z& z; z. @ RewriteEngine on- f8 s( B8 B6 k4 |
RewriteCond %{DOCUMENT_ROOT}%{SCRIPT_FILENAME} -s [OR]. q$ l/ L6 b+ a! t' ]" v9 S( c
RewriteCond %{DOCUMENT_ROOT}%{SCRIPT_FILENAME} -l [OR]( p( s J6 w8 D2 s# `
RewriteCond %{DOCUMENT_ROOT}%{SCRIPT_FILENAME} -d- c: I6 t" @. Z: G
RewriteRule ^.*$ - [NC,L]
1 i5 [1 g9 G S8 E+ \; V0 P. v! c RewriteRule ^.*$ /index.php [NC,L]9 M4 Y: _$ N6 U c0 D( n2 o6 _+ j
Q1 S/ W h9 u* L$ M(2)安装php的http模块 H5 F& y: H5 g, m
php发http请求的函数库找了好几个,发现http模块是用起来最简单的,不过需要你会linux操作哦,安装方法在这里http://php.net/manual/en/http.install.php
. V" f% l9 N/ p, Vps:如果安装不上或没有vps,请把下面程序的http模块的函数换成phpcurl等http lib' M+ q4 A4 W8 A8 q9 Z+ H. l
4 _& ~' V# r2 j$ P3.index.php的代码:- ] l: H9 o% o
4 P. @# R* @3 O! y7 k
7 O- }- n; x; g# D+ F+ h
$host = $_SERVER['HTTP_HOST'];8 R: v( W u, |$ R
//这里把假站的域名替换成原始网站的,用于生成原始url
5 ] ]# m1 F/ r/ b4 J( ]: k& F$host = str_ireplace('fake.com', "true.com", $host);$ P, d" g* v7 U+ {: R& U' y9 |" p# B
$toUrl = sprintf("http://%s%s", $host,$_SERVER['REQUEST_URI']);0 }5 @7 `; } M- I, F
0 ~# s3 J( N& z3 X0 s5 z+ G
$script_name = $_SERVER['SCRIPT_NAME'];
% R. L0 V" e4 b7 u" e- Y1 |$ m$arr = explode(".", $script_name);6 Z) J# z$ [% k$ [' d2 g w
$endName = $arr[count($arr) - 1];8 {0 Q; t& S- R
$ E# P4 x5 q0 I6 a. l A( F6 _! t! X- X3 { @ P7 K
//这些后缀结尾的url直接返回302
- o" D: s `. i2 X1 h, a3 q! S$STATIC_END_NAME = array('css','xml','rss','gif','jpg','jpeg','js','axd','atom',
/ H( x3 o1 u) I6 Q& W l 'mml','txt','jad','htc',
% w1 w. b7 V. B, J 'png','tif','tiff','wbmp','ico','jng','bmp','svg',
. A. s( ~! j( W) b. ^6 o 'jar','war','ear','hqx','doc','pdf','ps','eps','ai',
& p" p; w0 x9 J- K& @; t 'rtf', 'xls', 'ppt', 'wmlc', 'xhtml', 'cco', 'jardiff',3 u( a2 {/ K) }; Z3 g Z' O* r2 \( Q
'jnlp', 'run', 'pl', 'pm', 'prc', 'pdb', 'rar', 'rpm',8 R3 c- G! a6 j3 }- }/ `# t$ E
'sea', 'swf', 'sit', 'tcl', 'tk', 'der', 'der', 'crt',
2 A1 @2 A. r* S, m) F% ? 'xpi', 'zip', 'bin', 'exe', 'dll' ,'deb', 'dmg', 'eot', N& g. ], B! ]( O$ V* T# M- I& ^8 _+ J- T
'iso', 'img', 'msi', 'msp', 'msm' ,'mid', 'midi', 'kar',
' a& ?% E( j) b3 H; y+ H2 z 'mp3', 'ra', '3gpp', '3gp', 'mpeg', 'mpg', 'mov', 'flv',* L: A6 L3 s0 b# T: P( n
'mng', 'asx', 'asf', 'wmv', 'avi');$ X" W$ F. E4 f# s1 H
# ]2 A" v% V. p. P+ U: M% ?if(in_array($endName ,$STATIC_END_NAME))
! _. j$ W- q$ ]* K/ m. K. n{
4 e' M$ x2 W, S/ z# I $headerStr = sprintf("Location: %s", $toUrl);
9 N" \& O9 @4 R- f- d3 V' Y9 Q header( $headerStr, true, 302);/ q9 D3 n B* `5 u; x% F( g, t& R
exit;. `' h2 W0 U- }* G3 E9 P6 t9 @
}# T J1 y" G) Z0 |* V3 q7 A2 I
2 z; u( ~3 q% V: X% O
//一个简单的cache P& I, Q" h4 w" y
function GetFromCache( $url)
6 Y9 a. D; i" p) T. E6 h$ C{
! s& ^7 |" m: d# X# B G) d $current_dir = dirname(__FILE__);
9 ]' q0 [% n2 u8 p' n' \& a $cache_dir = $current_dir . "/cache/";
/ i# b D' Z* m# H' J1 p if( !is_dir( $cache_dir))0 G" a) E$ M, ~% T( N' L' w3 d, H3 Z
{- x+ E6 W& ^* D: {) R
0 ^1 A7 o4 s: e' I mkdir($cache_dir);# `' {$ s. G- V
}0 L& H2 M" P. ^! y' Q% _2 W) Z
. F$ s6 |. E, @* a+ T5 a; k $cache_file = $cache_dir . md5($url);; E! T/ ^# w$ c9 x
if(file_exists( $cache_file))
! c; e2 q8 ~" ^8 Z% v* U {
# i- a7 F2 L& a: ? $html = file_get_contents( $cache_file); K9 L! n4 Q/ h* P: o$ e
if($html == false)
% H8 Z7 S/ H5 T7 y {
- C# y1 F5 p' G' @1 J+ S1 A* ^ $html = "";
/ o1 b8 W( w: i; I$ N2 s }
. S- P5 v5 G5 f2 C) L }else
+ ]: V" ?0 l5 I7 M$ T) Z7 u {3 _+ K8 }& ]+ c" l
//访问原始网站
. _- h6 w! }4 k! K9 ]/ D9 a M+ P6 N $data = http_get($url ,array('redirect' => 5, 'timeout' => 10), $http_info );
1 Q0 V* A8 x+ g4 q# A $message = http_parse_message($data);
( A1 ]. U2 a7 l: m; M3 }- A$ g3 s$ L5 z& t
$html = trim($message->body);
( k4 P( P5 t9 m9 {4 L
# c5 i) L6 R. q2 }" U2 y6 d file_put_contents( $cache_file, $html);
9 N5 ]2 V7 k5 C9 W; x* m. g }/ O! U7 ~# w" o5 R% u2 y8 x
8 M5 n2 R0 I+ c2 b return $html;
# R& ]) c, V/ O( ]$ C$ G4 c7 i}
3 x" q+ t4 i& [8 I) d
+ l n( L9 q9 @, d8 L$html = GetFromCache( $toUrl );1 a* y0 S+ j- {& e
* K8 e0 t2 N X5 B
5 {4 d' V+ w" V2 i9 x$html = str_replace("circleid.com", "circleid.us", $html);% [$ F" i' F# N9 @
8 G5 ~' {$ e: D! L
$html = preg_replace('/<meta name=.*>/', "", $html);8 D2 [* {& T( p# C& ~/ J; K
8 |% ?( L, u& |3 N+ S! U3 _
8 x! D: t: s) V- W3 a6 ~0 Q//注释的这两句是用phpquery操作
. Q# s0 R; m; I//$body = htmlqp($body)->find('#header')->remove()->html();
/ G8 f( q" ?6 l9 k//$html = htmlqp($html)->find('#header')->remove()->document->saveHTML();
+ w+ ]7 g% N. ^: d: N- D
! p. K$ _% t# l6 c+ A4 w* ?- T$script = <<<EOD' j" P1 D, R% K9 }. b- ?
<script>+ f7 W' N* Q7 s
$(document).ready(function() {0 B; q* N: F# `* I
$("#footer").remove(); y# E" `- R% L, T, M2 G- f% P
' d9 [8 x$ h# L" X2 A});
( ~4 S/ j( a2 @9 @6 M& ?( Z$ Y( b* C3 ~
</script>
& y9 m: L) P- F; e9 K
/ V7 N8 q4 @" V: C' X0 vEOD;7 p; `: e3 {- H' w& K9 ^; T
' J$ S5 L3 s( {, y1 S
echo($html . $script);- r$ _" A3 l2 B+ e* r5 \
2 R7 [! }+ v, u, R) O0 w
! U8 i* \) T) A7 `
三、最后
4 t- X6 A6 v2 v0 m+ _6 K* {1.总之,这个程序还很简陋,没有处理post和cookie参数,也没有配置管理模块,距离大洲的程序差距有一个大洲那么大,仅适合稍微懂点程序又有点好奇心的新手玩玩
: X6 n. y) O K6 |4 C1 U2.最后当然是希望大家不令赐分啦,您的论坛币是我继续分享的动力,哈哈" Z; T* x5 J s) q( R3 D3 I
X0 _: S, ?$ L { n |