存档

‘只谈技术’ 分类的存档

完美解决nginx环境下服务器上多站点WebShell访问限制问题

2011年7月6日 没有评论

完美解决nginx环境下服务器上多站点WebShell访问限制问题

http://www.discuz.net/thread-1497466-1-1.html


wget http://www.php.net/get/php-5.2.10.tar.gz/from/this/mirror
wget http://php-fpm.org/downloads/php-5.2.10-fpm-0.5.13.diff.gz
tar zxvf php-5.2.10.tar.gz
gzip -cd php-5.2.10-fpm-0.5.11.diff.gz | patch -d php-5.2.10 -p1
cd php-5.2.10/
./configure --prefix=/usr/local/php --with-config-file-path=/usr/local/php/etc --with-mysql=/usr/local/mysql --with-mysqli=/usr/local/mysql/bin/mysql_config --with-iconv-dir=/usr/local --with-freetype-dir --with-jpeg-dir --with-png-dir --with-zlib --with-libxml-dir=/usr --enable-xml --disable-rpath --enable-discard-path --enable-safe-mode --enable-bcmath --enable-shmop --enable-sysvsem --enable-inline-optimization --with-curl --with-curlwrappers --enable-mbregex --enable-fastcgi --enable-fpm --enable-force-cgi-redirect --enable-mbstring --with-mcrypt --with-gd --enable-gd-native-ttf --with-openssl --with-mhash --enable-pcntl --enable-sockets --with-xmlrpc --enable-zip --enable-ftp --without-pear


vi main/fopen_wrappers.c


