升级PHP 7.1并启用PHP-FPM

一个多月前把系统升级到了Debian Buster,同时Apache也升级到了2.4.27,然后就发现HTTP/2没法用了,因为那时忙别的事情,也就没去管它。

今天闲着无事,就翻了翻文档,才发现在Apache 2.4.27中,Apache MPM (Multi-Processing Module) prefork取消了对HTTP/2的支持。因此,准备随即切换到Apache MPM event。

但随之而来的一个新问题就是,Apache服务器下,PHP所使用的mod_php模块只能支持prefork,因此,同时要将PHP切换到php-fpm以在FastCGI模式下运行PHP。然后想想,不如同时把PHP升级到7.1版本算了。

首先要做的,就是卸载PHP 7.0,虽然直接安装也行,但我还是选择了卸载,反正留着也没用。如果有安装phpMyAdmin,因为依赖被卸载,所以也会连带被卸载,这里直接选择卸载重装。

apt-get purge phpmyadmin php7.0-gd php7.0-xml php7.0 php-pear php7.0-mysql php7.0-common
apt-get autoremove

然后重新安装PHP 7.1,可以一步安装完所有包,也可以分开安装。这里为了写得清楚一点,分开写。但需要注意的是,如果一步安装PHP 7.1基本包的同时安装php7.1-fpm,默认就不会安装包含了mod_php模块的libapache2-mod-php7.1,如果你要用mod_php,要么分开两步装,要么别装php7.1-fpm。

首先安装LAMP需求的包。

apt-get install php7.1 php-pear php7.1-mysql

然后是WordPress需求的包。

apt-get install php7.1-gd php7.1-xml

然后是php-fpm。

apt-get install php7.1-fpm

最后装回phpMyAdmin,需要注意的是,phpMyAdmin默认安装的需求包是php7.0-mbstring,在PHP 7.1下会提示缺少mbstring,这个问题困扰了好久!最后发现,直接选择安装php7.1-mbstring就解决了!

apt-get install phpmyadmin php7.1-mbstring

安装完成之后重新配置以下phpMyAdmin就行。可以参考这里:写给像我这样的新手的phpMyAdmin教程 (Apache)

之后就是启用PHP-FPM了。

首先关闭Apache服务器。

service apache2 stop

再执行以下命令。

a2enmod proxy_fcgi setenvif
a2enconf php7.1-fpm
a2dismod php7.1
a2dismod mpm_prefork
a2enmod mpm_event

最后重新启动Apache,这样就大功告成了,很简单。然后测试一下,我遇到了些问题,最后发现是自己写的.htaccess里面有一些PHP语句需要更新,这方面注意一下。

本站已正式添加DNS CAA

DNS Certification Authority Authorization (DNS CAA)是通过为域名添加一条DNS CAA记录,来限制特定CA为该域名签发证书的一种方法,从而实现防止攻击者使用其他CA错误签发的证书进行中间人攻击。

现在支持DNS CAA的DNS服务供应商还不多,但从2017年9月8日起,所有CA将被要求检查并遵守域的CAA记录,到那个时候DNS CAA应该会快速普及。另一方面,SSL Labs早在今年年初就开始检测DNS CAA记录,虽然暂时还没有影响到评级,但没有添加CAA记录的域名会被标记为橙色警告。

本站现在添加的CAA记录有两条,分别为

prinice.org. IN CAA 0 issue “letsencrypt.org”
prinice.org. IN CAA 0 issue “comodoca.com”

也就是只允许Let’s Encrypt和COMODO两家CA为本域名签发证书。要了解更多DNS CAA的内容,可以参见本站另一篇文章:DNS Certification Authority Authorization (DNS CAA)简介和部署教程

DNS Certification Authority Authorization (DNS CAA)简介和部署教程

可能很多人对HTTP Public Key Pinning (HPKP)已经有所了解,也有少数网站已经开始部署HPKP用来防止攻击者使用CA错误签发的证书进行中间人攻击。但HPKP由于部署难度非常大,而且不合适的部署会影响网站的访问甚至弄垮一家公司,所以,HPKP的使用率一直不理想。DNS Certification Authority Authorization (DNS CAA)则用另一种实现方法解决了这个问题。

DNS CAA通过添加一条DNS CAA记录,限制可签发该域名证书的CA,从而实现防止攻击者使用其他CA错误签发的证书进行中间人攻击。相比HPKP,DNS CAA的实现更加简单方便,但缺点也很明显。HPKP可以根据需要,固定不同级别的证书,比如可以固定网站现有的证书来实现最高的安全性,也可以固定CA的中间证书,从而保证网站的可访问性,如果你高度信任CA的根证书,甚至还可以固定根证书。而DNS CAA却只能选择一家或几家信任的CA为其签发证书,效果类似于HPKP固定CA的证书。所以,相比HPKP的高部署难度,DNS CAA是一种非常好的折衷方案,并且,它可以和HPKP同时部署。

