tcpwrapper:工作在第四层(传输层),能够对有状态连接的服务进行安全检测并实现访问控制的工具。部分功能上跟iptables重叠。
对于进出本主机访问某特定服务的连接基于规则进行检查的一个访问控制工具,这个访问控制工具以库文件形式实现;某进程是否接受libwrap的控制取决于发起此进程的程序在编译时是否针对libwrap进行编译的。
tcpwrapper并非对所有的服务都生效,首先主要对于基于tcp的服务生效,其次,主要针对基于tcp并且在编译(两种编译方式:静态和动态)时链接到libwrap库上的程序才能生效。
所以tcpwrapper的功能并没有iptables强大。
判断一个二进制程序是否接受tcpwrapper的控制,只需检查二进制程序在编译的时候是否依赖libwrap.so库
[root@station39 ~]# ldd `which sshd` | grep libwrap
libwrap.so.0 => /lib/libwrap.so.0 (0x00c5a000)
某些二进制文件在编译时直接以静态的方式将对libwrap库的依赖性编译到文件中去,此时需要使用string来检查
[root@station39 ~]# strings `which sshd` | grep hosts
[root@station39 ~]# strings `which portmap` | grep hosts //**提供RPC服务的进程
hosts_access_verbose
hosts_allow_table
hosts_deny_table
/etc/hosts.allow
/etc/hosts.deny
链接到libwrap.so的独立进程有:sendmail,slapd,sshd,stunnel,xinetd,gdm,gnome-session,vsftpd,
portmap等等。
两个重要配置文件/etc/hosts.allow,/etc/hosts.deny
基本语法:
daemon_list: client_list [ :options ]
当来自客户端的访问请求访问某一个接受tcpwrapper控制的进程的时候,tcpwrapper先检查/etc/hosts.allow 中有没有匹配到的规则,然后检查/etc/hosts.deny中有无匹配。如果都没有,则默认放行。
默认规则:允许
先检查allow,再检查deny,如果都没有,则默认放行。
例:只允许192.168.1.0/24的主机访问sshd
/etc/hosts.allow /etc/hosts.deny
sshd: 192.168.1. sshd :ALL
PS:所写的服务名称一定是可执行的二进制程序的名字。
例:只允许192.168.1.0/24的主机访问telnet
/etc/hosts.allow /etc/host.deny
in.telnetd: 192.168.1. in.telnetd: ALL
PS:如果有多个服务需用逗号隔开。ALL:通配所有服务。
PS:如果客户端列表需要定义多个网段,可以这样写:
[email protected]: 192.168.0.
[email protected]: 192.168.1.
客户端的定义:
基于IP地址:192.168.10.1 192.168.1.
基于网络/掩码:不接受192.168.1.0/24的格式,只接受192.168.1.0/255.255.255.0长格式。
基于主机名称:www.a.com .a.com 不很精确,很少使用
基于网络组(NIS 域):@mynetwork
PS :tcpwrapper不需重启,立即生效。
下面以telnet来说明tcpwrapper是怎样使用的:
提供telnet 的二进制程序:in.telnetd(非独立守护进程,接受超级守护进程的管理)
软件包:telnet-server
先查看xinetd是否安装启用:
[root@station39 ~]# rpm -q xinetd
[root@station39 ~]# yum install xinetd -y
[root@station39 ~]# service xinetd start
[root@station39 ~]# yum install telnet-server -y
[root@station39 ~]# cd /etc/xinetd.d/
[root@station39 xinetd.d]# ls | grep telnet
ekrb5-telnet
krb5-telnet
telnet
[root@station39 xinetd.d]# chkconfig telnet on
[root@station39 xinetd.d]# service xinetd restart
[root@station39 xinetd.d]# netstat -ntlp | grep 23
tcp 0 0 0.0.0.0:23 0.0.0.0:* LISTEN 9612/xinetd
[root@station39 xinetd.d]# setenforce 0
此时telnet 已经可以被访问了。使用物理机访问下试试:
PS:telnet 默认不允许管理员登录。
开始设置规则:拒绝0网段访问,只允许192.168.0.1访问:
编辑/etc/hosts.allow
in.telnetd: 192.168.0.1
编辑/etc/hosts.deny
in.telnetd: 192.168.0.
OK,这样所有192.168.0网段的主机就只有192.168.0.1可以访问了。
我们也可以在/etc/hosts.deny里只写一句就能实现上述功能,使用关键字except:
in.telnetd: 192.168.0. EXCEPT 192.168.0.1
except也可以嵌套,如:/etc/hosts.deny
in.telnetd: ALL EXCEPT 192.168.0. EXCEPT 192.168.0.3
拒绝所有访问,但0网段除了192.168.0.3之外可以访问。
可用options:
access control
ALLOW/DENY: 可以在/etc/hosts.deny或/etc/hosts.allow 中被当做一个选项来使用。
例:编辑/etc/hosts.allow
in.telnetd: 192.168.1.
in.telnetd: ALL: DENY
running other command
spawn:在匹配到规则时重新发起一个额外的命令来执行其他的动作,可使用特殊展开。
在子进程中执行,并不影响当前进程。
in.telnetd: ALL : spawn ehco "login attempt from %c to %s" | mail -s waring root
twist:启动一个额外的命令来取代当前规则中定义的服务。
sshd: 192.168.0. twist /bin/echo "421 Connection prohibited."
通过一个例子来说明二者区别:
编辑/etc/hosts.allow
in.telnetd: 192.168.0.: spawn /bin/echo `date` %c accessd %d >> /var/log/tcpwrap.log
可以正常访问,我们来查看下日志:
[root@station39 xinetd.d]# cat /var/log/tcpwrap.log
Wed Mar 23 12:26:29 CST 2011 192.168.0.1 accessd in.telnetd
我们使用twist来试一下:/etc/hosts.allow
in.telnetd: 192.168.0.: twist /bin/echo "421 connetcion deny!"
使用物理机访问,被拒绝:
logging
severity [facility.] priority
定义访问某个服务时的日志级别,默认authpriv.info级别
in.telnetd:ALL: serverity local7.info
banners
访问某个服务时返回的信息
in.telnetd: ALL: banners /some/directory
编辑/etc/hosts.allow
in.telnetd: ALL: banners /var/tcpwrap
举例:
[root@station39 xinetd.d]# mkdir /var/tcpwrap
[root@station39 xinetd.d]# vim /var/tcpwrap/in.telnetd
"Welcome to 192.168.0.39"
使用物理机访问一下:
xinetd
xinetd 超级守护进程
主配置文件:/etc/xinetd.conf
includedir /etc/xinetd.d
启动脚本:/etc/init.d/xinetd
PS:每一个非独立守护进程是不需要启动的,是由xinetd来代为管理。
启动一个非独立守护进程:
chkconfig telnet on
service telnet restart
来看看超级守护进程中关于telnet的配置文件:
service telnet
{
disable = no //** 定义服务可否被访问
flags = REUSE
socket_type = stream //**套接字类型 stream:基于数据流
(stream-based)(基于tcp服务)的连接; dgram:基于数据报文(UDP)服务的连接
wait = no //**确定当前服务是单/多线程服务;yes:单线程(必
须基于TCP) no:多多线程 (TCP/UDP)
user = root //**以指定的用户身份去运行
server = /usr/sbin/in.telnetd //**启动服务所对应的二进制程序
log_on_failure += USERID
}
server_args = -c -s /tftpboot //** 启动服务的时候启用一些选项
protocol 指定服务所使用的协议。有些服务有,有些没有。
only_from 白名单,只允许来自哪些地址的客户端来访问当前服务,默认允许所有。
Example:
only_from = 192.168.0.0/24
only_from = 192.168.0.1
no_access 仅拒绝,不允许访问的网段
使用最佳匹配,最接近的规则先生效
Example:
only_from = 10.0.0.0/8
no_access = 10.0.0.0/24
第二条规则生效
access_times 允许访问的时间
Example:
access_times = 13:00-15:00
bind = 192.168.0.39 (IP地址或者网卡接口)只监听192.168.0.39这个地址
banner = /path/to/some/file 向远程客户端返回提示信息
per_source = 10 每一个IP地址并发连接数的设定
cps = 50 10 <连接数> <等待时间> 在某一秒内只允许多少个并发连接,限制访问速率
# Define general logging characteristics.
log_type = SYSLOG daemon info //** 定义日志类型
log_on_failure = HOST //**启动失败的日志
log_on_success = PID HOST DURATION EXIT //**成功启动的日志
+= :在默认基础上增加一个属性信息;
-= :在默认基础上减去一个属性信息。
客户端匹配模式:
基于数字地址的模式
完全或部分IP地址;
使用0做通配符
Example:192.168.1.0 来自192.168.1网段的客户机
基于网络名称或者NIS域:@mynetwork
基于主机名:.example.com
基于IP地址/子网掩码:192.168.0.0//24