将迅雷拒于Linux服务器门外

本文仅说明如何在服务器端屏蔽迅雷下载,包括HTTP方式和FTP方式,不涉及客户端和局域网内如何屏蔽迅雷的内容。

下面这里是废话,欢迎忽略,请直接跳到下面的“在Apache和屏蔽迅雷”
一旦服务器上的文件被迅雷索引,就会引来一大堆盗链的家伙,这对小带宽或低配置的服务器来说是致命的打击,于是如何限制迅雷下载服务器上的资源就成了一个很重要的问题。像我自己的服务器,用1MBps小水管来提供一个小网站的HTTP服务,开了内容压缩并设置好图片文件的缓存时间后,打开网页的速度还是比较快的,直到有一天,我发现网站打开的速度变得很慢,而且不是我自身的网络问题(当时我在外地,服务器在家里),当时仅仅知道是服务器上什么进程占用了大量带宽,还没有发现是迅雷的问题。后来经过了很多调查,才发现是迅雷在盗链,看访问日志里面一行行的大型文件下载记录,那真是触目惊心啊。
发现原因是迅雷盗链以后我就开始研究如何在服务器上屏蔽迅雷的下载。首先在HTTP协议上屏蔽迅雷是比较简单的,靠迅雷的用户代理(User Agent)就可以识别出迅雷了,但是在FTP协议上如何识别迅雷就比较棘手了。在好友的帮助下,最后我们终于发现一个在FTP协议上屏蔽迅雷的方法。在此之间和之后,我就写了IIS的反迅雷插件和Serv-U的反迅雷插件。
不过IIS和Serv-U只能在Windows平台上使用,这也是因为当时我的服务器还是Windows操作系统。其实Apache的mod_rewrite模块可以将用户代理作为重写条件,当时我也写了篇文章说明如何在Apache上屏蔽迅雷,但是在那之后还是有不少人发邮件问我如何在Apache上屏蔽迅雷。好吧,既然如此我就再写一篇文章来详细说明如何在Apache上屏蔽迅雷,顺便介绍libantixunlei,这是用于FTP反迅雷的一个C语言写的库。
上面是废话,欢迎忽略,下面进入正题。

在Apache上屏蔽迅雷

在HTTP协议上识别迅雷是通过迅雷的用户代理(User Agent)字串来进行识别的。我对我自己的网站的IIS访问日志以及一个评分系统的评分记录里面记录的用户字串进行了分析,之后发现迅雷使用的几个用户代理应该是唯一的,在访问日志中,除了下载文件的记录,只发现了极少量使用了和迅雷相同的用户代理的记录,这可能是个别用户出于杂七杂八的目使用迅雷下载普通网页而留下的日志。

有了这个分析结果,就可以保证通过用户代理来识别迅雷不会误杀普通用户了。但通过用户代理来识别迅雷有一个问题,如果以后迅雷把自己的用户代理改成和IE的用户代理一样的话怎么办?没关系,至少到现在为止(09年国庆),我还没有发现迅雷做此举动,等迅雷有动作了再想对策也不迟。另外,这里还有一个“脏数据”的方法,如果迅雷很不厚道地把自己伪装成IE的话,我们就只好也很不厚道地使用脏数据方法先反击一下迅雷。虽然脏数据对屏蔽迅雷没有什么帮助,至少可以出出气,让非最新版迅雷用户下载不到正确的内容,就这点应该够迅雷受的了,用户体验大受打击,我想大多数用户都不会追着使用最新版的。

于是,我在废话里面说了,使用Apache的mod_rewrite模块就可以很容易地屏蔽迅雷,因为这个模块的重写规则可以将用户代理作为判断条件。我们只要把用户代理和迅雷是一样的连接请求重定向到一个错误页面,或者干脆直接返回403,就可以在HTTP协议上屏蔽迅雷了。
到目前为止,我们观察到的迅雷使用的用户代理有以下几个:

Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; )
Mozilla/5.0 (compatible; MSIE 6.0; Windows NT 5.0)
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 3.5.20706)
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)

放心,根据网站访问日志和评分系统的日志,这些用户代理应该都是迅雷特有的,在.htaccess文件里面把带有这些用户代理的请求重定向到错误页面就可以了。
当然对于普通网页来说,是没有必要屏蔽迅雷的,所以我们只需要屏蔽访问大文件的请求就可以了,于是.htaccess里面的内容就像下面这样:

RewriteEngine On

#Anti Thunder
RewriteCond  %{HTTP_USER_AGENT}  ^Mozilla/4\.0\ \(compatible;\ MSIE\ 6\.0;\ Windows\ NT\ 5\.1\)$  [NC,OR]
RewriteCond  %{HTTP_USER_AGENT}  ^Mozilla/4\.0\ \(compatible;\ MSIE\ 6\.0;\ Windows\ NT\ 5\.0\)$  [NC,OR]
RewriteCond  %{HTTP_USER_AGENT}  ^Mozilla/5\.0\ \(compatible;\ MSIE\ 6\.0;\ Windows\ NT\ 5\.0\)$  [NC,OR]
RewriteCond  %{HTTP_USER_AGENT}  ^Mozilla/4\.0\ \(compatible;\ MSIE\ 6\.0;\ Windows\ NT\ 5\.1;\ \)$   [NC,OR]
RewriteCond  %{HTTP_USER_AGENT}  ^Mozilla/4\.0\ \(compatible;\ MSIE\ 6\.0;\ Windows\ NT\ 5\.0;\ \.NET\ CLR\ 3\.5\.20706\)$  [NC,OR]
RewriteCond  %{HTTP_USER_AGENT}  ^Mozilla/4\.0\ \(compatible;\ MSIE\ 6\.0;\ Windows\ NT\ 5\.1;\ SV1;\ \.NET\ CLR\ 1\.1\.4322;\ \.NET\ CLR\ 2\.0\.50727\)$  [NC]
RewriteRule  ^.*\.(gif|jpg|bmp|zip|rar|exe|mp3|swf)$   /   [NC,F]

如果你想制定更复杂的重写规则,可以参考Apache手册中mod_rewrite的部分,见:http://lamp.linux.gov.cn/Apache/ApacheMenu/mod/mod_rewrite.html
对于其他Web服务器软件,多多少少都能提供一些可将用户代理作为判断条件的网址重写模块或插件,参照上面Apache的设置方法对这些软件进行设置,都能达到屏蔽迅雷的效果。

在FTP协议上反迅雷

在FTP上反迅雷就比较麻烦,这需要获得每一个FTP会话的会话唯一标识和客户端发送的每一条FTP指令。因为这样的需求很少见,所以Linux下的FTP软件很少有提供相应的接口供我们使用。不过还好,Linux下的FTP软件大多都是开源的,我们可以自己修改源码。于是我就写了libantixunlei,然后针对不同的FTP软件,就套用libantixunlei来修改其源码,然后编译安装就可以了。

因为要修改FTP服务器软件的源码,这对技术的要求就比较高了,不见得每个服务器管理员都会C语言,所以对大多数服务器管理员来说目前还是只能等待别人为FTP软件写插件(如果支持的话),或者发布经过修改的FTP服务器软件源码。

于是,如果你想为某个FTP软件加入反迅雷的功能,请访问http://code.google.com/p/libantixunlei 。如果对libantixunlei的用法不太清楚的话,请给我发邮件,我会告诉你FTP协议上屏蔽迅雷的原理和应该使用libantixunei的哪些接口来识别迅雷。

不过先不要失望,现在已经有了可以反迅雷的Linux上的FTP服务器软件了,在我写这篇文章的时候我已经给pure-ftpd 1.0.22版本成功地打上了反迅雷补丁,补丁文件请到:http://code.google.com/p/libantixunlei/downloads/list 去下载,下载回来以后给纯净的pure-ftpd-1.0.22版本打上这个补丁(使用patch命令),然后编译安装就支持反迅雷了。对于其他版本的pure-ftpd我没有试验过是否能使用这个补丁,不知道能否正常使用。另外在此提醒一下没有自己编译安装过软件的管理员,pureftpd的一些功能需要在./configure的时候加上一些参数才能使用,具体请看源码根目录下面的说明文件,偷懒的话可以 ./configure –with-everything,不过印象中官方并不推荐使用这个参数。
另外,因为我很懒,所以把一些特性写死在程序里面了,是否屏蔽使用迅雷的IP和屏蔽IP的时间是写死在程序里面的,要改变的话只能重新编译。这两个配置在libantixunlei.h文件里面可以修改。

libantixunlei使用了pthread库,而在一些平台上编译的时候如果要使用pthread库需要显式指定-lpthread参数,我在PBS服务器上编译的时候没有问题,但是在自家的一台电脑上编译的时候却出错了。如果编译失败的话,点击这个地址查看处理方法:http://code.google.com/p/libantixunlei/wiki/BianYiShiBai

最后做广告:如果需要在Windows系统上反迅雷,请访问:http://www.gsea.com.cn/gs/fanxunlei/isapi.html

相关文章:

  1. 糟糕的蜘蛛再次出现
  2. 发现腾讯超级旋风(QQDownloader)的多源下载行为对YT造成了影响
  3. AWStats 其实可以统计任意格式的日志
  4. 做 libantixunlei 扯出来的无聊技术之二
  5. 百度傻掉了,竟然收录503网页
This entry was posted in 乱七八糟 and tagged , , , , . Bookmark the permalink.

36 thoughts on “将迅雷拒于Linux服务器门外

  1. 于是我发现 技术 这东西本身就是渣。。

    于是这东西至少比剧情渣好点就是了

    证明:
    已知品质因数 0 < 渣 < 1
    (渣^2 + 1)/2 >= sqrt(渣^2*1)
    整理得 渣^2 + 1 >= 渣 + 渣
    等号在 渣 = 1 时成立
    由已知得 渣 < 1
    所以 渣^2(渣技术) + 1(不渣的剧情) > 渣(一般技术) + 渣(渣剧情)
    orz,证毕。

  2. 群众纷纷表示东方夜神雪属于渣技术范围之内…纯剧情的?反正我下了看了看……通篇66RPG的影子然后就没玩了

  3. 灭写,因为在向木头请求最新用户代理信息时被拒绝,更新不能
    而且,咱会对整个服务器部署,不使用.htaccess

  4. 呃呃啊啊啊啊突然看到一条新闻说一国产东方同人叫 东方夜神雪
    然后发现作者我认识而且我知道这东西做了好长时间了
    发现我一直没干啥事的说

    • 生产力的发展让人们有更多的时间用于娱乐,嗯

      从预告片看来,似乎是RMXP/VX做的,RMXP/VX的“国18化”似乎不怎么好

  5. if(pos>=update_start)
                    threat_length[pos]+=FIVEGAME_TL_FIVE;
                  threat_length[pos4]+=FIVEGAME_TL_FOUR_CLOSED;
                }
                else if(pos>=update_start){
                  a+=occupied>>16;
                  int four_type=((int)(a & 0x2f0f)-0xe2c3)&0×4040;
                  if(four_type){
                    threat_length[pos]+=FIVEGAME_TL_FOUR(four_type==0×4040);

                    if(four_type & 0×40)
                      threat_length[pos4]+=FIVEGAME_TL_FOUR_CLOSED;
                  }
                  else{
                    a+=a>>4;
                    if((a & 0×500) == 0×500)
                      threat_length[pos]+=FIVEGAME_TL_THREE;
                    else{
                    }
                  }
                }
                else{
                  a+=occupied>>16;
                  if((a & 0xf) >= 3)
                    threat_length[pos4]+=FIVEGAME_TL_FOUR_CLOSED;
                }
            }

            occupied&=((long)(occupied & 0x0f0f0f0f)-1)&0×10101010;
            if(tbi != -2){
              current_color=tbi;
              threat_length=table_threat_length+(nn&-current_color);
              occupied+=cache_count[direction];
            }
            else
              break;
          }
        else if(tbi == -1){
          if((int)(position & 0xffff)> update_end)
            return;
          position<<=16;
          position|=i;
          occupied<<=8;
          occupied|=0×10;
        }
        else if(tbi != -2){
          current_color=tbi;
          threat_length=table_threat_length+(nn&-current_color);
          occupied+=cache_count
    [direction];
        }
        else
          break;
        if(i>=end){
          i=-1;
          tbi=-2;
        }
        else{
          i=cache_position
    [direction];
          tbi=table_board
    ;
        }
      }
    }

  6. (int start, int end, int update_start, int update_end, int direction, int update_mask)
    {
      int current_color=-1;
      unsigned long occupied=0;
      unsigned long position=0;
      int *threat_length;
      int nn=n*n;

      for(int i=start,tbi=table_board[start]; ;){
        if(current_color >= 0)
          if(tbi == current_color)
            occupied+=cache_count[direction];
          else if(tbi == -1){

            int pos=(position>>16) & 0xffff;

            if(pos>=update_start && (occupied & 0×1000)){

              unsigned int a=((occupied>>8)+occupied);
              
              if(a & 0xc00)
                threat_length[pos]+=FIVEGAME_TL_FIVE;
              else{
                a+=occupied>>16;
                int four_type=((int)(a & 0x2f0f)-0xe2c3)&0×4040;
                if(four_type)
                  threat_length[pos]+=FIVEGAME_TL_FOUR(four_type==0×4040);
                else{
                  a+=a>>4;
                  a&=0×505;
                  if(a & (a>>2))
                    threat_length[pos]+=FIVEGAME_TL_THREE;
                  else{
                  }
                }
              }
            }

            if((int)(position & 0xffff) > update_end)
              return;
            position<<=16;
            position|=i;

            occupied<<=8;
            occupied|=0×10;
            if(occupied == 0×10101010)
              current_color=-1;
          }
          else{
            int pos4=(WORD)position;
            if(pos4>=update_start && (occupied & 0×10)){
              int pos=(position>>16) & 0xffff;

              unsigned int a=((occupied>>8)+occupied);

              if((a & 0xc) && pos4<=update_end)
                threat_length[pos4]+=FIVEGAME_TL_FIVE;
              if(occupied & 0×1000)
                if(a & 0xc00){

  7. 呃突然毫无前兆的听人说的所以和自己看什么没关系而且事实上根本什么也没看不过x*7那个应该很好理解吧但是/7这个还真得想一下才明白

    • 实际上因为已经吸取了x*7的教训之后偶一看/7就知道是怎么回事了
      当时已经明确知道有一个*7的表达式了,于是一心在找mul,瞎弄了很久才发现这个,于是印象非常深刻

  8. 除了论坛里的人还有谁会下嘛。。那在论坛里发个不欢迎使用迅雷什么的你多烦烦总有人听的吧?。。。请忽略

  9. “我想大多数用户都不会追着使用最新版的。”
    小心迅雷自带检查一大堆软件的最新版本的功能

    • 那个到时候再说嘛
      而且如果这样的话倒也方便,可以集中精力想办法对付某一个版本而不用对付多个版本的说

发表评论

电子邮件地址不会被公开。

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>