作者:牛三羊

在nginx上搭建HTTPS服务

最近GFW抽风,动不动就把推的api proxy给封了。据我观察是根据访问内容进行关键字过滤,如果发现敏感词,就封掉这IP提供的所有HTTP服务。既然如此,就搭建个HTTPS的服务吧,应该是有效的。搭建过程记录如下:

首先,用-V参数看看当前的nginx是否在编译时载入了https模块,只要看到 “–with-http_ssl_module”就可以了。如果没有,就需要重新编译nginx。debian的默认安装很不错,集成了很多模块,为我省了不少事儿。
接下来我们先要生成密钥,通过这个密钥再去给自己颁发证书。

root@n3yang:~# openssl genrsa -out privkey.pem 1024

现在密钥已经存到了privkey.pem中了,1024位的rsa加密,对于我来讲这已经足够了。

再来就是颁发证书

root@n3yang:~# openssl req -new -x509 -key privkey.pem -out cacert.pem -days 1095

随便填就行了,但Common Name必须填即将使用HTTPS的站点名称,比如:*.n3yang.com 。

继续配置nginx,在配置文件中指定证书,加入监听端口什么的就可以了。

listen 443;
ssl on;
ssl_certificate cacert.pem;
ssl_certificate_key privkey.pem;

重启nginx后通过 https 的方式就可以访问了。

不知道这次能坚持多久,我会拭目以待地⋯⋯嘿嘿。

PHP数组按键值大小排序

在PHP中,想要将数组按照键值大小进行排序,使用array_multisort很容易就可以完成。但是这个函数会打乱原有key值,比如下面这段程序:

$data[5] = array('volume' => 67, 'edition' => 2);
$data[4] = array('volume' => 86, 'edition' => 1);
$data[2] = array('volume' => 85, 'edition' => 6);
$data[3] = array('volume' => 98, 'edition' => 2);
$data[1] = array('volume' => 86, 'edition' => 6);
$data[6] = array('volume' => 67, 'edition' => 7);
// 准备要排序的数组
foreach ($data as $k => $v) {
    $edition[] = $v['edition'];
}
array_multisort($edition, SORT_ASC, $data);
print_r($data);

将输出:
(更多…)

在debian上mutt提示附件加载失败

今天发现原来用于备份数据库并邮寄到信箱的脚本不能用了,调试了一下得到mutt发送email失败的提示。

root@n3yang:~# mutt -a n3yang-backup-20120425.sql.gz -s 'backup' backup@gmail.com
backup@gmail.com: unable to attach file.

这个脚本一直运行的很好,mutt也命令用过很多次,不应该有什么问题才对⋯⋯正当百思不得骑姐的时候,随手打了一下–help看看了帮助,发现比以前看多了一行提示:

  -- treat remaining arguments as addr even if starting with a dash
	when using -a with multiple filenames using -- is mandatory

恍然大悟,原来这个版本的mutt支持了多附件,在使用-a参数之后的需要使用 “–” 明确指出邮件地址:

root@n3yang:~# mutt -a n3yang-backup-20120425.sql.gz -s 'backup' -- backup@gmail.com

或者把邮件地址放到最前面,这样写:

root@n3yang:~# mutt backup@gmail.com -a n3yang-backup-20120425.sql.gz -s 'backup'

问题解决了,再找一台CentOS 5.5看看上面mutt的版本,和我这台debian果然不一样。在CentOS 5.5上的版本是

Mutt 1.4.2.2i (2006-07-14)

debian 6上的是

Mutt 1.5.20 (2009-06-14)

验证了之前版本不一样的推断。

利用nginx实时生成缩略图

Nginx?缩略图?两个貌似不搭边儿的词语怎么可以关联到一起?但nginx自0.75版本增加了实时转换图片的功能⋯⋯换句话说,假如服务器上存储的是大图,要想展示给用户一张缩略图,可以通过nginx进行实时转换,而不用生成实体文件,这样可以很大程度的节省磁盘空间资源。