接下来讲讲如何部署DNS CAA。如果DNS服务提供商有提供CAA记录,那么非常简单,设置一条CAA记录即可,例如Let’s Encrypt的CAA记录。

example.org. CAA 0 issue "letsencrypt.org"

也可以增加以下内容,在发现攻击者使用CA错误签发的证书进行中间人攻击时发送邮件告知。

example.org. CAA 0 iodef "mailto:caa@example.org"

但是,现在支持CAA记录的DNS服务提供商还很少,我知道的只有Google Cloud DNS、DNSimple,不过随着Qualys SSL Labs增加对DNS CAA的检测,相信很快会有更多的DNS服务提供商会增加对CAA记录的支持。

如果要自己部署DNS服务来实现DNS CAA,目前BIND ≥9.9.6, PowerDNS ≥4.0.0, NSD ≥4.0.1, Knot DNS ≥2.2.0都已经对其提供较好的支持。

使用iptables-persistent自动加载iptables规则 (Debian)

以前写过一个将脚本写入/etc/network/ifpreup.d目录下来加载iptables规则的方法:开机自动加载iptables规则 (Debian)

但是有些主机商的系统并不能很好地支持这种方式,所以这次再写一篇用iptables-persistent来实现的方法。

值得注意的是,iptables-persistent不仅支持IPv4规则,也支持IPv6规则,功能非常全面,而且使用非常方便。下面重点讲讲如何进行配置,适用于Debian和Ubuntu。

首先配置好iptables规则,如有需要,同时配置好ip6tables规则。

然后安装iptables-persistent。

apt-get update
apt-get install iptables-persistent

安装过程中,交互安装程序会问你是否要导入已经配置的IPv4和IPv6规则,选是就直接导入生效了,非常方便。

那么以后如果要修改iptables或ip6tables的配置怎么办呢?其实也很简单,iptables-persistent的配置文件有两个,分别是/etc/iptables/rules.v4和/etc/iptables/rules.v6。

重新配置完iptables或ip6tables规则后执行以下命令就可以。

iptables-save > /etc/iptables/rules.v4
ip6tables-save > /etc/iptables/rules.v6

通过这种方法配置iptables更为简便和直观,更加推荐。

Debian开启BBR算法

Linux Kernel 4.9中,增加了一种全新的TCP拥堵控制算法——BBR,拥有着非常优秀的性能,同时也保证了和其他TCP拥堵控制算法的相容性。BBR的目的是要尽量跑满带宽,并且尽量不要有排队的情况。

由于Linux Kernel 4.9还未正式发布,现阶段Debian要使用BBR,比较简单的方法只有通过experimental源来安装。

虽然Linux Kernel 4.9已经正式发布,但还在Debian的sid源,现阶段Debian要使用BBR,比较简单的方法只有通过sid源来安装。

首先在/etc/apt/sources.list中添加experimental源,用文本编辑器在文件最后添加以下内容。

首先在/etc/apt/sources.list中添加sid源,用文本编辑器在文件最后添加以下内容。

deb http://httpredir.debian.org/debian experimental main
deb http://httpredir.debian.org/debian sid main

需要注意的是,apt-get默认不会安装experimental源的包,所以,用以下命令安装。

apt-get update
apt-get -t experimental install linux-image-4.9.0-rc8-amd64-unsigned
apt-get install linux-image-4.9.0-1-amd64-unsigned

然后重启,默认就是使用新的内核,你也可以选择将老的内核删除。默认的TCP拥堵控制算法不是BBR,还要通过配置文件开启。

创建一个/etc/sysctl.d/local.conf文件,写入以下内容。

net.core.default_qdisc=fq
net.ipv4.tcp_congestion_control=bbr

然后输入以下命令使配置生效。

sysctl --system

再执行以下命令看下,如果结果里面有bbr说明已经成功开启。

sysctl net.ipv4.tcp_available_congestion_control

最后再输入以下命令,看到tcp_bbr模块就说明BBR已经启动。

lsmod | grep bbr

这样就搞定了,等Linux Kernel 4.9正式发布之后,开启就更简单了,Debian 9 (Stretch)正式版发布时应该会直接使用4.9或更新的内核,到时候直接开启就行。

Thanksgiving Day 2016