/* {{{ php_check_open_basedir
*/
PHPAPI int php_check_open_basedir_ex(const char *path, int warn TSRMLS_DC)
{
/* Only check when open_basedir is available */
if (PG(open_basedir) && *PG(open_basedir)) {
char *pathbuf;
char *ptr;
char *end;

下面加上:
char *env_document_root = sapi_getenv("DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT")-1 TSRMLS_CC);
if (php_check_specific_open_basedir(ptr, path TSRMLS_CC) == 0) {
efree(env_document_root);
return 0;
}

然后保存,退出。

php.in的open_basedir配置:
修改:
;open_basedir =

open_basedir = “/tmp/:/var/tmp/”

重启
/usr/local/php/sbin/php-fpm restart

如何安全的去除Nginx服务器的版本号

2011年3月11日 没有评论

http {
……省略配置
sendfile on;
tcp_nopush on;
keepalive_timeout 65;
tcp_nodelay on;
server_tokens off;
…….省略配置
}
重启nginx /usr/local/webserver/nginx/bin/nginx -s reload

这是我的nginx+tomcat服务器上执行前后的对比结果
[root@localhost ~]# curl –head 127.0.0.1
HTTP/1.1 403 Forbidden
Server: nginx/0.8.46
Date: Fri, 11 Mar 2011 08:26:51 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 169
Connection: keep-alive

[root@localhost ~]# /usr/local/webserver/nginx/sbin/nginx -s reload
[root@localhost ~]# curl –head 127.0.0.1
HTTP/1.1 403 Forbidden
Server: nginx
Date: Fri, 11 Mar 2011 08:26:58 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 162
Connection: keep-alive

如果服务器跑的是nginx+php-fpm,这时候需要编辑php-fpm配置文件 如fcgi.conf、fastcgi.conf(要看你是什么配置文件名),久违的403报错,看看,有没有nginx版本泄露的信息:

fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
改为fastcgi_param SERVER_SOFTWARE nginx;

记得平滑重启下 平滑重启:
/usr/local/webserver/nginx/sbin/nginx -s reload

转自:http://hi.baidu.com/yuhongchun027/blog/item/a4b25f774db3620fb051b993.html

分类: nginx相关 标签:

[转]基于SSD的数据库性能优化

2011年2月22日 没有评论

NOR和NAND

NOR和NAND都是闪存技术的一种,NOR是Intel公司开发的,它有点类似于内存,允许通过地址直接访问任何一个内存单元,缺点是:密度低 (容量小),写入和擦除的速度很慢。NAND是东芝公司开发的,它密度高(容量大),写入和擦除的速度都很快,但是必须通过特定的IO接口经过地址转换之 后才可以访问,有些类似于磁盘。

我们现在广泛使用的U盘,SD卡,SSD都属于NAND类型,厂商将flash memory封装成为不同的接口,比如Intel的SSD就是采用了SATA的接口,访问与普通SATA磁盘一样,还有一些企业级的闪存卡,比如FusionIO,则封装为PCIe接口。

SLC和MLC

SLC是单极单元,MLC是多级单元,两者的差异在于每单元存储的数据量(密度),SLC每单元只存储一位,只包含0和1两个电压符,MLC每单元 可以存储两位,包含四个电压符(00,01,10,11)。显然,MLC的存储容量比SLC大,但是SLC更简单可靠,SLC读取和写入的速度都比MLC 更快,而且SLC比MLC更耐用,MLC每单元可擦除1w次,而SLC可擦除10w次,所以,企业级的闪存产品一般都选用SLC,这也是为什么企业级产品 比家用产品贵很多的原因。

SSD的技术特点

SSD与传统磁盘相比,第一是没有机械装置,第二是由磁介质改为了电介质。在SSD内部有一个FTL(Flash Transalation Layer),它相当于磁盘中的控制器,主要功能就是作地址映射,将flash memory的物理地址映射为磁盘的LBA逻辑地址,并提供给OS作透明访问。

SSD没有传统磁盘的寻道时间和延迟时间,所以SSD可以提供非常高的随机读取能力,这是它的最大优势,SLC类型的SSD通常可以提供超过 35000的IOPS,传统15k的SAS磁盘,最多也只能达到160个IOPS,这对于传统磁盘来说几乎就是个天文数字。SSD连续读的能力相比普通磁 盘优势并不明显,因为连续读对于传统磁盘来说,并不需要寻道时间,15k的SAS磁盘,连续读的吞吐能力可以达到130MB,而SLC类型的SSD可以达 到170-200MB,我们看到在吞吐量方面,SSD虽然比传统磁盘高一些,但优势虽然并不明显。

SSD的写操作比较特殊,SSD的最小写入单元为4KB,称为页(page),当写入空白位置时可以按照4KB的单位写入,但是如果需要改写某个单 元时,则需要一个额外的擦除(erase)动作,擦除的单位一般是128个page(512KB),每个擦除单元称为块(block)。如果向一个空白的 page写入信息时,可以直接写入而无需擦除,但是如果需要改写某个存储单元(page)的数据,必须首先将整个block读入缓存,然后修改数据,并擦 除整个block的数据,最后将整个block写入,很显然,SSD改写数据的代价很高,SSD的这个特性,我们称之为erase-before- write。

经过测试,SLC SSD的随即写性能可以达到3000个左右的IOPS,连续写的吞吐量可以达到170-200MB,这个数据还是比传统磁盘高出不少。但是,随着SSD的 不断写入,当越来越多的数据需要被改写时,写的性能就会逐步下降。经过我们的测试,SLC在这个方面要明显好于MLC,在长时间写入后,MLC随机写IO 下降得非常厉害,而SLC表现则比较稳定。为了解决这个问题,各个厂商都有很多策略来防止写性能下降的问题。

wear leveling

因为SSD存在“写磨损”的问题,当某个单元长时间被反复擦写时(比如Oracle redo),不仅会造成写入的性能问题,而且会大大缩短SSD的使用寿命,所以必须设计一个均衡负载的算法来保证SSD的每个单元能够被均衡的使用,这就 是wear leveling,称为损耗均衡算法。

Wear leveling也是SSD内部的FTL实现的,它通过数据迁移来达到均衡损耗的目的。Wear leveling依赖于SSD中的一部分保留空间,基本原理是在SSD中设置了两个block pool,一个是free block pool(空闲池),一个是数据池(data block pool),当需要改写某个page时(如果写入原有位置,必须先擦除整个block,然后才能写入数据),并不写入原有位置(不需要擦除的动作),而是 从空闲池中取出新的block,将现有的数据和需要改写的数据合并为新的block,一起写入新的空白block,原有的block被标识为 invalid状态(等待被擦除回收),新的block则进入数据池。后台任务会定时从data block中取出无效数据的block,擦除后回收到空闲池中。这样做的好处在于,一是不会反复擦写同一个block,二是写入的速度会比较快(省略了擦 除的动作)。

Wear leveling分为两种:动态损耗均衡和静态损耗均衡,两者的原理一致,区别在于动态算法只会处理动态数据,比如数据改写时才会触发数据迁移的动作,对 静态数据不起作用,而静态算法可以均衡静态数据,当后台任务发现损耗很低的静态数据块时,将其迁移到其他数据库块上,将这些块放入空闲池中使用。从均衡的 效果来看,静态算法要好于动态算法,因为几乎所有的block都可以被均衡的使用,SSD的寿命会大大延长,但是静态算法的缺点是当数据迁移时,可能会导 致写性能下降。

写入放大

因为SSD的erase-before-write的特性,所以就出现了一个写入放大的概念,比如你想改写4K的数据,必须首先将整个擦除块(512KB)中的数据读出到缓存中,改写后,将整个块一起写入,这时你实际写入了512KB的数据,写入放大系数是128。写入放大最好的情况是1,就是不存在放大的情况。

Wear leveling算法可以有效缓解写入放大的问题,但是不合理的算法依然会导致写入放大,比如用户需要写入4k数据时,发现free block pool中没有空白的block,这时就必须在data block pool中选择一个包含无效数据的block,先读入缓存中,改写后,将整个块一起写入,采用wear leveling算法依然会存在写入放大的问题。

通过为SSD预留更多空间,可以显著缓解写入放大导致的性能问题。根据我们的测试结果,MLC SSD在长时间的随机写入后,性能下降很明显(随机写IOPS甚至降低到300)。如果为wear leveling预留更多空间,就可以显著改善MLC SSD在长时间写操作之后的性能下降问题,而且保留的空间越多,性能提升就越明显。相比较而言,SLC SSD的性能要稳定很多(IOPS在长时间随机写后,随机写可以稳定在3000 IOPS),我想应该是SLC SSD的容量通常比较小(32G和64G),而用于wear leveling的空间又比较大的原因。

数据库IO特点分析

IO有四种类型:连续读,随机读,随机写和连续写,连续读写的IO size通常比较大(128KB-1MB),主要衡量吞吐量,而随机读写的IO size比较小(小于8KB),主要衡量IOPS和响应时间。数据库中的全表扫描是连续读IO,索引访问则是典型的随机读IO,日志文件是连续写IO,而 数据文件则是随机写IO。

数据库系统基于传统磁盘访问特性来设计,最大特点是日志文件采用sequential logging,数据库 中的日志文件,要求必须在事务提交时写入到磁盘,对响应时间的要求很高,所以设计为顺序写入的方式,可以有效降低磁盘寻道花费的时间,减少延迟时间。日志 文件的顺序写入,虽然是物理位置是连续的,但是并不同于传统的连续写类型,日志文件的IO size很小(通常小于4K),每个IO之间是独立的(磁头必须抬起来重新寻道,并等待磁盘转动到相应的位置),而且间隔很短,数据库通过log buffer(缓存)和group commit的方式(批量提交)来达到提高IO size的大小,并减少IO的次数,从而得到更小的响应延迟,所以日志文件的顺序写入可以被认为是“连续位置的随机写入”,瓶颈还是在IOPS,而不是吞吐量。

数据文件采用in place update的方式,意思是数据文件的修改都是写入到原来的位置,数据文件不同 于日志文件,并不会在事务commit时写入数据文件,只有当数据库发现dirty buffer过多或者需要做checkpoint动作时,才会刷新这些dirty buffer到相应的位置,这是一个异步的过程,通常情况下,数据文件的随机写入对IO的要求并不是特别高,只要满足checkpoint和dirty buffer的要求就可以了。

SSD的IO特点分析

1.随机读能力非常好,连续读性能一般,但比普通SAS磁盘好。

2.不存在磁盘寻道的延迟时间,随机写和连续写的响应延迟差异不大。

3.erase-before-write特性,造成写入放大,影响写入的性能。

4.写磨损特性,采用wear leveling算法延长寿命,但同时会影响读的性能。

5.读和写的IO响应延迟不对等(读要大大好于写),而普通磁盘读和写的IO响应延迟差异很小。

6.连续写比随机写性能好,比如1M顺序写比128个8K的随即写要好很多,因为随即写会带来大量的擦除。

基于SSD的上述特性,如果将数据库全部放在SSD上,可能会有以下的问题:

1.日志文件sequential logging会反复擦写同一位置,虽然有损耗均衡算法,但是长时间写入依然会导致性能下降。

2.数据文件in place update会产生大量的随机写入,erase-before-write会产生写入放大。

3.数据库读写混合型应用,存在大量的随机写入,同时会影响读的性能,产生大量的IO延迟。

基于SSD的数据库优化法则

基于SSD的优化就是解决erase-before-write产生的写入放大的问题,不同类型的IO分离,减少写操作带来的性能影响。

1.将sequential logging修改为In-page logging,避免对相同位置的反复擦写。

2.通过缓存写入的方式将大量的in-place update随机写入合并为少量顺序写入。

3.利用SSD随机读写能力高的特点,减少写增加读,从而达到整体性能的提升。

In-page logging

In-page logging是基于SSD对数据库sequential logging的一种优化方法,数据库中的sequential logging对传统磁盘是非常有利的,可以大大提高响应时间,但是对于SSD就是噩梦,因为需要对同一位置反复擦写,而wear leveling算法虽然可以平衡负载,但是依然会影响性能,并产生大量的IO延迟。所以In-page logging将日志和数据合并,将日志顺序写入改为随机写入,基于SSD对随机写和连续写IO响应延迟差异不大的特性,避免对同一位置反复擦写,提高整 体性能。

In-page logging基本原理:在data buffer中,有一个in-memory log sector的结构,类似于log buffer,每个log sector是与data block对应的。在data buffer中,data和log并不合并,只是在data block和log sector之间建立了对应关系,可以将某个data block的log分离出来。但是,在SSD底层的flash memory中,数据和日志是存放在同一个block(擦除单元),每个block都包含data page和log page。

当日志信息需要写入的时候(log buffer空间不足或者事务提交),日志信息会写入到flash memory对应的block中,也就是说日志信息是分布在很多不同的block中的,而每个block内的日志信息是append write,所以不需要擦除的动作。当某个block中的log sector写满的时候,这时会发生一个动作,将整个block中的信息读出,然后应用block中的log sector,就可以得到最新的数据,然后整个block写入,这时,block中的log sector是空白的。

在in-page logging方法中,data buffer中的dirty block是不需要写入到flash memory中的,就算dirty buffer需要被交换出去,也不需要将它们写入flash memory中。当需要读取最新的数据,只要将block中的数据和日志信息合并,就可以得到最新的数据。

In-page logging方法,将日志和数据放在同一个擦除单元内,减少了对flash相同位置的反复擦写,而且不需要将dirty block写入到flash中,大量减少了in-place update的随机写入和擦除的动作。虽然在读取时,需要做一个merge的操作,但是因为数据和日志存放在一起,而且SSD的随机读取能力很高,in- page logging可以提高整体的性能。

SSD作为写cache—append write

SSD可以作为磁盘的写cache,因为SSD连续写比随机写性能好,比如:1M顺序写比128个8K的随机写要好很多,我们可以将大量随机写合并 成为少量顺序写,增加IO的大小,减少IO(擦除)的次数,提高写入性能。这个方法与很多NoSQL产品的append write类似,即不改写数据,只追加数据,需要时做合并处理。

基本原理:当dirty block需要写入到数据文件时,并不直接更新原来的数据文件,而是首先进行IO合并,将很多个8K的dirty block合并为一个512KB的写入单元,并采用append write的方式写入到一个cache file中(保存在SSD上),避免了擦除的动作,提高了写入性能。cache file中的数据采用循环的方式顺序写入,当cache file空间不足够时,后台进程会将cache file中的数据写入到真正的数据文件中(保存在磁盘上),这时进行第二次IO合并,将cache file内的数据进行合并,整合成为少量的顺序写入,对于磁盘来说,最终的IO是1M的顺序写入,顺序写入只会影响吞吐量,而磁盘的吞吐量不会成为瓶颈, 将IOPS的瓶颈转化为吞吐量的瓶颈,从而提升了整体系统能力。

读取数据时,必须首先读取cache file,而cache file中的数据是无序存放的,为了快速检索cache file中的数据,一般会在内存中为cache file建立一个索引,读取数据时会先查询这个索引,如果命中查询cache file,如果没有命中,再读取data file(普通磁盘),所以,这种方法实际不仅仅是写cache,同时也起到了读cache的作用。

SSD并不适合放数据库的日志文件,虽然日志文件也是append write,但是因为日志文件的IO size比较小,而且必须同步写入,无法做合并处理,对SSD来说,需要大量的擦除动作。我们也曾经尝试把redo log放在SSD上,考虑到SSD的随机写入也可以达到3000 IOPS,而且响应延时比磁盘低很多,但是这依赖于SSD本身的wear leveling算法是否优秀,而且日志文件必须是独立存放的,如果日志文件的写入是瓶颈,也算是一种解决方案吧。通常情况下,我还是建议日志文件放在普 通磁盘上,而不是SSD。

SSD作为读cache—flashcache

因为大部分数据库都是读多写少的类型,所以SSD作为数据库flashcache是优化方案中最简单的一种,它可以充分利用SSD读性能的优势,又 避免了SSD写入的性能问题。实现的方法有很多种,可以在读取数据时,将数据同时写入SSD,也可以在数据被刷出buffer时,写入到SSD。读取数据 时,首先在buffer中查询,然后在flashcache中查询,最后读取datafile。

SSD作为flashcache与memcache作为数据库外部cache的最大区别在于,SSD掉电后数据是不丢失的,这也引起了另外一个思 考,当数据库发生故障重启后,flashcache中的数据是有效还是无效?如果是有效的,那么就必须时刻保证flashcache中数据的一致性,如果 是无效的,那么flashcache同样面临一个预热的问题(这与memcache掉电后的问题一样)。目前,据我所知,基本上都认为是无效的,因为要保 持flashcache中数据的一致性,非常困难。

flashcache作为内存和磁盘之间的二级cache,除了性能的提升以外,从成本的角度看,SSD的价格介于memory和disk之间,作为两者之间的一层cache,可以在性能和价格之间找到平衡。

总结

随着SSD价格不断降低,容量和性能不断提升,SSD取代磁盘只是个时间问题。

Tape is Dead,Disk is Tape,Flash is Disk,RAM Locality is King.        Jim Gray

来源:http://www.hellodba.net/2010/10/ssd-database-2.html

分类: 硬件相关 标签: ,

解决编码为gb2312页面ajax交互汉字乱码的问题

2011年1月25日 没有评论

ajax只支持utf-8格式,不能支持gb2312编码格式,所以经常遇到gb2312的编码的程序使用ajax就出现乱码,刚找到一种解决方案是:

服务器端传送的数据仍是gb2312编码,客户端用js将汉字转变成utf8编码显示在页面

search.php

1
2
3
4
<?php
header("Content-type: text/html; charset=gb2312");
include './search.htm';
?>

search.htm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>高级搜索</title>
</head>
<body>
<h3>高级搜索</h3>
<form method="post" action="">
  学校类型:
  <select name="schooltype">
    <option value="">全部</option>
    <option value="1">小学</option>
    <option value="2">初中</option>
  </select>
  学校名称:
  <select name="sid" id="sid">
    <option value="">请选择学校</option>
  </select>
</form>
<script type="text/javascript">
function ajax(settings) {
    var XHR = window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest(), successed = false;
    XHR.open(settings.type, settings.url);
    if(settings.type == 'post')
     XHR.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    XHR.send((!settings.cache ? 'time=' + new Date().getTime() + '&' : '') + settings.data);
    settings.loader();
    setTimeout(function() {
        if(!successed) {
            alert('Resquest timeout!');
            XHR.abort();
        }
    }, settings.timeout);
    XHR.onreadystatechange = function() {
        if (XHR.readyState == 4 && XHR.status == 200) {
            settings.callback(XHR.responseText.replace(/(^\s*)|(\s*$)/g, ""));
        }
        successed = true;
    }
}
function a(t) {
ajax({
  type: 'post',
  url: 'ajax.php',
  data: 'schooltype=' + t,
  timeout: 8000,
  cache: true,
  loader: function() {},
  callback: function(d) {
   var arr = eval(d);
   if(typeof(arr) == 'object') {
    var obj, option;
    document.getElementById('sid').innerHTML = '';
    for(var i = 0; obj = arr; i ++) {
     option = document.createElement('option');
     option.value = obj[0];
     option.innerHTML = txt2utf8(obj[1], '&#');
     document.getElementById('sid').appendChild(option);
    }
   }
  }
})
}
function txt2utf8(string, prefix){
    for(var i=0,utf8=[];i<string.length;utf8.push((prefix||'\\u')+string.charCodeAt(i++)));
    return utf8.join('');
}
a(0);
</script>
</body>
</html>

ajax.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
header("Content-type: text/html; charset=gb2312");
$schooltype = !empty($_POST['schooltype']) ? $_POST['schooltype'] : 0;
switch($schooltype) {
    case 0:
        echo "[['40', '太平溪镇花栗包完全小学'],['41', '太平溪镇长岭黑龙江希望小学'],['42', '乐天溪镇初级中学'],['43', '乐天溪镇莲沱初级中学']]";
        break;
    case 1:
        echo "[['40', '太平溪镇花栗包完全小学'],['41', '太平溪镇长岭黑龙江希望小学']]";
        break;
    case 2:
        echo "[['42', '乐天溪镇初级中学'],['43', '乐天溪镇莲沱初级中学']]";
        break;
    default:
        break;
}
?>

这个提到的方案有:
一,服务器端json数据用php的iconv函数转换:iconv(‘GB2312′, ‘UTF8′, “被转换字符串,输出到浏览器”);
客户端获取UTF8数据,再转成gb2312:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function gb2utf8(data){//GB编码是,ie通过二进制码utf8->gbk转为中文  
     var glbEncode = [];  
     gb2utf8_data = data;  
     execScript("gb2utf8_data = MidB(gb2utf8_data, 1)", "VBScript");  
     var t=escape(gb2utf8_data).replace(/%u/g,"").replace(/(.{2})(.{2})/g|>,"%$2%$1").replace(/%([A-Z].)%(.{2})/g|>,"@$1$2");  
     t=t.split("@");  
     var i=0,j=t.length,k;  
     while(++i<j)>  
         k=t.substring(0,4);  
         if(!glbEncode[k]) {  
             gb2utf8_char = eval("0x"+k);  
             execScript("gb2utf8_char = Chr(gb2utf8_char)", "VBScript");  
             glbEncode[k]=escape(gb2utf8_char).substring(1,6);  
         }  
         t=glbEncode[k]+t.substring(4);  
     }  
     gb2utf8_data = gb2utf8_char = null;  
     return unescape(t.join("%"));  
}

