防火墙API,全新升级,支持iptables、ipset、pf、nftables
在上一篇“使用redis来调用iptables,封禁恶意IP” 一文中已经讲解RedisPushIptables的用法,在经过几个版本迭代后,该模块功能更强大了,语法有所改变,所以需要新开篇幅来讲解下。
RedisPushIptables-6.2.tar.gz为最新版本,已经支持iptables、ipset、pf、nftables防火墙,意味着它已经跨平台支持,Linux、BSD、MacOS。最重要的是添加了动态删除防火墙规则的功能,当然这个功能ipset也有。虽然fail2ban也有此功能,但是极其消耗资源因为它是轮询来获取任务的。
本篇主要介绍RedisPushIptables模块的实现原理、安装方法、API使用方法以及适用范围。并与Fail2ban作了对比以便读者了解二者的区别,RedisPushIptables不受编程语言的限制。意味着开发者都可以使用它来进行业务防护,接着讲解了怎样重新封装lib库从而支持API调用,最后给出了部分编程语言调用API的示例,供读者参阅。
简介
RedisPushIptables是Redis的一个模块, 也可以把它理解为防火墙API调用库,该模块可以通过 redis 来操作 iptables 的 filter表INPUT链规则ACCEPT和DROP,而相对于BSD系统该模块则是对应pf防火墙。RedisPushIptables更新防火墙规则以在指定的时间内拒绝IP地址或永远拒绝。比如用来防御攻击。自此普通开发者也可以使用iptables或者PF,而不必再理会复杂的防火墙语法。
与Fail2Ban比较
主要从两个方面,实现原理和实用性。Fail2Ban倾向于事后分析,需要监控日志,支持的应用也比较多,只需简单配置即可。而RedisPushIptables倾向于实效性,不需要监控日志,但是,需要程序编码时调用API,使用门槛较高,并不适用所有人。
Fail2Ban
Fail2Ban是一种入侵防御软件框架,可以保护计算机服务器免受暴力攻击。用Python编程语言编写,它能够在POSIX系统上运行,该系统具有本地安装的数据包控制系统或防火墙的接口,例如iptables或TCP Wrapper。
fail2ban通过监控操作日志文件(如/var/log/auth.log,/var/log/apache/access.log等)选中的条目并运行基于他们的脚本。最常用于阻止可能属于试图破坏系统安全性的主机的所选IP地址。它可以禁止在管理员定义的时间范围内进行过多登录尝试或执行任何其他不需要的操作的任何主机IP地址。包括对IPv4和IPv6的支持。可选择更长时间的禁令可以为不断回来的滥用者进行定制配置。Fail2Ban通常设置为在一定时间内取消阻止被阻止的主机,以便不“锁定”任何可能暂时错误配置的真正连接。但是,几分钟的unban时间通常足以阻止网络连接被恶意连接淹没,并降低字典攻击成功的可能性。
每当检测到滥用的IP地址时,Fail2Ban都可以执行多个操作:更新Netfilter / iptables或PF防火墙规则,TCP Wrapper的hosts.deny表,拒绝滥用者的IP地址; 邮件通知; 或者可以由Python脚本执行的任何用户定义的操作。
标准配置附带Apache,Lighttpd,sshd,vsftpd,qmail,Postfix和Courier Mail Server的过滤器。过滤器是被Python定义的正则表达式,其可以由熟悉正则表达式的管理员可以方便地定制。过滤器和操作的组合称为“jail”,是阻止恶意主机访问指定网络服务的原因。除了随软件一起分发的示例之外,还可以为任何创建访问日志文件的面向网络的进程创建“jail”。
Fail2Ban类似于DenyHosts [...],但与专注于SSH的DenyHosts不同,Fail2Ban可以配置为监视将登录尝试写入日志文件的任何服务,而不是仅使用/etc/hosts.deny来阻止IP地址/ hosts,Fail2Ban可以使用Netfilter / iptables和TCP Wrappers /etc/hosts.deny。
缺点
- Fail2Ban无法防范分布式暴力攻击。
- 没有与特定于应用程序的API的交互。
- 太过依赖正则表达式,不同的程序需要各自对应的正则。
- 效率低下,性能受日志数量影响
- IP列表很多时,内存消耗很高
RedisPushIptables
虽然与Fail2Ban比较起来,RedisPushIptables支持还不是很完善,但是,术业有专攻,它的优势在于高性能,用C语言实现,同样支持跨平台Linux、BSD、MacOS。可以通过API调用,意味着redis官方支持的编程语言都可以使用,应用范围不受限。Fail2Ban是被动防御的需要根据关键字实时获取应用程序日志,匹配字符串再计算阈值达到就封禁IP地址。而RedisPushIptables业务主动调用,不需要分析日志。同样支持动态删除iptables或者PF规则,比fail2ban更省资源。
缺点
- 需要开发者编码时调用API。
- 无法防范分布式暴力攻击。
- 目前IPv6在我国还没普及所以不支持
安装
在安装RedisPushIptables之前,需要先安装redis。下面为版本redis-5.0.3.tar.gz
root@debian:~/bookscode# git clone https://github.com/limithit/RedisPushIptables.git root@debian:~/bookscode# wget http://download.redis.io/releases/redis-5.0.3.tar.gz root@debian:~/bookscode# tar zxvf redis-5.0.3.tar.gz root@debian:~/bookscode#cd redis-5.0.3&& make root@debian:~/bookscode/redis-5.0.3# make test root@debian:~/bookscode/redis-5.0.3/deps/hiredis#make&& make install root@debian:~/bookscode/redis-5.0.3/src#cp redis-server redis-sentinel redis-cliredis-benchmark redis-check-rdb redis-check-aof /usr/local/bin/ root@debian:~/bookscode/redis-5.0.3/utils# ./install_server.sh root@debian:~/bookscode/redis-5.0.3# cd deps/hiredis root@debian:~/bookscode/redis-5.0.3/deps/hiredis# make && make install root@debian:~/bookscode/redis-5.0.3# echo /usr/local/lib >> /etc/ld.so.conf root@debian:~/bookscode/redis-5.0.3# ldconfig root@debian:~/bookscode# cd RedisPushIptables root@debian:~/bookscode/ RedisPushIptables # make && make install
注意
编译时有四个选项 make、make CFLAGS=-DWITH_IPSET、make CFLAGS=-DWITH_NFTABLES和make CFLGAS=-DBSD
Linux系统默认是make选项即使用iptables,make CFLAGS=-DWITH_IPSET则是使用ipset更快地管理规则,make CFLAGS=-DWITH_NFTABLES则是启用nftables防火墙
make CFLGAS=-DBSD则是在BSD和MacOS系统上默认编译使用
可以使用以下redis.conf配置指令加载模块:
loadmodule /path/to/iptablespush.so
也可以使用以下命令在运行时加载模块:
MODULE LOAD /path/to/iptablespush.so
可以使用以下命令卸载模块:
MODULE unload iptables-input-filter
动态删除配置
默认情况下,禁用键空间事件通知,虽然不太明智,但该功能会使用一些CPU。使用redis.conf的notify-keyspace-events或CONFIG SET启用通知。将参数设置为空字符串会禁用通知。为了启用该功能,使用了一个非空字符串,由多个字符组成,其中每个字符都具有特殊含义,如下所示:
K Keyspace events, published with __keyspace@<db>__ prefix. E Keyevent events, published with __keyevent@<db>__ prefix. g Generic commands (non-type specific) like DEL, EXPIRE, RENAME, ... $ String commands l List commands s Set commands h Hash commands z Sorted set commands x Expired events (events generated every time a key expires) e Evicted events (events generated when a key is evicted for maxmemory) A Alias for g$lshzxe, so that the "AKE" string means all the events.
字符串中至少应存在K或E,否则无论字符串的其余部分如何都不会传递任何事件。例如,只为列表启用键空间事件,配置参数必须设置为Kl,依此类推。字符串KEA可用于启用每个可能的事件。
# redis-cli config set notify-keyspace-events Ex
也可以使用以下redis.conf配置指令加载模块:
notify-keyspace-events Ex
#notify-keyspace-events "" #
注释掉这行
使用root用户运行ttl_iptables守护程序
root@debian:~/RedisPushIptables# /etc/init.d/ttl_iptables start
日志在/var/log/ttl_iptables.log中查看
root@debian:~# redis-cli TTL_DROP_INSERT 192.168.18.5 60 (integer) 12 root@debian:~# date Fri Mar 15 09:38:49 CST 2019 root@debian:~/RedisPushIptables# tail -f /var/log/ttl_iptables.log 2019/03/15 09:39:48 pid=5670 iptables -D INPUT -s 192.168.18.5 -j DROP
指令
RedisPushIptables目前有五个指令,管理filter表中的INPUT链。为了保证规则生效,采用插入规则而不是按序添加规则,这么做的原因是,因为iptables是按顺序执行的。此外加入了自动去重功能(ipset和pfctl自带去重)。使用者不必担心会出现重复的规则,只需要添加即可。
accept_insert
等同iptables -I INPUT -s x.x.x.x -j ACCEPT
- accept_delete
等同iptables -D INPUT -s x.x.x.x -j ACCEPT
- drop_insert
等同iptables -I INPUT -s x.x.x.x -j DROP
- drop_delete
等同iptables -D INPUT -s x.x.x.x -j DROP
- ttl_drop_insert
例ttl_drop_insert 192.168.18.5 60
等同iptables -I INPUT -s x.x.x.x -j DROP 60秒后ttl_iptables守护进程自动删除iptables -D INPUT -s x.x.x.x -j DROP
客户端API示例
理论上除了C语言原生支持API调用,其他语言API调用前对应的库都要重新封装,因为第三方模块并不被其他语言支持。这里只示范C、Python、Bash、Lua其他编程语言同理。
C编程
C只需要编译安装hiredis即可。步骤如下:
root@debian:~/bookscode/redis-5.0.3/deps/hiredis#make install
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <hiredis.h> int main(int argc, char **argv) { unsigned int j; redisContext *c; redisReply *reply; const char *hostname = (argc > 1) ? argv[1] : "127.0.0.1"; int port = (argc > 2) ? atoi(argv[2]) : 6379; struct timeval timeout = { 1, 500000 }; // 1.5 seconds c = redisConnectWithTimeout(hostname, port, timeout); if (c == NULL || c->err) { if (c) { printf("Connection error: %s\n", c->errstr); redisFree(c); } else { printf("Connection error: can't allocate redis context\n"); } exit(1); } reply = redisCommand(c,"drop_insert 192.168.18.3"); printf("%d\n", reply->integer); freeReplyObject(reply); reply = redisCommand(c,"accept_insert 192.168.18.4"); printf("%d\n", reply->integer); freeReplyObject(reply); reply = redisCommand(c,"drop_delete 192.168.18.3"); printf("%d\n", reply->integer); freeReplyObject(reply); reply = redisCommand(c,"accept_delete 192.168.18.5"); printf("%d\n", reply->integer); freeReplyObject(reply); redisFree(c); return 0; }
gcc example.c -I/usr/local/include/hiredis -lhiredis
编译即可
Python编程
root@debian:~/bookscode# git clone https://github.com/andymccurdy/redis-py.git #下载Python lib库
下载好之后不要急着编译安装,先编辑redis-py/redis/client.py文件,添加代码如下:
# COMMAND EXECUTION AND PROTOCOL PARSING def execute_command(self, *args, **options): "Execute a command and return a parsed response" ..... ..... def drop_insert(self, name): """ Return the value at key ``name``, or None if the key doesn't exist """ return self.execute_command('drop_insert', name) def accept_insert(self, name): """ Return the value at key ``name``, or None if the key doesn't exist """ return self.execute_command('accept_insert', name) def drop_delete(self, name): """ Return the value at key ``name``, or None if the key doesn't exist """ return self.execute_command('drop_delete', name) def accept_delete(self, name): """ Return the value at key ``name``, or None if the key doesn't exist """ return self.execute_command('accept_delete', name) def ttl_drop_insert(self, name, blocktime): """ Return the value at key ``name``, or None if the key doesn't exist """ return self.execute_command('ttl_drop_insert', name, blocktime)
为了不误导读者,上述代码不加注释了,只是在类里添加几个函数而已,不需要解释
root@debian:~/bookscode/redis-py# python setup.py build root@debian:~/bookscode/redis-py# python setup.py install root@debian:~/bookscode/8/redis-py# python Python 2.7.3 (default, Nov 19 2017, 01:35:09) [GCC 4.7.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import redis >>> r = redis.Redis(host='localhost', port=6379, db=0) >>> r.drop_insert('192.168.18.7') 12L >>> r.accept_insert('192.168.18.7') 12L >>> r.accept_delete('192.168.18.7') 0L >>> r.drop_delete('192.168.18.7') 0L >>> r.ttl_drop_insert('192.168.18.7', 600) 12L >>>
Bash编程
examples.sh
#!/bin/bash for ((i=1; i<=254; i++)) do redis-cli TTL_DROP_INSERT 192.168.17.$i 60 done redis-cli DROP_INSERT 192.168.18.5 redis-cli DROP_DELETE 192.168.18.5 redis-cli ACCEPT_INSERT 192.168.18.5 redis-cli ACCEPT_DELETE 192.168.18.5
Lua编程
git clone https://github.com/nrk/redis-lua.git #下载Lua lib库
下载后编辑redis-lua/src/redis.lua 添加以下代码:
redis.commands = { ..... ttl = command('TTL'), drop_insert = command('drop_insert'), drop_delete = command('drop_delete'), accept_insert = command('accept_insert'), accept_delete = command('accept_delete'), ttl_drop_insert = command('ttl_drop_insert'), pttl = command('PTTL'), -- >= 2.6 .....
示例代码examples.lua
package.path = "../src/?.lua;src/?.lua;" .. package.path pcall(require, "luarocks.require") --不要忘记安装Luasocket库 local redis = require 'redis' local params = { host = '127.0.0.1', port = 6379, } local client = redis.connect(params) client:select(0) -- for testing purposes client:drop_insert('192.168.1.1') client:drop_delete('192.168.1.1') client:ttl_drop_insert('192.168.1.2', '60') --加入规则后60秒后自动删除添加的规则 local value = client:get('192.168.1.2') print(value)
最后,目前还缺少Java、php常用语言的驱动,由于我不太擅长太多语言,有兴趣的朋友可以提交PR来补充。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
华为的测试大牛Python+Django接口自动化怎么写的?
最近被几个公司实习生整自闭了,没有基础,想学自动化又不知道怎么去学,没有方向没有头绪,说白了其实就是学习过程中没有成就感,所以学不下去。出于各种花里胡哨的原因,今天给大家整一个简单又有成就感的接口自动化学习吧。 不皮了,进入正题。本文中用到的技术点有:Python基础、Django基础、Request库、一丢丢前端基础。(考虑到大家零基础,所以文中代码编写使用纯新手手法) 1、先创建一个Django项目(具体请参考Django基础入门教程) 2、创建一个模板,新增一个index.html页面 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Parker接口测试</title> </head> <body> <h3 style="...">接口测试</h3> <form action="/index/" method="post"> <tabl...
- 下一篇
程序员随想-快速熟悉业务
前言 作为一名开发,经常面临着主动或被动切换业务做,有些时候切换至有一定相关联的另一个业务,本来做余额宝的被调到做证券。一些情况下是切换至完全相关的业务,如从商品切换到交易,甚至从电商业务切换至金融业务。在经常遇到这种的情况下,建立一个“快速熟悉陌生业务”的方法论就很重要了。下面经过个人思考,提出的一些不完善的想法。 一、划分模块 人的记忆和关系型数据库有些类型,较容易记住的大的关键点,而具体的细节可能想很久,甚至记不住。根据人的这种记忆方式,我们接触一个新的事务最好的方式应该就是分层,按照一定逻辑分几层,每层分多个模块,了解每层各个模块概念,然后再细分下一层子模块概念。这种思维方式有点像数据库的索引,符合人的思维习惯。 划分模块方式 模块是基于一定逻辑组织形式来划分的,只要按照逻辑来划分的话,划分模块的方式肯定有很多种,这里我提两种最容易的方式:业务功能,应用架构。 业务功能 按照业务功能性,对业务进行拆解,把复杂的业务进行拆分成功能单元,各功能单元再根据场景进行更细粒度的拆分。拆分有一个原则,要做到高内聚,低耦合。 应用架构 基本上应用都是分层的,下图就是最常见的应用的组织形式,当...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2整合Redis,开启缓存,提高访问速度
- Windows10,CentOS7,CentOS8安装Nodejs环境
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS7,8上快速安装Gitea,搭建Git服务器
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS7设置SWAP分区,小内存服务器的救世主
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- 设置Eclipse缩进为4个空格,增强代码规范
- CentOS7,CentOS8安装Elasticsearch6.8.6