ivre/masscanned

GitHub: ivre/masscanned

一个用 Rust 编写的低交互网络蜜罐,通过自研用户态网络栈对多种协议提供通用响应,用于捕获和分析互联网扫描器与僵尸网络行为。

Stars: 139 | Forks: 19

[![构建 masscanned](https://static.pigsec.cn/wp-content/uploads/repos/2026/05/0f87746f54213900.svg)](https://github.com/ivre/masscanned/actions/workflows/test.yml?branch=master) # Masscanned **Masscanned**(名称灵感当然来源于 [masscan](https://github.com/robertdavidgraham/masscan)) 是一个网络响应器。它的目的是尽可能多地对各种协议提供通用响应, 并尽可能少地对客户端的意图做出假设。 就像 [masscan](https://github.com/robertdavidgraham/masscan) 一样,**masscanned** 实现了自己的 用户态网络栈,类似于 [honeyd](http://honeyd.org/)。它的设计旨在尽可能多地 与扫描器和机会型机器人进行交互,并支持尽可能多的协议。 例如,当它接收到网络数据包时: * **masscanned** 使用 `ARP is-at` 回复 `ARP who is-at`(针对其 IP 地址), * **masscanned** 使用 `ICMP Echo Reply` 回复 `ICMP Echo Request`, * **masscanned** 使用 `TCP SYN/ACK` 回复任意端口的 `TCP SYN`, * **masscanned** 使用 `HTTP 401` 网页回复通过 `TCP/UDP`(任意端口)发送的 `HTTP` 请求(任何动词)。 ![demo](https://static.pigsec.cn/wp-content/uploads/repos/2026/05/4dad306b42213905.gif) ## 概述 **Masscanned** 目前支持第 2、3、4 层的大多数常见协议,以及一些应用层协议。 ### 网络协议 * ARP(回复 ARP 请求) * ICMP(回复 ping) * ICMPv6(回复 ND NS) * TCP(回复 SYN 和 PUSH) ### 应用协议 * HTTP(回复所有动词) * SSH(回复客户端横幅) * STUN(回复绑定请求) * SMB * DNS(回复 IN/A 查询) ## 本地试用 ### 在您的主机上 1. 构建 **masscanned** ``` $ cargo build ``` 2. 创建一个新的网络命名空间 ``` # ip netns add masscanned ``` 3. 在两个命名空间之间创建 veth ``` # ip link add vethmasscanned type veth peer veth netns masscanned # ip link set vethmasscanned up # ip -n masscanned link set veth up ``` 4. 在本地 veth 上设置 IP,以提供传出数据包的路由 ``` # ip addr add dev vethmasscanned 192.168.0.0/31 ``` 5. 在该命名空间中运行 **masscanned** ``` # ip netns exec masscanned ./target/debug/masscanned --iface veth -v[vvv] ``` 6. 使用另一个终端,向 **masscanned** 发送数据包 ``` # arping 192.168.0.1 # ping 192.168.0.1 # nc -n -v 192.168.0.1 80 # nc -n -v -u 192.168.0.1 80 ... ``` ### 在 Docker 中 1. 安装 docker: ``` # apt install docker.io ``` 1. 构建 docker 容器: ``` $ cd masscanned/docker && docker build -t masscanned:test . ``` 1. 运行 docker 容器: ``` $ docker run --cap-add=NET_ADMIN masscanned:test ``` 1. 向 **masscanned** 发送数据包 ``` # arping 172.17.0.2 # ping 172.17.0.2 # nc -n -v 172.17.0.2 80 # nc -n -v -u 172.17.0.2 80 ... ``` ## 使用 **masscanned** 的一个良好用例是将其部署在具有一个或多个公共 IP 地址的 VPS 上。 要使用这些结果,最好的方法是捕获 **masscanned** 正在监听/响应的网络接口上的所有网络流量。 然后可以使用 [zeek](https://zeek.org/) 分析 pcaps,并且输出文件通常可以被推送到一个 **IVRE** 实例中。 有关如何在 VPS 上部署 **masscanned** 实例的文档即将推出(参见 [Issue #2](https://github.com/ivre/masscanned/issues/2)))。 ### 支持的选项 ``` Network answering machine for various network protocols (L2-L3-L4 + applications) Usage: masscanned [OPTIONS] --iface Options: -i, --iface the interface to use for receiving/sending packets -m, --mac-addr MAC address to use in the response packets --self-ip-file File with the list of IP addresses handled by masscanned --self-ip-list Inline list of IP addresses handled by masscanned, comma-separated --remote-ip-deny-file File with the list of IP addresses from which masscanned will ignore packets --remote-ip-deny-list Inline list of IP addresses from which masscanned will ignore packets -v... Increase message verbosity -q, --quiet Quiet mode: do not output anything on stdout --format Format in which to output logs [default: console] [possible values: console, logfmt] -h, --help Print help information -V, --version Print version information ``` ## 支持的协议 - 详情 ### 第 2 层 #### ARP `masscanned` 回复针对由 `masscanned` 处理的 `IPv4` 地址的 `ARP` 请求 (即,通过 `-f` 选项指定的 IP 地址文件中的地址)。 该回复包含以下可能的 `MAC` 地址中的第一个: * 命令行中使用 `-a` 指定的 `MAC` 地址(如果有的话), * 命令行中使用 `-i` 指定接口的 `MAC` 地址(如果有的话), * 或 `masscanned` 的默认 `MAC` 地址,即 `c0:ff:ee:c0:ff:ee`。 #### Ethernet `masscanned` 仅在满足以下要求时回复 `Ethernet` 帧: * 帧的目标地址应由 `masscanned` 处理,这意味着: * `masscanned` 自身的 `MAC` 地址, * 广播 `MAC` 地址 `ff:ff:ff:ff:ff:ff`, * 与 `masscanned` 处理的 `IPv4` 地址之一对应的组播 `MAC` 地址([RFC 1112](https://datatracker.ietf.org/doc/html/rfc1112)), * 与 `masscanned` 处理的 `IPv6` 地址之一对应的组播 `MAC` 地址; * `EtherType` 字段为 `ARP`、`IPv4` 或 `IPv6` 之一。 **注意:** 即使对于非组播 IP 地址,`masscanned` 也会响应发送到相应组播 `MAC` 地址的 L2 帧。 例如,如果 `masscanned` 处理 `10.11.12.13`,它将回复发往 `01:00:5e:0b:0c:0d` 的帧。 ### 第 3 层 #### IPv4/IPv6 `masscanned` 仅在以下情况回复 `IPv4` 和 `IPv6` 数据包: * 文件中没有指定 `IP` 地址(即,没有指定 `-f` 选项或文件为空), **或者** * 传入数据包的目标 IP 地址是 `masscanned` 处理的 IP 地址之一。 另外一个要求是支持下一层协议 - 见下文。 #### IPv4 对于 `IPv4` 数据包,支持以下 L3+/4 协议: * `ICMPv4` * `UDP` * `TCP` 如果下一层协议不是其中之一,则丢弃该数据包。 #### IPv6 对于 `IPv6` 数据包,支持以下 L3+/4 协议: * `ICMPv6` * `UDP` * `TCP` 如果下一层协议不是其中之一,则丢弃该数据包。 ### 第 3+/4 层 #### ICMPv4 `masscanned` 当且仅当以下条件时回复 `ICMPv4` 数据包: * 传入数据包的 `ICMP` 类型为 `EchoRequest` (`8`), * 传入数据包的 `ICMP` 代码为 `0`。 如果满足这些条件,`masscanned` 将使用类型为 `EchoReply` (`0`)、代码为 `0` 且负载与传入数据包相同的 `ICMP` 数据包进行回复,如 [RFC 792](https://datatracker.ietf.org/doc/html/rfc792) 所规定。 #### ICMPv6 `masscanned` 当且仅当以下条件时回复 `ICMPv6` 数据包: * `ICMP` 类型为 `NeighborSol` (`135`) **并且**: * 没有为 `masscanned` 指定 IP(v4 或 v6) * **或者** 邻居请求的目标地址是 `masscanned` 之一 *在这种情况下,回复是一个带有 `masscanned` `MAC` 地址的 `Neighbor Advertisement` (`136`) 数据包* **或者** * `ICMP` 类型为 `EchoRequest` (`128`) *在这种情况下,回复是一个 `EchoReply` (`129`) 数据包。* #### TCP `masscanned` 回复以下 `TCP` 数据包: * 如果接收到的数据包带有 `PSH` 和 `ACK` 标志,`masscanned` 会检查 **SYNACK-cookie**,如果有效,则至少回复一个 `ACK`;如果检测到支持的协议(第 5/6/7 层),则回复 `PSH-ACK`, * 如果接收到的数据包带有 `ACK` 标志,则忽略, * 如果接收到的数据包带有 `RST` 或 `FIN-ACK` 标志,则忽略, * 如果接收到的数据包带有 `SYN` 标志,则 `masscanned` 尝试模拟 标准 Linux 栈的行为 - 即: * 如果存在不属于 `PSH`、`URG`、`CWR`、`ECE` 的附加标志,则忽略 `SYN`, * 如果同时设置了 `CWR` 和 `ECE` 标志,则忽略 `SYN`, * 在任何其他情况下,`masscanned` 使用 `SYN-ACK` 数据包进行回复,并在序列号中设置 **SYNACK-cookie**。 #### UDP `masscanned` 当且仅当上层协议被处理并提供回复时,才回复 `UDP` 数据包。 ### 应用协议 #### HTTP `masscanned` 使用 `401 Authorization Required` 回复任何 `HTTP` 请求(任何**有效**的动词)。 请注意,带有无效动词的 `HTTP` 请求将不会被回复。 示例: ``` $ curl -X GET 10.11.10.129 401 Authorization Required

401 Authorization Required


nginx/1.14.2
$ curl -X OPTIONS 10.11.10.129 401 Authorization Required

401 Authorization Required


nginx/1.14.2
$ curl -X HEAD 10.11.10.129 Warning: Setting custom HTTP method to HEAD with -X/--request may not work the Warning: way you want. Consider using -I/--head instead. 401 Authorization Required

401 Authorization Required


nginx/1.14.2
$ curl -X XXX 10.11.10.129 [timeout] ``` #### STUN 示例: ``` $ stun 10.11.10.129 STUN client version 0.97 Primary: Open Return value is 0x000001 ``` #### SSH `masscanned` 使用以下 `Server: Protocol` 消息回复 `SSH` `Client: Protocol` 消息: ``` SSH-2.0-1\r\n ``` #### SMB `masscanned` 回复 `Negotiate Protocol Request` 数据包,以便 客户端发送 `NTLMSSP_NEGOTIATE`,`masscanned` 随后对该请求回复一个挑战。 示例: ``` ##$ smbclient -U user \\\\10.11.10.129\\shared Enter WORKGROUP\user's password: ``` #### DNS `masscanned` 目前只回复类为 `IN` 且类型为 `A` 的 `DNS` 查询。 它提供的回复始终包含查询发送到的 IP 地址。 示例: ``` $ host -t A masscan.ned 10.11.10.129 Using domain server: Name: 10.11.10.129 Address: 10.11.10.129#53 Aliases: masscan.ned has address 10.11.10.129 $ host -t A masscan.ned 10.11.10.130 Using domain server: Name: 10.11.10.130 Address: 10.11.10.130#53 Aliases: masscan.ned has address 10.11.10.130 $ host -t A masscan.ned 10.11.10.131 Using domain server: Name: 10.11.10.131 Address: 10.11.10.131#53 Aliases: masscan.ned has address 10.11.10.131 $ host -t A masscan.ned 10.11.10.132 Using domain server: Name: 10.11.10.132 Address: 10.11.10.132#53 Aliases: masscan.ned has address 10.11.10.132 ``` ## 内部机制 ### 测试 #### 单元测试 ``` $ cargo test Compiling masscanned v0.2.0 (/zdata/workdir/masscanned) Finished test [unoptimized + debuginfo] target(s) in 3.83s Running unittests (target/debug/deps/masscanned-f9292f8600038978) running 92 tests test client::client_info::tests::test_client_info_eq ... ok test layer_2::arp::tests::test_arp_reply ... ok test layer_2::tests::test_eth_empty ... ok test layer_2::tests::test_eth_reply ... ok test layer_3::ipv4::tests::test_ipv4_reply ... ok test layer_3::ipv4::tests::test_ipv4_empty ... ok test layer_3::ipv6::tests::test_ipv6_empty ... ok test layer_3::ipv6::tests::test_ipv6_reply ... ok test layer_4::icmpv4::tests::test_icmpv4_reply ... ok test layer_4::icmpv6::tests::test_icmpv6_reply ... ok test layer_4::icmpv6::tests::test_nd_na_reply ... ok test layer_4::tcp::tests::test_synack_cookie_ipv6 ... ok test layer_4::tcp::tests::test_tcp_fin_ack_wrap ... ok test proto::dns::cst::tests::class_parse ... ok test layer_4::tcp::tests::test_tcp_fin_ack ... ok test layer_4::tcp::tests::test_synack_cookie_ipv4 ... ok test proto::dns::cst::tests::type_parse ... ok test proto::dns::header::tests::parse_byte_by_byte ... ok test proto::dns::header::tests::repl_id ... ok test proto::dns::header::tests::repl_opcode ... ok test proto::dns::header::tests::repl_ancount ... ok test proto::dns::header::tests::repl_rd ... ok test proto::dns::query::tests::parse_in_a_all ... ok test proto::dns::header::tests::parse_all ... ok test proto::dns::query::tests::repl ... ok test proto::dns::query::tests::reply_in_a ... ok test proto::dns::rr::tests::parse_all ... ok test proto::dns::rr::tests::parse_byte_by_byte ... ok test proto::dns::query::tests::parse_in_a_byte_by_byte ... ok test proto::dns::tests::parse_qd_all ... ok test proto::dns::tests::parse_qd_byte_by_byte ... ok test proto::dns::rr::tests::build ... ok test proto::dns::tests::parse_qd_rr_all ... ok test proto::dns::tests::parse_qr_rr_byte_by_byte ... ok test proto::dns::tests::parse_rr_byte_by_byte ... ok test proto::dns::tests::parse_rr_all ... ok test proto::dns::tests::reply_in_a ... ok test proto::http::tests::test_http_request_line ... ok test proto::http::tests::test_http_request_no_field ... ok test proto::http::tests::test_http_request_field ... ok test proto::http::tests::test_http_verb ... ok test proto::rpc::tests::test_probe_nmap ... ok test proto::rpc::tests::test_probe_nmap_split1 ... ok test proto::rpc::tests::test_probe_portmap_v4_dump ... ok test proto::rpc::tests::test_probe_nmap_split2 ... ok test proto::rpc::tests::test_probe_nmap_udp ... ok test proto::smb::tests::test_smb1_session_setup_request_parse ... ok test proto::smb::tests::test_smb1_protocol_nego_parsing ... ok test proto::smb::tests::test_smb1_protocol_nego_reply ... ok test proto::smb::tests::test_smb1_session_setup_request_reply ... ok test proto::smb::tests::test_smb2_protocol_nego_parsing ... ok test proto::smb::tests::test_smb2_protocol_nego_reply ... ok test proto::smb::tests::test_smb2_session_setup_request_reply ... ok test proto::smb::tests::test_smb2_session_setup_request_parse ... ok test proto::ssh::tests::ssh_1_banner_cr ... ok test proto::ssh::tests::ssh_1_banner_crlf ... ok test proto::ssh::tests::ssh_1_banner_lf ... ok test proto::ssh::tests::ssh_1_banner_space ... ok test proto::ssh::tests::ssh_2_banner_cr ... ok test proto::ssh::tests::ssh_1_banner_parse ... ok test proto::ssh::tests::ssh_2_banner_parse ... ok test proto::ssh::tests::ssh_2_banner_lf ... ok test proto::ssh::tests::ssh_2_banner_crlf ... ok test proto::stun::tests::test_change_request_port_overflow ... ok test proto::stun::tests::test_proto_stun_ipv4 ... ok test proto::stun::tests::test_change_request_port ... ok test proto::ssh::tests::ssh_2_banner_space ... ok test proto::stun::tests::test_proto_stun_ipv6 ... ok test proto::tcb::tests::test_proto_tcb_proto_state_http ... ok test proto::tests::dispatch_dns ... ok test proto::tcb::tests::test_proto_tcb_proto_state_rpc ... ok test proto::tcb::tests::test_proto_tcb_proto_id ... ok test proto::tests::test_proto_dispatch_http ... ok test proto::tests::test_proto_dispatch_ssh ... ok test proto::tests::test_proto_dispatch_ghost ... ok test proto::tests::test_proto_dispatch_stun ... ok test smack::smack::tests::test_anchor_end ... ok test smack::smack::tests::test_multiple_matches_wildcard ... ok test smack::smack::tests::test_multiple_matches ... ok test smack::smack::tests::test_anchor_begin ... ok test smack::smack::tests::test_http_banner ... ok test synackcookie::tests::test_clientinfo ... ok test synackcookie::tests::test_ip4 ... ok test synackcookie::tests::test_ip4_dst ... ok test synackcookie::tests::test_ip4_src ... ok test synackcookie::tests::test_ip6 ... ok test synackcookie::tests::test_key ... ok test synackcookie::tests::test_tcp_dst ... ok test synackcookie::tests::test_tcp_src ... ok test smack::smack::tests::test_wildcard ... ok test smack::smack::tests::test_proto ... ok test smack::smack::tests::test_pattern ... ok test result: ok. 92 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.41s ``` #### 功能测试 ``` # ./test/test_masscanned.py INFO test_arp_req......................................OK INFO test_arp_req_other_ip.............................OK INFO test_ipv4_udp_dns_in_a............................OK INFO test_ipv4_udp_dns_in_a_multiple_queries...........OK INFO test_ipv4_tcp_ghost...............................OK INFO test_ipv4_tcp_http................................OK INFO test_ipv4_tcp_http_segmented......................OK INFO test_ipv4_tcp_http_incomplete.....................OK INFO test_ipv6_tcp_http................................OK INFO test_ipv4_udp_http................................OK INFO test_ipv6_udp_http................................OK INFO test_ipv4_tcp_http_ko.............................OK INFO test_ipv4_udp_http_ko.............................OK INFO test_ipv6_tcp_http_ko.............................OK INFO test_ipv6_udp_http_ko.............................OK INFO test_icmpv4_echo_req..............................OK INFO test_icmpv6_neighbor_solicitation.................OK INFO test_icmpv6_neighbor_solicitation_other_ip........OK INFO test_icmpv6_echo_req..............................OK INFO test_ipv4_req.....................................OK INFO test_eth_req_other_mac............................OK INFO test_ipv4_req_other_ip............................OK INFO test_rpc_nmap.....................................OK INFO test_rpcinfo......................................OK INFO test_smb1_network_req.............................OK INFO test_smb2_network_req.............................OK INFO test_ipv4_tcp_ssh.................................OK INFO test_ipv4_udp_ssh.................................OK INFO test_ipv6_tcp_ssh.................................OK INFO test_ipv6_udp_ssh.................................OK INFO test_ipv4_udp_stun................................OK INFO test_ipv6_udp_stun................................OK INFO test_ipv4_udp_stun_change_port....................OK INFO test_ipv6_udp_stun_change_port....................OK INFO test_ipv4_tcp_empty...............................OK INFO test_ipv6_tcp_empty...............................OK INFO test_tcp_syn......................................OK INFO test_ipv4_tcp_psh_ack.............................OK INFO test_ipv6_tcp_psh_ack.............................OK INFO test_ipv4_udp_empty...............................OK INFO test_ipv6_udp_empty...............................OK INFO Ran 41 tests with 0 errors ``` 您还可以使用 `TESTS` 环境变量选择要运行的测试 ``` TESTS=smb ./test/test_masscanned.py INFO test_smb1_network_req.............................OK INFO test_smb2_network_req.............................OK INFO Ran 2 tests with 0 errors ``` ## 日志 ### 控制台日志记录器 **动词**: * `init` * `recv` * `send` * `drop` #### ARP ``` $ts arp $verb $operation $client_mac $client_ip $masscanned_mac $masscanned_ip ``` #### Ethernet ``` $ts eth $verb $ethertype $client_mac $masscanned_mac ``` ## 待办事项 * 如果校验和不正确,则丢弃传入的数据包 * 修复回复组播数据包时的源地址。
标签:ARP, BOF, certspotter, DNS, honeypot, HTTP 401, ICMP, IVRE集成, masscan替代, Rust, SMB, SSH, STUN, TCP SYN, 低交互蜜罐, 协议响应, 可视化界面, 威胁情报, 实时处理, 密码管理, 底层分析, 开发者工具, 插件系统, 攻击面分析, 替代GreyNoise, 机器人检测, 欺骗防御, 流量诱捕, 用户态网络栈, 私有化部署, 网络侦察发现, 网络协议栈, 网络命名空间, 网络响应器, 网络安全, 网络安全审计, 网络扫描器, 网络模拟, 网络流量审计, 自托管, 请求拦截, 通知系统, 错误配置检测, 防御规避, 隐私保护