nginx的默认编译中不支持此功能,需要在编译的时候增加 –with-http_image_filter_module 参数。如果之前安装过,就需要重新编译了。编译之前最好备份一下配置文件:

cp /usr/local/webapp/nginx/conf/nginx.conf /usr/local/webapp/nginx/conf/nginx.conf.bak

编译安装:

root@n3yang:~# cd /root/soft/
root@n3yang:~# tar zxf nginx-0.8.29.tar.gz
root@n3yang:~# cd nginx-0.8.29
root@n3yang:~# ./configure --user=www --group=www --prefix=/usr/local/webapp/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_image_filter_module
root@n3yang:~# make;make install

安装完成后,需要配置nginx转换哪些图片到什么样的尺寸。
假定原图地址为 http://avatar.n3yang.com/1.jpg
转化后图片路径为 http://avatar.n3yang.com/1_(width)x(height).jpg
如果头像文件不存在,将显示默认的头像:default-avatar.jpg
括号中的width与height分别为欲转化的图片宽度和高度。例如宽为45高为65的头像,那头像地址为http://avatar.n3yang.com/1_45x65.jpg

在配置文件nginx.conf 添加配置:

location ~ /(\d+)_(\d+)x(\d+)\.(JPG|jpg|GIF|gif|PNG|png)$ {
	if (!-f /$1.$4) {
		rewrite ^ /default-avatar.jpg break;
	}
	image_filter resize $2 $3;
	image_filter_buffer 2M;
}

重新载入配置文件后才能生效。

几点说明:
1、生成缩略图只是image_filter功能中的一个,它一共支持4种参数:

test:返回是否真的是图片
size:返回图片长短尺寸
corp:截取图片的一部分
resize:缩放图片

2、可以实现backend server的图片转换。对于访问量不大,但是需求多种尺寸的网站可以使用1台图片服务器作为原图存储,在展示时使用nginx进行实时转换,以节省空间资源。

3、对于大访问量的站点,可以在nginx之前再搭建一台vanish做缓存。由vanish分担并发压力,nginx仅在图片被第一次访问时生成缩略图。这样便可以在很大程度上节省了服务器空间。这种设计也有一个问题,就是在vanish崩溃、重启之后,缓存未生成,大量图片需要进行实时转换,nginx的压力一定会很大。

Mac OSX中关闭打开下载文件时的警告

OSX上的打开下载文件警告提示太烦人了,尤其是当你解开一个从网上下载回来的程序包的,比如wordpress,每点开一次文件都要点一次确认。google一番总算找到了方法,记录如下:
10.5的系统,因为xattr命令不支持递归操作,所以只能用find搭配-exec参数来做了
find ~/Downloads/ -type f -exec xattr -d com.apple.quarantine {} \;

对于10.6(snow leopard): 直接用-r参数即可
xattr -d -r com.apple.quarantine ~/Downloads

以上两条是针对~/Download目录进行的,也可以通过直接关闭系统配置,停用这一功能。但是据说在10.7(mountain lion)中无效⋯⋯
defaults write com.apple.LaunchServices LSQuarantine -bool NO

后悔的时候可以改回来
defaults write com.apple.LaunchServices LSQuarantine -bool YES

公元二零一一年总结

二零一一,飘忽迷离。
碎碎小事,提笔轻记。
生有所依,睡有所栖。
食能自适,无甚恶疾。
山路崎岖,戚戚寂寂。
人间百态,感触不一。
世外桃源,吾心之系。
日有所思,夜无所弃。
拾得正果,前途无际。

Nginx像Apache一样做反向代理

我们都知道Nginx是可以做反向代理的,就像Apache的ProxyPassReverse一样。
在apache中配置反向代理,我们这样写:

<VirtualHost myhost:80>
ServerName myhost
  DocumentRoot /path/to/myapp/public
  ProxyPass / http://myapp:8080/
  ProxyPassReverse / http://myapp:8080/
</VirtualHost>

但是Nginx没有ProxyPassReverse,解决办法就是添加丢失的HTTP头:

server {
  listen myhost:80;
  server_name myhost;
  location / {
    root /path/to/myapp/public;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://myapp:8080;
  }
}

