Category Archives: VPS && hosting

KVM的node被死锁了怎么办

有个KVM的VM死锁了,无论是用virsh shutdown 111 还是 virsh shutdown 111 都会报错:

  #[root@s10 ~]# virsh shutdown 111
  #错误:关闭域 111 失败
  #错误:Timed out during operation: cannot acquire state change lock

解决的办法如下:

  #virsh undefine 111
  #virsh define /etc/libvirtd/111.xml
  #virsh start 111

用undefine命令取消这个VM,然后重新定义,启动就OK了

极高的CPU的load average

有个Openvz guest对CPU占用太高,就限制CPU使用率,没想到引起load average的奇高无比,甚至达到了24!后来才发现就是因为给这个guest限制了CPU,所以导致如此。可以用Openvz的工具查看guest的load average:

vzlist -o ctid,laverage

Openvz的guest一般在被CPU限速或者IO限制的情况下,都会导致CPU load average居高不下。

WHCMS强制https后支付宝掉单的问题

自动前几天whmcs强制使用https后,支付宝支付一直处于掉单的状态:具体表现为,客户以及通过支付宝支付,但是WHMCS后台仍显示“未支付”。

看了下alipay的gateway源码,有一项是设置callback的:

$parameter = array(
	"service"         => "create_direct_pay_by_user",  //交易类型
	"partner"         => $gatewayPID,          //合作商户号
	"return_url"      => $systemurl."/modules/gateways/callback/alipay_return.htm",       //同步返回
	"notify_url"      => $systemurl."/modules/gateways/callback/alipay_callback.php",       //异步返回
	"_input_charset"  => $_input_charset,   //字符集,默认为GBK
	"subject"         => "$companyname 订单",        //商品名称,必填
	"body"            => $description,      //商品描述,必填
	"out_trade_no"    => $invoiceid,        //商品外部交易号,必填(保证唯一性)
	"total_fee"       => $amount,           //商品单价,必填(价格不能为0)
	"payment_type"    => "1",               //默认为1,不需要修改

	"show_url"        => $systemurl,         //商品相关网站
	"seller_email"    => $gatewaySELLER_EMAIL      //卖家邮箱,必填
);

我猜想“/modules/gateways/callback/alipay_callback.php”就是支付宝服务器在用户支付成功后通知whmcs支付宝gateway的,但是由于Nginx强制使用https导致支付宝服务器和这个callback的通讯有问题,引起掉单。

解决办法就是在Nginx中去掉对callback的URL强制转换https,本来想用Nginx rewrite模块的if条件,但是Nginx官方不建议使用if条件,因为if is evil,后来直接在conf中独立对callback添加一处设置就行了:

location whmcs/modules/gateways/callback/alipay_callback.php {
break;
}

重启Nginx后,一切OK

申请SSL证书以及Nginx配置

申请的namecheap的ssl证书(其实namacheap也是comodo的代理),首先要创建Certificate Signing Request (CSR)后才能把CSR输入网站,邮件验证后才能生成证书。

1. 在服务器上创建Certificate Signing Request (CSR)

要使用SSL必须有独立IP地址,所有共享IP的虚拟主机是没有办法申请的。首先把目录切换到Nginx的conf文件目录:

#cd /usr/local/nginx/conf
#openssl req -nodes -newkey rsa:2048 -keyout myserver.key -out server.csr

运行上述命令后就在目录下创建了两个文件:myserver.key和server.csr.myserver.key是你的私钥,要妥善保管。然后openssl会让你输入一些信息:

Country Name (2 letter code) [AU]: GB
State or Province Name (full name) [Some-State]: Yorks
Locality Name (eg, city) []: York
Organization Name (eg, company) [Internet Widgits Pty Ltd]: MyCompany Ltd
Organizational Unit Name (eg, section) []: IT
Common Name (eg, YOUR name) []: mysubdomain.mydomain.com
Email Address []:

域名一定要输入你的域名,email也要输入注册域名时候的whois信息中的邮箱地址。

A challenge password []:
An optional company name []:

这两项可以留空。

然后运行下面命令,显示CSR文件内容:

#cat server.csr

把包含“—–BEGIN CERTIFICATE REQUEST—– ”和“—–END CERTIFICATE REQUEST—– ”在内的内容拷贝。

2. 验证

把CSR的信息输入namecheap后,第二步会有一个可选的邮件地址让你选择,本别是admin@youdomain.com或者webmaster@youdomain.com还有你的whois信息中的邮箱地址,我让选了了whois信息中的邮箱地址。namecheap会向这个邮箱发送一封验证信,根据信中的地址输入验证码后就会向你发送包含证书文件的压缩包了。

解压后把这三个文件通过FTP或者SFTP上传到Nginx的conf目录。

