Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Banner Fingerprint System (Golang)

接收一批网络扫描原始数据(ip / port / banner),自动识别协议、软件与版本信息。 Client + Server 架构,Docker Compose 一键启动,生产级部署标准。

架构

flowchart LR
    A[scan dump JSON] --> C[client]
    C -- "POST /fingerprint<br/>http://server:8080 (compose service DNS)" --> S[server :8080]
    S --> E[fingerprint engine<br/>regex rules from rules.json]
    S --> R[results JSON]
    C --> T[table output]
    H[docker HEALTHCHECK<br/>binary -healthcheck mode] -.-> S
Loading
  • server:无状态 HTTP API(POST /fingerprint 批量识别、GET /health 健康检查)。
  • client:独立 CLI,读本地 JSON 文件 → 发给 server → 表格展示结果。
  • 容器间只通过 compose 私有网络 banner-net 上的服务名 server 访问,无 host IP 硬编码。
  • 识别规则与程序代码解耦:规则全部在 internal/fingerprint/rules.json(数据驱动), 代码只负责执行规则引擎;规则文件通过 go:embed 内嵌进二进制,也可运行时用 RULES_PATH 指向外部文件热加载(免重新编译)。

快速开始

docker compose up -d --build     # 启动 server(client 为一次性任务,不随 up 常驻)
curl localhost:8080/health       # 健康检查
docker compose run --rm client   # 用 testdata/input.json 跑一次全量识别

curl 直接调 API:

curl -s -X POST localhost:8080/fingerprint -d '[
  {"ip":"1.2.3.4","port":22,"banner":"SSH-2.0-OpenSSH_8.9p1 Ubuntu-3"},
  {"ip":"1.2.3.5","port":80,"banner":"HTTP/1.1 200 OK\r\nServer: nginx/1.24.0"}
]'

本地开发(不依赖 Docker):

go test ./...                    # 单元测试
go run ./cmd/server -addr :8080
go run ./cmd/client -server http://localhost:8080 -file testdata/input.json

API 契约

POST /fingerprint

  • 请求体:JSON 数组(或单个对象)[{ "ip": string, "port": number, "banner": string }]
  • 响应:与输入一对一、保序、同数量的结果数组 [{ "ip", "port", "protocol", "product", "version", "os_hint", "confidence" }]
  • 认不出的记录返回 protocol: "unknown"永远不会因为某个 banner 无法识别而报错或崩溃。
  • 限制:请求体 ≤ 10 MiB,单批 ≤ 10 000 条。

GET /health

  • 返回 200 {"status":"ok","service":"banner-fingerprint-server","time":...}
  • compose 的 HEALTHCHECK 不是"进程活着"检查:server -healthcheck 会在容器内发起 真实 HTTP GET 到 /health,探针地址由实际监听地址推导(任意 -addr 都正确)。

HTTP 错误码

状态码 含义
200 成功(含全部 unknown 的结果)
400 JSON 非法 / 空输入 / 批次超限
405 非 POST
413 请求体超限
500 仅作为兜底(panic 恢复中间件),正常路径不会出现

client 退出码

退出码 含义
0 批次处理完成(包含 unknown 结果,不算失败)
1 用法 / 文件读取错误
2 输入解析错误
3 网络错误(连不上 server)
4 server 返回错误响应

输出字段与 confidence 语义

字段 说明
protocol 协议族;未命中恒为 "unknown"空字符串也不会出现
product 具体软件(OpenSSH / Dropbear / nginx / Apache / Jetty / Microsoft IIS / lighttpd / Caddy / MySQL / MariaDB / Redis / ProFTPD / vsFTPd / Pure-FTPd;SMTP 问候语不携带产品名,product 为空)
version 软件版本;banner 未携带时为 ""(如 Redis、Pure-FTPd)
os_hint 从 banner 尾部提取的 OS 线索(如 SSH-2.0-OpenSSH_8.9p1 Ubuntu-3Ubuntu);没有则为 ""
confidence 01,由命中的规则给出(协议层→产品层逐级覆盖):SSH/常见 HTTP 产品 0.850.95,MySQL/MariaDB 0.9,FTP 0.85~0.9,Redis 0.7(错误类 banner 不含版本,置信度保守),HTTP 无版本 Server 头(如 Server: nginx/x.y)经回退规则识别产品 0.6,TLS 0.4(仅握手字节,无产品信息),unknown 恒为 0

