SQLite资料

Sqlite是一种嵌入式/内存轻型数据库,它跨平台,快速,小巧,高效。如果你想选择小型数据库,我相信sqlite将是最佳的选择。它要比access数据库强大很多很多。当然如果你想说MSSQL或者MySQL要比SQLite高效的多。这一点我解释如下:

首先:sqlite定位是小型数据库(轻型),处理大数据自然有局限性。定位标准不同。

其次:sqlite在处理小型数据并不逊色于大型数据库,而且他体积更小。

由于这方面的资料比较多,我以链接的形式来介绍。

 

入门:

什么是SQLitehttp://baike.baidu.com/view/19310.htm

Sqlite官网:http://www.sqlite.org/

Sqlite中文社区:http://www.sqlite.com.cn/

最希望大家去的sqlite官网,里面写的很详细,虽然是英文。

 

Sqlite局限:

Sqlite局限性:http://apps.hi.baidu.com/share/detail/17043674

Sqlite不支持的操作:http://apps.hi.baidu.com/share/detail/17095537

 

Sqlite封装:

CppSqlitehttp://www.codeproject.com/KB/database/CppSQLite.aspx 

该类是最方便的类之一,可惜不支持加密和中文路径,后来有人做了改进

支持中文路径:http://hi.baidu.com/wangguang246/blog/item/4a521f96f5b2006355fb96bf.html

 

关于加密:

wxSqlite3http://wxcode.sourceforge.net/components/wxsqlite3/ 

这个库更新的很快,完全和sqlite3的发布同步,同时支持强大的加密功能,但是这个类使用关于麻烦,后来有人仅仅获取里面的加密功能和CppSqlite结合使用。

加密的另一种方案:http://news.2ky.cn/149/4101.htm 

 

如何编加密版本的sqlite

如何使用VC6编译sqlite3源码生成动态链接库

http://blog.csdn.net/littletigerat/archive/2010/04/19/5502491.aspx

如何对sqlite3数据库进行加密

http://blog.csdn.net/littletigerat/archive/2010/04/20/5502690.aspx

如果编译加密版本的sqlite请认真看上面两篇博客,我亲自测试,但是有些错误,后来做了一些说明:

上面的教程中有许些错误(测试版本3.73

1vc6编译sqlite源码的时候操作的时候,会提示提示出现找不到:“sqlite3rtree.h”头文件

解决方法:这个地方改成rtree.h

2:编译加密时候复制 到pagec的时候,同时要把复制的文件中的#include sqlite3.c”去掉

3:引用的时候要把sqlite3.h中的#ifdef SQLITE_HAS_CODEC以及对应的#endif去掉

 

 

Sqlite数据库查看工具

1:官网自带的工具,黑色的doc,不好用~

2Navicat for SQLite

http://www.sz1001.net/soft/43670.htm 

Linux C判断文件是否存在

一、access函数

功能描述:
检查调用进程是否可以对指定的文件执行某种操作。 

用法:
#include <unistd.h>
#include <fcntl.h>

int access(const char *pathname, int mode);  
 
参数:
pathname: 需要测试的文件路径名。  
mode: 需要测试的操作模式,可能值是一个或多个R_OK(可读?), W_OK(可写?), X_OK(可执行?) 或 F_OK(文件存在?)组合体。
 


返回说明:
成功执行时,返回0。失败返回-1,errno被设为以下的某个值
EINVAL: 模式值无效  
EACCES: 文件或路径名中包含的目录不可访问
ELOOP : 解释路径名过程中存在太多的符号连接
ENAMETOOLONG:路径名太长
ENOENT:  路径名中的目录不存在或是无效的符号连接
ENOTDIR: 路径名中当作目录的组件并非目录
EROFS: 文件系统只读
EFAULT: 路径名指向可访问的空间外
EIO:  输入输出错误
ENOMEM: 不能获取足够的内核内存
ETXTBSY:对程序写入出错

 

  1. #include <stdio.h>   
  2. #include <stdlib.h>   
  3. #include <unistd.h>   
  4. #include <fcntl.h>   
  5.   
  6. int main()   
  7. {   
  8.     if((access(“test.c”,F_OK))!=-1)   
  9.     {   
  10.         printf(“文件 test.c 存在.\n”);   
  11.     }   
  12.     else  
  13.     {   
  14.         printf(“test.c 不存在!\n”);   
  15.     }   
  16.   
  17.     if(access(“test.c”,R_OK)!=-1)   
  18.     {   
  19.         printf(“test.c 有可读权限\n”);   
  20.     }   
  21.     else  
  22.     {   
  23.         printf(“test.c 不可读.\n”);   
  24.     }   
  25.   
  26.     if(access(“test.c”,W_OK)!=-1)   
  27.     {   
  28.         printf(“test.c 有可写权限\n”);   
  29.     }   
  30.     else  
  31.     {   
  32.         printf(“test.c 不可写.\n”);   
  33.     }   
  34.     if(access(“test.c”,X_OK)!=-1)   
  35.     {   
  36.         printf(“test.c 有可执行权限\n”);   
  37.     }   
  38.     else  
  39.     {   
  40.         printf(“test.c 不可执行.\n”);   
  41.     }   
  42.   
  43.     return 0;   
  44. }  

 

  1. #include <stdio.h>   
  2. #include <time.h>   
  3. int main()   
  4. {   
  5.     time_t now = time(NULL);   
  6.     char buf[25];   
  7.     strftime(buf,24,“%Y%m%d”,localtime(&now));   
  8.     printf(“%s\n”,buf);   
  9.   
  10.     strftime(buf,24,“%Y-%m-%d %H:%M:%S”,localtime(&now));   
  11.     printf(“%s\n”,buf);   
  12.   
  13.     strftime(buf,24,“%y%m%d %H:%M:%S”,localtime(&now));   
  14.     printf(“%s\n”,buf);   
  15.   
  16.     strftime(buf,24,“%y%m%d”,localtime(&now));   
  17.     printf(“%s\n”,buf);   
  18.   
  19.     strftime(buf,24,“%H:%M:%S”,localtime(&now));   
  20.     printf(“%s\n”,buf);   
  21.     return 0;   
  22. }  

 

PHP:使用fseek函数处理大文件

最近又遇到一个难緾的客户,明明在网站后台已经给他们做了一个积分导入模块,他们嫌手工导入麻烦,非要做个自动化的,而且要两套方案、

方案1:他们开放一个内部数据库,由我们读取数据并写到新数据库里。他们领导说不安全,但是还是让做,作为备用方案。

方案2:他们将数据定时导出成TXT文本格式,放在一个指定的路径,我们定时读取它并解析。由于数据量很大,至少8万条数据,目前导入的TXT样本文件达25M,之后的数据会更多,我怕file或file_get_contents函数会吃不消。

在网上找了一下,发现如下方法很是管用。

fseek函数不需要把文件全部装入内存,而是直接通过指针来操作,所以效率很高。代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$fp = fopen($file, "r");
$line = 10;
$pos = -2;
$t = " ";
$data = "";
while ($line > 0) {
    while ($t != "\n") {
        fseek($fp, $pos, SEEK_END);
        $t = fgetc($fp);
        $pos --;
    }
    $t = " ";
    $data .= fgets($fp);
    $line --;
}
fclose ($fp);
echo $data

再提升一点,按块读取,然后计算块内的\n标记来算到了多少行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$fp = fopen($file, "r");
$num = 10;
$chunk = 4096;
$fs = sprintf("%u", filesize($file));
$max = (intval($fs) == PHP_INT_MAX) ? PHP_INT_MAX : filesize($file);
for ($len = 0; $len < $max; $len += $chunk) {
$seekSize = ($max - $len > $chunk) ? $chunk : $max - $len;
    fseek($fp, ($len + $seekSize) * -1, SEEK_END);
    $readData = fread($fp, $seekSize) . $readData;
  
    if (substr_count($readData, "\n") &gt;= $num + 1) {
        preg_match("!(.*?\n){".($num)."}$!", $readData, $match);
        $data = $match[0];
        break;
    }
}
fclose($fp);
//echo $data;
// code to process file contents

有了这个函数,以后用PHP处理大文件就方便了。

MySQL的mysqldump工具的基本用法

导出要用到MySQL的mysqldump工具,基本用法是:   

shell> mysqldump [OPTIONS] database [tables]  

如果你不给定任何表,整个数据库将被导出。   

通过执行mysqldump –help,你能得到你mysqldump的版本支持的选项表。  

注意,如果你运行mysqldump没有–quick或–opt选项,mysqldump将在导出结果前装载整个结果集到内存中,如果你正在导出一个大的数据库,这将可能是一个问题。  

mysqldump支持下列选项:   

–add-locks   
在每个表导出之前增加LOCK TABLES并且之后UNLOCK TABLE。(为了使得更快地插入到MySQL)。   
–add-drop-table   
在每个create语句之前增加一个drop table。   
–allow-keywords   
允许创建是关键词的列名字。这由表名前缀于每个列名做到。   
-c, –complete-insert   
使用完整的insert语句(用列名字)。   
-C, –compress   
如果客户和服务器均支持压缩,压缩两者间所有的信息。   
–delayed   
用INSERT DELAYED命令插入行。   
-e, –extended-insert   
使用全新多行INSERT语法。(给出更紧缩并且更快的插入语句)   
-#, –debug[=option_string]   
跟踪程序的使用(为了调试)。   

–help  

显示一条帮助消息并且退出。   
–fields-terminated-by=…   
   
–fields-enclosed-by=…   
   
–fields-optionally-enclosed-by=…   
   
–fields-escaped-by=…   
   
–fields-terminated-by=…   


这些选择与-T选择一起使用,并且有相应的LOAD DATA INFILE子句相同的含义。   
LOAD DATA INFILE语法。   
-F, –flush-logs   
在开始导出前,洗掉在MySQL服务器中的日志文件。   
-f, –force,   
即使我们在一个表导出期间得到一个SQL错误,继续。   
-h, –host=..   
从命名的主机上的MySQL服务器导出数据。缺省主机是localhost。   
-l, –lock-tables.   
为开始导出锁定所有表。   
-t, –no-create-info   
不写入表创建信息(CREATE TABLE语句)   
-d, –no-data   
不写入表的任何行信息。如果你只想得到一个表的结构的导出,这是很有用的!   
–opt   
同–quick –add-drop-table –add-locks –extended-insert –lock-tables。   
应该给你为读入一个MySQL服务器的尽可能最快的导出。   
-pyour_pass, –password[=your_pass]   
与服务器连接时使用的口令。如果你不指定“=your_pass”部分,mysqldump需要来自终端的口令。   
-P port_num, –port=port_num   
与一台主机连接时使用的TCP/IP端口号。(这用于连接到localhost以外的主机,因为它使用 Unix套接字。)   
-q, –quick   
不缓冲查询,直接导出至stdout;使用mysql_use_result()做它。   
-S /path/to/socket, –socket=/path/to/socket   
与localhost连接时(它是缺省主机)使用的套接字文件。   
-T, –tab=path-to-some-directory   
对于每个给定的表,创建一个table_name.sql文件,它包含SQL CREATE 命令,和一个table_name.txt文件,它包含数据。 注意:这只有在mysqldump运行在mysqld守护进程运行的同一台机器上的时候才工作。.txt文件的格式根据–fields-xxx和–lines–xxx选项来定。   
-u user_name, –user=user_name   
与服务器连接时,MySQL使用的用户名。缺省值是你的Unix登录名。   
-O var=option, –set-variable var=option设置一个变量的值。可能的变量被列在下面。   
-v, –verbose   
冗长模式。打印出程序所做的更多的信息。   
-V, –version   
打印版本信息并且退出。   
-w, –where=\’where-condition\’   
只导出被选择了的记录;注意引号是强制的!   
“–where=user=\’jimf\'” “-wuserid>1” “-wuserid<1” 

最常见的mysqldump使用可能制作整个数据库的一个备份:  
mysqldump –opt database > backup-file.sql   
但是它对用来自于一个数据库的信息充实另外一个MySQL数据库也是有用的:   
mysqldump –opt database | mysql –host=remote-host -C database   
由于mysqldump导出的是完整的SQL语句,所以用mysql客户程序很容易就能把数据导入了:   
shell> mysqladmin create target_db_name   
shell> mysql target_db_name < backup-file.sql  
就是  
shell> mysql 库名 < 文件名 

================================

几个常用用例:

1.导出整个数据库
 mysqldump -u 用户名 -p 数据库名 > 导出的文件名    
 mysqldump -u wcnc -p smgp_apps_wcnc > wcnc.sql
2.导出一个表
 mysqldump -u 用户名 -p 数据库名 表名> 导出的文件名
 mysqldump -u wcnc -p smgp_apps_wcnc users> wcnc_users.sql
3.导出一个数据库结构
  mysqldump -u wcnc -p -d –add-drop-table smgp_apps_wcnc >d:\wcnc_db.sql
 -d 没有数据 –add-drop-table 在每个create语句之前增加一个drop table 
4.导入数据库
  常用source 命令
  进入mysql数据库控制台,
  如mysql -u root -p 
  
  mysql>use 数据库
  然后使用source命令,后面参数为脚本文件(如这里用到的.sql)
  mysql>source d:\wcnc_db.sql

C语言格式化输出系统时间

源自:http://blog.csdn.net/jiadelin/article/details/2916329  部分代码有改动


我们可以使用strftime()函数将时间格式化为我们想要的格式。它的原型如下:



size_t strftime(

     char *strDest,

     size_t maxsize,

     const char *format,

     const struct tm *timeptr 

);



我们可以根据format指向字符串中格式命令把timeptr中保存的时间信息放在strDest指向的字符串中,最多向strDest中存放maxsize个字符。该函数返回向strDest指向的字符串中放置的字符数。



函数strftime()的操作有些类似于sprintf():识别以百分号(%)开始的格式命令集合,格式化输出结果放在一个字符串中。格式化命令说明串strDest中各种日期和时间信息的确切表示方法。格式串中的其他字符原样放进串中。格式命令列在下面,它们是区分大小写的。



%a 星期几的简写 

%A 星期几的全称 

%b 月分的简写 

%B 月份的全称 

%c 标准的日期的时间串 

%C 年份的后两位数字 

%d 十进制表示的每月的第几天 

%D 月/天/年 

%e 在两字符域中,十进制表示的每月的第几天 

%F 年-月-日 

%g 年份的后两位数字,使用基于周的年 

%G 年分,使用基于周的年 

%h 简写的月份名 

%H 24小时制的小时 

%I 12小时制的小时

%j 十进制表示的每年的第几天 

%m 十进制表示的月份 

%M 十时制表示的分钟数 

%n 新行符 

%p 本地的AM或PM的等价显示 

%r 12小时的时间 

%R 显示小时和分钟:hh:mm 

%S 十进制的秒数 

%t 水平制表符 

%T 显示时分秒:hh:mm:ss 

%u 每周的第几天,星期一为第一天 (值从0到6,星期一为0)

%U 第年的第几周,把星期日做为第一天(值从0到53)

%V 每年的第几周,使用基于周的年 

%w 十进制表示的星期几(值从0到6,星期天为0)

%W 每年的第几周,把星期一做为第一天(值从0到53) 

%x 标准的日期串 

%X 标准的时间串 

%y 不带世纪的十进制年份(值从0到99)

%Y 带世纪部分的十制年份 

%z,%Z 时区名称,如果不能得到时区名称则返回空字符。

%% 百分号



如果想显示现在是几点了,并以12小时制显示,就象下面这段程序:



#include “time.h”

#include “stdio.h”

int main(void)

{

struct tm *ptr;

time_t lt;

char str[80];

lt=time(NULL);

ptr=localtime(&lt);

strftime(str,100,”It is now %I %p”,ptr);

printf(str);

return 0;

}



其运行结果为:

It is now 4PM



而下面的程序则显示当前的完整日期:



#i nclude 

#i nclude 



void main( void )

{

          struct tm *newtime;

          char tmpbuf[128];

          time_t lt1;

          lt1 = time(NULL);

          newtime=localtime(&lt1);

          strftime( tmpbuf, 128, “Today is %A, day %d of %B in the year %Y.\n”, newtime);

          printf(tmpbuf);

}



运行结果:



Today is Saturday, day 30 of July in the year 2005.

深入浅出DDoS攻击防御

敌情篇 ——DDoS攻击原理


DDoS攻击基础

DDoS(Distributed Denial of Service,分布式拒绝服务)攻击的主要目的是让指定目标无法提供正常服务,甚至从互联网上消失,是目前最强大、最难防御的攻击之一。

按照发起的方式,DDoS可以简单分为三类。

第一类以力取胜,海量数据包从互联网的各个角落蜂拥而来,堵塞IDC入口,让各种强大的硬件防御系统、快速高效的应急流程无用武之地。这种类型的攻击典型代表是ICMP Flood和UDP Flood,现在已不常见。

第二类以巧取胜,灵动而难以察觉,每隔几分钟发一个包甚至只需要一个包,就可以让豪华配置的服务器不再响应。这类攻击主要是利用协议或者软件的漏洞发起,例如Slowloris攻击、Hash冲突攻击等,需要特定环境机缘巧合下才能出现。

第三类是上述两种的混合,轻灵浑厚兼而有之,既利用了协议、系统的缺陷,又具备了海量的流量,例如SYN Flood攻击、DNS Query Flood攻击,是当前的主流攻击方式。

本文将一一描述这些最常见、最具代表性攻击方式,并介绍它们的防御方案。

SYN Flood

SYN Flood是互联网上最经典的DDoS攻击方式之一,最早出现于1999年左右,雅虎是当时最著名的受害者。SYN Flood攻击利用了TCP三次握手的缺陷,能够以较小代价使目标服务器无法响应,且难以追查。

标准的TCP三次握手过程如下:

  • 客户端发送一个包含SYN标志的TCP报文,SYN即同步(Synchronize),同步报文会指明客户端使用的端口以及TCP连接的初始序号;
  • 服务器在收到客户端的SYN报文后,将返回一个SYN+ACK(即确认Acknowledgement)的报文,表示客户端的请求被接受,同时TCP初始序号自动加1;
  • 客户端也返回一个确认报文ACK给服务器端,同样TCP序列号被加1。

经过这三步,TCP连接就建立完成。TCP协议为了实现可靠传输,在三次握手的过程中设置了一些异常处理机制。第三步中如果服务器没有收到客户端的最终ACK确认报文,会一直处于SYN_RECV状态,将客户端IP加入等待列表,并重发第二步的SYN+ACK报文。重发一般进行3-5次,大约间隔30秒左右轮询一次等待列表重试所有客户端。另一方面,服务器在自己发出了SYN+ACK报文后,会预分配资源为即将建立的TCP连接储存信息做准备,这个资源在等待重试期间一直保留。更为重要的是,服务器资源有限,可以维护的SYN_RECV状态超过极限后就不再接受新的SYN报文,也就是拒绝新的TCP连接建立。

SYN Flood正是利用了上文中TCP协议的设定,达到攻击的目的。攻击者伪装大量的IP地址给服务器发送SYN报文,由于伪造的IP地址几乎不可能存在,也就几乎没有设备会给服务器返回任何应答了。因此,服务器将会维持一个庞大的等待列表,不停地重试发送SYN+ACK报文,同时占用着大量的资源无法释放。更为关键的是,被攻击服务器的SYN_RECV队列被恶意的数据包占满,不再接受新的SYN请求,合法用户无法完成三次握手建立起TCP连接。也就是说,这个服务器被SYN Flood拒绝服务了。

对SYN Flood有兴趣的可以看看http://www.icylife.net/yunshu/show.php?id=367,这是我2006年写的代码,后来做过几次修改,修改了Bug,并降低了攻击性,纯做测试使用。

DNS Query Flood

作为互联网最基础、最核心的服务,DNS自然也是DDoS攻击的重要目标之一。打垮DNS服务能够间接打垮一家公司的全部业务,或者打垮一个地区的网络服务。前些时候风头正盛的黑客组织anonymous也曾经宣布要攻击全球互联网的13台根DNS服务器,不过最终没有得手。

UDP攻击是最容易发起海量流量的攻击手段,而且源IP随机伪造难以追查。但过滤比较容易,因为大多数IP并不提供UDP服务,直接丢弃UDP流量即可。所以现在纯粹的UDP流量攻击比较少见了,取而代之的是UDP协议承载的DNS Query Flood攻击。简单地说,越上层协议上发动的DDoS攻击越难以防御,因为协议越上层,与业务关联越大,防御系统面临的情况越复杂。

DNS Query Flood就是攻击者操纵大量傀儡机器,对目标发起海量的域名查询请求。为了防止基于ACL的过滤,必须提高数据包的随机性。常用的做法是UDP层随机伪造源IP地址、随机伪造源端口等参数。在DNS协议层,随机伪造查询ID以及待解析域名。随机伪造待解析域名除了防止过滤外,还可以降低命中DNS缓存的可能性,尽可能多地消耗DNS服务器的CPU资源。

关于DNS Query Flood的代码,我在2011年7月为了测试服务器性能曾经写过一份代码,链接是http://www.icylife.net/yunshu/show.php?id=832。同样的,这份代码人为降低了攻击性,只做测试用途。

HTTP Flood

上文描述的SYN Flood、DNS Query Flood在现阶段已经能做到有效防御了,真正令各大厂商以及互联网企业头疼的是HTTP Flood攻击。HTTP Flood是针对Web服务在第七层协议发起的攻击。它的巨大危害性主要表现在三个方面:发起方便、过滤困难、影响深远。

SYN Flood和DNS Query Flood都需要攻击者以root权限控制大批量的傀儡机。收集大量root权限的傀儡机很花费时间和精力,而且在攻击过程中傀儡机会由于流量异常被管理员发现,攻击者的资源快速损耗而补充缓慢,导致攻击强度明显降低而且不可长期持续。HTTP Flood攻击则不同,攻击者并不需要控制大批的傀儡机,取而代之的是通过端口扫描程序在互联网上寻找匿名的HTTP代理或者SOCKS代理,攻击者通过匿名代理对攻击目标发起HTTP请求。匿名代理是一种比较丰富的资源,花几天时间获取代理并不是难事,因此攻击容易发起而且可以长期高强度的持续。

另一方面,HTTP Flood攻击在HTTP层发起,极力模仿正常用户的网页请求行为,与网站业务紧密相关,安全厂商很难提供一套通用的且不影响用户体验的方案。在一个地方工作得很好的规则,换一个场景可能带来大量的误杀。

最后,HTTP Flood攻击会引起严重的连锁反应,不仅仅是直接导致被攻击的Web前端响应缓慢,还间接攻击到后端的Java等业务层逻辑以及更后端的数据库服务,增大它们的压力,甚至对日志存储服务器都带来影响。

有意思的是,HTTP Flood还有个颇有历史渊源的昵称叫做CC攻击。CC是Challenge Collapsar的缩写,而Collapsar是国内一家著名安全公司的DDoS防御设备。从目前的情况来看,不仅仅是Collapsar,所有的硬件防御设备都还在被挑战着,风险并未解除。

慢速连接攻击

提起攻击,第一反应就是海量的流量、海量的报文。但有一种攻击却反其道而行之,以慢著称,以至于有些攻击目标被打死了都不知道是怎么死的,这就是慢速连接攻击,最具代表性的是rsnake发明的Slowloris。

HTTP协议规定,HTTP Request以\r\n\r\n结尾表示客户端发送结束,服务端开始处理。那么,如果永远不发送\r\n\r\n会如何?Slowloris就是利用这一点来做DDoS攻击的。攻击者在HTTP请求头中将Connection设置为Keep-Alive,要求Web Server保持TCP连接不要断开,随后缓慢地每隔几分钟发送一个key-value格式的数据到服务端,如a:b\r\n,导致服务端认为HTTP头部没有接收完成而一直等待。如果攻击者使用多线程或者傀儡机来做同样的操作,服务器的Web容器很快就被攻击者占满了TCP连接而不再接受新的请求。

很快的,Slowloris开始出现各种变种。比如POST方法向Web Server提交数据、填充一大大Content-Length但缓慢的一个字节一个字节的POST真正数据内容等等。关于Slowloris攻击,rsnake也给出了一个测试代码,参见http://ha.ckers.org/slowloris/slowloris.pl

DDoS攻击进阶

混合攻击

以上介绍了几种基础的攻击手段,其中任意一种都可以用来攻击网络,甚至击垮阿里、百度、腾讯这种巨型网站。但这些并不是全部,不同层次的攻击者能够发起完全不同的DDoS攻击,运用之妙,存乎一心。

高级攻击者从来不会使用单一的手段进行攻击,而是根据目标环境灵活组合。普通的SYN Flood容易被流量清洗设备通过反向探测、SYN Cookie等技术手段过滤掉,但如果在SYN Flood中混入SYN+ACK数据包,使每一个伪造的SYN数据包都有一个与之对应的伪造的客户端确认报文,这里的对应是指源IP地址、源端口、目的IP、目的端口、TCP窗口大小、TTL等都符合同一个主机同一个TCP Flow的特征,流量清洗设备的反向探测和SYN Cookie性能压力将会显著增大。其实SYN数据报文配合其他各种标志位,都有特殊的攻击效果,这里不一一介绍。对DNS Query Flood而言,也有独特的技巧。

首先,DNS可以分为普通DNS和授权域DNS,攻击普通DNS,IP地址需要随机伪造,并且指明服务器要求做递归解析;但攻击授权域DNS,伪造的源IP地址则不应该是纯随机的,而应该是事先收集的全球各地ISP的DNS地址,这样才能达到最大攻击效果,使流量清洗设备处于添加IP黑名单还是不添加IP黑名单的尴尬处境。添加会导致大量误杀,不添加黑名单则每个报文都需要反向探测从而加大性能压力。

另一方面,前面提到,为了加大清洗设备的压力不命中缓存而需要随机化请求的域名,但需要注意的是,待解析域名必须在伪造中带有一定的规律性,比如说只伪造域名的某一部分而固化一部分,用来突破清洗设备设置的白名单。道理很简单,腾讯的服务器可以只解析腾讯的域名,完全随机的域名可能会直接被丢弃,需要固化。但如果完全固定,也很容易直接被丢弃,因此又需要伪造一部分。

其次,对DNS的攻击不应该只着重于UDP端口,根据DNS协议,TCP端口也是标准服务。在攻击时,可以UDP和TCP攻击同时进行。

HTTP Flood的着重点,在于突破前端的cache,通过HTTP头中的字段设置直接到达Web Server本身。另外,HTTP Flood对目标的选取也非常关键,一般的攻击者会选择搜索之类需要做大量数据查询的页面作为攻击目标,这是非常正确的,可以消耗服务器尽可能多的资源。但这种攻击容易被清洗设备通过人机识别的方式识别出来,那么如何解决这个问题?很简单,尽量选择正常用户也通过APP访问的页面,一般来说就是各种Web API。正常用户和恶意流量都是来源于APP,人机差别很小,基本融为一体难以区分。

之类的慢速攻击,是通过巧妙的手段占住连接不释放达到攻击的目的,但这也是双刃剑,每一个TCP连接既存在于服务端也存在于自身,自身也需要消耗资源维持TCP状态,因此连接不能保持太多。如果可以解决这一点,攻击性会得到极大增强,也就是说Slowloris可以通过stateless的方式发动攻击,在客户端通过嗅探捕获TCP的序列号和确认维护TCP连接,系统内核无需关注TCP的各种状态变迁,一台笔记本即可产生多达65535个TCP连接。

前面描述的,都是技术层面的攻击增强。在人的方面,还可以有一些别的手段。如果SYN Flood发出大量数据包正面强攻,再辅之以Slowloris慢速连接,多少人能够发现其中的秘密?即使服务器宕机了也许还只发现了SYN攻击想去加强TCP层清洗而忽视了应用层的行为。种种攻击都可以互相配合,达到最大的效果。攻击时间的选择,也是一大关键,比如说选择维护人员吃午饭时、维护人员下班堵在路上或者在地铁里无线上网卡都没有信号时、目标企业在举行大规模活动流量飙升时等。

这里描述的只是纯粹的攻击行为,因此不提供代码,也不做深入介绍。


来自P2P网络的攻击

前面的攻击方式,多多少少都需要一些傀儡机,即使是HTTP Flood也需要搜索大量的匿名代理。如果有一种攻击,只需要发出一些指令,就有机器自动上来执行,才是完美的方案。这种攻击已经出现了,那就是来自P2P网络的攻击。

大家都知道,互联网上的P2P用户和流量都是一个极为庞大的数字。如果他们都去一个指定的地方下载数据,使成千上万的真实IP地址连接过来,没有哪个设备能够支撑住。拿BT下载来说,伪造一些热门视频的种子,发布到搜索引擎,就足以骗到许多用户和流量了,但这只是基础攻击。

高级P2P攻击,是直接欺骗资源管理服务器。如迅雷客户端会把自己发现的资源上传到资源管理服务器,然后推送给其他需要下载相同资源的用户,这样,一个链接就发布出去。通过协议逆向,攻击者伪造出大批量的热门资源信息通过资源管理中心分发出去,瞬间就可以传遍整个P2P网络。更为恐怖的是,这种攻击是无法停止的,即使是攻击者自身也无法停止,攻击一直持续到P2P官方发现问题更新服务器且下载用户重启下载软件时为止。

 

应对篇 ——DDoS防御方案

防御基础

攻击流量到底多大

谈到DDoS防御,首先就是要知道到底遭受了多大的攻击。这个问题看似简单,实际上却有很多不为人知的细节在里面。

以SYN Flood为例,为了提高发送效率在服务端产生更多的SYN等待队列,攻击程序在填充包头时,IP首部和TCP首部都不填充可选的字段,因此IP首部长度恰好是20字节,TCP首部也是20字节,共40字节。

对于以太网来说,最小的包长度数据段必须达到46字节,而攻击报文只有40字节,因此,网卡在发送时,会做一些处理,在TCP首部的末尾,填充6个0来满足最小包的长度要求。这个时候,整个数据包的长度为14字节的以太网头,20字节的IP头,20字节的TCP头,再加上因为最小包长度要求而填充的6个字节的0,一共是60字节。

但这还没有结束。以太网在传输数据时,还有CRC检验的要求。网卡会在发送数据之前对数据包进行CRC检验,将4字节的CRC值附加到包头的最后面。这个时候,数据包长度已不再是40字节,而是变成64字节了,这就是常说的SYN小包攻击,数据包结构如下:

|14字节以太网头部|20字节IP头部|20字节TCP|6字节填充|4字节检验|
|目的MAC|源MAC|协议类型| IP头 |TCP头|以太网填充 | CRC检验 |

到64字节时,SYN数据包已经填充完成,准备开始传输了。攻击数据包很小,远远不够最大传输单元(MTU)的1500字节,因此不会被分片。那么这些数据包就像生产流水线上的罐头一样,一个包连着一个包紧密地挤在一起传输吗?事实上不是这样的。

以太网在传输时,还有前导码(preamble)和帧间距(inter-frame gap)。其中前导码占8字节(byte),即64比特位。前导码前面的7字节都是10101010,1和0间隔而成。但第八个字节就变成了10101011,当主机监测到连续的两个1时,就知道后面开始是数据了。在网络传输时,数据的结构如下:

|8字节前导码|6字节目的MAC地址|6字节源MAC地址|2字节上层协议类型|20字节IP头|20字节TCP头|6字节以太网填充|4字节CRC检验|12字节帧间距|

也就是说,一个本来只有40字节的SYN包,在网络上传输时占的带宽,其实是84字节。

有了上面的基础,现在可以开始计算攻击流量和网络设备的线速问题了。当只填充IP头和TCP头的最小SYN包跑在以太网络上时,100Mbit的网络,能支持的最大PPS(Packet Per Second)是100×106 / (8 * (64+8+12)) = 148809,1000Mbit的网络,能支持的最大PPS是1488090。

SYN Flood防御

前文描述过,SYN Flood攻击大量消耗服务器的CPU、内存资源,并占满SYN等待队列。相应的,我们修改内核参数即可有效缓解。主要参数如下:

net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_synack_retries = 2

分别为启用SYN Cookie、设置SYN最大队列长度以及设置SYN+ACK最大重试次数。

SYN Cookie的作用是缓解服务器资源压力。启用之前,服务器在接到SYN数据包后,立即分配存储空间,并随机化一个数字作为SYN号发送SYN+ACK数据包。然后保存连接的状态信息等待客户端确认。启用SYN Cookie之后,服务器不再分配存储空间,而且通过基于时间种子的随机数算法设置一个SYN号,替代完全随机的SYN号。发送完SYN+ACK确认报文之后,清空资源不保存任何状态信息。直到服务器接到客户端的最终ACK包,通过Cookie检验算法鉴定是否与发出去的SYN+ACK报文序列号匹配,匹配则通过完成握手,失败则丢弃。当然,前文的高级攻击中有SYN混合ACK的攻击方法,则是对此种防御方法的反击,其中优劣由双方的硬件配置决定

tcp_max_syn_backlog则是使用服务器的内存资源,换取更大的等待队列长度,让攻击数据包不至于占满所有连接而导致正常用户无法完成握手。net.ipv4.tcp_synack_retries是降低服务器SYN+ACK报文重试次数,尽快释放等待资源。这三种措施与攻击的三种危害一一对应,完完全全地对症下药。但这些措施也是双刃剑,可能消耗服务器更多的内存资源,甚至影响正常用户建立TCP连接,需要评估服务器硬件资源和攻击大小谨慎设置。

除了定制TCP/IP协议栈之外,还有一种常见做法是TCP首包丢弃方案,利用TCP协议的重传机制识别正常用户和攻击报文。当防御设备接到一个IP地址的SYN报文后,简单比对该IP是否存在于白名单中,存在则转发到后端。如不存在于白名单中,检查是否是该IP在一定时间段内的首次SYN报文,不是则检查是否重传报文,是重传则转发并加入白名单,不是则丢弃并加入黑名单。是首次SYN报文则丢弃并等待一段时间以试图接受该IP的SYN重传报文,等待超时则判定为攻击报文加入黑名单。

首包丢弃方案对用户体验会略有影响,因为丢弃首包重传会增大业务的响应时间,有鉴于此发展出了一种更优的TCP Proxy方案。所有的SYN数据报文由清洗设备接受,按照SYN Cookie方案处理。和设备成功建立了TCP三次握手的IP地址被判定为合法用户加入白名单,由设备伪装真实客户端IP地址再与真实服务器完成三次握手,随后转发数据。而指定时间内没有和设备完成三次握手的IP地址,被判定为恶意IP地址屏蔽一定时间。除了SYN Cookie结合TCP Proxy外,清洗设备还具备多种畸形TCP标志位数据包探测的能力,通过对SYN报文返回非预期应答测试客户端反应的方式来鉴别正常访问和恶意行为。

清洗设备的硬件具有特殊的网络处理器芯片和特别优化的操作系统、TCP/IP协议栈,可以处理非常巨大的流量和SYN队列。

HTTP Flood防御

HTTP Flood攻击防御主要通过缓存的方式进行,尽量由设备的缓存直接返回结果来保护后端业务。大型的互联网企业,会有庞大的CDN节点缓存内容。

当高级攻击者穿透缓存时,清洗设备会截获HTTP请求做特殊处理。最简单的方法就是对源IP的HTTP请求频率做统计,高于一定频率的IP地址加入黑名单。这种方法过于简单,容易带来误杀,并且无法屏蔽来自代理服务器的攻击,因此逐渐废止,取而代之的是JavaScript跳转人机识别方案。

HTTP Flood是由程序模拟HTTP请求,一般来说不会解析服务端返回数据,更不会解析JS之类代码。因此当清洗设备截获到HTTP请求时,返回一段特殊JavaScript代码,正常用户的浏览器会处理并正常跳转不影响使用,而攻击程序会攻击到空处。

DNS Flood防御

DNS攻击防御也有类似HTTP的防御手段,第一方案是缓存。其次是重发,可以是直接丢弃DNS报文导致UDP层面的请求重发,可以是返回特殊响应强制要求客户端使用TCP协议重发DNS查询请求。

特殊的,对于授权域DNS的保护,设备会在业务正常时期提取收到的DNS域名列表和ISP DNS IP列表备用,在攻击时,非此列表的请求一律丢弃,大幅降低性能压力。对于域名,实行同样的域名白名单机制,非白名单中的域名解析请求,做丢弃处理。

慢速连接攻击防御

Slowloris攻击防御比较简单,主要方案有两个。

第一个是统计每个TCP连接的时长并计算单位时间内通过的报文数量即可做精确识别。一个TCP连接中,HTTP报文太少和报文太多都是不正常的,过少可能是慢速连接攻击,过多可能是使用HTTP 1.1协议进行的HTTP Flood攻击,在一个TCP连接中发送多个HTTP请求。

第二个是限制HTTP头部传输的最大许可时间。超过指定时间HTTP Header还没有传输完成,直接判定源IP地址为慢速连接攻击,中断连接并加入黑名单。

企业级防御

互联网企业防御DDoS攻击,主要使用上文的基础防御手段,重点在于监控、组织以及流程。

监控需要具备多层监控、纵深防御的概念,从骨干网络、IDC入口网络的BPS、PPS、协议分布,负载均衡层的VIP新建连接数、并发连接数、BPS、PPS到主机层的CPU状态、TCP新建连接数状态、TCP并发连接数状态,到业务层的业务处理量、业务连通性等多个点部署监控系统。即使一个监控点失效,其他监控点也能够及时给出报警信息。多个点信息结合,准确判断被攻击目标和攻击手法。

一旦发现异常,立即启动在虚拟防御组织中的应急流程,防御组织需要囊括到足够全面的人员,至少包含监控部门、运维部门、网络部门、安全部门、客服部门、业务部门等,所有人员都需要2-3个备份。流程启动后,除了人工处理,还应该包含一定的自动处理、半自动处理能力。例如自动化的攻击分析,确定攻击类型,自动化、半自动化的防御策略,在安全人员到位之前,最先发现攻击的部门可以做一些缓解措施。

除了DDoS到来之时的流程等工作之外,更多的工作是在攻击到来之前。主要包含CDN节点部署、DNS设置、流程演习等。对于企业来说,具备多个CDN节点是DDoS防御容量的关键指标。当一个机房承担不住海量数据时,可以通过DNS轮询的方式,把流量引导到多个分布节点,使用防御设备分头处理。因此DNS的TTL值需要设置得足够小,能够快速切换,每个CDN节点的各种VIP设置也需要准备充分。

在虚拟化时代,各种用户的不同业务共处在相同的物理机平台,遭受DDoS攻击的可能性越来越高,而且一个用户被攻击可能牵扯到大量的其他用户,危害被显著放大,因此防御显得尤为重要。阿里云的虚拟化业务,平均每天遭受约20起DDoS攻击,最大流量达到接近20Gbit/s,所有这些攻击都在15分钟内自动处理完成,让客户远离DDoS的威胁,专心发展业务。

总地来说,对DDoS防御,主要的工作是幕后积累。台上十分钟,台下十年功,没有充分的资源准备,没有足够的应急演练,没有丰富的处理经验,DDoS攻击将是所有人的噩梦。

开源是种生活方式

走上开源道路

清晨六点钟,被儿子闹醒,第一件事是打开邮箱,迎面而来的是数以百计的邮件,我知道新一天的工作开始了。

这是一个典型的场景, 过去四年多的时间, 我一直在家工作,全职参与Apache旗下多个开源项目的开发。以开源社区为核心, 以maillinglistIRCJIRASVNGitMaven等为工具,参与全球化协作的开源项目。


走上Apache开源道路,要从2006年谈起,当时源于ObjectWeb社区的Celtix和源于Codehaus社区的Xfire合并,成为了Apache旗下的一个新项目CXF。我当时所服务的公司IONA是开源项目Celtix的主要推动者,也是Celtix的代码提交者(Committer), 因此成为了Apache CXFInitial Committer。 从那之后, 我一直从事开源软件开发工作,期间伴随着IONAProgress收购, 以及Progress成立独立的专门从事开源项目的子公司FuseSource。根据项目发展的需要,我从事的工作也从最初的Apache CXF扩展到了Apache旗下的多个开源项目。目前,我是Apache CXFServicemixKarafCamelFelixCommitter(在Apache开源社区中我使用Freeman Fang这个名字),并且是Apache CXFServicemixKarafPMC member(项目管理委员会成员)。


我想读者最为关心的问题是,全职从事开源软件的开发,靠什么来生活?是完全凭兴趣吗?如何保证自身的可持续性发展?

Ok,要回答这些问题, 必须先谈一种基于开源的商业模式—围绕开源社区和开源软件, 通过雇用主要的开源项目开发者, 向外提供付费的商业服务, 这种付费服务包括订阅、咨询、培训等。我的雇主就是提供类似服务的商业公司。这种开源商业模式在基础软件架构领域(如开源操作系统、开源数据库和开源基础中间件)已被证明是一种行之有效的方式,在欧美市场被广泛接受。但在国内, 这种商业模式还没有被普遍认可,很多人还认为开源就是免费,不愿意承认特定领域专家的价值,这种现象很值得深思。


在我看来,这种开源商业模式下,开源项目和开源社区因为有了商业公司的介入更加活跃,开源开发者有了稳定的收入获得了可持续发展,付费用户由于有了商业支持能更有效地使用开源软件,非付费用户也能从活跃的开源社区获得支持,构成了一个共赢的生态环境。

回到本文开头,我的日常工作是:阅读大量我所从事的Apache开源项目的邮件和公司论坛帖子,回答社区用户问题;实现新功能或者修复Bug,提交代码到Apache代码库中。同时,如果付费用户提交了问题,那么高优先级处理付费用户问题,但实现的新功能或者修复的Bug都会第一时间回馈到相关Apache项目的代码库中。



为什么从事开源项目

如果一个人能很长时间做一件事情并乐此不疲,那么只有一个解释,他很喜欢做这件事。我喜欢开源的原因很多,且听我一一道来。


原因之一:开源意味着最大程度的分享,降低了知识学习的壁垒, 给了后发者赶超的机会。

在从事开源软件开发的过程中,我经历了这样一个心理变化,从很自信到很不自信到慢慢找回自信。 由于有机会和世界上最好的一群软件工程师一起工作,我可以很清楚地看到自身的差距,但开源意味着一切都是透明的,不仅仅是代码,公开的社区讨论也能给你很大的启发。时间长了,你会看到自己的进步,慢慢找回自信的过程就是进步的过程。对于一个喜欢技术、追求技术的人, 开源是一个能提供无限可能的大平台。


原因之二:开源给了我最大程度的自由。

我不用去办公室工作,能自由安排自己的工作时间。在北京这个大都市里,不用去办公室意味着每天能节省2~3个小时的通勤时间, 我可以用这个时间来学习、健身、娱乐,甚至加班。有了孩子之后,我每天早7点之前开始工作, 通常下午4点我会将工作停下, 接管照顾孩子的任务。在晚上8点孩子睡了之后,我会最后再工作一会儿。

随着Internet等基础设施的飞速发展,伴随着大量辅助工具软件的出现,远程办公成为可能,越来越多的工作由集中式变成分散式,我们的工作模式正在改变。这种模式降低了大城市的交通压力,办公场地的压力,更加节能环保,同时也提高了工作者的生活质量。


原因之三:开源给了我成就感。

每次获得一个Apache项目的Committer权限,都是一次被认可的过程。通常意味着你要不断地提交高质量的Patch给该项目,积极参与该项目的社区讨论,之后该项目PMC才会提名和投票表决。每当收到一个项目的Committer邀请,都会带给我巨大的喜悦和强烈的成就感。此外,参与社区讨论,回答别人的问题,也是一件非常愉快的事情,这真的是可以上瘾的。 

从事开源,就有机会和最好的工程师一起工作,做领先的技术和项目,这些项目不仅能直接服务最终用户,还能成为其他项目的重要组成部分。例如,Apache Geronimo选择基于Apache Karaf来实现OSGi容器;还例如Apache CXF作为但不限于JAX-WS协议的一个实现,得到了很广泛的应用。 多个JEE服务器如Apache GeronimoJBossJOnASPramati选择CXF作为自己的JAX-WS实现(从JEE5开始则要通过TCK认证且需要有JAX-WS的支持)。


原因之四:开源让我更好地了解世界。

从事开源项目的开发人员,来自世界各地,具备不同的文化背景、教育背景和思维方式。通过和他们交流, 我更好地了解了他们的技术水平以及引发了我思考人家为什么会达到这样的技术水平。

举个例子,西方的工程师从事开源软件只有一个理由—兴趣。英文里有一个单词是Geek, 翻译成中文是极客,代指狂热于技术、思维异于常人的人群。用Geek来形容开源开发者再合适不过了,他们对技术的追求无止境,他们喜欢创造新的东西,他们渴望改变和引导技术发展的进程。对比国内研发工程师经常忧虑一些现实的困境,他们从来不考虑30或者35岁之后老了没有竞争力的问题, 他们很少考虑转型做管理者。他们通常年龄在35岁或者更大一些,10余年的行业技术积累让他们知识的深度和广度都很好。由于社会文化真正认可技术的价值,他们只凭做工程师就能生活得非常好(真的是非常好),他们要考虑的内容相对单纯一些, 就是从兴趣出发,完全以技术为导向。当一个人真正对自己从事的工作有极大兴趣、引以为豪且有多年的经验积累之后, 其创造力和生产力是惊人的。


技术专家的产生需要土壤,需要社会价值观作为导向,让有天赋的研发人员愿意长期从事技术积累且无后顾之忧,并能获取相应的回报是产生群体性技术专家的基本前提。如果我们的技术人员都在考虑找机会转型, 那么恐怕永远只能做低水平的简单重复,离诞生伟大的软件公司这个目标会越来越远,与和世界一流的软件水平之间的差距会越来越大。


原因之五:开源已经、正在和将继续改变软件业的发展以及我们的生活。

基于成本优势;代码可见,可深度定制;系统高度自由,无需绑定到特定厂商;更敏捷等原因, 越来越多的公司采用开源软件和开源架构,这种趋势也使更多的商业公司开源自己的产品, 以适应市场的发展。

且不说国外开源应用风起云涌, 国内也有很多公司重视开源技术,采用开源架构,例如国内某著名电商互联网公司。该公司重视技术积累,有自己的给力技术团队,有能力对开源解决方案深度定制,快速满足自身需求。该公司的系统每天都在承受超大规模的并发请求但依然很稳定。我一直认为在大压力复杂应用环境中,只有自己是自己的上帝,开源给了你主宰自己命运的机会。这个例子说明真正重视技术积累,有给力技术团队对企业自身的应用是多么的重要。



为什么国人参与开源力度不够大

参与Apache开源项目以来,有一个现象非常困扰我,就是很少有同胞在相关项目邮件列表/论坛问问题,是国人很少使用这些开源项目吗?显然不是,以Apache CXF为例子,如果我们使用Google Trend来查看关键字CXFGoogle被搜索的统计,我们可以看到最多的搜索请求来自中国,搜索者使用的语言排在第一位的是中文;同时,我可以在互联网上搜索到大量的关于使用Apache CXF的中文技术博客。以上都能证明, Apache CXF在国内被大量使用,但我为什么在Apache CXF的邮件列表中很少看到中国人问问题, 更不要说参与讨论、解答问题甚至打Patch了。我在这里想尝试分析一下为何同胞很少参与讨论,并帮您打消顾虑。


我认为最主要的原因是文化上的差异,它首先表现为语言上面的障碍。开源社区的参与人员来自世界各地,为了保证大家的交流,采用的语言是英语,毕竟英语目前是国际上最为通用的语言。在线下交流中,我了解到,很多人因为要用英语问问题而迟疑,甚至放弃问问题。其实大可不必,因为Apache社区很多参与讨论的人员的母语都不是英语,这并不妨碍大家用英语讨论技术问题;再者,我和欧美同行交流过语言方面的问题,他们(尤其是英语是母语的同行)认为很多中国人过于低估自己的英语交流水平。实际把自己的问题用英语描述清楚并没有那么难,别担心,没有人会像针对我们的英语考试中短文改错那样对待你的邮件/帖子。毕竟, 我们掌握英语的程度远远超过西方人掌握中文的程度。另外,多参与讨论, 对实用英语的挺高也很有帮助。


文化上第二个差异体现在不同的学习方式上,我们擅长的学习方式是有系统的教材,有标准的大纲, 最好再有大量的练习题来强化知识点。我们习惯于这种学习方式,我们对规划好的知识点可以掌握得非常好,具体的体现是我们很擅长考试,但我们很少主动问问题。大多数人在考完试之后, 马上就会忘掉之前死记硬背的东西。西方人要学习一个东西,习惯自己找材料,找问题,讨论问题,因此,讨论问题本身就是他们所习惯的学习方式的一部分。而通过这种方式获得的知识更让人记忆深刻。我认为他们更善于学习新东西,尤其是需要自己主动学习时,他们的学习方式让他们更有优势。我们害怕没有面子,害怕问出不靠谱的问题,回避交流。不要这样,要更开放一些,善于利用Apache社区这个很好的资源,和技术专家讨论问题。况且,英语有一句俗语,“No question is stupid”,就是在鼓励大家问问题。

大势所趋话开源——中国开源现状分析

随着计算机技术的发展,尤其是互联网技术和相关企业的兴起,开源软件在操作系统、编译工具链、数据库、Web服务器、移动操作系统等各方面已成为主流。而且许多企业利用开源软件形成了独特的商业模式。比如Google的Android操作系统,从2007年开源发布第一个版本起,到今天已经发展到4.1版本,占据了智能手机操作系统一半以上的市场份额,Google也通过Android操作系统在移动互联网这一新兴行业中占据了领先和主导地位。以前一直和开源软件做斗争的微软公司,为顺应潮流,也开始拥抱开源,比如向Samba项目贡献代码,放弃自己研发多年的大数据项目而选择Hadoop为其大数据的核心等。

显然,纵观IT行业这20多年的发展,开源项目已形成一股推进计算机及相关行业不停进步的巨大力量。本文将重点讲述国内的开源项目及社区的现状,以及发展过程中面临的困难和问题。


国内开源项目的发展及社区现状

国内开源软件的发展简史

国内开源项目的发展始于1997年前后。那时,中国第一个(局部)互联网(CERNET)刚建立不久,1995年在清华大学建立的著名的水木清华BBS就是开源项目。之后,Linux内核以及GNU项目中的成百上千个开源项目逐渐展现在国人的面前。

随后,中国也逐渐出现了一些开源项目。最初由国人开发的开源项目,主要解决的是Linux系统的汉化问题,流传最为广泛的应该是可以显示和输入中文的伪终端应用程序CCE。在1998年之后的两三年内,出现了以下三个开源项目。

  • LVSLinux Virtual Server)是由章文嵩博士开发的,后来被Linux内核收录,成为使用Linux操作系统搭建集群服务器的重要核心软件组件。
  • Smart Boot Manager是当时的清华大学博士生苏哲开发的,它是一个引导管理器,类似现在流行的GRUB,主要解决引导多种操作系统的问题。苏哲后来主持开发的SCIM系统,被各种流行的Linux发行版收录,成为Linux操作系统上提供多语种输入法支持的标准框架。
  • MiniGUI是由我开发的,后来由我创立的北京飞漫软件技术有限公司维护和发展,在功能手机、数码相框、工业控制系统和工业仪表中得到了广泛应用。