二,header(“Content-type”, “application/x-www-form-urlencoded; charset=GBK”); //输出头标,设置为GBK编码

三,在ajax请求数据前调用上面的方法指定请求使用的字符集:xmlHttp.setRequestHeader( “Content-Type”, “application/x-www-form-urlencoded;charset=gbk”);

分类: php相关, 软件相关 标签:

防盗链技术终极解决方案

2010年12月21日 没有评论

防盗链技术现状:
1、通过识别Referer确认请求来源页面
2、Apache,squid等都能对Referer进行识别
3、通过ActiveX显示的内容不向服务器提供Referer Header(例如,Flash,WindowsMedia视频等)
4、流媒体的RTSP协议也不向服务器提供Referer Header
5、通过服务器端程序代码实现

防盗链应用现状:
1、对图片、HTML等可以实现防盗链
2、无法对Flash,WindowsMedia视频(MMS,RTSP)实现防盗链
3、服务器端程序代码实现的防盗链无法通过CDN加速

对于Flash,WindowsMedia视频这种占用流量较大的服务无法实现防盗链,对一个依靠这类内容作为盈利点的网站来说是非常头疼的,俺通过一些研究以及测试实现了采用Cookie技术的防盗链解决方案,完美的解决了对Flash,WindowsMedia视频的防盗链。