识别规则引擎

两阶段、数据驱动:

  1. protocol 阶段:按规则 ID 排序逐个匹配 banner;首个命中确定 protocol。 自包含规则(如 SSH/MySQL/MariaDB/Redis)同时给出 product / version / confidence。
  2. product 阶段:泛型协议(HTTP/FTP)命中后,继续在该协议的规则子集内匹配具体产品。 有版本规则(http-nginx)按 ID 先于无版本回退规则(http-nginx-noversion,置信 0.6)匹配: banner 带版本走精确规则,Server: nginx 这类无版本头也能识别出产品。

规则字段:

{
  "id": "http-nginx",        // 唯一 ID
  "stage": "product",        // protocol | product
  "protocol": "HTTP",        // 所属协议(product 阶段必填)
  "product": "nginx",        // 产品名
  "pattern": "(?i)Server:\\s*nginx/([0-9][0-9.]*)",  // Go RE2;捕获组 1 = version
  "os_pattern": "...",       // 可选:捕获组 1 = os_hint
  "confidence": 0.9          // 该规则的置信度
}

扩展规则无需改代码:把 rules.json 挂到容器里并设置 RULES_PATH

server:
  environment:
    RULES_PATH: /app/rules/rules.json
  volumes:
    - ./my-rules.json:/app/rules/rules.json:ro

健壮性(脏数据不崩)

  • 宽容 JSON 解析:banner 转储常见 C 风格 \xHH 转义(非法 JSON)与 UTF-8 BOM, 客户端/服务端自动归一化(\x00\u0000、剥离 BOM)后解析;标准 JSON 同样支持。
  • banner 内任意二进制字节(NUL、非法 UTF-8、控制字符)由正则按字节匹配,不会异常。
  • 服务端有 panic 恢复中间件兜底;单条记录失败不影响整批。
  • 引擎是纯函数、并发安全;server 无状态,可水平扩展。

生产级部署要点

维度 实现
编译打包 多阶段构建:golang:1.23-alpine 编译 → 静态剥离二进制(CGO_ENABLED=0 -trimpath -s -w
运行镜像 最终阶段 FROM scratch(空用户态,无 shell/curl/包管理器,攻击面最小),镜像仅 ~6 MB
权限 固定非 root UID 65532cap_drop: ALLno-new-privilegesread_only 根文件系统
健康检测 真实 HTTP 探针 + compose depends_on: condition: service_healthy(client 只在 server 就绪后启动)
容器间访问 私有 bridge 网络 + 服务名 DNS 收敛,client 无对外端口
优雅停机 SIGTERM/SIGINT → http.Server.Shutdown 排空连接
日志 结构化访问日志;json-file 驱动限制 10MB×3 滚动

目录结构

├── cmd/
│   ├── server/main.go        # HTTP API 服务(含 -healthcheck 探针模式)
│   └── client/main.go        # 批量客户端 CLI
├── internal/
│   ├── fingerprint/          # 指纹引擎:engine.go + rules.json(规则表)
│   ├── parse/                # 宽容 JSON 解析(\xHH / BOM / \u0000)
│   └── model/                # 输入输出类型
├── testdata/input.json       # 自测数据(23 条,覆盖全部识别目标与脏数据)
├── Dockerfile                # 多阶段:build / server(scratch) / client(scratch)
├── docker-compose.yml        # 一键启动编排
└── README.md

测试

go test ./... 覆盖:自测语料逐条断言(协议/产品/版本/OS/置信度)、unknown 契约、 批量保序、泛化场景(HTTP/2、不同 MySQL 包长、Redis 错误类、dropbear/lighttpd/Caddy)、 脏 banner(NUL 尾随、非法 UTF-8)、宽容 JSON(BOM + \xHH)。

About

Banner fingerprint identification system (Go): batch ip/port/banner -> protocol/product/version, client+server, Docker Compose

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages