最近接到一个很有意思的需求:搭建一个能被外部探测到但所有服务端口都被严格封锁的虚拟机环境。这种"看得见但摸不着"的设计,在安全领域被称为蜜罐系统的变种,专门用于渗透测试训练和攻击行为分析。
这个沙箱需要满足三个核心要求:
我在实际部署中发现,单纯依靠防火墙规则很容易出现疏漏。比如有一次测试时忘记限制ICMP重定向,导致攻击者可以利用路由协议绕过防护。后来我采用了三层防护体系:
这种组合拳的效果相当可靠,在我负责的多个企业红蓝对抗演练中,从未被测试团队完全突破过。
先来看最关键的端口封锁方案。很多新手会直接用iptables -P INPUT DROP,这确实能关闭所有入站连接,但存在两个严重问题:
iptables -F清除,必须手动恢复默认策略更安全的做法是使用以下命令序列:
bash复制# 清空现有规则
iptables -F
iptables -X
# 设置默认策略
iptables -P INPUT DROP # 入站全拒
iptables -P FORWARD DROP # 转发全拒
iptables -P OUTPUT ACCEPT # 出站允许
# 保留已建立连接
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
这种配置下,所有主动入站连接都会被拒绝,但系统发起的连接可以正常收到回复。我曾经在测试环境做过对比:
-P INPUT DROP:无法进行yum更新等需要网络连接的操作有时需要开放个别端口用于管理,比如SSH的22端口。推荐使用IP+端口双重限制:
bash复制# 只允许特定IP访问22端口
iptables -A INPUT -p tcp -s 192.168.1.100 --dport 22 -j ACCEPT
# 或者允许整个网段
iptables -A INPUT -p tcp -s 192.168.1.0/24 --dport 22 -j ACCEPT
有个容易踩的坑:如果先配置了-P INPUT DROP,后加的ACCEPT规则必须放在DROP之前才有效。可以通过iptables -L -n --line-numbers查看规则顺序,用iptables -I INPUT [num]插入到正确位置。
临时规则重启后会丢失,需要保存到配置文件:
bash复制# CentOS/RHEL
iptables-save > /etc/sysconfig/iptables
# Ubuntu/Debian
apt install iptables-persistent
netfilter-persistent save
我遇到过保存后规则不生效的情况,排查发现是firewalld服务冲突。解决方法:
bash复制systemctl stop firewalld
systemctl disable firewalld
在默认拒绝策略下,需要专门放行ICMP协议。ICMP有多个类型,其中type 8是echo请求(ping),type 0是echo回复。最简配置:
bash复制iptables -A INPUT -p icmp --icmp-type 8 -j ACCEPT
iptables -A OUTPUT -p icmp --icmp-type 0 -j ACCEPT
但实际部署时发现,不同网络环境下可能需要更完整的ICMP规则集:
bash复制# 允许常见ICMP类型
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
iptables -A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT
iptables -A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT
# 出站规则
iptables -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT
iptables -A OUTPUT -p icmp --icmp-type source-quench -j ACCEPT
除了iptables,还可以通过内核参数控制ping:
bash复制# 临时允许ping
echo 0 > /proc/sys/net/ipv4/icmp_echo_ignore_all
# 永久生效
echo "net.ipv4.icmp_echo_ignore_all=0" >> /etc/sysctl.conf
sysctl -p
在某个金融项目里,客户要求完全隐藏系统存在性。我们采用了限速ping方案:
bash复制# 每分钟只响应5个ping包
iptables -A INPUT -p icmp --icmp-type 8 -m limit --limit 5/min -j ACCEPT
iptables -A OUTPUT -p icmp --icmp-type 0 -m limit --limit 5/min -j ACCEPT
这样普通扫描会认为系统离线,但持续监控能发现极少量响应,达到迷惑攻击者的效果。
iptables属于网络层防护,应用层还需要加固。hosts.allow和hosts.deny的匹配规则是:
典型配置示例:
bash复制# /etc/hosts.allow
sshd: 192.168.1.100
mysqld: 192.168.1.0/255.255.255.0
# /etc/hosts.deny
ALL: ALL
注意陷阱:如果hosts.allow为空,hosts.deny配了ALL:ALL,会导致所有连接被拒绝,包括本地控制台。建议先在hosts.allow放行管理IP。
在某次护网行动中,我们发现攻击者通过伪造IP绕过hosts限制。于是增加了双因素验证:
对应配置:
bash复制# /etc/ssh/sshd_config
Match Address 192.168.1.0/24
PasswordAuthentication yes
AuthenticationMethods publickey,password
静态防护容易被绕过,需要动态监控。这个脚本可以检测SSH暴力破解:
bash复制#!/bin/bash
LOG_FILE="/var/log/secure"
BLOCK_IP="/tmp/block_ip.list"
# 检测失败登录
grep "Failed password" $LOG_FILE | awk '{print $11}' | sort | uniq -c | while read count ip
do
if [ $count -gt 3 ]; then
if ! grep -q $ip $BLOCK_IP; then
echo $ip >> $BLOCK_IP
iptables -A INPUT -s $ip -j DROP
echo "$(date) 封禁IP: $ip 失败次数: $count" >> /var/log/iptables_block.log
fi
fi
done
建议通过crontab每分钟执行一次,避免长期占用资源:
bash复制* * * * * root /usr/local/bin/block_ssh_attack.sh
单纯封禁不够,还需要通知管理员。在脚本中添加:
bash复制# 邮件通知
MAIL_TO="admin@example.com"
if [ -s $BLOCK_IP ]; then
mail -s "检测到SSH攻击" $MAIL_TO < $BLOCK_IP
fi
某次实际攻击中,这个机制帮助我们发现了内网横向移动行为,攻击者从已沦陷的跳板机发起爆破。通过分析封禁IP,最终定位到入口点。
部署完成后需要进行全面测试:
端口扫描测试:
bash复制nmap -sS -p- 目标IP
正确结果应显示所有端口filtered
ICMP测试:
bash复制ping 目标IP
应该能收到回复,但TTL值可能被修改过
服务渗透测试:
bash复制hydra -L user.txt -P pass.txt ssh://目标IP
应该立即被阻断并触发告警
在最近一次模拟攻击中,这套防护体系成功抵挡了:
最终攻击者获得的唯一信息就是:这个系统在线,但所有服务端口都坚不可摧。这正是渗透测试沙箱的理想状态。