首先发现虽然ActiveX插件不传递Referer,但是却忠实的传递Cookie。于是在显示ActiveX的页面的 标签内嵌入一段代码:

这段代码用 javascript 设置了一段 Cookie: Cache=vod

然后通过各种ACL来判断这个Cookie的存在以及验证其值的操作了

Squid:
建立脚本 /usr/local/squid/libexec/squid_cookie.pl
———–
#!/usr/bin/perl -w
# programmed by oknet http://blog.sina.com.cn/m/oknet
# 这个脚本仅仅是验证了Cache这个cookie的存在,没有严格的校验其值。
# This is the cookie to check for.
$COOKIE=”Cache=”;
# disable output buffering
$|=1;
# cookie matches?
while () {
chop;
$cookie=$_;
if( $cookie =~ /$COOKIE/i) {
print “OK\n”;
} else { print “ERR\n”; }
}
———–
然后在squid.conf添加:
external_acl_type download children=15 %{Cookie} /usr/local/squid/libexec/squid_cookie.pl
acl dl external download
然后选择需要进行防盗链的文件类型:
acl filetype url_regex -i \.wmv
acl filetype url_regex -i \.wma
acl filetype url_regex -i \.asf
acl filetype url_regex -i \.asx
acl filetype url_regex -i \.avi
acl filetype url_regex -i \.mp3
acl filetype url_regex -i \.smi
acl filetype url_regex -i \.rm
acl filetype url_regex -i \.ram
acl filetype url_regex -i \.rmvb
acl filetype url_regex -i \.swf
acl filetype url_regex -i \.mpg
acl filetype url_regex -i \.mpeg
acl filetype url_regex -i \.mov
acl filetype url_regex -i \.zip
acl filetype url_regex -i \.mid
如果仅仅只是禁止用户访问的话,就没意思了,要让盗链者帮我们宣传我们的网站,特别是发现盗链比较多的时候,这个时候,可以让任何盗链的网站帮我们免费宣传~~~那就是把盗链的url重定向到我们的网站宣传页~~
建立脚本:/usr/local/squid/libexec/squid_redir.pl
————————–
#!/usr/bin/perl -T -w
#
# rredir.pl
#
# Author: Peter Eisenhauer # First Version: 26. May 1997
# Modified by oknet http://blog.sina.com.cn/m/oknet
#
# Description: Direct all request to files who are in a local dir to
# this directory
#
use File::Basename;
use URI::URL;
# flush after every print
$| = 1;
# Process lines of the form ‘URL ip-address/fqdn ident method’
# See release notes of Squid 1.1 for details
while ( <> ) {
$r302=0;
($url, $addr, $fqdn, $ident, $method) = m:(\S*) (\S*)/(\S*) (\S*) (\S*):;
$url = url $url;
$host = lc($url->host);
if ( $host !~ /\./ ) {
next;
}
if ( $host =~ /vod\.domain\.com/ ) {
$url->path(“/ad.wmv”);
$r302=1;
}
} continue {
if ( $r302 ) {
print “302:$url\n”;
} else {
print “$url $addr/$fqdn $ident $method\n”;
}
}
————————–
然后在squid.conf添加:
redirect_program /usr/local/squid/libexec/squid_redir.pl
redirect_children 5
acl superurl url_regex -i ^http://vod\.domain\.com/tom\.wmv$
redirector_access deny superurl
redirector_access allow filetype !dl
redirector_access deny all
设置superurl是因为宣传我们自己站点的视频是不做防盗链的,这样才能起到宣传的作用。现在大功告成啦!网站的流量大幅增加~~~PV是原来的三倍,Oh,Yeah~

