RedHat AS3下安装PHP5有libxml2的问题:
升级安装libxml2有很多问题,很多相关的rpm都有关联,一下子能把人给懵了。
如果编译过程放弃libxml,那还有一堆的功能需要libxml,然后很多功能都得disable掉。
下面是参考的一篇安装笔记,已经证明可行,大家有相关问题可以参考一下,不重复了。
(各人的版本号不一样,处理过程自己看好了。。)
checking for xml2-config path... /usr/bin/xml2-config
configure: error: libxml2 version 2.6.11 or greater required.
configure: error: libxml2 version 2.6.11 or greater required.
升级安装libxml2有很多问题,很多相关的rpm都有关联,一下子能把人给懵了。
如果编译过程放弃libxml,那还有一堆的功能需要libxml,然后很多功能都得disable掉。
下面是参考的一篇安装笔记,已经证明可行,大家有相关问题可以参考一下,不重复了。
(各人的版本号不一样,处理过程自己看好了。。)
一直都是memcachedb+magent处理一个存储的需求,达到400G的内容,都是一个db,我发现这个已经导致了两块硬盘的罢工,不知道是因为他们比较老了折腾不了了还是这个架构的问题导致大数据文件的读写有难度而崩垮了。。
原先的方案是:
A和B都备有500G左右的空间,可也挺浪费的,500G空间做备份,而很不幸,如果发生问题,切换到备用的服务器后,再建立一个新的备用就得复制这500G的文件了,这个并不是好事情,而且这里面不好的地方是,只有一半的空间有用。
改良方案:
利用分布式存储的优势,建立magent的多源方式
也就是用多个服务器解决存储的问题,这样500G的数据,分到一个数据库的数据压力都平分了,不担心大文件的问题,也可以在一个节点出问题的时候换上另外一个服务器,但这里就导致备份的问题了。
一些问题:
1 magent有备份服务器的时候,所有的写操作都会发送到备份,那备份的机器就并没法达到减小文件的作用了。
2 magent是hash算法,key对应固定的节点,对应的是A则永久的对应为A,不会在A机器挂掉后自动调节对应关系,而是请求备份机器,如果没有备份,单节点失败则影响该节点的存储
也就是说,备份是必须的,但如果使用一样的方式,备份并没有改善。
那可以启用memcached作为备份,有下面的好处:
1 只占用固定的内存数量
2 可以应对不断的存储需求,自动把前面的存储内容清理掉
3 可以应对短时间的节点失败
我们看看这个方案的过程:
1 存储key1时magent会计算那个服务器(A)存储key1,存储key1到A,存储到备份E
2 存储key2时要存到B,但B节点失败,存储到E
3 读取key1,从A读取
4 读取key2,从B读取,节点失败,从E读取
5 B恢复后,读写B,备份只存储
注意到一个问题,备份只保持存储的数据有一定的时效,如果存储请求很多并且分配的内存很小,可能在短时间就被替换了,而读取会失败,所以备份只是保证访问能够一定程度正常,并非保证数据的完整性。
相关话题:
memcachedb的缓存解决方案
原先的方案是:
magent -s A -b B
A和B都备有500G左右的空间,可也挺浪费的,500G空间做备份,而很不幸,如果发生问题,切换到备用的服务器后,再建立一个新的备用就得复制这500G的文件了,这个并不是好事情,而且这里面不好的地方是,只有一半的空间有用。
改良方案:
利用分布式存储的优势,建立magent的多源方式
magent -s A -s B -s C -s D -b E
也就是用多个服务器解决存储的问题,这样500G的数据,分到一个数据库的数据压力都平分了,不担心大文件的问题,也可以在一个节点出问题的时候换上另外一个服务器,但这里就导致备份的问题了。
一些问题:
1 magent有备份服务器的时候,所有的写操作都会发送到备份,那备份的机器就并没法达到减小文件的作用了。
2 magent是hash算法,key对应固定的节点,对应的是A则永久的对应为A,不会在A机器挂掉后自动调节对应关系,而是请求备份机器,如果没有备份,单节点失败则影响该节点的存储
也就是说,备份是必须的,但如果使用一样的方式,备份并没有改善。
那可以启用memcached作为备份,有下面的好处:
1 只占用固定的内存数量
2 可以应对不断的存储需求,自动把前面的存储内容清理掉
3 可以应对短时间的节点失败
我们看看这个方案的过程:
1 存储key1时magent会计算那个服务器(A)存储key1,存储key1到A,存储到备份E
2 存储key2时要存到B,但B节点失败,存储到E
3 读取key1,从A读取
4 读取key2,从B读取,节点失败,从E读取
5 B恢复后,读写B,备份只存储
注意到一个问题,备份只保持存储的数据有一定的时效,如果存储请求很多并且分配的内存很小,可能在短时间就被替换了,而读取会失败,所以备份只是保证访问能够一定程度正常,并非保证数据的完整性。
相关话题:
memcachedb的缓存解决方案
为什么要用awstats?
1 你需要知道服务器流量都怎么导致的
2 你想查处莫名其妙的流量
awstats会给你很多网页访问统计系统无法告诉你的问题:流量分配,你不需要知道,那就不用它。
怎么做搭建?
下载安装awstats即可,我这里就不重复了,参考文章附录的参考资料。
Nginx怎么记录日志?
Nginx默认的日志格式就是awstats需要的,所以你不需要重新定义即可使用。
加buffer参数估计可以对日志效率有提高。
Nginx的日志切割脚本
别人写的脚本都太简单,不太适应,自己重新整理一下,合用的朋友可以借鉴一下
nginx_log_cut.sh
加入计划任务即可
配置awstats的配置文件
其它就不说了,我这里的脚本是按小时切割的,所以说一下格式:
使用实例
发现了一个网页文件存取次数最多,可网页受访却没有那么多,后来发现是有一个域名设置302跳转到此而导致的。
发现异常流量,可以看到awstats里面的流量比较大的ip,可以确认了那可以用iptables封禁异常的ip。
发现404错误,自己调整好。
1 你需要知道服务器流量都怎么导致的
2 你想查处莫名其妙的流量
awstats会给你很多网页访问统计系统无法告诉你的问题:流量分配,你不需要知道,那就不用它。
怎么做搭建?
下载安装awstats即可,我这里就不重复了,参考文章附录的参考资料。
Nginx怎么记录日志?
Nginx默认的日志格式就是awstats需要的,所以你不需要重新定义即可使用。
加buffer参数估计可以对日志效率有提高。
server {
server_name www.aslibra.com;
location / { proxy_pass http://backend; }
access_log /Data/logs/access.www.aslibra.com.log combined buffer=32k;
}
server_name www.aslibra.com;
location / { proxy_pass http://backend; }
access_log /Data/logs/access.www.aslibra.com.log combined buffer=32k;
}
Nginx的日志切割脚本
别人写的脚本都太简单,不太适应,自己重新整理一下,合用的朋友可以借鉴一下
nginx_log_cut.sh
#!/bin/sh
#日志最小记录
Min_Row=50
Log_Dir=/Data/logs
Nginx_Dir=/Data/apps/nginx
#你的日志格式
Date_Dir="/Data/logs/date/"`date +%Y/%m/%d/%H -d "1 hours ago" `
echo ""
echo "=== "`date`" ==="
echo "Date_Dir: $Date_Dir"
if [ ! -d $Date_Dir ];then
mkdir -p $Date_Dir
fi
#你的所有域名日志
Logs="www.aslibra.com\
test.aslibra.com"
#注意,0.7才支持 -s 参数,否则你需要用 kill -USR1 方式
#把buffer都写入文件
$Nginx_Dir/sbin/nginx -s reopen
for domain in $Logs;do
if [ -f $Log_Dir/access.$domain.log ];then
Row=`wc -l $Log_Dir/access.$domain.log | awk '{print $1}'`
if [ $Row -gt $Min_Row ];then
if [ -f $Date_Dir/$domain.log ];then
echo "Append: "$Log_Dir/access.$domain.log
cat $Log_Dir/access.$domain.log >> $Date_Dir/$domain.log
rm -f $Log_Dir/access.$domain.log
else
echo "Move: "$Log_Dir/access.$domain.log
mv $Log_Dir/access.$domain.log $Date_Dir/$domain.log
fi
else
echo "Delete(less then $Min_Row Rows): "$Log_Dir/access.$domain.log
rm -f $Log_Dir/access.$domain.log
fi
fi
done
#重开日志
$Nginx_Dir/sbin/nginx -s reopen
#日志最小记录
Min_Row=50
Log_Dir=/Data/logs
Nginx_Dir=/Data/apps/nginx
#你的日志格式
Date_Dir="/Data/logs/date/"`date +%Y/%m/%d/%H -d "1 hours ago" `
echo ""
echo "=== "`date`" ==="
echo "Date_Dir: $Date_Dir"
if [ ! -d $Date_Dir ];then
mkdir -p $Date_Dir
fi
#你的所有域名日志
Logs="www.aslibra.com\
test.aslibra.com"
#注意,0.7才支持 -s 参数,否则你需要用 kill -USR1 方式
#把buffer都写入文件
$Nginx_Dir/sbin/nginx -s reopen
for domain in $Logs;do
if [ -f $Log_Dir/access.$domain.log ];then
Row=`wc -l $Log_Dir/access.$domain.log | awk '{print $1}'`
if [ $Row -gt $Min_Row ];then
if [ -f $Date_Dir/$domain.log ];then
echo "Append: "$Log_Dir/access.$domain.log
cat $Log_Dir/access.$domain.log >> $Date_Dir/$domain.log
rm -f $Log_Dir/access.$domain.log
else
echo "Move: "$Log_Dir/access.$domain.log
mv $Log_Dir/access.$domain.log $Date_Dir/$domain.log
fi
else
echo "Delete(less then $Min_Row Rows): "$Log_Dir/access.$domain.log
rm -f $Log_Dir/access.$domain.log
fi
fi
done
#重开日志
$Nginx_Dir/sbin/nginx -s reopen
加入计划任务即可
0 * * * * root /Data/scripts/nginx_log_cut.sh >>/Data/logs/log_cut.log
配置awstats的配置文件
其它就不说了,我这里的脚本是按小时切割的,所以说一下格式:
LogFile="/Data/logs/date/%YYYY-1/%MM-1/%DD-1/%HH-1/www.aslibra.com.log"
使用实例
发现了一个网页文件存取次数最多,可网页受访却没有那么多,后来发现是有一个域名设置302跳转到此而导致的。
发现异常流量,可以看到awstats里面的流量比较大的ip,可以确认了那可以用iptables封禁异常的ip。
发现404错误,自己调整好。
正向代理和反向代理是forward/reverse proxy的意思,在代理功能上来讲,有一点不太一样。
举个例子:
你要去租房,你找房屋中介找房子,房屋中介找房屋的全权代理人要房子,房屋的全权代理人是由户主委托的。
这里有四个角色:
你=client
房屋中介=forword proxy
代理人=reverse proxy
户主=server
客户端访问网络如果需要指定某个代理服务器为你去获取内容,那就是正向代理
而服务器隐藏在代理服务器后面,让代理服务器作为冲锋陷阵的,那这个代理服务器就是反向代理
而squid是一个 forword/reverse proxy,两个功能兼备,一般可以作为局域网的上网缓存,此时作为正向代理。
一般服务器会让squid作为前端,那就是充当反向代理,反向代理有很多软件都可以,比如nginx、lighttpd,但他们两个一般做不了正向代理。
举个例子:
你要去租房,你找房屋中介找房子,房屋中介找房屋的全权代理人要房子,房屋的全权代理人是由户主委托的。
这里有四个角色:
你=client
房屋中介=forword proxy
代理人=reverse proxy
户主=server
客户端访问网络如果需要指定某个代理服务器为你去获取内容,那就是正向代理
而服务器隐藏在代理服务器后面,让代理服务器作为冲锋陷阵的,那这个代理服务器就是反向代理
而squid是一个 forword/reverse proxy,两个功能兼备,一般可以作为局域网的上网缓存,此时作为正向代理。
一般服务器会让squid作为前端,那就是充当反向代理,反向代理有很多软件都可以,比如nginx、lighttpd,但他们两个一般做不了正向代理。
服务器在收到浏览器请求的时候,可能会有不同的header信息,我们做个测试。
做个简单的php文件,打印出接受到的header信息:
注:php接受到信息都在 $_SERVER[HTTP_xxxxx] 变量里。
IE访问
[HTTP_ACCEPT] => image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/msword, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/x-silverlight, application/x-shockwave-flash, */*
[HTTP_ACCEPT_LANGUAGE] => zh-cn
[HTTP_ACCEPT_ENCODING] => gzip, deflate
[HTTP_USER_AGENT] => Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; CIBA)
[HTTP_HOST] => www.aslibra.com
[HTTP_CONNECTION] => Keep-Alive
google浏览器
[HTTP_HOST] => www.aslibra.com
[HTTP_CONNECTION] => keep-alive
[HTTP_USER_AGENT] => Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/530.5 (KHTML, like Gecko) Chrome/2.0.172.33 Safari/530.5
[HTTP_ACCEPT] => application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
[HTTP_ACCEPT_ENCODING] => gzip,deflate,bzip2,sdch
[HTTP_ACCEPT_LANGUAGE] => zh-CN,zh;q=0.8
[HTTP_ACCEPT_CHARSET] => UTF-8,*;q=0.5
firefox
[HTTP_HOST] => www.aslibra.com
[HTTP_USER_AGENT] => Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3
[HTTP_ACCEPT] => text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
[HTTP_ACCEPT_LANGUAGE] => zh-cn,zh;q=0.5
[HTTP_ACCEPT_ENCODING] => gzip,deflate
[HTTP_ACCEPT_CHARSET] => gb2312,utf-8;q=0.7,*;q=0.7
[HTTP_KEEP_ALIVE] => 300
[HTTP_CONNECTION] => keep-alive
file_get_contents
[HTTP_HOST] => www.aslibra.com
wget
[HTTP_USER_AGENT] => Wget/1.9+cvs-stable (Red Hat modified)
[HTTP_HOST] => www.aslibra.com
[HTTP_ACCEPT] => */*
[HTTP_CONNECTION] => Keep-Alive
curl
[HTTP_USER_AGENT] => curl/7.12.1 (i386-redhat-linux-gnu) libcurl/7.12.1 OpenSSL/0.9.7a zlib/1.2.1.2 libidn/0.5.6
[HTTP_HOST] => www.aslibra.com
[HTTP_PRAGMA] => no-cache
[HTTP_ACCEPT] => */*
curl访问经过squid代理
( curl http://www.aslibra.com/ -x 127.0.0.1:3128 )
[HTTP_USER_AGENT] => curl/7.12.1 (i386-redhat-linux-gnu) libcurl/7.12.1 OpenSSL/0.9.7a zlib/1.2.1.2 libidn/0.5.6
[HTTP_HOST] => www.aslibra.com
[HTTP_PRAGMA] => no-cache
[HTTP_ACCEPT] => */*
[HTTP_VIA] => 1.1 cache.aslibra.com:3128 (squid/2.5.STABLE14)
[HTTP_X_FORWARDED_FOR] => 127.0.0.1
[HTTP_CACHE_CONTROL] => max-age=259200
[HTTP_CONNECTION] => keep-alive
我们可以看出来,每个方式都有很大的不同,一般服务器可以通过HTTP_USER_AGENT做出不同的限制。
要做欺骗行为,那也可以调整header信息达到效果。
一般浏览器会发出 [HTTP_ACCEPT_ENCODING] => gzip,deflate 表示可以接受代码压缩
做个简单的php文件,打印出接受到的header信息:
<?php
foreach($_SERVER as $k=>$v){
if(substr($k,0,5)=='HTTP_')echo "[$k] => $v\n";
}
?>
foreach($_SERVER as $k=>$v){
if(substr($k,0,5)=='HTTP_')echo "[$k] => $v\n";
}
?>
注:php接受到信息都在 $_SERVER[HTTP_xxxxx] 变量里。
IE访问
[HTTP_ACCEPT] => image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/msword, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/x-silverlight, application/x-shockwave-flash, */*
[HTTP_ACCEPT_LANGUAGE] => zh-cn
[HTTP_ACCEPT_ENCODING] => gzip, deflate
[HTTP_USER_AGENT] => Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; CIBA)
[HTTP_HOST] => www.aslibra.com
[HTTP_CONNECTION] => Keep-Alive
google浏览器
[HTTP_HOST] => www.aslibra.com
[HTTP_CONNECTION] => keep-alive
[HTTP_USER_AGENT] => Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/530.5 (KHTML, like Gecko) Chrome/2.0.172.33 Safari/530.5
[HTTP_ACCEPT] => application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
[HTTP_ACCEPT_ENCODING] => gzip,deflate,bzip2,sdch
[HTTP_ACCEPT_LANGUAGE] => zh-CN,zh;q=0.8
[HTTP_ACCEPT_CHARSET] => UTF-8,*;q=0.5
firefox
[HTTP_HOST] => www.aslibra.com
[HTTP_USER_AGENT] => Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3
[HTTP_ACCEPT] => text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
[HTTP_ACCEPT_LANGUAGE] => zh-cn,zh;q=0.5
[HTTP_ACCEPT_ENCODING] => gzip,deflate
[HTTP_ACCEPT_CHARSET] => gb2312,utf-8;q=0.7,*;q=0.7
[HTTP_KEEP_ALIVE] => 300
[HTTP_CONNECTION] => keep-alive
file_get_contents
[HTTP_HOST] => www.aslibra.com
wget
[HTTP_USER_AGENT] => Wget/1.9+cvs-stable (Red Hat modified)
[HTTP_HOST] => www.aslibra.com
[HTTP_ACCEPT] => */*
[HTTP_CONNECTION] => Keep-Alive
curl
[HTTP_USER_AGENT] => curl/7.12.1 (i386-redhat-linux-gnu) libcurl/7.12.1 OpenSSL/0.9.7a zlib/1.2.1.2 libidn/0.5.6
[HTTP_HOST] => www.aslibra.com
[HTTP_PRAGMA] => no-cache
[HTTP_ACCEPT] => */*
curl访问经过squid代理
( curl http://www.aslibra.com/ -x 127.0.0.1:3128 )
[HTTP_USER_AGENT] => curl/7.12.1 (i386-redhat-linux-gnu) libcurl/7.12.1 OpenSSL/0.9.7a zlib/1.2.1.2 libidn/0.5.6
[HTTP_HOST] => www.aslibra.com
[HTTP_PRAGMA] => no-cache
[HTTP_ACCEPT] => */*
[HTTP_VIA] => 1.1 cache.aslibra.com:3128 (squid/2.5.STABLE14)
[HTTP_X_FORWARDED_FOR] => 127.0.0.1
[HTTP_CACHE_CONTROL] => max-age=259200
[HTTP_CONNECTION] => keep-alive
我们可以看出来,每个方式都有很大的不同,一般服务器可以通过HTTP_USER_AGENT做出不同的限制。
要做欺骗行为,那也可以调整header信息达到效果。
一般浏览器会发出 [HTTP_ACCEPT_ENCODING] => gzip,deflate 表示可以接受代码压缩
阿权今天要说的问题是:
用户粘贴的图片是对方防盗链处理的图片,别人就无法看到图片了,体验很不好。
有问题就有解决办法,但需要预热一下:
1 别人是如何做图片防盗链的?
2 如何可以避免在防盗链范围?
了解或者解决以上两个问题你就可以出师了啦!
众所周知,图片防盗链是为了让自己的服务器提供给固定的某些域名下的网页显示自己的图片,主要为了解决带宽的占用问题。
阿权之前管理的图片类型的网站,居然可以让盗链的图片流量跑满了服务器带宽,所以盗链的问题很讨厌,一般网站都会处理此问题,一般采取的是检查图片请求的referer参数,这个不明白那这个课题还不适合你来读。
我们来看看凤凰网的图片防盗链,图片是很hot的美女哦,curl就可以测试:
第一个是没有来源标识的,一般为在窗口直接输入图片地址
第二个是模拟在网页里面的图片,网址假设为http://www.aslibra.com/
第三个是模拟在img.ifeng.com的网页打开的
第一个和第三个返回是200的状态码,图片正常,第二个则因为是非授权网页引用,返回了403禁止的消息。
也有可能是返回200的状态码的,比如百度hi的图片:
当然,如果对方服务器是验证用户的信息的,那就没法解决了,我们能够解决的防盗链一般是根据来源防盗链的服务器。
注意了,破解对方的防盗链并非坏事,是为了提高用户体验,解决一般的用户的疑惑,他们根本不知道粘贴的图片为什么不正常,这你没必要跟他们聊一下图片防盗链吧?
你也许只要付出一台服务器就可以解决了:
1 首先你得把防盗链的域名的图片地址给替换为你的服务器域名,因为正常的访问你是控制不了referer信息的
2 交给代理服务器去掉或者修改referer信息,这个nginx很简便解决
3 再交给缓存服务器下载此图片,缓存此图片,这样对对方服务器没有什么影响,是好事来的
步骤1:替换图片地址
第一个就不用多说了,比如php就可以处理:
这样的简单处理可以保留所有的图片地址信息,而且可以自动还原原来的请求地址
步骤2 去掉或更改referer信息
这个有很多方法,比如配置proxy.www.aslibra.com/m交给php处理,php容易分析出地址,并且可以用socket或者调用curl等系统命令来下载图片,然后返回给用户。
这里用web服务器(nginx)解决这个问题,肯定比php来的简便和高效:
简单来说就是rewrite回原先的地址,并且设置referer,交给squid的后端。
步骤3 交给代理服务器缓存
以上是squid的配置(2.5版本),基本不用配置什么参数,能代理缓存即可,有别的合适软件也许也可以做,但squid做这个实在是太合适了!你的不二之选!
实验效果很正常,返回的信息如下,访问两次有HIT说明就正常了:

效果对比,前面会提示禁止引用,后面是解决后正常显示图片的效果!
很神奇吧~~ 这样就为用户体验提高了一个等级啦~
注意,以上方案域名为测试指定,访问并非正常,请自行修改相关内容进行试验,大家使用愉快!
本方案更新请关注:
http://www.aslibra.com/blog/post/crack_pic_referer_solution.php
本解决方案目前无法解决的类型:
1 不是判断referer信息来防盗链的,当然如果你知道,也许可以类似方式解决
2 不能解决redirect后的图片,也许可以使用nginx的内部redirect来处理,还没试验,这类情况还不多
用户粘贴的图片是对方防盗链处理的图片,别人就无法看到图片了,体验很不好。
有问题就有解决办法,但需要预热一下:
1 别人是如何做图片防盗链的?
2 如何可以避免在防盗链范围?
了解或者解决以上两个问题你就可以出师了啦!
众所周知,图片防盗链是为了让自己的服务器提供给固定的某些域名下的网页显示自己的图片,主要为了解决带宽的占用问题。
阿权之前管理的图片类型的网站,居然可以让盗链的图片流量跑满了服务器带宽,所以盗链的问题很讨厌,一般网站都会处理此问题,一般采取的是检查图片请求的referer参数,这个不明白那这个课题还不适合你来读。
我们来看看凤凰网的图片防盗链,图片是很hot的美女哦,curl就可以测试:
[root@aslibra ~]# curl -I http://img.ifeng.com/res/200906/0610-070615_1339_20.jpg
HTTP/1.1 200 OK
Server: DnionOS/1.0
Date: Fri, 26 Jun 2009 13:14:31 GMT
Content-Type: image/jpeg
Connection: keep-alive
Last-Modified: Wed, 10 Jun 2009 11:16:05 GMT
Accept-Ranges: bytes
Content-Length: 37727
Expires: Wed, 23 Jun 2010 08:11:48 GMT
Cache-Control: max-age=31536000
X-Cache: HIT from cache26.ifeng.com
Age: 24507
X-Cache: HIT from CNC-BJBY-53-172.fastcdn.com
[root@aslibra ~]# curl -I http://img.ifeng.com/res/200906/0610-070615_1339_20.jpg -H "referer:http://www.aslibra.com/"
HTTP/1.1 403 Forbidden
Server: DnionOS/1.0
Date: Fri, 26 Jun 2009 13:14:57 GMT
Content-Type: text/html
Connection: keep-alive
Content-Length: 1204
Expires: Fri, 26 Jun 2009 13:15:02 GMT
X-Squid-Error: ERR_ACCESS_DENIED 0
X-Cache: MISS from CNC-BJBY-53-172.fastcdn.com
[root@aslibra ~]# curl -I http://img.ifeng.com/res/200906/0610-070615_1339_20.jpg -H "referer:http://img.ifeng.com/"
HTTP/1.1 200 OK
Server: DnionOS/1.0
Date: Fri, 26 Jun 2009 13:17:37 GMT
Content-Type: image/jpeg
Connection: keep-alive
Last-Modified: Wed, 10 Jun 2009 11:16:05 GMT
Accept-Ranges: bytes
Content-Length: 37727
Expires: Wed, 23 Jun 2010 08:11:48 GMT
Cache-Control: max-age=31536000
X-Cache: HIT from cache26.ifeng.com
Age: 24691
X-Cache: HIT from CNC-BJBY-53-172.fastcdn.com
HTTP/1.1 200 OK
Server: DnionOS/1.0
Date: Fri, 26 Jun 2009 13:14:31 GMT
Content-Type: image/jpeg
Connection: keep-alive
Last-Modified: Wed, 10 Jun 2009 11:16:05 GMT
Accept-Ranges: bytes
Content-Length: 37727
Expires: Wed, 23 Jun 2010 08:11:48 GMT
Cache-Control: max-age=31536000
X-Cache: HIT from cache26.ifeng.com
Age: 24507
X-Cache: HIT from CNC-BJBY-53-172.fastcdn.com
[root@aslibra ~]# curl -I http://img.ifeng.com/res/200906/0610-070615_1339_20.jpg -H "referer:http://www.aslibra.com/"
HTTP/1.1 403 Forbidden
Server: DnionOS/1.0
Date: Fri, 26 Jun 2009 13:14:57 GMT
Content-Type: text/html
Connection: keep-alive
Content-Length: 1204
Expires: Fri, 26 Jun 2009 13:15:02 GMT
X-Squid-Error: ERR_ACCESS_DENIED 0
X-Cache: MISS from CNC-BJBY-53-172.fastcdn.com
[root@aslibra ~]# curl -I http://img.ifeng.com/res/200906/0610-070615_1339_20.jpg -H "referer:http://img.ifeng.com/"
HTTP/1.1 200 OK
Server: DnionOS/1.0
Date: Fri, 26 Jun 2009 13:17:37 GMT
Content-Type: image/jpeg
Connection: keep-alive
Last-Modified: Wed, 10 Jun 2009 11:16:05 GMT
Accept-Ranges: bytes
Content-Length: 37727
Expires: Wed, 23 Jun 2010 08:11:48 GMT
Cache-Control: max-age=31536000
X-Cache: HIT from cache26.ifeng.com
Age: 24691
X-Cache: HIT from CNC-BJBY-53-172.fastcdn.com
第一个是没有来源标识的,一般为在窗口直接输入图片地址
第二个是模拟在网页里面的图片,网址假设为http://www.aslibra.com/
第三个是模拟在img.ifeng.com的网页打开的
第一个和第三个返回是200的状态码,图片正常,第二个则因为是非授权网页引用,返回了403禁止的消息。
也有可能是返回200的状态码的,比如百度hi的图片:
[root@aslibra ~]# curl -I http://hiphotos.baidu.com/yuanyingmanhua/pic/item/6e1da9d832163a3b33fa1c2b.jpg
HTTP/1.1 200 OK
...
Cache-Control: max-age=315360000
Expires: Sun, 08 May 2016 14:12:03 GMT
Last-Modified: Sat, 29 Apr 2006 07:04:00 GMT
Content-Length: 43171
...
[root@aslibra ~]# curl -I http://hiphotos.baidu.com/yuanyingmanhua/pic/item/6e1da9d832163a3b33fa1c2b.jpg -H "referer:http://www.aslibra.com/"
HTTP/1.1 200 OK
...
Cache-Control: no-cache
Content-Length: 1809
...
HTTP/1.1 200 OK
...
Cache-Control: max-age=315360000
Expires: Sun, 08 May 2016 14:12:03 GMT
Last-Modified: Sat, 29 Apr 2006 07:04:00 GMT
Content-Length: 43171
...
[root@aslibra ~]# curl -I http://hiphotos.baidu.com/yuanyingmanhua/pic/item/6e1da9d832163a3b33fa1c2b.jpg -H "referer:http://www.aslibra.com/"
HTTP/1.1 200 OK
...
Cache-Control: no-cache
Content-Length: 1809
...
当然,如果对方服务器是验证用户的信息的,那就没法解决了,我们能够解决的防盗链一般是根据来源防盗链的服务器。
注意了,破解对方的防盗链并非坏事,是为了提高用户体验,解决一般的用户的疑惑,他们根本不知道粘贴的图片为什么不正常,这你没必要跟他们聊一下图片防盗链吧?
你也许只要付出一台服务器就可以解决了:
1 首先你得把防盗链的域名的图片地址给替换为你的服务器域名,因为正常的访问你是控制不了referer信息的
2 交给代理服务器去掉或者修改referer信息,这个nginx很简便解决
3 再交给缓存服务器下载此图片,缓存此图片,这样对对方服务器没有什么影响,是好事来的
步骤1:替换图片地址
第一个就不用多说了,比如php就可以处理:
//example php code
$content = ereg_replace("http://($domain)/", "http://proxy.www.aslibra.com/m/\\1/", $content);
// from http://img.ifeng.com/res/200906/0610-070615_1339_20.jpg
// to http://proxy.www.aslibra.com/m/img.ifeng.com/res/200906/0610-070615_1339_20.jpg
$content = ereg_replace("http://($domain)/", "http://proxy.www.aslibra.com/m/\\1/", $content);
// from http://img.ifeng.com/res/200906/0610-070615_1339_20.jpg
// to http://proxy.www.aslibra.com/m/img.ifeng.com/res/200906/0610-070615_1339_20.jpg
这样的简单处理可以保留所有的图片地址信息,而且可以自动还原原来的请求地址
步骤2 去掉或更改referer信息
这个有很多方法,比如配置proxy.www.aslibra.com/m交给php处理,php容易分析出地址,并且可以用socket或者调用curl等系统命令来下载图片,然后返回给用户。
这里用web服务器(nginx)解决这个问题,肯定比php来的简便和高效:
upstream squid {
server 127.0.0.1:3128;
}
server {
expires 240h;
server_name proxy.www.aslibra.com;
if ( $uri ~ ^/m/([^/]+)(.+)) {
set $new_host $1;
set $referer "";
#set $referer http://$1/; #you can set it like this
rewrite ^/m/([^/]+)(.+) $2 break;
}
location / {
proxy_set_header host $new_host;
proxy_set_header referer $referer;
proxy_pass http://squid;
}
}
server 127.0.0.1:3128;
}
server {
expires 240h;
server_name proxy.www.aslibra.com;
if ( $uri ~ ^/m/([^/]+)(.+)) {
set $new_host $1;
set $referer "";
#set $referer http://$1/; #you can set it like this
rewrite ^/m/([^/]+)(.+) $2 break;
}
location / {
proxy_set_header host $new_host;
proxy_set_header referer $referer;
proxy_pass http://squid;
}
}
简单来说就是rewrite回原先的地址,并且设置referer,交给squid的后端。
步骤3 交给代理服务器缓存
visible_hostname cache.aslibra.com
acl all src 0.0.0.0/0.0.0.0
http_access allow all
http_port 127.0.0.1:3128
httpd_accel_host virtual
httpd_accel_port 80
httpd_accel_uses_host_header on
httpd_accel_with_proxy off
cache_dir ufs /cache/proxy.www.aslibra.com 2000 16 256
cache_effective_user daemon
cache_access_log none
cache_store_log none
cache_log none
acl all src 0.0.0.0/0.0.0.0
http_access allow all
http_port 127.0.0.1:3128
httpd_accel_host virtual
httpd_accel_port 80
httpd_accel_uses_host_header on
httpd_accel_with_proxy off
cache_dir ufs /cache/proxy.www.aslibra.com 2000 16 256
cache_effective_user daemon
cache_access_log none
cache_store_log none
cache_log none
以上是squid的配置(2.5版本),基本不用配置什么参数,能代理缓存即可,有别的合适软件也许也可以做,但squid做这个实在是太合适了!你的不二之选!
实验效果很正常,返回的信息如下,访问两次有HIT说明就正常了:
(Status-Line) HTTP/1.1 200 OK
Cache-Control max-age=864000
Connection keep-alive
Content-Length 59969
Content-Type image/jpeg
Date Fri, 26 Jun 2009 13:42:32 GMT
Expires Mon, 06 Jul 2009 13:42:32 GMT
Last-Modified Mon, 18 Dec 2006 07:25:14 GMT
Server nginx/0.7.59
X-Cache HIT from cache.aslibra.com
Cache-Control max-age=864000
Connection keep-alive
Content-Length 59969
Content-Type image/jpeg
Date Fri, 26 Jun 2009 13:42:32 GMT
Expires Mon, 06 Jul 2009 13:42:32 GMT
Last-Modified Mon, 18 Dec 2006 07:25:14 GMT
Server nginx/0.7.59
X-Cache HIT from cache.aslibra.com