最近一直很忙,本来想写一篇Let’s Encrypt的帐户ID管理的文章的,一直没空动笔,等这阵子忙完吧。总之,Happy Thanksgiving!

让浏览器下载而不是打开某些文件的简单方法 (Apache)

很多时候,我们希望能让浏览器下载某些Web服务器上的文件,而不是直接打开它们。常见的比如txt、jpg等文件,大多数浏览器通常会默认选择打开而不是下载。这就需要我们在服务器上作一些简单的配置。实现的方法有很多种,这里我写一下现在比较常用的一种简单方法,通过.htaccess文件来配置,适用于Apache。

首先要让.htaccess文件生效,具体就不再写了,不了解的参考这里:Apache开启重定向HTTP至HTTPS

然后在网站放置下载资源的目录创建.htaccess文件,并写入下列内容,这里以.txt和.jpg为例。

AddType application/octet-stream .txt
AddType application/octet-stream .jpg

设置完之后,只要是在该文件夹下的.txt和.jpg文件,浏览器默认会下载该文件而不是直接打开。

Apache启用HTTP/2

这几天启用了HTTP/2,其实方法很简单,我懒得编译,就直接把系统升级到了Debian Stretch,然后只要输几条命令就开启了HTTP/2。注意,在Apache下启用HTTP/2需要Apache版本在2.4.17及以上,OpenSSL版本1.0.2及以上。

首先启用mod_http2。

a2enmod http2

然后修改站点的配置文件,这里以默认的default-ssl.conf为例。

vi /etc/apache2/sites-available/default-ssl.conf

在最后添加以下字段。

# HTTP/2 in a VirtualHost context (TLS only)
Protocols h2 http/1.1

这是针对浏览器的仅启用TLS,如果你针对的是自己开发的程序,并且不启用TLS,可以写成。

# HTTP/2 in a Server context (TLS and cleartext)
Protocols h2 h2c http/1.1

很简单,这样就搞定了。

本站已开始使用ECC证书

Let’s Encrypt开始签发ECC证书已经有一段时间了,而且很多网站都开始换用ECC证书了,本站也在最近换用了Let’s Encrypt的ECC证书。这里简单就写个介绍和教程。

ECC证书也就是内置了ECDSA公钥的证书,而传统的RSA证书内置的是RSA公钥。ECC证书公钥长度短,256 bits的ECC Key安全性等效于3072 bits的RSA Key,运算速度更快。因此,ECDHE密钥交换+ECDSA数字签名无疑是目前更好的选择。ECC证书并不支持老旧的Windows XP和Android 2.x,但考虑到本站的客户群根本不是这些用古老客户端的人群,所以就无视了。

比较遗憾的是,现在Let’s Encrypt的中间证书依然是RSA证书,所以从整个证书链来讲也没有缩短多少,期待明年Let’s Encrypt开始采用ECC中间证书。ECDSA Intermediates (ETA: Before March 31, 2017)

这里推荐使用acme.sh来获取ECC证书,使用起来非常简单,而且还支持DNS验证域名,更灵活。

先是安装。

wget -O -  https://get.acme.sh | sh

acme.sh支持多种验证方式,并且支持Apache配置,非常方便,详见GitHub页面

如果你已经在服务器上运行了Apache,并且正确配置了DNS解析、hostname、fully-qualified domain name (FQDN)、ServerName和ServerAlias,那可以直接使用Apache模式,很简单的命令。

acme.sh --issue --apache -d aa.com -d www.aa.com -d user.aa.com --keylength ec-256

这样就获得了ECC证书,并且acme.sh支持自动续期,只要你不更改上面所说的配置,每隔80天会自动续期。ec-256是ECC Key长度,可选ec-384,但其实选用ec-256已经足够安全。

接下来,OpenSSL版本是1.0.2或更高,可以尝试部署ECC+RSA双证书以保证向后兼容性,你也许还需要获取一个RSA证书,只要输入以下命令就行。

acme.sh --issue --apache -d aa.com -d www.aa.com -d user.aa.com

接下来这里讲讲DNS验证,其实也很简单,先输入以下命令。

acme.sh --issue --dns -d aa.com -d www.aa.com -d user.aa.com --keylength  ec-256

然后会看到一串字符串。

Add the following txt record:
Domain:_acme-challenge.aa.com
Txt value:9ihDbjYfTExAYeDs4DBUeuTo18KBzwvTEjUnSwd32-c

Add the following txt record:
Domain:_acme-challenge.www.aa.com
Txt value:9ihDbjxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Please add those txt records to the domains. Waiting for the dns to take effect.

