Ubuntu 16.04.01 LTS 安装 Nginx PHP MYSQL环境

blog之前运行在Ubuntu 14.04上,虽然是LTS版本不过毕竟新的LTS版本16.04已经出来了这么久,得益于VPS供应商增加了16.04的镜像故找个时间把blog重新安装了一下,这里留下记录仅供参考。

之前服务器使用的apache,不过更新版本的时候考虑到http2的支持,所以服务器这次选择了nginx来作为web服务。
很多网站表示Ubuntu 16.04的nginx不支持http2需要手动编译,然而截止到目前为止仓库里最新的deb包已经默认支持http2。

那么直接apt-get一下安装nginx即可

然后安装mysql

可以运行一个mysql的安全设置向导mysql_secure_installation进行一些安全性配置。使用脚本可以做到,更改root密码、移除MySQL的匿名用户、禁止root远程登录、删除test数据库。使用上面的这些选项可以提高MySQL的安全。
由于blog的vps配置比较低,所以为了预防内存不足需要修改一下mysqld的配置。
修改/etc/mysql/mysql.conf.d/mysqld.cnf

最后安装php,Ubuntu 16.04默认已经是php7了,而不是php5,需要注意一下。

安装完成之后需要对nginx做一些配置。Ubuntu下面默认的配置目录是/etc/nginx/。
首先是/etc/nginx/nginx.conf
这里我修改了server_tokens选项为off
server_tokens的作用是隐藏Nginx的版本号,隐藏web服务的版本可以提高攻击难度,有利于提高安全性。

接着是/etc/nginx/sites-enabled,nginx启动时会读取目录下的所有配置。
我个人删除了/etc/nginx/sites-enabled/default
因为我个人的配置准备直接写在一个文件里,所以就没必要使用default了

出于安全性考虑,我选择全站强制https,所以80端口只需要做一些跳转工作就行了。配置如下。

80端口就只有一个作用,返回301跳转到https链接。关于几个常见的安全http头我们大致解释一下。
Strict-Transport-Security(HSTS)
一个网站接受一个HTTP的请求,然后跳转到HTTPS,用户可能在开始跳转前,通过没有加密的方式和服务器对话,比如,用户输入http://example.com,传统的做法是服务器返回301跳转到https://example.com。但是服务器返回301时并不是加密的,这将导致服务器返回的结果容易篡改,从而产生了劫持的现象。启用HSTS后,用户访问网站后浏览器会把网站加入HSTS列表,之后如果再次访问则强制https访问,从而尽可能的避免劫持的产生。
注意的是,一旦启用在参数时间内不能关闭https访问。
Content-Security-Policy
W3C的Content Security Policy,简称 CSP,CSP旨在减少跨站脚本攻击。这里我们配置为Content-Security-Policy: default-src ‘self’
这样可以阻止非本站的资源被浏览器加载,这样即使页面遭到篡改仍然不会加载非本站的元素。
X-Frame-Options
设置这个http头之后将会阻止浏览器通过FRAME加载你的网站页面。
X-XSS-Protection
设置此http头后,如果IE检测到了跨站脚本攻击(Cross-Site Scripting),那么IE将对页面做相应的修改以阻止攻击的发生。

80端口配置好了,那么剩下的就是配置443端口。HTTPS配置起来比较麻烦。
我们选择Nginx其中一个考虑是默认支持http2,启用http2很简单。
listen 443 ssl http2;
只要像这样配置端口即可。
出于安全性考虑,我选择放弃浏览器兼容。
SSLv2和SSLv3目前已经被证明是不安全的了,目前为止最新的TLS标准是1.2。所以我选择只支持TLS1.2。通过如下配置完成。
ssl_protocols TLSv1.2;
注意:只支持TLSv1.2代表着放弃很大部分老旧浏览器,他们将无法访问。
ssl_ciphers用来控制加密协议,放弃低强度的加密算法很显然有助于提高安全性。具体放弃或者应该启用什么样的算法我推荐直接参考https://cipherli.st
或者
https://wiki.mozilla.org/Security/Server_Side_TLS
ssl_certificate
相信大家很熟悉了,TLS证书,我这里选择的是Let’s Encrypt的证书。个人推荐使用acme.sh签发证书。参见github的地址https://github.com/Neilpang/acme.sh
ssl_dhparam
通过DHE密钥,我们能获得更高的安全性.Diffie Hellman 算法会确保预主密钥绝不会离开客户端和服务器,而且不能被中间人攻击所拦截。
我们可以通过openssl生成一个强DH密钥。

做完这些配置如下所示

之后我还需要安装phpmyadmin方便配置,一样通过apt-get就可以安装。

如果不安装php-zip那么在导入zip格式压缩后的sql数据是会提示“您正在载入不支持的压缩格式”
备注:由于Ubuntu源提供的包版本可能相对较phpmyadmin较为老旧,固推荐使用phpmyadmin官方提供的ppa源来保持更新。关于PPA源的有关信息可参见本站文章https://www.exvs.org/?p=263

剩下的就是站点的配置,包括启用PHP配合Nginx,还有配置phpmyadmin的别名,配置如下。
当然,虚拟机主机不想配置的话直接软连接一下也是可以的。

那么到此只需要导入之前wordpress的文件,恢复数据库那么blog就重新配置完成了。
配置完成后最后只需要使用
systemctl restart nginx
重启nginx即可。
配置完成后可以通过ssllabs来检测https的安全性。
https://www.ssllabs.com/ssltest/
如果按照本文进行配置的话,应该会得到A+评级。
https://www.ssllabs.com/ssltest/analyze.html?d=exvs.org

