ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

三种蜜罐部署实战:HFish、Cowrie与端口诱饵构建内网感知

三种蜜罐部署实战:HFish、Cowrie与端口诱饵构建内网感知 简介一套覆盖三种主流蜜罐工具的实操文档面向网络安全初学者、渗透测试人员及运维人员。资源围绕Defnet、Pentbox、Cowrie三款工具系统讲解蜜罐的搭建与使用方法其中Pentbox与Cowrie的部署在Kali Linux环境中完成Defnet则支持在Windows端虚拟Web、FTP、SMTP、POP3、Telnet等服务可通过自定义监听端口、错误信息、日志与报警方式构建诱捕环境。整个资源为单个docx文档大小约7.96MB内容包含Pentbox快速/手动配置、Defnet的Monitore监听、Cowrie的Python虚拟环境搭建与SSH端口修改等关键步骤并附有telnet远程连接、端口扫描等入侵检测演示覆盖从下载安装、参数配置到攻击验证的完整链路。文档采用步骤化笔记形式命令、参数和验证结果对照清晰便于按章节复现。已有3080人学习该资源尤其适合想通过实际部署理解蜜罐原理并强化网络防御技能的读者参考。1. 三种蜜罐怎么选从一次内网横向移动告警说起晚上十一点内网一台测试服务器突然对外发起大量 SSH 连接请求防火墙日志里出现一串陌生内网 IP。这种时候最怕的不是告警多而是你不知道攻击者已经在内网横着走了多久。蜜罐就是把这种「未知」变成「已知」的探针故意放几个看似弱口令、实则记录一切的服务在网段里等攻击者踩上来留下来源 IP、爆破口令和操作命令。下文要讲的三种蜜罐分别是容器化平台 HFish、SSH 中交互蜜罐 Cowrie以及一个自写的 TCP 端口诱饵脚本。它们覆盖的场景完全不同但组合起来就是一套能落地的内网感知方案。适合正在做攻防演练、护网布防或者只想摸清内网扫描情况的从业者照着重现。先别急着全上按内网规模和预算选一种起步就够了。2. 用 HFish 搭内网蜜罐平台容器部署与第一个告警事件2.1 HFish 是什么为什么内网感知选它而不是单点蜜罐HFish 是一个开源的分布式蜜罐平台管理端和节点端分离能在一台管理端上给多台节点下发不同协议的蜜罐服务。它内置 HTTP、SSH、Redis、MySQL、Web 等几十种蜜罐类型攻击者一旦触碰平台会自动生成攻击者画像用了什么账号密码、命令是什么、从哪个 IP 来、有没有文件下载行为。相比单点蜜罐它最大的优势是「聚拢」所有节点的告警汇聚到管理端按攻击链排好序省得一台一台翻日志。原理上HFish 的节点端是真正开放蜜罐服务的地方管理端只负责策略下发和数据汇总。这意味着你可以把节点散到各个网段贴近真实业务跑让攻击者更容易踩进陷阱。我一般把它当成整个蜜罐体系的入口先挂着让其他人观察平台里的攻击时间线再用 Cowrie 这类专用蜜罐去深挖攻击者具体做了什么。对新手来说HFish 的部署门槛不高只要管理端口、节点端口放通再跟着界面一步步初始化就行。真正要留心的是下面这几个配置点。2.2 用 docker compose 拉起 HFish 管理端最小命令与目录约定常见做法是把管理端跑在单独的目录下数据目录和配置文件统一挂载方便备份。先建目录、放一个最小的 compose 文件我这里不贴完整版本因为不同发行版对路径有要求但最小可用的结构是这样mkdir -p /opt/hfish/data /opt/hfish/config cat /opt/hfish/docker-compose.yml EOF services: hfish: image: chaitin/hfish container_name: hfish restart: always ports: - 4433:4433 # 管理端 web 界面 - 4434:4434 # 节点回连端口 volumes: - ./config:/var/lib/hfish/config - ./data:/var/lib/hfish/data EOF cd /opt/hfish docker compose up -d这个编排里4433 是管理端 Web 控制台的访问端口4434 是节点端主动回连管理端的通信端口。./config和./data分别挂载配置与数据容器重启不会丢日志和攻击者画像。参数说明两点第一restart: always保证节点宕机后自动拉起第二conf 目录必须可写HFish 首次启动会在里面生成运行时配置文件。启动后别急着访问先改一个必调参数管理端 IP。因为节点回连管理端时要用到这个 IP如果默认配置里写的是容器 IP节点端永远连不上。# 查看容器启动情况 docker compose ps # 修改管理端对外 IP假设管理端所在主机是 192.168.1.10 vi /opt/hfish/config/config.yaml # 找到 admin_ip 或类似字段改成 192.168.1.10改完重启容器docker compose restart然后浏览器访问https://192.168.1.10:4433按初始化向导创建管理员账号。这一步不复杂但 4433 的 HTTPS 证书是平台自签发的浏览器会有告警属正常现象加入信任即可。初始化完成后平台提示「管理端就绪」就可以加节点了。2.3 添加节点和下发蜜罐服务管理端与节点的握手参数节点端是真正暴露诱饵服务的机器。先在管理端界面「节点管理」里生成一个节点 token然后在目标机器上同样用容器方式拉起节点端把 token 和回连地址传进去# 在目标节点机上执行假设管理端 IP 仍是 192.168.1.10 docker run -d --name hfish-node \ -e HFISH_NODE_TOKEN管理端生成的token \ -e HFISH_NODE_ADDR192.168.1.10:4434 \ chaitin/hfish节点端跑起来后它会主动连管理端的 4434 端口做握手然后在管理端界面显示在线。参数说明HFISH_NODE_TOKEN是节点身份凭证每个节点单独一个HFISH_NODE_ADDR是管理端可达地址端口必须匹配 compose 里映射的 4434。如果节点显示离线先看节点机上能否 telnet 通管理端的 4434再看两台机器时间是否同步时间偏差过大会导致握手被拒。节点在线后回到管理端「服务管理」给节点下发蜜罐服务。字段有服务类型、监听端口、日志开关一般选 HTTP 蜜罐监听 8080、MySQL 蜜罐监听 3306再选一个 Redis 蜜罐。下发完成界面会显示服务状态是「运行中」。2.4 校验部署从攻击者视角看蜜罐是否「真的活了」部署完最容易忽略的是确认蜜罐服务真的在对外响应。我一般会从另一台机器模拟触碰一下拿 HTTP 蜜罐当例子# 从另一台机器发起请求验证 HTTP 蜜罐有响应 curl -k http://192.168.1.20:8080/admin/login # 查看节点机上端口监听情况 ss -lntp | grep 8080如果 curl 返回了伪造的登录页面ss也能看到 8080 在监听说明服务已经生效。再去管理端事件列表看有没有生成对应事件。这一步的意义是确认端口对外的可达路径是通的否则蜜罐只是白跑一个端口。HFish 的事件会记录 src_ip、目标端口、请求路径这些字段是后续溯源和封禁的原始依据。3. 用 Cowrie 搭 SSH 中交互蜜罐命令行里藏着的证据3.1 Cowrie 的定位伪装 SSH 服务并完整记录攻击者操作HFish 虽然记录了账号密码和请求但攻击者真的钻进去以后做了什么它不够深。Cowrie 的定位就是补上这一层它是一个中交互 SSH/Telnet 蜜罐攻击者用账号密码登录后会进入一个伪装的 shell 环境。输入的命令会被记录成结构化日志包括whoami、cat /etc/passwd甚至用 wget 下载文件的 URL。它不会真的执行系统命令也不会给攻击者真实文件系统但足够骗过大多数自动化脚本和一些人工操作。选 Cowrie 而不是直接在真实机器上开个假账号原因是安全边界攻击者在假的 shell 里折腾永远波及不了宿主机。而且它的日志是 JSON 格式字段非常干净适合接 SIEM 或者自己写解析脚本。以下部署步骤基于 Python 虚拟环境不污染全局依赖也方便之后升级。3.2 源码安装与启动cowrie.cfg 的三个必调参数Cowrie 的常见做法是用 venv 安装再单独跑成服务。先准备环境apt update apt install -y python3 python3-venv python3-pip git mkdir -p /opt/cowrie cd /opt/cowrie git clone https://github.com/cowrie/cowrie.git . python3 -m venv cowrie-env source cowrie-env/bin/activate pip install --upgrade pip pip install -r requirements.txt依赖装完后先复制一份默认配置再编辑。它默认监听 2222 端口这不算坑但对真实攻击者来说有点刻意我会顺手改掉。长期运维我会把配置里几个关键项逐个确认不照抄默认值# etc/cowrie.cfg 中的关键配置片段 [ssh] listen_endpoints tcp:2222:interface0.0.0.0 [honeypot] hostname web-ops-01 contents_path ${honeypot:data_path}/pickle [shell] filesystem_class CowrieFilesystem这三个参数解释一下。listen_endpoints决定 Cowrie 监听在哪必须绑0.0.0.0只绑 127.0.0.1 的话外面根本连不进来这是新手最常翻车的地方。hostname是伪造的主机名写得太 「honeypot」 一眼穿帮我一般起个像业务机的名字。shell段保持默认的伪造文件系统即可配合contents_path指向预置文件让ls命令能看到几个假目录。启动前再检查一下当前目录权限避免日志写不进去mkdir -p var/log/cowrie source cowrie-env/bin/activate bin/cowrie start tail -f var/log/cowrie/cowrie.log看到日志里出现Cowrie started就算起来了。注意bin/cowrie start是以前台模式托管进程调试没问题正式跑我建议配合 supervisor 或 systemd后面会讲到。3.3 验证攻击者交互记录cowrie.json 里的字段含义装好之后不能只看它跑着要真的模拟一次登录行为。用 SSH 客户端连过去密码随便输一个ssh -p 2222 root192.168.1.20 # 密码随意, 例如 admin123 whoami cat /etc/passwd exit然后回去看 JSON 日志。它的路径在/opt/cowrie/var/log/cowrie/cowrie.json是追加写入的。用tail拿最后几条tail -5 /opt/cowrie/var/log/cowrie/cowrie.json | python3 -m json.tool里面会出现多条事件我挑两个重点登录失败的login.failed事件里src_ip和password字段说明攻击者用了哪些爆破口令登录成功后的command.input事件记录每条具体命令system字段是我刚才敲的whoami、cat /etc/passwd。这组数据就是取证的关键证据。参数上建议保留默认日志轮转cowrie.json增长很快几天的爆破流量就能到几百 MB不轮转会写满/var/log。4. 自研 TCP 端口诱饵20 行脚本接住全端口扫描器4.1 为什么还要自研平台和 Cowrie 覆盖不到的端口HFish 和 Cowrie 覆盖的是知名端口但内网扫描器不挑食。它们通常全端口扫一遍3389、445、1433、6379、9000这些只要开着就会上来摸一把。一个只有几十行代码的 TCP 诱饵可以在一个 IP 上挂多个端口只要有人 connect 就记下来源 IP 和首包内容。这是低交互蜜罐里成本最低、见效最快的一种。我选择自研而不是找现成工具原因很实在一是现成的低交互蜜罐多数又要装依赖、开服务不如一个脚本干净二是脚本里想加端口、加日志格式、对接告警改起来都是几行的事不用研究别人的配置语法。缺点是交互深度浅只能记录连接行为和首包拿不到后续操作但它和 Cowrie、HFish 正好互补成三层平台看全貌、Cowrie 看深交互、脚本看扫描足迹。4.2 脚本实现监听多端口并落日志下面是我在实际运维里用着顺手的版本去掉注释不到 30 行。它给每个端口开一个监听线程连接上来后读取最多 1024 字节并记录来源 IP、端口、时间到/var/log/honeypot/下按端口拆分的文件#!/usr/bin/env python3 # tcp_probe.py - 多端口 TCP 诱饵, 记录来源与首包内容 import socket import threading import datetime PORTS [21, 22, 23, 25, 445, 1433, 3306, 6379, 8080, 9000] LOG_DIR /var/log/honeypot def log_line(src_ip, port, payload): ts datetime.datetime.now().strftime(%Y-%m-%d %H:%M:%S) with open(f{LOG_DIR}/port_{port}.log, a, encodingutf-8) as fp: fp.write(f{ts}\t{src_ip}\t{port}\t{payload!r}\n) def on_connect(sock, port): sock.settimeout(10) try: data sock.recv(1024) payload data.decode(utf-8, errorsreplace) log_line(sock.getpeername()[0], port, payload[:200]) except socket.timeout: pass finally: sock.close() def listen_port(port): srv socket.socket(socket.AF_INET, socket.SOCK_STREAM) srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) srv.bind((0.0.0.0, port)) srv.listen(128) while True: conn, addr srv.accept() threading.Thread(targeton_connect, args(conn, port), daemonTrue).start() if __name__ __main__: for p in PORTS: threading.Thread(targetlisten_port, args(p,), daemonTrue).start() print(f[*] listening on {p}) threading.Event().wait()两个参数值得说明。PORTS按你内网的实际服务来不必贪多10 个就够端口越多越容易被安全设备当成扫描源得不偿失。payload[:200]做截断是必须的有些扫描器会发很长的畸形包全写进日志会让文件快速膨胀。日志格式里用!r会把不可见字符转义避免控制字符搞乱后续的文本解析。整个脚本不依赖第三方库纯标准库实现Python 3.6 以上就能跑。4.3 用 systemd 托管开机自启与崩溃自动拉起脚本写好后要让它常驻后台并且机器重启后自动拉起来。我会写一个 systemd unit 文件比nohup靠谱得多# /etc/systemd/system/tcp-probe.service [Unit] DescriptionTCP honeypot probe Afternetwork.target [Service] ExecStart/usr/bin/python3 /opt/honeypot/tcp_probe.py WorkingDirectory/opt/honeypot Restarton-failure RestartSec5 StandardOutputjournal StandardErrorjournal [Install] WantedBymulti-user.target这里的Restarton-failure表示只有非正常退出才拉起避免脚本里主动退出还疯狂重启。RestartSec5是重启间隔太短会在持续崩溃时刷满日志。StandardOutputjournal让 print 的输出进 journal可通过journalctl -u tcp-probe查看不让进程自己写文件导致磁盘占用。启用它mkdir -p /opt/honeypot cp tcp_probe.py /opt/honeypot/ mkdir -p /var/log/honeypot sudo systemctl daemon-reload sudo systemctl enable --now tcp-probe ss -lntp | grep -E 445|6379|9000最后一条ss能同时看到 10 个端口在监听说明脚本跑起来了。日志目录权限要处理好脚本是用 root 跑的/var/log/honeypot也必须可写如果用的普通用户记得chown。到这里三种蜜罐就都上线了接下来是更关键的避坑部分这些坑每一个我都实际踩过。5. 蜜罐部署避坑节点不显示、空日志、日志爆盘的排查记录5.1 管理端集群里节点一直显示离线现象HFish 管理端明明运行正常节点端容器也起来了集群列表里节点状态却是「离线」或始终「未注册」。排查的思路是节点根本没连上管理端的 4434。先用telnet从节点机测到管理端的 4434 端口通不通大多数时候是防火墙只放行了 4433 而没放 4434。解决在内网边界和节点机本机防火墙同时放行 TCP 4434方向为节点端出方向、管理端入方向。另一个常见原因是两台机器时间差超过 5 分钟TLS 握手直接失败做一次chronyc makestep或配置 NTP 同步即可。这类问题的关键词是「握手」不是配置错词先抓包看 TCP 有没有到。5.2 Cowrie 只记录握手看不到密码和命令现象Cowrie 日志里有大量connection事件但就是没有login.failed或command.input。原因一般分两种一是攻击者用的是端到端扫描工具只发 TCP SYN 不交互根本不会进入 SSH 认证流程二是监听端口绑在回环上外部扫描没打进来。解决先确认/opt/cowrie/var/log/cowrie/cowrie.json里有没有src_ip不是 127.0.0.1 的记录如果没有就是监听地址问题回cowrie.cfg检查listen_endpoints里的interface0.0.0.0。还有一种情况是攻击者用密钥登录而非密码Cowrie 的日志字段对应的是public_key事件不等于没有记录不要把密码字段缺失误判为蜜罐失效。5.3 自研诱饵日志全空现象脚本启动正常ss能看到端口监听但/var/log/honeypot下没有任何文件。一次典型的翻车是脚本里写了bind((127.0.0.1, port))外部连接根本进不来这属于自作自受。更隐蔽的是日志目录权限脚本自身有写入权限但父目录/var/log开了noexec或 SELinux 限制Python 写文件时不会报错而是悄悄丢弃。解决先手动跑一次python3 -c import socket; ssocket.socket(); s.connect((127.0.0.1, 445))制造一条本地连接然后ls /var/log/honeypot看有没有文件浮出来。没有文件就先在脚本里加flushTrue强制落盘再不行就audit2why看 SELinux 拦截记录。这类问题最怕的不是难修是难发现。5.4 蜜罐日志爆盘和告警风暴现象跑了一周后/var被写满或者 HFish 告警每小时轰炸几十条管理员的免疫力直接被打废。原因很简单cowrie.json 是无限追加的自研脚本每分钟可能记几百行HFish 自带告警又没有按源 IP 聚合。解决日志轮转是底线。Cowrie 官方默认带logrotate配置但很多人忘了启用常见做法是在/etc/logrotate.d/cowrie里写按天切割、保留 7 天、compress。自研脚本的日志也要同样处理或者更简单一点按天命名文件port_445_20241126.log再定时清理 14 天前的文件。告警侧在 HFish 里做按源 IP 聚合并按分钟收紧触发阈值未命中的扫描不产生告警。别等到磁盘满了才想起来蜜罐日志爆盘是排第一的运维事故。5.5 蜜罐被当成内网真实资产现象蜜罐节点上线后运维巡检脚本把 3306 端口误判为数据库打了工单要求下线「僵尸服务」或者攻击者扫描时发现蜜罐响应特性与真实服务差异大直接绕过。原因在于蜜罐默认配置太「标准」指纹太明显。解决一是给蜜罐的响应内容做伪装HFish 里尽量用带真实业务特征的模板比如把 HTTP 蜜罐的前端页面改成本单位登录页样式不要把默认页面直接挂上去二是做了假端口就要承担后续被当真实资产的管理成本在资产台账里显式标注「HOOK-端口诱饵」同时把蜜罐服务与业务机房隔离不混在同一网段。这个问题没有一劳永逸的解法只能靠台账和制度兜底。6. 蜜罐上线后的验证与封禁联动把日志变成防火墙策略6.1 上线验证一条命令确认三种蜜罐都在线蜜罐部署完不是终点要定期确认它们还活着。我习惯用nc写一条批量探测脚本每天定时跑结果发到工作群里for p in 21 22 23 445 3306 6379 8080 9000; do timeout 2 nc -z 192.168.1.20 $p echo $p open || echo $p dead done这条命令不会产生交互数据只验证端口可达适合加进crontab。注意别用扫描器去测自己的蜜罐扫出来的行为会混进正常日志干扰统计。如果某个端口报dead就回看是否进程挂了、systemd 有没有自动拉起、日志目录是否还在写入。验证节奏上新上线蜜罐的前三天每天看一次事件量后面一周看一次即可。6.2 从一段实际日志到封禁策略告警联动的落法蜜罐的价值在于把日志变成行动。我最常用的操作是直接从 cowrie.json 里提取攻击源和命令生成封禁名单# 提取尝试过多个密码的源 IP grep eventid: login.failed /opt/cowrie/var/log/cowrie/cowrie.json \ | python3 -c import sys,json; [print(json.loads(l)[src_ip]) for l in sys.stdin if src_ip in json.loads(l)] \ | sort | uniq -c | sort -rn | head # 封禁出现次数超过 5 次的源 IP awk {print $1} /var/log/honeypot/port_22.log | sort | uniq -c | awk $15{print $2} \ | xargs -I {} iptables -A INPUT -s {} -j DROP这里要提醒一点封禁动作要谨慎先确认 IP 不是自己的内网出口或云上探测源否则会把自己锁在外面。我吃过这个亏源 IP 里有云厂商的负载均衡健康检查封完之后业务端口全断当时整个人都麻了。后来我加上了一层白名单判断凡是资产台账里出现过的内网 IP 一律跳过封禁流程。蜜罐日志读完落成的规则要留记录方便后续审计。整套东西跑顺之后我更倾向于把以上操作打包成小型脚本挂在 cron 里每天只处理新增的源 IP让蜜罐真正变成一个每天自动产出封禁清单的抓手而不是躺在那里的黑匣子。这点经验希望帮到你。本文还有配套的精品资源点击获取
返回列表