去你的DNS服务提供商处添加相应的TXT记录,等DNS记录生效后,再运行以下命令。

acme.sh --renew -d aa.com --ecc

这样就获得了ECC证书。

接下来,你也许还需要获取一个RSA证书,只要输入以下命令就行。

acme.sh --issue --dns -d aa.com -d www.aa.com -d user.aa.com

这时会看到域名已经验证的提示,直接获得对应的RSA证书。更改Apache或者其他要用证书的服务器端软件的配置,也许还要更改一下Cipher Suite等安全配置,参考这里,这样就大功告成了。

HTTP Public Key Pinning (HPKP)简介和部署教程(Apache)

HTTP Public Key Pinning (HPKP),中文一般译作“HTTP公钥固定”或者“HTTP公钥钉”,它是一种HTTPS网站防止攻击者使用CA错误签发的证书进行中间人攻击的安全机制,例如有时攻击者可以入侵CA然后偷偷签发证书,现在也有一些还在被浏览器信任的CA频频被曝出签发伪造证书。启用HPKP的网站,由HTTPS网站服务器提供一个公钥哈希列表并使客户端在后续的链接中只接受在列表上的一个或多个公钥。

服务器通过Public-Key-Pins HTTP头向浏览器指定公钥,退一步,也可以通过Public-Key-Pins-Report-Only HTTP头向浏览器报告非法公钥,而非直接拒绝访问。当然,最追求安全的做法就是强制固定公钥。

如今配置了HPKP的网站还不到1%,其原因在于,HPKP的部署是需要深思熟虑的,不恰当的配置会引来诸多麻烦,错误的配置会导致网站长期无法访问,这可以直接毁掉一家大型的公司。

关于HPKP更多的介绍建议直接搜索专业的文档,这里接下来就以Apache服务器端为例讲讲如何在一个网站上使用HPKP。

首先,最关键的一点,确定需要固定的公钥,HPKP一般可以固定三种公钥,一是网站当前的证书公钥,二是包含CA和中级证书的公钥,三是备份公钥,而备份公钥可以是已经签发的网站有效证书公钥,也可以是CA和中级证书的公钥,这里就要考虑哪种部署方案适合该网站。直接固定网站当前的证书公钥无疑是最安全的,但如果哪天更换该证书,而HPKP规则过期时间还没有到,这时候如果没有固定其他有效的公钥,会直接导致网站无法访问。如果固定的是CA和中级证书的公钥,万一这家CA被攻破或者恶意签发了网站证书,你的网站将面临中间人攻击风险,但好处就是,你只要不换CA,且CA的公钥还在继续签发证书,这个固定就是有效的,无论你换了多少该CA的证书。所以,绑定一个备用公钥是很有必要的。

本站目前的选择是,首先固定了Let’s Encrypt Authority X3的公钥,这是本站目前的CA所使用的公钥,是非常安全可靠的。然后固定了另一个大家所熟知但不太靠谱的免费CA为本站签发的有效证书公钥作为备份公钥,因为我不太信任那家CA,所以并没有选择直接固定那家CA的公钥。

选择好了要固定的公钥,接下来一个困难的选择就是HPKP规则过期时间,因为一旦固定的公钥不能用,而HPKP规则过期时间还没到,那网站就无法访问了。时间设置越久,越能有效保护访问的用户,但证书不能用的风险就越大,而时间设置越短,越容易在HPKP规则过期后用户第一次访问时遭遇中间人攻击。本站并不是特别重要的站点,也没有被中间人攻击的价值,所以目前仅仅设置了一周的时间,一些注重安全又走在技术前沿的著名站点往往会设置一个月以上的时间。

接下来,其实设置的过程非常简单。首先,为需要绑定的证书公钥生成SPKI指纹。

openssl x509 -noout -in certificate.pem -pubkey | \
openssl asn1parse -noout -inform pem -out public.key;
openssl dgst -sha256 -binary public.key | openssl enc -base64

输出结果。

YLh1dUR9y6Kja30RrAn7JKnbQG/uEtLMkBgFF2Fuihg=

其他要绑定哪些密钥也用同样的方法生成SPKI指纹,然后打开Apache的HTTPS站点配置文件,加入HPKP头。

Header always set Public-Key-Pins "pin-sha256=\"YLh1dUR9y6Kja30RrAn7JKnbQG/uEtLMkBgFF2Fuihg=\"; max-age=604800; includeSubDomains"

其中,pin-sha256可以设置多个,max-age为规则过期时间,includeSubDomains是指包含子域名。

然后重启Apache,规则就生效了,很简单,最关键的,还是选择合适的固定公钥以及合适的过期时间。