Nginx ssl_preread传递客户端IP

ssl_preread是基于L4的反代方案,TLS SNI握手时客户端会提供域名,所以可以让Nginx在无需完成TLS握手的情况下,就根据域名进行后端服务器的选择。简单来讲,你只需要给后端服务器配置一个SSL证书,而提供反代功能的Nginx则无需配置。文档见此:http://nginx.org/en/docs/stream/ngx_stream_ssl_preread_module.html

因为这是L4反代,所以通过“proxy_set_header”传递客户端IP的方法是行不通的。其实传递客户端IP的解决办法跟上一篇文章类似:L4(传输层)IP透明反向代理的实现(传递客户端真实IP),nginx也是实现了IP_TRANSPARENT的:https://www.nginx.com/blog/ip-transparency-direct-server-return-nginx-plus-transparent-proxy#ip-transparency,所以,在server里面加上下面一行:

然后按前一篇文章的思路,对路由表进行配置即可。

提醒一下,ssl_preread是配置在stream block下的,放在别的地方,会提示:

所以正确的nginx.conf结构应该如下:

另外,如果在stream中listen了443,http中就无法listen 443了,启动nginx会提示:

可以让http中的server listen loopback地址的另一个端口,让stream中的server proxy_pass这个loopback地址的端口,例如127.0.2.1:8443,然后通过127.0.2.1做策略路由:

然后配置策略路由:

 

Nginx下简单实现MediaWIKI的伪静态

最近要写一个说明文档,于是就用上了MediaWIKI。

这东西默认情况下,文章地址格式为http://domain/index.php?title=标题。

如果要改成使用http://domain/标题 的方式访问,rewrite规则明显有点繁琐,除非使用 if -e判断文件是否存在,否则正则表达式的.*会把一切东西,包括静态资源也匹配进去。

想了想,于是决定把文章的地址都变成子目录的形式:http://domain/wiki/标题,这样的话伪rewrite规则就变得简单多了,对/wiki进行匹配即可,仅需一行代码:

然后修改MediaWIKI的配置文件LocalSettings.php,修改与文章地址有关的变量wgArticlePath的值(没有的话就加进去):

这样文章的地址格式就会变为/wiki/标题了

最后重启Nginx,再次访问WIKI:

Media WIKI

可以看到,文章的地址格式已成功变为/wiki/标题,且无发现错误。

一个高频率的HTTP服务监控Shell Script

Nginx/Apache之类的长期运行,无法保证在遇到各种突发情况进程不会死掉。如果这时候又出门在外,一时间无法操作,那网站岂不是要宕机数个小时?

明显我无法接受这事情。于是一个简简单单的监控HTTP服务的Shell Script就出来了。

真的简简单单。

可见我并没有采用cron功能,毕竟这东西正常情况最低频率只能一分钟了。

restart那个function是http服务不正常后执行的,可以自行增添,删减,替换。sleep后面跟着的是秒数,在这里简单理解成监控频率吧。wget处,-t参数指的是尝试次数,这里我写了一次。

执行方式:

其中的/root/monitor指的是该Shell Script所存放的路径。记得要先赋予当前用户对该文件的执行权限。

可以添加到/etc/rc.local里面实现系统启动自动执行:

 

终止:

其中grep后面跟着的是你Shell Script的文件名。

有了这东西,出门在外,至少能安心一点了。

巧用Nginx的日志功能配合IPTABLES实现防范基础CC攻击(2013年11月24日8:24:13更新)

相信不少人都被CC过,我也不例外,因此一直以来想尽各种办法降低PHP所占的资源。

PHP所耗的资源算压下去了,带宽却满了……

之前也看过有人使用Nginx的第三方模块limit req2实现防CC攻击,自己也弄过,但效果没想象中的好,只用了几十分钟我就抛弃了……

昨天其中考试结束后,突然灵机一动,想到一个新的防CC方法。回家后经过多次调试,几经完善,已经基本能正常使用了。

