大洲的小偷程序非常让人眼馋,无奈本diao丝程序员,一无RMB,二无论坛币,只能望洋兴叹,所幸我有web程序开发的经验,对于这个小偷程序的基本原理能猜到不少,本着自力更生,服务大众的精神,我自己实现了一个简易版,在此开源给大家,希望能赚点论坛币,早日进入email版见见世面。
" {0 m1 l1 L* B3 V6 \* x( c; _. A4 X- w! E* ?% p f- A
一、原理
8 `1 g2 w7 L# L. \: A7 @# z: b" _2 e9 j1.用户访问流程:
* Y9 P( D0 c y4 c5 Y/ |" R% L(1)用户访问我们的冒牌站(A.com)
9 [3 ^2 F8 e. c(2)网站后台程序根据用户的query参数(包括get/post/cookie)构造原始网站B.com的url,用后台程序去访问该url,此时可以拿到原始网站的html和header输出。这里有一点需要注意的是原始网站输出的头也不可以忽略,里面的set-cookie信息也可以转发给用户的,这样就可以实现注册和登陆原网站啦。
N# z- ? |' |* q# }7 H3 |5 i(3)对原始网站的html输出和header输出按某些规则做替换,比如把某些广告去掉啦,把B.com的地址替换成A.com啦,其实这一步是最关键的,也是玩法最多最好玩的部分
% k4 ?: L# F. h: T/ `6 n" W, g(4)将替换后的html和header输出给用户。6 @2 T& v/ |+ s6 V4 q
" u: G/ r3 b7 i# R8 k7 r* V' k0 r6 M
2.规则替换的几种玩法:! T# _( V |& |; k! v: a
(1)最简单的当然是字符串和正则表达式了,这就不多说了
% i }6 C3 c6 M3 c( [(2)用html解析库对html的dom节点做操作,然后重新生成html,比如可以把页面中的text node翻译成另一种语言,或者做文章重写,这样比较容易逃过搜索引擎的法眼。0 U9 n* E$ O# [ E8 G
据我所知每种语言都由若干个html库,比如php的有DOM、phpQuery等,java的有htmlcleaner等9 o- @" t9 o8 M
(3)在原始html代码的后面加入一些javascript代码,用来隐藏一些页面元素,或加入一些广告代码等* i- {, r: h9 ?1 t
- P2 e& A" b; E3.关于速度和性能:0 t2 x1 v, G Q: Q8 l9 n. M: n0 s
(1)提到性能第一个想到的当然是缓存啦,我觉得最适合加缓存的地方就是上文1.1.2中提到的生成原始网站url后,这里可以对原始url做md5编码,访问一次改url后就把它的内容和头存到硬盘上,这样就不用每次都去原网站拉取了。做缓存的另一个好处是不用担心被原网站屏蔽。
4 n9 m* e3 u6 N U1 M' V6 H9 c8 u; d4 |; i3 Q, Q: {
(2)对于css,图片,js等静态文件,其实不用每个文件都让php访问原网站拉取,可以直接返回个302,让浏览器直接去原网站拉取。
+ `# t: f3 M, I- T/ x9 C4 O- B1 v1 j2 r) J/ g5 R0 v+ u( N+ N
M7 n# b6 c. o( M1 f2 p
二、实现
& t/ m; T: F% h0 c, R/ S8 e1.程序语言:
8 }, P1 O7 x1 H+ y% \3 c1 Q: F' I其实这个东西哪种语言都能搞定,也都不麻烦,我对php比较熟,就选了php。
* E2 ^* l" B8 Z0 K0 T& {. C5 g2.一些准备工作:
8 Q \) q( `: f* h; C0 w1 D(1)修改apache的rewrite规则,因为我们的程序只有一个文件,我们必须把所有接收到的请求都重定向到这个文件,这里我假设重定向到index.php,在apache的<VirtualHost>中加入这几句,如果是虚拟主机的话就修改.htaccess吧,不过我没试过,所以不知道怎么写re它的write规则2 a" V. l/ X! y' ^. g, e
RewriteEngine on$ `: Z% {% y* n4 }# i3 |1 A
RewriteCond %{DOCUMENT_ROOT}%{SCRIPT_FILENAME} -s [OR]) T" g+ w0 I9 E' ]- u* o
RewriteCond %{DOCUMENT_ROOT}%{SCRIPT_FILENAME} -l [OR]
8 \0 x1 F* n; }# A+ ]3 Z RewriteCond %{DOCUMENT_ROOT}%{SCRIPT_FILENAME} -d
( E& l+ E4 T" O# J: o) J RewriteRule ^.*$ - [NC,L] r6 m, o2 z: }& C1 p. G" ]
RewriteRule ^.*$ /index.php [NC,L]& g$ ?' k8 Y6 O+ s6 I# [4 z+ F0 q
, _$ f' x5 N/ d1 y3 B+ X$ f s6 A(2)安装php的http模块
; g2 S" }$ N. @, D! g8 aphp发http请求的函数库找了好几个,发现http模块是用起来最简单的,不过需要你会linux操作哦,安装方法在这里http://php.net/manual/en/http.install.php% Y$ {1 M; z5 |! o3 @
ps:如果安装不上或没有vps,请把下面程序的http模块的函数换成phpcurl等http lib
) m/ `4 V2 g3 D& B+ _" w: P$ B( {* s% z' q+ l. J, E9 a% }
3.index.php的代码:
8 ^( F8 h0 @: G- K r8 ~+ I; i, z
, l4 y% L; o4 I+ H9 Y
0 @! Q* u! C# r" y$host = $_SERVER['HTTP_HOST'];+ |. [& V. {, i0 [2 o# \
//这里把假站的域名替换成原始网站的,用于生成原始url; v0 ^8 b1 D6 n" g# p5 F6 x
$host = str_ireplace('fake.com', "true.com", $host);; b% j: r7 n3 [" M9 p4 q9 q B) X
$toUrl = sprintf("http://%s%s", $host,$_SERVER['REQUEST_URI']);. M9 i* p' \, z+ E
7 A) W3 j/ b( c) [! @
$script_name = $_SERVER['SCRIPT_NAME'];
" G8 Q8 g- o6 {$arr = explode(".", $script_name);
3 t/ U) ~# o: J& V) q. _. U$endName = $arr[count($arr) - 1];
- j. ]5 e# o3 B- t) A! C+ N: f7 N! H. N |3 @
/ K# @1 n& g# p8 H1 z5 D
//这些后缀结尾的url直接返回302
/ u& x7 d8 R+ A( t/ @1 n$ y$STATIC_END_NAME = array('css','xml','rss','gif','jpg','jpeg','js','axd','atom',
- v' c4 `7 N- [8 T 'mml','txt','jad','htc',( T2 }2 b1 }1 Q% o
'png','tif','tiff','wbmp','ico','jng','bmp','svg',
1 G! F6 F$ i p8 P6 x 'jar','war','ear','hqx','doc','pdf','ps','eps','ai',) V; H$ \. v0 B/ Q" t, K# M+ e
'rtf', 'xls', 'ppt', 'wmlc', 'xhtml', 'cco', 'jardiff',
, G0 L- R. x: z, L4 m: N( E) w W 'jnlp', 'run', 'pl', 'pm', 'prc', 'pdb', 'rar', 'rpm',! j- M1 A ~0 G. o; ~1 ^
'sea', 'swf', 'sit', 'tcl', 'tk', 'der', 'der', 'crt',
9 e( Z) }* Y) i 'xpi', 'zip', 'bin', 'exe', 'dll' ,'deb', 'dmg', 'eot',4 }+ u% A7 I. e1 k% G4 ]+ f5 A
'iso', 'img', 'msi', 'msp', 'msm' ,'mid', 'midi', 'kar',
& _4 u, C5 B% e 'mp3', 'ra', '3gpp', '3gp', 'mpeg', 'mpg', 'mov', 'flv',8 [8 c9 ]$ r! ~8 A0 r7 X3 [
'mng', 'asx', 'asf', 'wmv', 'avi');: S! P& V2 o! g8 P( o# J( W
3 P3 F0 w' B# @9 E# \
if(in_array($endName ,$STATIC_END_NAME))
4 s# g" w; ^: g s9 V/ Q{
7 l$ S8 s1 [4 l- `: j, z7 O6 p. a $headerStr = sprintf("Location: %s", $toUrl);
3 L+ M8 m/ M% ^! d1 ~; I header( $headerStr, true, 302);
9 i8 w+ p" V6 q, `9 l exit;
/ u- c) ~% \" E6 D' Y5 \, p9 o. u}/ _4 B# Z9 q- ]" T$ w" k
) ]3 M$ X# N5 w- S6 O g
//一个简单的cache
- P5 t2 q6 B8 t9 _+ [2 Efunction GetFromCache( $url)$ K1 d: ]! c& M1 K/ V
{; p+ c6 j% O* K) w" G
$current_dir = dirname(__FILE__);9 {+ ]$ p+ a- C9 k
$cache_dir = $current_dir . "/cache/";: I; q, W; t5 N! t; O
if( !is_dir( $cache_dir))' W* Z0 F$ E. ~% ]4 T, m0 N
{- R" {$ T+ M }+ E# I: v
- `( T# B- A. }( n- a3 N! N mkdir($cache_dir);
% B% y; `1 |4 g" X ]: H- m }
6 {- z8 ~( C6 L5 K, T7 P
1 p2 M! I4 J! Y$ \0 M) z$ j/ | $cache_file = $cache_dir . md5($url);3 U Q" }( [. T" U: o
if(file_exists( $cache_file))' i5 p) [' d2 `0 }& G5 \ \
{2 j0 k3 \+ F( ^, T0 j# U, I n
$html = file_get_contents( $cache_file);" k6 n- d) D) R# u5 Q
if($html == false)
% i) X4 v4 ?# x! [& T# c {1 ?" N7 v- a1 a4 y+ N
$html = "";; F) O/ s: S7 i% q) ^$ T
}
7 ^6 v8 K! j+ c: D7 ] }else6 ?! W9 l- u& g6 Z( Q$ X4 v
{5 K% _6 G2 u {6 V% C" |
//访问原始网站
0 T0 {6 V6 R2 Q" { $data = http_get($url ,array('redirect' => 5, 'timeout' => 10), $http_info );
" a+ ?1 {/ x7 d5 F $message = http_parse_message($data);( R9 r: F/ v4 c. x/ z6 f
) H7 l4 u. ^# ~; q) q( H4 P0 h $html = trim($message->body);# U; p$ Z+ H9 I0 j
# C$ o- [6 s* H8 E
file_put_contents( $cache_file, $html);
. D9 s5 R( t% o1 S6 x/ B+ q }
+ W! N0 V. s8 l. Q/ X% C; J
0 b3 G5 Y' M6 q5 s" Q return $html;
7 g! J2 q0 i* A+ l4 l2 W! I}9 [8 d: U# R8 S* q" a2 P
. x% K# [: n3 Y" m$html = GetFromCache( $toUrl );, F8 H+ w4 w/ b# _: M
* {2 z1 r& J& i( @
8 f S9 S& ]: ^' [( o' G$html = str_replace("circleid.com", "circleid.us", $html);
& K/ B$ N9 P1 x: }5 n) }- j, B6 ]( \
$html = preg_replace('/<meta name=.*>/', "", $html);
! ^3 \/ b" w' T; p, J; d2 \
7 F0 s: X( u/ Z# _$ c! {+ K, e, k1 Z p* H" u* J. Y5 N; I9 @! H# O% R: m
//注释的这两句是用phpquery操作
( ^6 |# k7 A, O( k2 [& B; S//$body = htmlqp($body)->find('#header')->remove()->html();. P4 O% }! ]; I" @- a
//$html = htmlqp($html)->find('#header')->remove()->document->saveHTML();
5 |2 ]; \" J+ x) {+ Q4 [8 k P
" ^/ v% [* I& R$script = <<<EOD8 Y/ _) o4 B8 A; J# ?8 V6 y1 c$ A
<script>
" w% m# l/ X4 h3 l$(document).ready(function() {) Y& U6 _$ {; K
$("#footer").remove();
+ F9 U) M6 j4 m! k
c" ]% K: U' t});
2 {! z" w) C( P! O5 C2 H) _8 g. ]
4 w J# } R8 m2 i6 V</script>
: W* P1 _4 E/ z/ N+ P
: O: u3 r4 Q, s% A- ~7 XEOD;
3 ~- \! E: i4 N/ D; h# n! X# l9 {4 f% Y3 ^
echo($html . $script);
3 g' {, `7 [1 c* [3 f2 k7 I2 n7 j; n" z
1 {5 Q0 \8 a' F三、最后
& J, _, D! F6 u. v% d( o8 u0 C; d1.总之,这个程序还很简陋,没有处理post和cookie参数,也没有配置管理模块,距离大洲的程序差距有一个大洲那么大,仅适合稍微懂点程序又有点好奇心的新手玩玩; }( H, g" c! a# n9 I% }' X% b8 W
2.最后当然是希望大家不令赐分啦,您的论坛币是我继续分享的动力,哈哈
3 k) w7 o7 B% m
* a7 B% U8 Y0 q% p/ |7 h( o |