TCP Wrapper 是一种用于增强网络服务安全性的主机级访问控制工具,它通过拦截对特定守护进程的连接请求来实现访问过滤。该机制位于操作系统内核与应用程序之间的共享库层,仅作用于支持它的基于 TCP 的服务。
识别支持 TCP Wrapper 的服务
由于 TCP Wrapper 只能控制部分应用,需确认目标程序是否链接了 libwrap 库。可通过
ldd 命令检查其动态依赖:
ldd $(which sshd) | grep libwrap
若输出包含类似
libwrap.so.0 => /lib64/libwrap.so.0 的内容,则说明该服务支持 wrapper 机制。例如 SSH 和 VSFTP 通常具备此支持,而 Apache httpd 则一般不依赖该库。
对于静态编译的服务(如早期版本的 portmap),
ldd 不会显示 libwrap 信息。此时可使用
strings 提取二进制文件中的字符串并搜索关键配置项:
strings $(which portmap) | grep -E "hosts_allow|/etc/hosts.(allow|deny)"
若发现相关路径或函数名,表明其已将访问控制逻辑嵌入程序内部。
值得注意的是,若超级守护进程 xinetd 被 TCP Wrapper 控制,则其托管的所有子服务也将受控。
访问控制文件语法
TCP Wrapper 使用两个主要配置文件:
/etc/hosts.allow:定义允许的连接
/etc/hosts.deny:定义拒绝的连接
两者的规则格式一致:
daemon_list : client_list [:command]
其中
daemon_list 指定服务名称,必须与实际运行的进程名匹配,常见写法包括:
sshd
sshd,vsftpd,in.telnetd
ALL
vsftpd@192.168.100.8
最后一项表示仅针对绑定在指定 IP 上的服务进行控制。
client_list 支持多种客户端标识方式:
192.168.100.5 # 单个IP
172.16. # 网段前缀匹配
10.0.0.0/255.0.0.0 # 掩码形式网段
host.example.com # 完整域名
.a.org # 通配域后缀
ALL # 所有主机
LOCAL # 本地网络主机
KNOWN/UNKNOWN # DNS解析成功/失败的主机
PARANOID # 正向和反向DNS不匹配的主机
EXCEPT # 排除操作符
规则匹配顺序为:
hosts.allow → hosts.deny → 默认放行。即只要在 allow 中命中且未被 deny 覆盖,则允许;否则查看 deny 是否拒绝;均未匹配则默认允许。
典型策略示例
限制 SSH 仅允许 172.16 网段接入:
# /etc/hosts.allow
sshd: 172.16.
# /etc/hosts.deny
sshd: ALL
阻止 telnet 对 172.16 整体访问,但放行特定主机 172.16.100.200:
方法一:拆分至不同文件
# /etc/hosts.allow
in.telnetd: 172.16.100.200
# /etc/hosts.deny
in.telnetd: 172.16.
方法二:利用 EXCEPT 在 deny 中排除例外
# /etc/hosts.deny
in.telnetd: 172.16. EXCEPT 172.16.100.200
方法三:在 allow 中嵌套多重排除
# /etc/hosts.allow
in.telnetd: ALL EXCEPT 172.16. EXCEPT 172.16.100.200
# /etc/hosts.deny
in.telnetd: ALL
注意:EXCEPT 并非直接"拒绝",而是从当前规则范围中剔除对应条目,使其继续向下匹配后续规则。
扩展动作配置
可在规则末尾添加指令以执行额外操作:
:ALLOW — 显式允许(常用于 deny 文件中覆盖默认行为)
:DENY — 显式拒绝(可用于 allow 文件中设置黑名单)
:spawn — 触发外部命令执行
例如记录非法 telnet 尝试时间:
in.telnetd: 172.16. :spawn echo "$(date): Attempt from %a" >> /var/log/access.log
其中
%a 是自动替换为客户端地址的通配符,其他可用变量详见手册页。
完整语法细节可通过
man 5 hosts_access 查阅。