3.Nginx配置文件
Nginx的配置文件需要两个文件,一个是SSL的私钥,也就是刚才第一步创建的myserver.key;另一个是comodo通过邮件发给我的压缩包中文件的“合体”:

cat www_yourdomain_com.crt PositiveSSLCA2.crt AddTrustExternalCARoot.crt >> ssl-bundle.crt

创建的ssl-bundle.crt就是所需的“合体”。
下面创建一个ssl.conf:

server
{
        listen      443;
        server_name yourdomain.com www.yourdomain.com;
        index index.html index.htm index.php;
        root /home/wwwroot;
        ssl on;
        ssl_certificate ssl-bundle.crt;
        ssl_certificate_key myserver.key;
        ssl_protocols SSLv3 TLSv1;
        ssl_ciphers ALL:!aNULL:!ADH:!eNULL:!LOW:!EXP:RC4+RSA:+HIGH:+MEDIUM;
        location ~ .*\.(php|php5)?$
        {
        fastcgi_pass  unix:/tmp/php-cgi.sock;
        fastcgi_index index.php;
        fastcgi_param  HTTPS on;
        include fcgi.conf;
        }
        access_log  off;
}

然后在ningx.conf中引用这个ssl.conf即可。

6.Nginx子目录rewrite
如果网站全部通过https访问的话,肯定会给服务带来很多压力(ssl证书每次加密需要CPU运算),所以我只希望某些子目录使用https访问,并且对使用http访问的强制转向至https:

server {
        listen          80;
        server_name     domain.com;

        location / {
                index index.php index.html;
                root  /home/domain.com/public;
                }

        #Redirect Admin requests to secure server
        location ^~ /www/admin/ {
                rewrite ^/(.*) https://domain.com$1 permanent;
                }
}

这样就能强制所有试图用http访问/www/admin/子目录的请求rewrite至https,增加网站的安全性。

5.结尾
重启后通过https就能访问网站了,不过我发现申请comodo廉价SSL证书后,浏览器并没有出现像其他大网站SSL访问时候的效果:

我申请的征收只有显示一把绿色的锁而已,后来查了Google的说明才知道,那样效果的SSL证书是EV SSL证书,价格比较贵:

图标 含义
圆球 此网站未使用 SSL。大多数网站不需要使用 SSL,因为它们不处理敏感信息。请避免在此类网页上输入敏感信息,比如用户名和密码。
锁定图标绿色的 https Google Chrome 浏览器成功地与该网站建立了安全连接。如果您需要登录该网站或在该网页上输入敏感信息,请查找此图标并确保该网址具有正确的域名。

如果网站使用了扩展验证安全套接字层 (EV-SSL) 证书,则单位名称也会以绿色字体显示在该图标旁。请务必将浏览器设置为检查服务器证书吊销状态,以鉴别网站是否有 EV-SSL 证书。

提醒图标 黄色的 https 该网站使用 SSL,但 Google Chrome 浏览器在网页上检测到不安全的内容。请勿轻易在此网页上输入敏感信息。不安全的内容会产生漏洞,给他人提供更改网页外观的可乘之机。
提醒图标 红色的 https 该网站使用 SSL,但 Google Chrome 浏览器在该网页上检测到高风险的不安全内容或该网站的证书有问题。请勿在此网页上输入敏感信息。无效证书或其他严重的 https 问题表明有人试图篡改您与该网站的连接。

Nginx实现目录密码保护

web目录的管理目录一般都不希望除了管理员之外的人访问吗,当然php内置的用户验证安全性非常重要,如果在web服务器上加入目录访问验证的话,效果当然更好。目前我用的是Nginx,需要如下开启目录访问密码验证:

location /secret {
   auth_basic            "Restricted";
   auth_basic_user_file  /etc/htpasswd;
 }

这样设置的话,如果用户访问secret目录的话,首先要接受Nginx本身内置的密码验证系统(保存在/etc/htpasswd文件中)。但是如何创建这个密码验证文件?如果安装了Apache的话,apache内置有生成htpasswd的工具,nginx的话只有利用shell的内置工具:

printf "user:$(openssl passwd -crypt yourdomian)\n" >> /etc/htpasswd

上面的命令就能创建一个用户名为user,密码为yourdomian的用户。

但是如果被保护的web目录中包含有php文件的话,直接访问php的话就不需要输入密码了,需要把Nginx的conf文件改一下:

location /secret {
   auth_basic            "Restricted";
   auth_basic_user_file  /etc/htpasswd;
   location ~ \.php$ {
        fastcgi_pass   127.0.0.1:9000;
        include        fastcgi.conf;
    }
}

把php的解析复制一段,放在对secret目录里面,再访问这个目录里面的php文件的话就需要输入密码了。

用Nginx的GoIP做转向

目的是不像让非国内用户访问whmcs系统,nginx.conf配置如下:

location /whmcs/ {
if ($geoip_country_code = CN) {
rewrite ^/whmcs/(.*)$ /p.php last;
break;
}
}

但是如果访问/whmcs/index.php 这样存在的文件的时候,nginx还是会解析而不是参考我的rewrite规则,后来换成了:

location ^~ /whmcs/ {
if ($geoip_country_code = CN) {
rewrite ^/whmcs/(.*)$ /p.php last;
break;
}
}

一切OK了。

IP地址以及子网掩码的关系

什么是IP地址?
人们为了通信方便给每一台计算机都事先分配一个类似电话号码一样的标识地址,即IP地址。
根据TCP/IP协议,IP地址由32位二进制数组成,而且在INTERNET范围内是唯一的。
如:某IP地址为11000000 10101000 00001010 00000010
为了方便记忆,人们把32位的IP地址分成四段,每段8位,中间用小数点“.”隔开,然后再将每8位二进制换成十进制,即192.168.10.2

IP地址的分类
就像电话号码一样分为区号和具体号码一样,我们把IP地址分为两个部分:网络标识和主机标识。
网络标识
同一物理网络上的所有主机都用同一个网络标识,网络上每一个主机都有一个主机标识与其对应。
主机标识
即为某个网络中特定的计算机号码。
例:一个主机服务器的IP地址为192.168.10.2,其中
网络标识为192.168.10.0
主机标识为2

IP地址共占4个字节32位,其一部分为网络标识,另一部分为主机标识。由于网络中所包含的计算机数量可能不一样多,人们按照网络规模的大小把IP地址按3种方法来划分,分别是:
1,A类IP地址
在IP地址的4段号码中,第1段为网络标识,其余3段为主机标识。也就是说:A类IP地址由1字节的网络标识和3字节的主机标识组成。
网络地址的最高位必须是0,网络标识的长度为7位,主机标识的长度占24位。
A类IP网络地址数量较多,适用于大型网络,可用主机数达1600万多台。
2,B类IP地址
在IP地址的4段号码中,前2段为网络标识,后2段为主机标识。也就是说:B类IP地址由2字节的网络标识和2字节的主机标识组成。
网络地址的最高位必须是10,网络标识的长度为14位,主机标识的长度为16位。
B类IP网络地址适用于中等规模网络,可用主机数达6万多台。
3,C类IP地址
在IP地址的4段号码中,前3段为网络标识,最后1段为主机标识。也就是说:C类IP地址由3字节的网络标识和1字节的主机标识组成。
网络地址的最高位必须是110,网络标识的长度为21位,主机标识的长度为8位。
C类IP网络地址数量较少,适用于小型局域网络,可用主机数最多254台。

另外,TCP/IP协议规定,凡IP地址中的第一个字节以11110开始的地址叫 多点广播地址 。因此,任何第一个字节大于223小于240的IP地址是多点广播地址;IP地址中凡是以11110的地址都将留着作为特殊用。

IP地址的寻址规则
1.网络寻址规则
A、网络地址必须唯一。
B、网络标识不能以数字127开头。在A类地址中,数字127保留给内部回送函数(127.1.1.1用于回路测试)。
C、网络标识的第一个字节不能为255。数字255作为广播地址。
D、网络标识的第一个字节不能为“0”,“0”表示该地址是本地主机,不能传送。
2.主机寻址规则
A、主机标识在同一网络内必须是唯一的。
B、主机标识的各个位不能都为“1”,如果所有位都为“1”,则该机地址是广播地址,而非主机的地址。
C、主机标识的各个位不能都为“0”,如果各个位都为“0”,则表示“只有这个网络”,而这个网络上没有任何主机。

子网掩码简述
子网掩码也是一个32位地址,其作用是:
用于屏蔽IP地址的一部分以区分网络标识和主机标识,并说明该IP地址是在局域网上,还是在远程网上。
只有同在一个子网中的主机才能互相通讯联系,否则就要通过特殊手段了。

例1:设IP地址为192.168.10.2,子网掩码为255.255.255.240,那么子网掩码是怎样来区分网络标识和主机标识的呢。
答:
用“与”运算。将十进制转换成二进制进行与运算
IP地址:11000000 10101000 00001010 00000010
子网掩码:11111111 11111111 11111111 11110000
AND运算:
--------------------------
11000000 10101000 00001010 00000000
则可得其网络标识为192.168.10.0,主机标识为2。

例2:设设IP地址为192.168.10.5,子网掩码为255.255.255.240
用“与”运算。将十进制转换成二进制进行与运算
IP地址:11000000 10101000 00001010 00000101
子网掩码:11111111 11111111 11111111 11110000
AND运算:
--------------------------
11000000 10101000 00001010 00000000
则可得其网络标识为192.168.10.0,主机标识为5。

从以上两个例子可以得出,只要有一个IP地址和以上的子网掩码运算后得到192.168.10.0,那么这些IP地址就在同一个子网中。

如果比较熟悉二进制的朋友就会发现,由于掩码最后一段为11110000,所以,在前三段都一样的情况下,只要主机标识的前四位都为0,所得到的IP地址必在同一个子网中。而且也不难算出,在255.255.255.240这样一个子网掩码下,最多只有16台主机在同一子网中。
由此可得出,经常在局域网中见到的子网掩码255.255.255.0,最多也只能有255台主机在同一子网中。

VLSM(可变长掩码)
3类IP地址默认的子网掩码分别为255.0.0.0、255.255.0.0和255.255.255.0。但这难免会浪费一些IP地址。
就拿C类IP地址的默认掩码来说,可以有253台主机共在一个子网中(除去全为1和0的,见上IP地址的寻址规则)。
假设申请了一个C类IP地址:192.168.10.*,那么IP地址从192.168.10.1到192.168.10.254都在一个子网,假设现在只有13台主机,那么就会浪费240台主机了。
但如果有VLSM就不同了。上述例子中的255.255.255.240就是这一种,根据我们刚才的运算,它只会有14台可用主机(除去全为0和1的)。
在使用该子网掩码255.255.255.240时:
IP地址为192.168.10.1到192.168.10.15在同一子网中,其网络标识为192.168.10.0;
而IP地址为192.168.10.16或1923168.10.18就不在上面的子网中,其网络标识为192.168.10.16。

安装Munin监控替代Cacti

这次添加第二台服务器的时候是在受不了Cacti了,全都换成了Munin监控。

在CentOS5上安装的话,Munin并没有在官方的yum源中,需要自己手工添加yum源:

#rpm -Uvh http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-4.noarch.rpm
#wget http://download.fedoraproject.org/pub/epel/5/i386/epel-release-5-4.noarch.rpm
#rpm -Uvh epel-release-5-4.noarch.rpm

centos6的话可能需要安装epel6.5的版本:

wget http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-5.noarch.rpm
rpm -ivh epel-release-6-5.noarch.rpm

然后在创建一个文件:/etc/yum.repos.d/dag.repo

#vim /etc/yum.repos.d/dag.repo
[dag]
name=Dag RPM Repository for Red Hat Enterprise Linux
baseurl=http://apt.sw.be/redhat/el$releasever/en/$basearch/dag
gpgcheck=1
gpgkey=http://dag.wieers.com/rpm/packages/RPM-GPG-KEY.dag.txt
enabled=1

弄完以后就可以通过yum来安装Munin了。

1. 监控端(生成Munin图表的server)安装:

#yum -y install munin

2. 被监控端(提供运行数据的server)安装:

#yum -y install munin-node

3. 监控端配置:
Munin不用设置用户,只需要制定一个发布图表的目录即可,当然这个目录最好是web服务器中的目录,这样就能够直接通过web服务器查看监控信息了:

# vim /etc/munin/munin.conf
Configfile for Munin master
dbdir       /var/lib/munin/
htmldir     /var/www/munin/
#如果/var/www是web服务器的主目录的话,就在里面创建一个用户名为munin的目录否则munin无法写入;名称随便可以起,例子中的名称也是munin
logdir      /var/log/munin
rundir      /var/run/munin/

# This is an example of the correct way to activate Nagios warnings
contact.nagios.command /usr/local/nagios/bin/send_nsca nagioshost.example.com -c /usr/local/nagios/etc/send_nsca.cfg -to 60

# From and including the first host, no more global directives can be defined.
# Everything after one host definition belongs to that host, until another host definition is found.

[foo.example.com]             # 创建一个名为foo.example.com的监控
                              # 
  address 12.23.34.56         #被监控的IP地址为12.23.34.56 

4. 被监控端配置

# vim /etc/munin/munin-node.conf
log_level 4
log_file /var/log/munin/munin-node.log
port 4949
pid_file /var/run/munin/munin-node.pid
background 1
host *
user root
group root
setsid yes
ignore_file ~$
ignore_file \.bak$
ignore_file %$
ignore_file \.dpkg-(tmp|new|old|dist)$
ignore_file \.rpm(save|new)$
# host_name localhost.localdomain
allow ^127\.0\.0\.1$
#指定自己允许被那个IP地址监控,写成正则表达式的格式,例如允许被12.21.34.43监控就写成allow ^12\.21\.34\.43$

然后分别启动监控端的munin服务和被监控端的munin-node服务即可。第一次画图会比较慢,等几个小时后图形就正常了。
监控服务端启动:

#service munin start
#chkconfig munin on //为了保证服务开机启动

被监控段启动:

#service munin-node start
#chkconfig munin-node on //为了保证服务开机启动