TCP_Wrappers 简介
TCP_Wrappers 全称: Transmission Control Protocol(TCP)Wrappers
是一个基于主机的网络访问控制表系统, 用于过滤对类 Unix 系统 (如 Linux 或 BSD) 的网络访问
其能将主机或子网 IP 地址名称及 ident 查询回复作为筛选标记, 实现访问控制
Tcp_Wrappers 主要特点
? 工作在第四层 (传输层) 的 TCP 协议
? 对有状态连接的特定服务进行安全检测并实现访问控制
? 以库文件形式实现
? 某进程是否接受 libwrap 的控制取决于发起此进程的程序在编译时是否针对 libwrap 进行编译的
判断程序是否支持 tcp_wrapper
程序如果调用了 libwrap.so 库, 表示支持
ldd 程序路径 | grep libwrap.so
strings 程序路径 | grep libwrap.so
- #ldd /usr/sbin/sshd|grep libwrap.so
- libwrap.so.0 => /lib64/libwrap.so.0 (0x00007f9851678000)
- #ldd /usr/sbin/vsftpd |grep libwrap.so
- libwrap.so.0 => /lib64/libwrap.so.0 (0x00007f802ef50000)
- #strings `which sshd`|grep libwrap.so
- libwrap.so.0
TCP_Wrappers 的使用
TCP Wrappers 是通过 / etc/hosts.allow 和 / etc/hosts.deny 这两个配置文件来实现一个类似防火墙的机制
配置文件
帮助参考: man 5 hosts_access,man 5 hosts_options
配置文件 | 规则定义 |
---|---|
/etc/hosts.allow | 允许访问规则 |
/etc/hosts.deny | 拒绝访问规则 |
注意: 说明文档中表示此文件也可以实现拒绝的规则, 本着见名知义和管理清晰化的指引, 这种写法不是讨论的重点
语法
- daemon_list : client_list [ : shell_command ]
- daemon_list
单个应用程序的二进制文件名, 而不是服务名, 如果有多个, 用逗号或空格分隔如 sshd,vsftpd 或 sshd vsftpd
可以绑定服务地址, 如, sshd@192.168.7.202:ALL
ALL 表示所有接受 tcp_wrapper 控制的服务程序
支持通配符
client_list
客户端列表
? 基于单个 IP 地址: 192.168.10.1
? 基于网段 IP 地址: 192.168.1. 注意, 192.168.1.0 这个写法是错误的
? 基于主机名: www.hunk.tech .hunk.tech 较少用
? 基于网络 / 掩码: 192.168.0.0/255.255.255.0
? 基于 net/prefixlen: 192.168.1.0/24(仅 CentOS7)
? 基于网络组(NIS 域):@mynetwork
? 内置 ACL:
ALL 所有(进程或者主机)
LOCAL 名称中不带点的主机
KNOWN 可以解析的主机名
UNKNOWN 无法解析的主机名
PARANOID 正反向查询不匹配或无法解析
支持通配符
shell_command
执行指令
如: sshd:all:spawn echo "`date +%%F-%%T` from %a pid=%p to %s" >> /app/sshd.log
EXCEPT 是排除的意思, 一行规则里可以有多个, 后面的是对前面的结果集进行排除
vsftpd:172.16. EXCEPT 172.16.100.0/24 EXCEPT 172.16.100.1
匹配整个 172.16 网段, 但是把 172.16.100 的网段排除, 在排除 172.16.100 网段中又把 172.16.100.1 的 IP 给排除
spawn 启动一个外部程序完成执行的操作, 可以支持内置变量内置变量请 man , 找 % 的选项
%a (%A) 客户端 IP
%c 客户端信息, 可以是 IP 或主机名(如果能解析)
%p 服务器进程信息 (PID)
%s 连接的服务端的信息
%% 当规则中包含 % 时, 使用双 % 转义
twist 特殊扩展
以指定的命令执行, 执行后立即结束该连接需在 spawn 之后使用
示例
使用的 2 台测试主机网络 IP 配置如下:
本文中简称 | 主机 | IP 1 | IP 2 |
---|---|---|---|
6A | 6-web-1.hunk.tech | 192.168.7.201 | 192.168.5.102 |
7B | 7-web-2.hunk.tech | 192.168.7.202 | 192.168.5.103 |
默认 hosts.allow 和 hosts.deny 配置文件为空, 表示全部允许
- #ssh 192.168.7.202
- Last login: Thu Feb 8 11:04:58 2018 from 192.168.7.201
拒绝某个 IP 访问:
- 7B:
- vim /etc/hosts.deny
- sshd:192.168.7.201
- 6A:
- #ssh 192.168.7.202
- ssh_exchange_identification: Connection closed by remote host
配置规则保存后, 立即生效
7B: 日志会明确记录
- #tail - n1 /
- var / log / secure Feb 8 11 : 18 : 29 7 - web - 2 sshd[1811] : refused connect from 192.168.7.201(192.168.7.201)
那如果一个 client_list 同时存在于 2 个文件呢
- 7B:
- tail -n1 /etc/hosts.deny >> /etc/hosts.allow
- 6A:
- #ssh 192.168.7.202
- Last login: Thu Feb 8 11:05:33 2018 from 192.168.7.201
看到了吧, 是可以允许访问的, 这就涉及到了执行处理机制了
因此, 上面的结果就是允许访问了因为在 hosts.allow 已经匹配了
仅允许内网 IP 访问
假设 192.168.7.202 是 7B 的肉网卡地址, 那么规则应该为:
- #vim /etc/hosts.deny
- sshd@192.168.7.202:ALL
- #ssh -b 192.168.7.201 192.168.7.202 > -b 是使用源地址为 X.X.X.X 访问
- bind: 192.168.7.201: Cannot assign requested address
- ssh: connect to host 192.168.7.202 port 22: Cannot assign requested address
把每个 ssh 登录日志记录到文件
- #vim /etc/hosts.allow
- sshd:all:spawn echo "`date +%%F-%%T` from %a pid=%p to %s" >> /app/sshd.log
- #cat /app/sshd.log
- 2018-02-08-15:59:53 from 192.168.7.202 pid=2565 to sshd@192.168.7.202
- #ps aux |grep 2565
- root 2565 0.0 2.3 145696 5328 ? Ss 15:59 0:00 sshd: root@pts/2
应用实例
编写脚本 / root/bin/checkip.sh, 每 5 分钟检查一次, 如果发现通过 ssh 登录失败次数超过 10 次, 自动将此远程 IP 放入 Tcp_Wrapper 的黑名单中予以禁止防问
- #!/bin/bash
- # 定义 休眠时间
- sleeptime=300
- # 定义 通过 ssh 登录失败次数
- num=10
- # 定义 黑名单文件
- file=/etc/hosts.deny
- # 无限循环
- while true;do
- #将失败登录的记录逐行读入变量
- lastb | grep ssh|awk -F "[ ]+" {print $3}|uniq -c | while read conn ip;do
- #判断失败次数
- if [ "$conn" -ge "$num" ];then
- #判断记录的 IP 是否存在
- egrep -q ^sshd.*$ip $file
- #如果不存在记录, 将追加记录至指定黑名单文件
- [ $? -ne 0 ] && echo "sshd:$ip" >> $file
- fi
- done
- sleep $sleeptime
- done
使用 watch -n1 cat /etc/hosts.deny 来观察动态文件
总结: TCP_Wrappers
适用于需求简单的应用场景, 并且受到监控软件的是否支持 libwrap.so 库局限
来源: http://www.bubuko.com/infodetail-2492872.html