那些丢失的头信息都是什么呢?

X-Forwarded-For:客户端IP地址
X-Forwarded-Host:客户端发起的原始主机请求头信息
X-Forwarded-Server:代理服务器主机名

Mac OSX上重新编译PHP后提示Syntax error的解决办法

Mac OS X 对于非开发人员提供了很好的体验,对于Web开发人员也很厚道。不但提供了Apache Web Server、FTP Server,还集成了很多开发环境:C、Python、PHP等等,而且版本比较新,扩展也很完善。可套餐终归是不如单点。在产品经理的各式各样需求前面,终于还是闹饥荒了。

不久之前由于需要PHP扩展的freetype模块,但是系统本身没有内建,所以只能自己动手。首先想到的是编译成动态扩展库的方式,按照装各种lib都很顺畅,也成功的编译gd.so文件。但是由于系统的PHP已经内建了gd,再load此文件会报错,google一番无解,所以只好放弃。重新编译吧,没有别的办法了。编译过程比较顺利,和Linux下过程一样,不在啰嗦了。但是重启Apache的时候出现下面的提示:

httpd: Syntax error on line 117 of /private/etc/apache2/httpd.conf: Cannot load /usr/libexec/apache2/libphp5.so into server: dlopen(/usr/libexec/apache2/libphp5.so, 10): Symbol not found: __cg_png_create_info_struct
Referenced from: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/ImageIO
Expected in: /usr/lib/libpng15.15.dylib
in /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/ImageIObogon:php-5.3.6

(更多…)

Debian中升级Nginx到最新1.0

新版本的Nginx中提供了很多功能,而且在生产服务器中表现也相当不错。可惜VPS上用的是Debian 6,而在apt源中提供的Nginx版本太低,只有0.7。我能想到的升级办法有3个:1、更换其他的源;2、自己重新编译;3、使用测试版本。前2种方式都比较麻烦,更何况本人对于第三方源所提供的软件感觉不正统,也不是很信任。所以第三个方法就成了最适合我的选择。更新步骤很简单,流水记录如下:
1、安装apt-spy
apt-get install apt-spy
2、测试速度最快的源地址,并切换到测试版。部分参数说明:
-a 选择镜像服务器区域。VPS在美国,所以这里使用North-america。如果在中国使用Asia
-d 选择部署版本:stable稳定版、testing测试、unstable不稳定版本
-t 服务器相应时间,默认15
apt-spy -d testing -a North-america -t 10
3、更新apt的packages list
apt-get update
4、重新安装nginx
apt-get install nginx
如果之前修改了nginx的配置文件,那么重新安装的过程中会给予是否备份的提示。当然手动备份还是最保险的~

PHP的ntohl网络字节序函数及相关知识

最近项目中使用到了PHP与C服务器的socket通信,在做数据转换的时候,PHP没有提供对应将网络字节序和机器字节序相互转换的程序,但是根据函数的意义,我们可以做相应的转换来实现这一函数:

function ntohl($str){
	$arr = unpack('I', pack('N', $str));
	return $arr[1];
}

函数的意义
程序的作用是将网络字节序和机器字节序进行相互转换。在C/C++、Python、Delphi中都提供了相应的函数“ntohl”和“htonl”,如果是short类型就是“ntohs”和“htons”。下面是这些函数的意义:

ntohl()--"Network to Host Long"
htonl()--"Host to Network Long"
htons()--"Host to Network Short"
ntohs()--"Network to Host Short"

什么是主机字节序
不同的机器字节序不相同,这与使用的CPU有关。不同的CPU在处理高位字节时所存储的顺序是不同的。
例如Intel x86结构下, short型数0x1234表示为34 12, int型数0x12345678表示为78 56 34 12
如IBM power PC结构下, short型数0x1234表示为12 34, int型数0x12345678表示为12 34 56 78

网络字节序
正是由于每个主机的处理顺序有可能不同,所以在网络协议中规定数据从高到低顺序存储,目的是在不同架构的主机中可以正常通信,避免兼容性问题。