效果对比,前面会提示禁止引用,后面是解决后正常显示图片的效果!
很神奇吧~~ 这样就为用户体验提高了一个等级啦~
注意,以上方案域名为测试指定,访问并非正常,请自行修改相关内容进行试验,大家使用愉快!
本方案更新请关注:
http://www.aslibra.com/blog/post/crack_pic_referer_solution.php
本解决方案目前无法解决的类型:
1 不是判断referer信息来防盗链的,当然如果你知道,也许可以类似方式解决
2 不能解决redirect后的图片,也许可以使用nginx的内部redirect来处理,还没试验,这类情况还不多
memcachedb使用的BerkeleyDB的数据库,但每10M生成一个log文件:
定期清理为好,否则就要有两倍数据的空间了,以前写的是定期清理某个时间修改的日志:
清理100分钟前的文件,导致了一个文件,如果停用或者100分钟内没有更新动作,将删掉了所有日志,吃亏了,导致启动失败了,当然,可能可以修复,只是糊涂的话就没法再启用了。
稳当点,就删除所有的日志文件,保留最新的100个:
简单解析一下脚本意思:
ls -t log.* 是列出所有log开头的日志文件,按时间排序,也就是最新的排前面
awk里面NR代表当前行数,NR>100则是100行后的才输出
xargs就是接收到awk输出的文件才转给rm删除
参考资料:awk手册
[root@aslibra db]# ll -h
total 26G
-rw-r--r-- 1 root root 25G Jun 22 00:12 data.db
-rw-r----- 1 root root 24K Jun 20 19:33 __db.001
-rw-r----- 1 root root 3.8M Jun 20 19:33 __db.002
-rw-r----- 1 root root 81M Jun 20 19:33 __db.003
-rw-r----- 1 root root 96K Jun 20 19:33 __db.004
-rw-r----- 1 root root 11M Jun 20 19:33 __db.005
-rw-r----- 1 root root 48K Jun 20 19:33 __db.006
-rw-r----- 1 root root 10M Jun 21 22:47 log.0000002271
-rw-r----- 1 root root 10M Jun 21 22:47 log.0000002272
-rw-r----- 1 root root 10M Jun 21 22:48 log.0000002273
-rw-r----- 1 root root 10M Jun 21 22:49 log.0000002274
.....
total 26G
-rw-r--r-- 1 root root 25G Jun 22 00:12 data.db
-rw-r----- 1 root root 24K Jun 20 19:33 __db.001
-rw-r----- 1 root root 3.8M Jun 20 19:33 __db.002
-rw-r----- 1 root root 81M Jun 20 19:33 __db.003
-rw-r----- 1 root root 96K Jun 20 19:33 __db.004
-rw-r----- 1 root root 11M Jun 20 19:33 __db.005
-rw-r----- 1 root root 48K Jun 20 19:33 __db.006
-rw-r----- 1 root root 10M Jun 21 22:47 log.0000002271
-rw-r----- 1 root root 10M Jun 21 22:47 log.0000002272
-rw-r----- 1 root root 10M Jun 21 22:48 log.0000002273
-rw-r----- 1 root root 10M Jun 21 22:49 log.0000002274
.....
定期清理为好,否则就要有两倍数据的空间了,以前写的是定期清理某个时间修改的日志:
find /BerkeleyDB/aslibra.com/db/ -maxdepth 1 -type f -name 'log.*' -mmin +100 | xargs -i rm -f {}
清理100分钟前的文件,导致了一个文件,如果停用或者100分钟内没有更新动作,将删掉了所有日志,吃亏了,导致启动失败了,当然,可能可以修复,只是糊涂的话就没法再启用了。
稳当点,就删除所有的日志文件,保留最新的100个:
#!/bin/sh
cd /BerkeleyDB/aslibra.com/db/
ls -t log.* | awk '{ if(NR>100)print $0}'|xargs -i -t rm -f {}
cd /BerkeleyDB/aslibra.com/db/
ls -t log.* | awk '{ if(NR>100)print $0}'|xargs -i -t rm -f {}
简单解析一下脚本意思:
ls -t log.* 是列出所有log开头的日志文件,按时间排序,也就是最新的排前面
awk里面NR代表当前行数,NR>100则是100行后的才输出
xargs就是接收到awk输出的文件才转给rm删除
参考资料:awk手册