上述三个开源软件是中国开源软件早期的代表作,在国际上具有较强的影响力。

之后,国内开源项目的发展长期处于停滞状态,这与2000年左右互联网泡沫的破裂有一定关系。互联网泡沫的破裂,让许多梦想通过开源项目来创造商业奇迹的Linux发行版厂商很受伤。我曾供职的蓝点软件,在NASDAQ OTCBB板借壳上市,半年之内股价从20多美元跌到0.2美元,后于2001年贱卖。


2005年起,开源项目的发展逐渐走出低谷。在此期间,国内也出现了为数不多的开源项目,其中以清华大学陈渝副教授主持的SkyEye最具代表性。该项目旨在提供一个面向嵌入式软件开发和调试的ARM或其他架构的纯软件仿真器(虚拟机)。该项目持续活跃长达7年时间,吸引了许多海外高手参与,是为数不多的具有国际影响力且充分体现了国际化协作、分享的开源项目。


在参与开源项目的企业当中,最为活跃的是淘宝,接下来是新浪、百度、腾讯和华为等。同时,随着“开源中国”等社区的兴起,个人主持或者参与的开源项目逐渐多了起来。根据“开源中国”收录的开源软件,当前已经有一千多个由国人开发或者主持的开源软件。这和十年前相比,有了非常大的进步。有兴趣的读者可访问http://www.oschina.net。以下开源项目非常值得一提。

  • TFS是一款由淘宝开发的分布式对象存储系统,于20109月开源,存储了淘宝的几百亿张图片和交易快照。目前新浪微博已在生产系统中使用TFS作图片等对象的存储。
  • RT-Thread。这是一个由国人主持开发的开源实时操作系统,曾获得“第六届中日韩开源软件竞赛”的技术优胜奖(其他两个技术优胜奖获得者为淘宝的OceanBase和红旗的Qomo Linux)。RT-Thread 目前也获得了诸多商业应用。
  • Linux Deepin是近几年发展起来的面向桌面的中文Linux发行版,由一群来自武汉的Linux高手发起并维护。
  • ucore。从2010年暑假开始,陈渝博士组织清华大学学生开展教学用开源操作系统ucore的设计与实现,并直接用于清华大学的操作系统课程,学生可参考实验文档和ucore源码通过实践逐步深入掌握操作系统。这相对国内操作系统旧有的教学方法有较大改变,获得了国内外操作系统教学领域专家的认可,并将在教育部的支持下进行更大范围的推广。

国内开源软件的特点和问题

国内开源项目存在很多问题,如缺乏重量级项目、缺乏持续维护和更新、质量一般、用户不多等。另外,正如开源中国创始人所言,国人所开发的这些开源项目,和国际主流开源项目脱节严重,绝大多数处于单打独斗的状态。

例如,淘宝主导或参与的开源软件,大多数和互联网服务器后台、云计算相关,这些项目的主要用户是淘宝自己。因为门户之见,这些软件很难被其他的互联网企业所使用,大家不停地“造轮子”而忽视了开源软件发展必须具备的“共享”、“协作”精神。不过,现在这种情况正在改变,上面提到的淘宝TFS系统已被其他互联网企业使用,ucore项目也得到了诸多国内外大学积极的响应和支持。


我希望国内的开源项目能够和国际主流的开源项目步伐保持一致,要么加入国际化的开源软件,要么将自己主持的开源软件逐步国际化。这样,我们的开源项目才能得到源源不断的前进动力,也才能在国际化舞台上扮演更加重要的角色。

新的力量

无论如何,国内大型IT企业参与开源项目就是一个良好的开端,将为中国开源项目的发展起到非常大的促进作用。与此同时,各种开源社区活动也越来越活跃,例如具有政府背景的“开源软件高峰论坛”和草根性质的“我们的开源项目”巡回展演等。这表明,开源软件即将在国内引起新一轮的发展浪潮。

开源我的软件?

在高物价、高房价的今天,大部分人对此问题的第一反应是:“我就是一刚解决温饱的码农,我开源,谁养我?”这几乎与我们在十年前推广开源项目理念时遇到的问题一样。但这已大大落后于时代了!我们不仅可以通过使用其他人的开源项目赚钱,还可以通过开源自己的项目来赚钱。

如何靠开源项目赚钱?

在证明上述论点之前,我们先看看别人是如何利用开源项目赚钱的。靠开源项目赚钱的方式(经过验证的)无外乎有如下几种。

  • 双许可证模式。在采取严格的开源软件许可证的同时(通常选择GPL),给商业用户提供非GPL许可方式。这本质上是一种贩卖软件许可的行为,但开源软件带给开发者一个很大的好处,即传播迅速、快速迭代。我主持的MiniGUI项目就采用这种模式,在过去的五年当中,获得了几千万元的软件许可收费。当然,使用这个模式最成功的当属MySQL
  • 基础软件采用宽松许可证,同时向基础软件的商业用户贩卖增值服务或者增强组件、开发工具等的许可。这种模式可用于类似RT-Thread这类的基础性软件上,RT-Thread本身可以是开源且可无偿商用的,但其上的各种增值组件,如网络、文件系统、图形系统等,可以是商业软件。国外采用这种模式的以各类CMS系统为主。例如DrupalConcrete系统,其基本系统是开源且免费的,但其上的许多插件、主题、模版等是收费的。有兴趣的读者可访问 http://www.concrete5.org网站,其中还有“Marketplace(市场)”频道。
  • 混合模式,既贩卖工具等软件的许可,同时还向用户提供付费服务的模式。比如Ubuntu Linux发行版。
  • 成为平台型项目,并承载自己的互联网业务。这种模式在大型互联网企业中应用广泛。例如Google开发并开源Chrome浏览器,短短几年抢占了微软的很多市场份额,通过在Chrome中默认使用Google搜索引擎而获得极大的收入;再比如Google开源Android,一方面为了遏制苹果iOS的增长势头,另一方面通过预置Google搜索而获得了大量来自移动互联网的流量收入。

显然,有了先驱们的成功案例,作为开源软件参与者,不论是企业还是个人,都可能名利双收。

IT企业为何要参与开源项目?

作为企业,参与或者主导一个开源项目,其最为明显的动力应该是上述的第四个商业模式,即打造一个平台型项目。但就中国的IT企业来讲,我尚未看到有此种实力,或者此种抱负的企业存在,毕竟,打造一个平台需要长期的投入,一般情况需要五年或更长时间。貌似中国没有一个企业有这个耐心来投入五年这么长的时间在一个项目上。

那为什么企业还要参与到开源软件的开发中呢?我认为,谋不了大利就谋点小利,企业主导或参与开源软件,至少有以下几个好处。

  • 提高企业的美誉度。在利用开源项目的同时,也参与到开源项目中,企业的美誉度会得到很大提升。
  • 员工更有激情。因为自己的作品能够公之于众,虽然著作权本质上属于企业,但作为实际的编码者,可以通过开源自己的作品来获得额外的成就感和满足感。这对于稳定开发团队、提高开发人员的积极性会有很大的帮助。

当然,也许过不了几年,中国也能出现实践第四种商业模式的大型IT企业,让我们拭目以待吧!


个人开发者如何利用开源项目获益?

如果你是一名开源软件的开发者,打算利用自己的软件开创一家软件公司,该如何做?第一,我们要确定好自己的商业模式;第二,为自己的开源软件选择恰当的许可证。

