news 2026/9/25 10:15:39

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
三种蜜罐部署实战: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_ADDR="192.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:interface=0.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 root@192.168.1.20 # 密码随意, 例如 admin@123 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", encoding="utf-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", errors="replace") 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(target=on_connect, args=(conn, port), daemon=True).start() if __name__ == "__main__": for p in PORTS: threading.Thread(target=listen_port, args=(p,), daemon=True).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] Description=TCP honeypot probe After=network.target [Service] ExecStart=/usr/bin/python3 /opt/honeypot/tcp_probe.py WorkingDirectory=/opt/honeypot Restart=on-failure RestartSec=5 StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target

这里的Restart=on-failure表示只有非正常退出才拉起,避免脚本里主动退出还疯狂重启。RestartSec=5是重启间隔,太短会在持续崩溃时刷满日志。StandardOutput=journal让 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里的interface=0.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; s=socket.socket(); s.connect(("127.0.0.1", 445))'制造一条本地连接,然后ls /var/log/honeypot看有没有文件浮出来。没有文件就先在脚本里加flush=True强制落盘,再不行就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 '$1>5{print $2}' \ | xargs -I {} iptables -A INPUT -s {} -j DROP

这里要提醒一点:封禁动作要谨慎,先确认 IP 不是自己的内网出口或云上探测源,否则会把自己锁在外面。我吃过这个亏:源 IP 里有云厂商的负载均衡健康检查,封完之后业务端口全断,当时整个人都麻了。后来我加上了一层白名单判断,凡是资产台账里出现过的内网 IP 一律跳过封禁流程。蜜罐日志读完,落成的规则要留记录,方便后续审计。整套东西跑顺之后,我更倾向于把以上操作打包成小型脚本挂在 cron 里,每天只处理新增的源 IP,让蜜罐真正变成一个每天自动产出封禁清单的抓手,而不是躺在那里的黑匣子。这点经验希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/25 10:15:08

Windows窗口置顶原理与强制解除实战指南

1. 窗口“焊死”在最前&#xff1a;这不是Bug&#xff0c;是Windows底层UI权限机制在说话 你有没有遇到过这种情况&#xff1a;正用着记事本写方案&#xff0c;突然某个旧版财务软件的登录框像块磁铁一样牢牢吸在屏幕最上层&#xff0c;遮住Excel表格、盖住微信对话框&#xf…

作者头像 李华
网站建设 2026/9/25 10:15:02

Win10日历节日红字看不清?改这3个设置即可恢复清晰

先把话放前面&#xff1a;win10日历里那一堆中国传统节日的红字&#xff0c;真的不是每次都能让人看清楚。我自己就遇到过好几次&#xff0c;春节前一天打开日历想确认放假安排&#xff0c;屏幕上“春节”两个字和背景糊在一起&#xff0c;得歪着头凑近才能分清楚。后来把系统主…

作者头像 李华
网站建设 2026/9/25 10:14:56

手写机器学习算法:吴恩达课程核心知识点全解析

简介&#xff1a;斯坦福大学吴恩达机器学习课程资源包&#xff0c;是机器学习入门与进阶的经典配套资料&#xff0c;面向希望系统掌握监督学习、无监督学习及神经网络的学习者。资源梳理了线性回归、逻辑回归、支持向量机、决策树、聚类等核心算法&#xff0c;并融汇梯度下降、…

作者头像 李华
网站建设 2026/9/25 10:13:16

Mybatis Cursor 避免 OOM 异常:TaoToken 配置骨架与验证方法详解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/25 10:13:04

Atlas 300V实战:从ATC转换到YOLO推理部署全流程指南

1. Atlas 300V到底是个什么卡&#xff1f;先把这个“是不是运算加速卡”的问题说清楚1.1 从一张“陌生卡”说起前阵子项目组进了几张新卡&#xff0c;标签上印着“Atlas 300V 24G”。同事第一反应问我&#xff1a;这不是运算加速卡吗&#xff1f;是不是跟GPU一样&#xff0c;插…

作者头像 李华