iptables限制连接迸发连接数

由于遇到了迸发连接数太多导致服务器服务器出现问题的案例,这里记录一下使用iptables限制迸发连接数。
这里使用connlimit模块
–connlimit-above n 限制为多少个
–connlimit-mask n 这组主机的掩码,默认是connlimit-mask 32 ,即每ip.也可以是24,16,8这样。
例如:
限制一个IP访问80,443端口最大连接数为16个连接

限制一个段访问80,443端口最大为16个连接

Ubuntu下安装使用Spamassassin对Postfix的邮件进行邮件过滤-spampd

系统我这里用的是Ubuntu 16.04 LTS
网上大部分使用spamassassin的说明都是通过调用spamc来完成邮件过滤的,但是如果邮件数量比较多调用spamc需要大量的fork,这个开销比较大,所以这里介绍另一种使用spampd的过滤方法。
如有疑问可参考wiki http://wiki.apache.org/spamassassin/IntegratePostfixViaSpampd
apt-get install spamassassin spamc
添加用户组
groupadd spamd
useradd -g spamd -s /bin/false -d /opt/spamassassin spamd
创建目录修改权限
mkdir /opt/spamassassin
chown spamd:spamd /opt/spamassassin

修改启动配置可以修改
/etc/default/spamassassin
创建SAHOME变量
SAHOME="/opt/spamassassin/"

修改启动选项,由于我需要处理的邮件数量较多,这里做了一定调整

OPTIONS="–create-prefs \
--min-children=4 --max-children=16 --min-spare=4 --timeout-child=30 \
-–username=spamd \
--helper-home-dir ${SAHOME}"

之后修改spamassassin配置
/etc/spamassassin/local.cf

修改完成后可以service spamassassin restart

安装spampd
apt-get install spampd
如果需要修改启动配置可以修改
/etc/default/spampd
这里默认配置没有什么要修改的所以跳过
如果修改完毕可以service spampd restart重启程序

安装postfix
apt-get install postfix
修改/etc/postfix/master.cf
如果需要高迸发数量注意修改maxproc值

修改完毕后看起来应该是这样

之后再修改
/etc/postfix/main.cf
添加
content_filter =scan:[127.0.0.1]:10025
限制邮件最大大小为20M
message_size_limit = 20971520
由于我这里需要进行邮件中继所以修改了
relayhost = [127.0.0.1]:1250
设置relay_domains
relay_domains = hash:/etc/postfix/relay_domains
创建relay_domains运行命令
touch /etc/postfix/relay_domains
echo “test.com OK” > /etc/postfix/relay_domains
postmap /etc/postfix/relay_domains
如果不需要邮件中继请不要修改
最后看起来效果是这样的

最后service postfix restart即可

Ubuntu下使iptables规则重启继续生效

重启后iptable规则丢失,解决方法很简单,安装iptables-persistent即可
apt-get install iptables-persistent
也可以手动管理iptables规则
保存规则
Debian/Ubuntu: iptables-save > /etc/iptables/rules.v4
Debian/Ubuntu: ip6tables-save > /etc/iptables/rules.v6
恢复规则
Debian/Ubuntu: iptables-restore < /etc/iptables/rules.v4

2016/10/15 xmlrpc.php引起的网站瘫痪

说来装上wordpress也有一段时间了,一直没遇到过什么问题,不过今天突然发现blog挂掉了,访问主页显示Error establishing a database connection
粗略一看我想可能是mysql出问题了,于是果断的
service mysql restart
恢复正常后过了很短的时间又出现了同样的情况,所以果断去/var/log/mysql下看了error.log
日记中是这样记录的
161015 18:34:42 InnoDB: Using Linux native AIO
161015 18:34:42 InnoDB: Initializing buffer pool, size = 128.0M
InnoDB: mmap(137363456 bytes) failed; errno 12
161015 18:34:42 InnoDB: Completed initialization of buffer pool
161015 18:34:42 InnoDB: Fatal error: cannot allocate memory for the buffer pool
161015 18:34:42 [ERROR] Plugin ‘InnoDB’ init function returned error.
161015 18:34:42 [ERROR] Plugin ‘InnoDB’ registration as a STORAGE ENGINE failed.
161015 18:34:42 [ERROR] Unknown/unsupported storage engine: InnoDB
161015 18:34:42 [ERROR] Aborting
很显然是内存不够用,导致mysql挂掉了。毕竟blog用的服务器只有512M内存,可加swap的方案我觉得不太好,所以选择修改mysql设置。
Google了一下,修改mysql的配置/etc/mysql/my.cnf,在[mysqld]下面加上一行
innodb_buffer_pool_size =32M
之后service mysql restart,网站恢复正常。
网站正常后通过top我看到apache的负载很高,觉得肯定有问题,就去看了Wordfence的日志
日志显示有来自俄罗斯一个IP的大量访问xmlrpc.php文件
ip是191.96.249.53和 191.96.249.54
想必就是因为大量的访问导致此问题出现。搜索了一下xmlrpc.php,发现这个文件对我用处不大,并且存在一定的安全问题,所以我直接做了以下措施。
1、iptables禁止ip段
iptables -I INPUT -s 191.96.249.0/24 -j DROP
这样一来就缓解了访问情况
2、.htaccess禁止使用xmlrpc.php
修改网站.htaccess加上下面的
# protect xmlrpc

Order Deny,Allow
Deny from all

至此,网站问题解决。记录下来仅供参考