如果决定选择双许可证模式,应选择GPL这样较为严格的许可证,它是这种商业模式能够成功的基础。当然,选择双许可证会阻碍产品在商业用户中的推广。尤其是对初生的开源项目来讲,显然是一种两难的境地。MiniGUI之所以可以采用双许可证模式,是因为在成立公司之前和最初的一段时间内,MiniGUI采取的是LGPL许可证,之后在软件足够成熟时才改为GPL许可证。另外,MiniGUI用于功能手机等系统中时,因为这种设备一般使用实时操作系统,缺乏应用LGPL/GPL许可证的技术条件,所以面向这种设备收取许可费也是天经地义的事情。MySQL采用双许可证模式得以成功的原因在于,MySQL AB公司并不会对仅仅用于Web服务器的MySQL商用行为收费,因为这种情况下,商业用户并不会发布MySQL的副本—它只是在服务器上运行而已。

因此,看起来上面提到的第二种、第三种商业模式是最适合个人开发者或者初创公司的商业模式,能够很快地速度推广和迭代软件本身,还能够确保有足够的收入来保证下一步的发展。在这种模式下,应该选择较为宽松的许可证。但大部分开源软件作者,由于并不真正理解开源软件的许可证,所以采取了错误的许可证(指在法律上是错误的)。例如RT-Thread,一方面采用GPL V2许可证,另一方面又承诺不会对商业使用收费。这其实没有解决根本的法律问题,即使用RT-Thread开发的衍生作品,到底要不要遵循GPL?这个问题和是否收费没有直接关系。要解决这个问题很简单,采用类似ApacheBSD或者MIT许可证即可。有读者会问,那为什么不能采用LGPL许可证?就RT-Thread这样的软件来讲,采用LGPLGPL没有本质的区别,因为RT-Thread的应用场合下一般不支持函数库的动态链接,这导致失去了适用LGPL许可证的技术条件。

上面提到的最后一种模式,是否适用于个人开发者或者初创公司呢?我的答案是,这种模式是大公司的玩法,小团队或小公司没法做这类事情。

大专院校应该成为开源软件的主力军

一个有趣的现象是,很多开源项目其实是作者在大专院校或者研究机构工作或学习时发起的,比如本文提到的三个国内早期的开源项目。甚至某些开源项目由特定的大学主持和维护,如BSD操作系统、PostgreSQL关系数据库、Minix操作系统等。

从国际视角看,开源软件的发展离不开一些知名大学的参与,BSDMIT许可证分别由加州大学伯克利分校和麻省理工学院定义,并由两所大学在其众多开源软件中使用,也被其他开源软件广泛应用。值得一提的是,苹果公司Mac操作系统和iOS操作系统,均使用了加州大学伯克利分校开发的BSD操作系统内核。

从现实情况看,在职的程序员,除非因为供职单位支持,否则很难独立发起和维护一个大型的开源项目,但在大专院校和科研机构工作的老师和学生,则有得天独厚的条件(主要是有大量的时间,并可能与科研课题和教学任务相结合)来发起和持续维护一个开源项目。清华大学陈渝副教授主持的SkyEyeucore两个开源项目就是典型的案例。笔者希望国内有更多的大专院校和科研单位(尤其是教师)能够积极参与到开源项目的发展当中,并成为国内开源项目的主力军。



政府和开源社区应该做什么?

在促进开源项目的发展中,政府要做的就是制定公平、合理的规则,促进相关法律法规的完善。如果知识产权保护力度不够,不仅会阻碍软件产业的发展,也会阻碍开源项目的发展。此外,需要政府支持建立以支持开源项目为己任的非营利性基金会组织。

加大知识产权的保护力度,一方面可以让商业软件在传统贩卖软件使用许可的商业模式下得到良性发展的机会,另一方面可以促使一部分人使用免费的开源软件,进而促进开源软件的发展。

就现阶段而言,如果政府能设立一些奖励基金等奖项,给开源项目的作者以一些奖励,也是不错的支持途径。

开源项目应该以松散、自组织的形式开发和发展,开源社区的存在,为开源软件开发者和使用者提供赖以生存的土壤。开源社区可以是网站、论坛,也可以是松散的交流、展演等。当然,开源社区第一步要解决的问题就是自己的生存问题。

我的建议是,开源社区应该尝试在现有法律框架下,以有限责任公司的形式来做国外开源基金会所做的工作。通过这种方式,可以有效避免无法注册NGO组织的问题,然后从企业(尤其是那些大型互联网企业)当中募集捐款,通过赞助一些开源项目,逐步推进开源软件社区的良性发展。

另外,国内开源社区还需要从使用者社区转向开发者社区,为开发者参与开源软件提供便利,如建立类似GitHub/SourceForge那样的开源软件托管站点,为开源软件项目提供邮件列表、论坛、博客服务等。



结语

将开源项目和商业结合,不管是在自己的项目中使用开源项目,还是靠自己的开源项目来赚钱,都无可厚非。关键是,我们需要尊重开源软件著作权的拥有者,按照开源软件所采纳的许可证办事,只有这样,开源软件才能得到长足发展。合法使用开源软件的前提,就是遵守开源软件的许可证规定的各种义务。

当然,更有积极意义的参与开源项目的方式是,将使用开源软件中遇到的问题或者修正、增强代码提交给开源软件的作者,帮助其改善作品。其实,这是任何使用开源项目的企业和个人都能做到的。

从技术到管理:思维转变是关键

IT公司研发部门的管理人员大多是从公司内部的技术人员中提拔的。在快速发展的公司里,这样的机会更多。然而这种“半路出家”的转型也给我们带来了很多挑战,其中最关键的部分在于思维方式的转变。

从个人成就到团队成就。无论是做管理还是做技术,成就导向意识是优秀员工的基本素质。只有具备很强的成就导向意识,才能把事情做得超预期,才能追求卓越。


刚刚上任的管理人员的思维方式往往还处于个人成就导向阶段,他们希望向外界发出一个明确的信号,团队之所以取得这样的成绩或者解决某个难题,是因为我的组织和领导。然而这种信号被团队成员多次接到后,会产生功劳都被领导拿走的感觉,从而导致团队的向心力下降。

这 时,比较好的做法是:要保护团队成员的成就导向,并且进行鼓励,从而刺激大家的积极性。例如,与某个团队成员共同解决了某个难题后,要弱化自己,重点表扬 这个团队成员对问题的贡献。这样再遇到某个难题时,这个团队成员才能保持一样或更高的激情。只有将自己的成就感定位在团队成就上,才能站得更高,避免和团 队成员产生直接竞争,从而有效地领导自己的团队。

上下同欲的氛围。兵法有云:“上下同欲者胜”。一个团队能够健康运作的基础就是“上下同欲”的氛围。要想拥有这种氛围,必须处理好两件事情:发言权和信息透明。

发言权:每个人都希望发表自己对某件事情的看法,尤其是比较关键的事情,并获得聆听。如果管理人员屏蔽这些,所表达的就是一种不尊重。当然不是所有的意见都要被采纳,需要需要合理的决策,但要让大家有发言的机会。

信息透明:这里的信息包括一切可以公开的信息,如上级期望和项目进展等。保持这些信息的透明度,能够提高团队成员对团队绩效的关注度和荣辱感。当大家都站在团队的高度上思考问题时,能够省去很多协调工作。

转型到管理岗位后,就要多花些时间来考虑团队建设问题。只有团队的氛围比较好,才有机会取得较好的成绩。

合理计划,要事第一。刚刚转型的管理人员往往会有类似这样的抱怨“杂事太多,被不停地打断”。造成这一问题的很大部分原因在于,计划不够周全或者缺乏例行 沟通机制。例如,每日站立例会基本上可以消除很多这样的杂事。同时因为管理人员需要接触的人比较多,所以日常处理的事情也会比较多。这与做技术人员有很大 不同。

这时就要有非常合理的计划,保证要事被及时处理。需要注意的是,时间的急迫性往往会夸大事情的重要性。如果管理人员总是习惯将任务拖到最后的截止时间处理,则会打乱事情的优先级,导致做事失去计划性。

培养人才,用人所长。杰克•韦尔奇说过:“在你成为领导之前,成功只同自己的成长有关。当你成为领导之后,成功同别人的成长有关。” 管理人员要把培养下属作为一件重要的事情,只有团队里的人才层出不穷,团队才有能力去不断挑战更高的目标。用人所长则指在工作的安排过程中需要多关注下属 的长处,不能过度放大他们的缺点。正所谓“用人所长,天下无不用之人;用人所短,天下无可用之人”。人事任命需谨慎考虑,用对一个人,能省很多心;用错一 个人,要操很多心。将合适的人放到合适的位置,是管理人员必须面对的一个难题。

2012,当我们谈论移动互联网创业时,我们在谈论些什么?

2012年的移动互联网市场可以用“冰火两重天”来形容。

根据Google官方数据,Android设备激活量在2012 年3-6月4个月内,由3亿部增长至4亿部,增长率为33%。据苹果官方数字,iOS设备激活量从2012年4-6月由3.6亿部增长至4.1亿部,增长 了12%。而对于中国市场,根据友盟的数据,2012年第二季度Android App启动次数增长159%;iOS活跃设备增长42%,iOS App启动次数增长112%。 这些数字都表明了移动互联网用户和终端量在2012年仍在高速增长。