WMS视频的MMS协议由于不是明文,无法实现防盗链,但是RTSP协议基本就是HTTP协议的变种,可以在BIGIP等可以进行Layer 7处理数据的设备上实现对Cookie的校验。但是WMS视频防盗链要禁止MMS协议,因为MMS协议不是明文,无法进行cookies的识别。但是可以在HTTP,RTSP上进行识别,WMS V9都是支持HTTP,RTSP的。下面是用于BIGIP的防盗链iRule:
————————–
if (http_uri matches_regex “vod.domain.com”) {
if (http_cookie(“Cache”) == “vod”) {
use pool vod-rtsp
}
else {
discard
}
}
else {
use pool vod-rtsp
}
————————–
其他的系统可以参考以上的规则。
采用Cookie的防盗链方式对于大多数的系统都可以轻易实现,Cookie一般都是用来传递认证信息,相信不会出现不传递的状况。

转自:http://blog.sina.com.cn/s/blog_544465b00100034a.html

pureftpd如何刷新用户目录已使用的总容量

2010年9月8日 没有评论

今天一个部门打电话来说文件传不上ftp,看了下提示是空间满了,结果扫描了下实际容量似乎没满,感觉是quota的识别容量错了。
说实话这pureftpd用的还很少在安装目录里面逛了圈发现了pure-quotacheck这个命令,应该就是了。
试了试使用格式如下:
/usr/local/pureftpd/sbin/pure-quotacheck -u www -d /www/aaa.com

-u 是你指定pure-quotacheck运行时以系统的什么用户去扫描
-d 就是你ftp站点的目录

RHEL5/CentOS5 上支持 Ext4

2010年8月4日 没有评论

根据我以前的测试 Ext4 的性能好过 Ext3,在 RHEL5 上的 2.6.18-110 也有加入 Ext4 了。但默认没有让我们使用,怎么样才能不重起,能使用这个啦。
其实我们只要加入一个包e4fsprogs 就行,它其实和 e2fsprogs 是一样的功能,这 RHEL-6 中,会变成一个默认的包的。所以我们目前还只能使用这个包来调整和设置Ext4.

yum -y install e4fsprogs

在 RHEL 和 Centos5 中使用 Ext4 前,很多想可能想先给现有的文件系统转换成 Ext4 ,只要运行下面的命令就行了

tune4fs -O extents,uninit_bg,dir_index,flex_bg /dev/sdb1

在重起前,我还要让内核支持 Ext4 的文件系统,需要修改 initrd 的文件本身的内容。如下命令来生成 支持 Ext4 的 initrd。

mkinitrd --with=ext4 --with=ext3 -f /boot/initrd-2.6.18-194.8.1.el5.img 2.6.18-194.8.1

转载自:扶凯[http://www.php-oa.com]

分类: linux相关 标签:

php开启open_basedir后启用eaccelerator时File() on line 0报错解决

2010年6月14日 没有评论

open_basedir是php提升安全性的重要功能,eaccelerator是提速php的扩展模块,但是似乎默认环境下他们2一起用只要有require就会造成大量的php错误。


PHP Warning: Unknown: open_basedir restriction in effect. File() is not within the allowed path(s): (/www/:/tmp/) in Unknown on line 0

要解决这个问题的话在编译eaccelerator时 加上一个参数就行 –without-eaccelerator-use-inode
官方也说将在0.9.6.1的下一个release中默认启用这个参数。

由nginx漏洞想到的禁止某个目录执行php权限

2010年5月22日 没有评论

这次的nginx漏洞可谓是惊天,具体就不说了,详情见 http://www.80sec.com/nginx-securit.html
这漏洞可怕之处就是一旦有用户可以上传的地方如果能把php改后缀方式上传到服务器的话,就能任意执行。
其实有一个通用的方法可以来避免这种未知漏洞,就是禁止用户上传目录执行php权限。
在apache下面我们可以通过:

1
2
3
   <Directory /website/attachments>
        php_flag engine off
   </Directory>

的方式来来禁用目录下文件php执行权限。
那么在nginx里面同样可以实现这种方法,那就是location的优先匹配,关于location可以参考我之前的一批文章http://226617.cn/archives/392.htm
这里简单就举个例子

1
2
3
4
   location ^~ /attachments/
   {
      access_log  off;
   }

这样 attachments这个目录 就不会再去跳转给fastcgi去执行php了

分类: nginx相关 标签: , ,

linux下如何在一台机器上安装多个mysql实例

2010年4月27日 没有评论

最近再做个mysql一从多主的配置,需要在一台机器上安装多个mysql。
起先是按照复制了多了mysql 同时起,在琢磨如何做启动脚本的时候发现support-files目录下有个mysqld_multi.server文件,一查发现原来是现成的多实例管理工具。
首先得新建个data目录给新的实例,可以把原来的data目录复制个新的 只需要mysql库,也可以用工具部属个

1
./scripts/mysql_install_db --basedir=/usr/local/mysql3307 --datadir=/mysql/mysql3307/data --user=mysql

然后修改下my.cnf
主要增加

1
2
3
4
5
6
[mysqld_multi]
mysqld = /usr/local/mysql/bin/mysqld_safe
mysqladmin = /usr/local/mysql/bin/mysqladmin
user = shutdown
password = 123456
log = /mysql/mysqld_multi.log

然后把原来的 [mysqld] 改为 [mysqld1]
在新增新的实例配置

1
2
3
4
5
6
[mysqld2]
port = 3307
socket = /tmp/mysql3307.sock
datadir = /storage/mysql/data3307
............
............

然后把 mysqld_multi.server 做成启动服务

1
2
3
4
5
6
cp ./support-files/mysqld_multi.server /etc/rc.d/init.d/mysqld
chown root:root /etc/rc.d/init.d/mysqld
chmod 755 /etc/rc.d/init.d/mysqld
chkconfig --add mysqld
chkconfig --level 3 mysqld on
chkconfig --level 5 mysqld on

启动和关闭全部mysql实例
启动:service mysqld start
关闭:service mysqld stop

对单台数据库的启动和关闭
启动: service mysqld start 1
关闭: service mysqld stop 1

也可以同时启动和关闭多个数据库实例
启动: service mysqld start 1-2
关闭: service mysqld stop 1-2

如果启动的时候提示出错信息:
WARNING: my_print_defaults command not found.
Please make sure you have this command available and
in your path. The command is available from the latest
MySQL distribution.
ABORT: Can’t find command ‘my_print_defaults’.
This command is available from the latest MySQL
distribution. Please make sure you have the command
in your PATH.

先添加
export PATH=/usr/local/mysql/bin:$PATH
然后在启动mysql