这其中利用了Nginx的日志功能,还有自己写的一个Shell Script。本文出自微宇宙(http://zhensheng.im),转载者死一户口本。

Apache的请移步这里:Apache:只有访客IP的日志格式

首先给Nginx添加一个只有访客IP的日志格式,在nginx.conf的http层加入以下代码:

重启nginx,就会多一个名为iponly的日志格式。本文出自微宇宙(http://zhensheng.im),转载者死一户口本。

顺便提一下:$remote_addr是HTTP请求头,此变量包含访客真实IP地址。更详细的介绍请移步:多重代理时如何防止伪造X-Forwarded-For且获取真实IP

然后修改需要开启防CC的网站配置文件,在server层加入以下代码:

除非nginx对日志目录有写入权限,否则要把这一步也执行了:

然后重启nginx,这样该站点就会多一个只记录访客IP的日志。其中的/var/log/nginx/iponly.log是日志的路径,可以自行更改。

刷新一下网站,看看日志文件里面有没有出现真实IP地址。有的话就代表一切正常。

接下来是最关键的一步,写监控该日志文件的Shell Script。本文出自微宇宙(http://zhensheng.im),转载者死一户口本。

2013年11月24日修改,可同时封禁多个IP:

因为要该Shell Script一直执行,因此我使用while…do…done制作了一个“死循环”。
在第六行写了一个函数ban_ip(),是使用iptables对IP进行封禁,并且完成后给我的邮箱发一封邮件。标题为:“IP和封禁时间”。内容为IP封禁时间和iptables的filter表。本文出自微宇宙(http://zhensheng.im),转载者死一户口本。

为何与200对比?经过我多次测试,发现五秒内200请求数是比较正常的。当然你可以改小或者改大一点。

保存以上代码后,赋予x(执行)权限。

要实现该Shell Script在后台类似daemon,就需要使用nohup这个东西了:

>/dev/null 2>&1表示把执行该shell script所输出的信息(shell script中的几个echo,我调试是时候用的。)重定向至/dev/null里面。

最后面的&代表后台执行。本文出自微宇宙(http://zhensheng.im),转载者死一户口本。

这样的话,即使注销了登录,该Shell Script也一样会在后台执行。

到此文章首发为止,暂未出现误封的情况:

Result

 

看了下日志,就知道此IP不怀好意了:Log File

 

经过多次测试,效果是不错的,但该方法也有不足:仅限于防那些单IP连接数较大的CC攻击。遇到成百上千个IP的攻击,且每IP连接数只有一两个的话,那恐怕安全宝什么的都无能为力了(貌似阿里云的云盾可以,会看到域名后面有尾巴)……本文出自微宇宙(http://zhensheng.im),转载者死一户口本。

设置ACL增强网站目录安全性

Linux的安全性高是人人皆知的,可以分别设置user,group,other的r/w/x的权限。

但是,对于我这种注重数据安全的人来说,这样简单的权限设置已无法满足我的需求。

就以Nginx+PHP-FPM的环境为例。一般给Nginx和php-fpm fork出来的进程的用户身份不同的。

假如给Nginx的执行身份是用户nginx,而php-fpm的执行身份是php-fpm。

在网站所有文件owner都是php-fpm的情况下,给网站目录的文件的最低权限就是505(user:r_x,group:___,other:r_x)(不能再低了,再低就无法正常访问了)本文出自微宇宙(http://zhensheng.im),转载不标明出处者死一户口本。

WHY?其中user的r权限是给PHP-FPM读取php文件的,x是给php-fpm进入该目录。other的r是给nginx读取静态资源的,x权限是允许nginx进入该网站目录。(根目录可501)。本文出自微宇宙(http://zhensheng.im),转载不标明出处者死一户口本。

假如有一个用户获得了服务器的shell权限,他的身份不是nginx,也不是php-fpm,由于该网站根目录给了other的x权限,以及网站文件有r权限,那么他就可以轻易地把网站的东西cat出来,例如wp-config.php……本文出自微宇宙(http://zhensheng.im),转载不标明出处者死一户口本。

 

cat

前面已经说了,Linux的安全性很高,那么对权限的设置,肯定还有更高级的东西——ACL。本文出自微宇宙(http://zhensheng.im),转载不标明出处者死一户口本。

ACL是Access Control List的缩写,中文全名是“访问控制列表”。该东西的强大之处就在于:可以单独的赋予某个用户对某个文件/目录的权限。本文出自微宇宙(http://zhensheng.im),转载不标明出处者死一户口本。

其实Windows也有ACL,NTFS才支持:本文出自微宇宙(http://zhensheng.im),转载不标明出处者死一户口本。

Windows ACL

 

Linux要启用ACL,首先就要为挂载的分区增加ACL参数(OpenVZ貌似不支持)本文出自微宇宙(http://zhensheng.im),转载不标明出处者死一户口本。

取得设备文件名:

df

mount

成功执行后,执行mount,看到那个挂载的分区有了acl这三个字母就代表成功了。建议把ACL参数增加到/etc/fstab里面,不然重启后就没了。本文出自微宇宙(http://zhensheng.im),转载不标明出处者死一户口本。

FSTAB ACL

然后安装ACL,

Debian/Ubuntu的执行:

CentOS的执行:

安装后,系统就会多两个可以使用的命令:setfacl,getfacl

setfacl是设置ACL权限的,getacl是获取ACL权限。

例如:

以/var/www这个目录为例:

www

 

首先给该目录赋予正确的所有者以及群组,并且根据是否需要给予写入权限,来赋予700或者500权限:本文出自微宇宙(http://zhensheng.im),转载不标明出处者死一户口本。

需要给所有者写入权限就执行:

不需要写入权限则执行:

chmod

接下来要使用setfacl,赋予Nginx的执行用户nginx访问该目录以及文件的权限:

要使用的参数有-R(递归设置),-m(修改权限),-d(默认权限)

使用ls -l可以看到文件的权限最后都有一个+:

ls files

此时可以使用getfacl查看这些文件的真实权限:

getfacl

 

可以看到user(所有者)的权限没变,而用户nginx的权限变成了rx,群组,其他人则无任何权限。本文出自微宇宙(http://zhensheng.im),转载不标明出处者死一户口本。

请注意此时不要用chmod更改群组和other的权限,否则可能会导致ACL权限失效。本文出自微宇宙(http://zhensheng.im),转载不标明出处者死一户口本。

用other的身份再去访问和读取一下这些目录和文件:

ACL CAT

 

均提示权限不足。

然后切换为nginx再看看:

nginx cat

读取毫无阻碍。

这样的话,极大地增强了网站目录的安全性,减少被跨站的机会。。本文出自微宇宙(http://zhensheng.im),转载不标明出处者死一户口本。

如果要删除ACL权限呢?把-m参数改成-b参数就行:

执行后使用ls -l查看,+没了就代表成功删除。

至于setfacl和getfacl更详细的介绍,大家可以看man page:

 

本文出自微宇宙(http://zhensheng.im),转载不标明出处者死一户口本。