但另一方面,移动互联网创业之路却愈发举步维艰:同质化竞争加剧,推广成本攀升,盈利模式迟迟未能清晰,投资者的钱也烧得差不多了……

但移动互联网始终是座巨大的宝藏,吸引着无数人甘愿冒险探寻。那么当前,如何度过寒冬,成功地求生是每个创业者、投资人都在思考的问题。本文中我将列举几个2012年移动互联网创业的关键点进行讨论,内容仅供引发思考,不做结论。


创业机会在哪里?

洗牌前期,巨头们开始以各种方式大肆进驻。一方面是以腾讯为代表的巨头正在进行全面的软件布局。目前腾讯已推出了几十款覆盖各个平台的App,涵盖了社交、 浏览、订阅、输入、同步、安全、音乐、游戏、阅读等领域,以强大的资金、渠道和人才优势与大批创业者直接竞争。另一方面,百度、阿里巴巴、奇虎360、盛 大等公司开始竞相推出搭载自己定制的操作系统的手机,抢占移动互联网的入口……

如果比拼渠道、资金和对人才的吸引,小公司毫好无胜算。因 此,在巨头驻足的通用领域,采取与巨头直接竞争的方式异常艰难。那么,在这种环境下创业者在创新方向选择时可能需要考虑“垂直化”和“行业化”,更多地去 挖掘那些还未被发现或者巨头没有兴趣去做的细分市场。在游戏、SoLoMo、O2O、移动电商、儿童教育等直接可以从消费者手上收钱的领域都有机会,在整 个行业的真实收入迅速攀升的基础上,移动广告、开发工具、各种外包等周边产业也会迎来相应的繁荣,与之相关的风险投资、孵化器、财务、法务、媒体、人力资 源等领域也会被拉动,各种企业的移动化也需要“行业化”应用的推动。在这些方向上,都尚未出现真正集大成、占据绝对优势的产品,如果能做出好产品加上合适 的分发渠道,创业者仍然有机会。

同时“硬件化”也是一个选择方向。随着中国二三线城市智能手机的普及,智能手机的细分市场也开始成型,针对 不同性别、层级、年龄段消费者的手机需要配套的软件和系统定制,因此这个层面上创业者与厂商间的软硬整合合作也存在一定的机会,当然,其中还包括平板、智 能电视等领域。

Native App还是Web App?

记得2011年时,Web App的概念大行其道,同时伴随着Adobe Flash Player的诸多不利消息,一时间HTML5被一些人捧上了制高点。但近期,Flash产品(首当其冲是游戏)开始全面爆发。依靠着Adobe AIR、Stage 3D等强大技术的布局,移动设备上开始涌现大量高品质的Flash游戏。而HTML5却从云端跌回残酷的现实:HTML5移动游戏领域的早期探索者 Moblyng倒闭,Mark Zuckerburg亲口承认Facebook的HTML5战略是个错误,Chrome Web Store里面力推的游戏表现都不甚理想……由于表现能力不足,自身标准一直未确定,并且缺少Web App分发和盈利的渠道,导致HTML5阵营中并未出现拿得出手的成功案例。也许就像一位开发者曾经说过那样:“HTML5是未来的趋势,但不是现在的优 势。”

毫无疑问,每种技术方案都各自有其优劣之处,必须要根据实际情况灵活选择。例如对于许多交互不多的传统内容型网站来说,HTML5已 基本可以覆盖全部需求。但在目前Web App受限于浏览器或前端技术未标准化的情况下,开发者可以考虑进行组合应用,对于侧重性能、体验、设备特性、本地数据管理等HTML5表现力达不到的部 分用Native来做,HTML5表现力能达到的部分就用HTML5来做。

总的来说,开发者应该掌握并提前布局多种技术,不能在一棵树上吊死。

最好的盈利模式?

无论怎样,成功不是一时半会儿的事,“活下去”是当前最重要的话题。由于投资锐减,创业者需要更多、更早地去考虑盈利问题。其实目前的移动互联网有一系列的盈利模式可供开发人员选择:

  • Pay-Per-Download。下载支付,为获得App使用权一次性支付费用。
  • In-App Purchasing。应用内购买,通常是一些应用的功能、提升游戏等级以及虚拟商品,目前是大陆最容易获得高收入的模式。
  • Subscriptions。订阅,一般是逐月为App付费,《程序员》杂志等阅读类App通常会采取这一模式。
  • Freemium。免费下载,提供增值付费服务,在Evernote等工具类应用中常见。
  • Commissioned Applications。提供外包服务。
  • In-App Advertising。App内展示广告模式和传统互联网的广告模式十分接近,被开发者大量使用,但效果渐减。
  • Product Placement。植入式广告,例如在游戏中的某一道具就是某品牌的饮料。
  • Purchase Intermediation。为从第三方App中带来的流量或其他资源拿到分成,但在大陆也常常演变为资源、流量互换。
  • Per-unit royalties。通常是与终端厂商和各大平台合作,例如厂商为手机上预装付费等。
  • Distribution Exclusivity Deals。针对独家应用商店发部应用,前段时间Rovio的《Amazing Alex》通过应用汇发布时似乎就采用了这种模式。

在 2012年6月VisionMobile对全球1500名创业者的调查中发现,Pay-Per-Download是当前最频繁使用的盈利模式。共有34% 的创业者选择了这种方式,较2011年相比略有下降。紧随其后的就是In-App Advertising,占33%。而从今年起,In-App Purchasing模式开始火热,已跻身高回报的收益模式之一。

但创业者需要明白,没有最好的模式,只有最适合的模式。而选择标准往往取 决于他们的产品模型、规模和目标市场。例如在大陆,游戏用户很难为一款未知的游戏下载付费,因此In-App Purchasing在今年大肆流行。而对于一些理财类工具,用户反而愿意付费来选择高品质的产品来保证自己的安全和隐私。同时,对于同一款产品,在不同 阶段“盈利模式”也可以转型,《Angry Birds》就是最好的例子,在长期霸占App收费榜前排位置之后,随着新产品的推出和游戏生命周期到来,小鸟们已从排行榜上跌落,却找到了更为稳健的盈 利模式:其周边产品和授权费为其带来了丰厚的回报,当然在大陆这种模式可能会被山寨得让人吐血。

生态系统困境

再好的产品也需要依靠良好的分发渠道和健全的市场,可2012年的中国移动互联网生态系统可谓满目疮痍,大部分开发者都多多少少面对迷局。对于中国开发者而言,山寨术依然是亘古不变的话题,而在这之外,新的问题接踵而来。

App Store一度帮助苹果打造了最优秀的移动生态系统。但2012年的种种迹象表明,这片生态系统似乎正在遭受侵蚀。刷榜问题日益严重,在2012年3月 时,App Store曾经采用技术更新的方式阻止刷榜,但也默认了对之前刷榜严重的公司不追究。果不其然,苹果的这种“不作为”态度让新算法仅见效2个多月,一股新 的刷榜风潮就开始愈演愈烈。有开发者认为苹果应该像Google Play那样摆出“令可错杀一千,不可放过一个”的态度,然假设如此,想必肯定会有无良对手花钱帮你“刷榜”,让你欲哭无泪。

同样,在 Android的第三方市场,刷榜也是同样泛滥。因此,有许多国内的开发者和媒体开始曝光和谴责这些产品。但从市场层面来看,这种影响并不会波及到消费 者,倘若刷榜风险和成本极小,加上一些投资人“有钱赚,怎么赚都是赚”的纵容态度,那么必定会有更多的人铤而走险。

除此之外,App Store审核周期常常是漫长且毫无规律可循;去对手产品下面刷差评;有程序员直接拿别人游戏安装包破解反编译加入自己的广告账号,放渠道上偷广告流 量……开发者不仅要注意暴风雨和暗礁,还需要迎战其他船只的攻击,移动互联网生态圈的困局还有多久才能解开?

不过在2012年9月17日,App Store出现7小时的“锁榜”现象(指整个榜单全部锁住,排名几乎不动,偶尔有一两名上下的波动只是因为某些限免App到期,从免费应用榜单下架所 致)。这个情况与2012年3月20日(上一轮排名算法完全改变的前2天)出现的7小时锁榜现象如出一辙。因此,有人预测排名算法即将再次大调整,希望会 带来一些积极有效的变革。

走向海外?

虽然有一些应用在中国也取得了不错的成绩,但暂时而言,大陆终归是付费意愿较低的市场,并且还有着前文提到的各种恶劣的竞争环境,在此状况下,走“国际化” 战略似乎是个不错的选择。实际上,如今中国移动互联网的很多明星团队已走向海外、专注海外甚至如《海豚浏览器》这样“来自海外”。

成功者固然令人艳羡,但成功的路却并非所见即所得。作为一个统称,海外市场实际上被细分成很多个不同的市场:欧美市场、日本市场、韩国市场、拉美市场、东南亚市 场……每个市场都依靠语言、文化、渠道特色、市场机制等地域特点建立了壁垒,倘若没有找对法门,可能不仅没有找到宝藏,反而撞得头破血流。简单地以日本市场为例,虽然其ARPU值非常高,但日本市场的用户口味与其他国家有很大区别,盈利主要来 自卡牌游戏,而且日本用户对于美术画风、各种细节的要求非常高(例如相比其他亚洲市场,欧美风格的产品可能更受欢迎)。

另外,也不是所有的产品都适合走向海外。很多产品一开始就拥有中国市场的基因,离开这个环节与其他本土产品竞争,很可能水土不服。在近期我采访的几位开发者中,他们在谈到海外市场时纷纷谈到中国团队的技术优势,看来这一点是每个想要异国求生的团队必须具备的素质。