Skip to content

feat: add Venus IPS log query service package - #258

Open
cc06 wants to merge 7 commits into
chaitin:mainfrom
cc06:add-venus-ips
Open

feat: add Venus IPS log query service package#258
cc06 wants to merge 7 commits into
chaitin:mainfrom
cc06:add-venus-ips

Conversation

@cc06

@cc06 cc06 commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

接入设备

项目 说明
设备 Venustech IPS(启明星辰入侵防御系统)
设备版本 Web 控制台(攻击日志页 /log/memorylog/ipslog.php
API 版本 Web HTML 日志页(非公开 REST API)
认证方式 Session-based(浏览器会话 Cookie)

实现方法

本 service package 封装了 Venustech IPS 的攻击日志查询能力,提供 1 个 gRPC 方法:

方法 说明 类型
QueryIpsLog 查询 IPS 攻击日志(内存日志),解析 HTML 表格为结构化条目

技术实现要点:

  • 使用 @chaitin-ai/octobus-sdkdefineService 封装,运行时模式:long-running
  • 通过 GET /log/memorylog/ipslog.php 拉取攻击日志页,按 HTML 表格中带 title 的日志列解析为结构化 entries
  • 支持 limit 参数,对返回条目数做客户端侧截断;<=0 表示返回全部解析结果
  • 通过日志页标记 ips_log_filter 识别有效页面;设备会话失效时即使返回 200 登录页,也会映射为 FAILED_PRECONDITION,避免误判为空结果
  • 支持 timeoutMsskipTlsVerify 配置,适配私有化自签证书环境
  • 支持额外自定义请求头透传(headers),并兼容 host / restBaseUrl / baseUrlcookie / sessionCookie / session_cookie 别名

错误码映射

场景 gRPC 状态码 说明
缺少 host / cookie INVALID_ARGUMENT 调用前拦截
上游 401 / 403 PERMISSION_DENIED 会话无效或无权限
其它 4xx FAILED_PRECONDITION 请求前置条件不满足
200 但返回登录页(无 ips_log_filter 标记) FAILED_PRECONDITION 识别为会话失效,而非空日志页
网络错误 / 超时 / 上游 5xx UNAVAILABLE 设备不可用或请求失败
非预期异常 UNKNOWN 未分类错误

测试命令

cd services

# 验证 package 结构
npm run validate -- --service-dir venus__ips

# 验证打包清单
npm run pack:check

测试结果

静态校验:

  • npm run validate -- --service-dir venus__ips
  • npm run pack:check

内网真机联调:

  • 根据真实浏览器请求包,请求方式为 GET /log/memorylog/ipslog.php,使用 credentials: include,与当前实现的 Cookie 会话鉴权方式一致
  • 根据真实响应包,页面包含 ips_log_filter 标记,说明当前实现用于区分“有效日志页”和“登录失效页”的判定依据与真机一致
  • 根据真实响应包,日志表头包含:名称源IP源端口目的IP目的端口协议类型时间类型事件级别优先级动作入侵防御策略ID发生次数内容,与当前字段映射一致
  • 根据真实响应包,分页脚本中存在 allpage = 316,确认该接口返回的是设备真实日志列表页
  • 根据真实响应包中的样例日志行,可解析出以下结构化字段:
    • name: TCP_可疑行为_安全风险_MYSQL_查询系统变量
    • src_ip: 10.40.164.2
    • src_port: 60782
    • dst_ip: 10.249.184.8
    • dst_port: 3883
    • protocol: TCP
    • time: 2026-06-25 17:49:45
    • type: 可疑行为
    • severity:
    • priority: 警示
    • action: PASS
    • policy_id: 1
    • count: 1
  • content 列在真实页面中通过 td title 承载长文本内容,当前实现按 title 提取,可覆盖该字段

覆盖场景:

  • HTML 日志表行解析与结构化字段映射
  • limit 截断逻辑
  • 会话失效(登录页返回 200)识别
  • host / cookie 缺失校验
  • HTTP 状态码与网络错误映射
  • 内部辅助函数覆盖
  • rpcdef 与 service handler 暴露校验

已知限制

  1. 当前仅支持基于 Web Session Cookie 的只读日志查询,不支持用户名/密码自动登录
  2. 当前仅实现全量攻击日志抓取,未支持按源/目的 IP、时间等条件过滤
  3. 上游返回为 HTML 页面,字段解析依赖当前日志表结构;若设备页面结构变化,需同步调整解析逻辑

Closes #256

@cc06 cc06 changed the title Add Venus IPS log query service package feat: add Venus IPS log query service package Jun 25, 2026
@innomentats

Copy link
Copy Markdown
Member

Review 阻塞:这个 service package PR 有测试文件,但我没有在 PR 描述、评论或改动文件中找到真实的测试截图证据(图片链接或提交的图片文件)。请补充能证明该 service package 跑通的截图,例如 npm test -- --service-dir <service> 通过,以及 OctoBus 实例调用/联调成功的截图。

@innomentats
innomentats marked this pull request as draft June 26, 2026 12:15
@innomentats

Copy link
Copy Markdown
Member

Reviewer note: this PR currently has merge conflicts with the target branch, so it cannot be merged or reviewed safely in its current state.

Please rebase or merge the latest base branch, resolve the conflicts, and make sure GitHub Actions pass again. I am marking/keeping this PR as draft until the conflicts are resolved.

@kingfs

kingfs commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Service L2 自动检查结果:l2:blocked

  • 状态:blocked
  • PR head:2b40f0577d2a4f06b137b8706c346492c80b7e95
  • 门禁版本:e4397c85f817bb1054bdbcb75713141613bf0382
  • 结论:PR 当前为 Draft,未执行 L2。

L2 只验证包结构、mock 测试、80% line/branch/function coverage、打包、构建和 OctoBus smoke 链路;真实设备兼容性仍需人工检查作者提供的脱敏证据。

@kingfs kingfs added the l2:blocked Service L2 检查被 Draft、冲突或基础条件阻塞 label Aug 12, 2026
@monkeyscan

monkeyscan Bot commented Aug 17, 2026

Copy link
Copy Markdown

PR Title: feat: add Venus IPS log query service package

Commit: ff42f1b

该 PR 新增 Venus IPS(启明星辰 IPS)攻击日志查询的 OctoBus 服务包:通过 web 会话 Cookie 认证,对 GET /log/memorylog/ipslog.php 返回的 HTML 日志页做表格解析,映射为结构化条目,并提供 ProbeConnectivity / QueryIpsLog 两个 RPC。变更包括核心实现 venus-ips.js、proto 定义、config/secret schema、mock 上游与测试、以及 package.json / octobus-tentacles.js / bin 等接线文件。

整体质量较好:host/cookie 绑定做了校验,cookie 防 CRLF 注入,禁止跨站重定向(redirect:'manual'),响应体按字节上限截断,错误信息脱敏,TLS 默认校验,测试覆盖较全。

主要问题集中在 fetch 调用方式:代码把 timeoutMs 以及 skipTlsVerify/tlsInsecureSkipVerify/insecureSkipVerify 作为非标准的 RequestInit 选项直接传给全局 fetch。标准 undici fetch 只识别规范内选项(method/headers/body/signal/redirect/dispatcher 等),这些自定义键会被静默忽略,因此超时与跳过 TLS 校验两个文档化配置实际不生效。同仓库其他服务(topsec__edr、venus__ads_v3-6)均使用 AbortController+setTimeout 生成 signal、以及 undici Agent 的 dispatcher 实现同样能力,可作参照修复。

@kingfs
kingfs marked this pull request as ready for review August 17, 2026 02:32
@kingfs

kingfs commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

维护者深度修复已推送(ff42f1b):已重放最新 main,升级 SDK 0.6 单 context ABI,补齐 executable/registry/dispatcher,并加固 URL、header/cookie、TLS/timeout、redirect、limit、响应体上限及错误脱敏。新增语义明确的 ProbeConnectivity,L2 daemon smoke 已通过 Connect、原生 gRPC、MCP,三种协议均命中 mock upstream。13/13 测试通过;覆盖率 99.72% line / 92.31% branch / 97.06% function;本地完整 service L2 gate、pack、build 均通过。原作者说明实现按设备抓包对齐,但现有 PR 没有可独立审计的脱敏真机截图,因此真实 Venus IPS 兼容性仍作为人工证据项保留。

Comment thread services/venus__ips/src/venus-ips.js
Comment thread services/venus__ips/src/venus-ips.js Outdated
@monkeyscan

monkeyscan Bot commented Aug 17, 2026

Copy link
Copy Markdown

PR Title: feat: add Venus IPS log query service package

Commit: 4820de1

本 PR 新增 Venustech IPS(启明星辰 IPS)攻击日志查询的 OctoBus service 包(services/venus__ips),含 service 定义、proto、config/secret schema、mock 上游与较完整的测试。核心实现 venus-ips.js 通过 web 会话 cookie 认证,GET /log/memorylog/ipslog.php 获取 HTML 日志页并解析为结构化条目。整体安全设计良好:默认校验 TLS、redirect=manual 拒绝跨站重定向、响应体 2MiB 上限、cookie/授权头过滤、错误信息脱敏、用 ips_log_filter 标记区分会话失效与空结果、cookie 长度/CRLF 校验。测试覆盖解析、limit、会话失效、错误映射、超时/TLS、响应体上限等路径。发现两个低危问题:1) limit 参数契约不一致——proto/README 声明 <=0 表示全部,实现却对负值抛 INVALID_ARGUMENT(测试已固化该行为),应按文档统一;2) 非 2xx/超限等提前 throw 路径未 cancel 响应体,可能影响 undici 连接池复用(OK 分支已 cancel,错误分支遗漏)。另外 README 已自行声明真机兼容性待维护者核验,HTML 解析(title 属性 + 严格日期格式 + 固定 UTF-8 解码)对真实设备差异存在静默丢数据/乱码风险,建议合并前用真实抓包验证。

@monkeyscan

monkeyscan Bot commented Aug 17, 2026

Copy link
Copy Markdown

PR Title: feat: add Venus IPS log query service package

Commit: 6e64982

本 PR 新增 OctoBus service package services/venus__ips,用于查询启明星辰(Venustech) IPS 攻击日志:核心实现 venus-ips.js 以会话 Cookie 认证访问 GET /log/memorylog/ipslog.php,将设备 HTML 日志表解析为结构化条目,并附带 proto、config/secret schema、bin 入口、mock upstream 与测试,同时更新了根 package.json、octobus-tentacles.js 注册。

总体评估:实现质量较高——会话失效检测(ips_log_filter 标记)、错误映射、响应体大小上限(2 MiB 默认/8 MiB 上限)、redirect: manual 防跨站重定向、Cookie/上游详情脱敏、超时 AbortController 等安全与可靠性边界均处理得当,测试覆盖较全面(会话失效、错误映射、超时、大小上限、Cookie 校验等)。集成注册(根 package.json files/bin、octobus-tentacles)与既有服务模式一致,undici 依赖沿用根依赖 + bundled 的既有约定。

提交了 2 条低严重度数据完整性 findings:(1) decodeEntities 顺序 replace 链造成 HTML 实体双重解码,日志 name/content 等攻击者可控字段可能被改写;(2) parseIpsLog 仅校验 title 单元格数量下限并按固定下标映射,真实设备 HTML 与 mock 不一致时(# 列带 title / 空单元格缺 title 属性)字段会被静默错标,缺少列对齐校验与对应回归测试。

Comment thread services/venus__ips/src/venus-ips.js
Comment thread services/venus__ips/src/venus-ips.js
@monkeyscan

monkeyscan Bot commented Aug 17, 2026

Copy link
Copy Markdown

PR Title: feat: add Venus IPS log query service package

Commit: 3b7116c

本次改动针对 venus-ips 服务做了一组收尾修复,包含 4 个文件:

  1. services/venus__ips/src/venus-ips.js(核心改动):

    • 新增 cancelResponseBody 辅助函数,对 response.body.cancel() 做 best-effort 调用并吞掉所有异常,确保取消动作不会覆盖原本要抛出的映射错误(UNAVAILABLE/PERMISSION_DENIED/RESOURCE_EXHAUSTED)。
    • runQueryIpsLog!response.ok 分支、runProbeConnectivity!response.ok 分支,以及 readBoundedText 的 content-length 预检超限分支中,于抛错前取消上游响应体,避免未消费的响应流占用 undici keep-alive 连接。这正好修复了历史 finding #19891b52(错误路径未排空/取消响应体)。
    • cancelResponseBody 加入 _test 导出以便测试。
  2. proto/README:将 limit 契约从「<=0 表示全部」修正为「0 表示全部,负值返回 INVALID_ARGUMENT」,与实现(rawLimit < 0 抛 INVALID_ARGUMENT)保持一致,修复历史 finding #2fb26dae 的契约不一致。

  3. 测试:新增用例覆盖 HTTP 500(query)、HTTP 403(probe)、content-length 超限三种路径下 cancel 均被调用,且验证取消异常被吞掉。断言 cancellations === 3 准确对应三条路径;createHeaders mock 与 readBoundedTextheaders.get 调用匹配。

核查结论:

  • 错误路径现在都会在抛错前取消响应体,历史资源泄漏 finding 已修复且无回归;错误映射在取消失败时仍能保持(吞异常逻辑正确)。
  • limit 文档契约与实现现已一致。
  • 新增测试对三条取消路径及异常吞掉场景均有断言,覆盖充分。
  • 未发现由本次改动引入的高置信度新缺陷。流式读取超限分支仍使用 await reader.cancel?.()(未吞异常)属既有行为,且 reader.cancel() 实际极少 reject,风险很低,不构成可报告的回归。

Comment thread services/venus__ips/src/venus-ips.js Outdated
Comment thread services/venus__ips/src/venus-ips.js
@monkeyscan

monkeyscan Bot commented Aug 17, 2026

Copy link
Copy Markdown

PR Title: feat: add Venus IPS log query service package

Commit: 2434119

本次变更针对 Venus IPS 日志解析服务做了两处加固,均是对两条历史确认发现的修复:(1) decodeEntities 由链式 replace 重构为基于 HTML_ENTITIES 常量表的单次正则替换,修复了 &amp;lt; 等实体被双重解码的问题,新逻辑只解码一层,行为正确;(2) parseIpsLog 行过滤由“至少 13 个 title 单元格且任意位置含时间”收紧为“恰好 ENTRY_FIELDS.length(14)个且时间必须位于 titles[6]”,修复了设备 HTML 与 mock 不一致时字段被静默错标的问题。核对确认:ENTRY_FIELDS 共 14 个字段、index 6 为 time,mock 行结构(# 无 title + 14 个有 title 数据格 + 操作无 title)与新逻辑一致;decodeEntities 的正则分支与映射表键一一对应,不存在回调返回 undefined 的路径。新增测试覆盖了实体单层解码、超/缺单元格、时间列错位三类场景,质量良好。遗留两点建议:(a) 严格列校验在真实设备格式偏离(15 或 13 个 title,历史发现已点名)时会静默丢弃全部行,接口仍以 200 返回 total=0,研判方可能把解析失败误读为“无攻击”,建议对“有数据行但全部被跳过”显式报错或返回告警;(b) parseIpsLog 上方注释仍写“至少 13 个 title 单元格”,与实际规则不一致,需同步更新。

Comment thread services/venus__ips/src/venus-ips.js Outdated
Comment thread services/venus__ips/src/venus-ips.js Outdated
@monkeyscan

monkeyscan Bot commented Aug 17, 2026

Copy link
Copy Markdown

PR Title: feat: add Venus IPS log query service package

Commit: a7483fa

本次改动(services/venus__ips)继续收紧 Venus IPS 日志解析:parseIpsLog 由返回数组改为返回 { entries, skipped, structuralRows },并把"任一候选行(带 title 的 )列数不是恰好 14 或时间不在第 7 列"计为 skipped;runQueryIpsLog 在 skipped>0 时抛 FAILED_PRECONDITION,实现 fail-closed,避免此前确认的"解析失败被静默表现为空/无攻击"的数据完整性问题。新增 malformed 候选行 fail-closed 测试,并同步更新 helper 测试。

评估:方向正确,修复了历史发现 d33c4c89 的主要场景(有 title 但列数/时间列位置不对的偏离现在会显式失败)。但 fail-closed 覆盖仍不完整,共报告 3 个发现:(1) 若格式偏离导致所有行都提取不到 title(rowTitles 只匹配双引号 title="...",单引号/换属性/去 title 均匹配不到),skipped 恒为 0,接口仍以 200 返回空列表——历史发现 d33c4c89 的"静默零攻击"风险在该类偏离下依旧存在;(2) 设置 limit>0 时解析在收集满 limit 条后提前 break,后续 malformed 行不再计入 skipped,同一页面在 limit=0 时抛错、带 limit 时却静默成功,与新增注释宣称的保证相矛盾,新增测试未覆盖 limit 组合;(3) parseIpsLog 上方注释仍写"至少 13 个 title 单元格",与实际"恰好 14 列且时间在 index 6"及新返回结构不符(历史发现 6f218730 仍在)。设计取舍上,任意带 title 的非数据行(页脚/汇总/分页行)都会导致整个查询失败,可用性更脆,需结合真实设备页面确认。

Comment thread services/venus__ips/src/venus-ips.js
Comment thread services/venus__ips/src/venus-ips.js
Comment thread services/venus__ips/src/venus-ips.js
@monkeyscan

monkeyscan Bot commented Aug 18, 2026

Copy link
Copy Markdown

PR Title: feat: add Venus IPS log query service package

Commit: 5450659

本次变更新增 venus__ips 服务包,用于查询启明星辰 IPS 攻击日志:通过 web 会话 Cookie 调用 GET /log/memorylog/ipslog.php,将设备返回的 HTML 日志表解析为结构化条目。核心实现位于 src/venus-ips.js(绑定解析、HTTP 请求加固、响应体 2MiB 上限、HTML 表解析、错误映射),并配套 proto、config/secret schema、service/bin 注册、mock 上游与较为完整的测试。设计要点:fail closed(解析结构异常即报 FAILED_PRECONDITION,避免静默返回不完整数据)、错误信息脱敏、cookie 仅经 secret 传入、redirect manual、可选 skipTlsVerify。测试覆盖端到端解析、limit 截断、会话失效、错误映射、大小限制、TLS dispatcher 与 helper。总体实现稳健、测试充分;主要风险集中在 fail-closed 解析对整页任意“无 title 的 行”(空态/分页/其它表格)都会判定为结构损坏并让整个查询失败,以及 config schema 未禁止把会话 cookie 放进普通 config 的安全边界。

@@ -0,0 +1,16 @@
{

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

config schema 未禁止把会话 cookie 放入普通 config,绕过 secret 安全边界

config.schema.json 使用 additionalProperties: true 且未禁止 cookie 字段,而 resolveCallContext 会把 config 与 secret 合并进 bindings,resolveCookie 从合并后的 bindings 中读取 cookie/sessionCookie/session_cookie。因此运维人员若按 README 警告将 cookie 放在 config 中,服务仍会静默接受并以该 cookie 请求上游——config 与 secret 在 octobus 中通常有不同的存取/展示保护级别,会话 cookie 落入普通 config 会增加泄露面。README 明确要求“仅放 secret,勿写入 config”,但 schema 与代码都没有强制执行这一安全边界。

Problem code:

Changed code at services/venus__ips/config.schema.json:1-16

Recommendation:
在 config.schema.json 中显式禁止 cookie 相关字段(例如增加 "not": { "required": ["cookie", "sessionCookie", "session_cookie"] }),或让 resolveCookie 仅从 secret(ctx.secret)读取、不接受来自 config 的 cookie,从而强制 cookie 只能经 secret 注入。

Suggested diff:

   "headers": { "type": "object", "additionalProperties": { "type": "string" }, "description": "Optional non-sensitive HTTP headers. Authentication and hop-by-hop headers are ignored." },
-  }
+  },
+  "not": { "required": ["cookie", "sessionCookie", "session_cookie"] }
 }

const host = resolveHost(bindings);
if (!host) throw errorWithCode('INVALID_ARGUMENT', 'bindings.host is required');
const cookie = resolveCookie(bindings);
if (!cookie) throw errorWithCode('INVALID_ARGUMENT', 'bindings.cookie (web session cookie) is required');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fail-closed 解析会把整页任意“无 title 的 行”当作结构损坏,导致整个查询失败

parseIpsLog 对整个 HTML 页面扫描 :只要某行含 但没有任何带 title 的单元格(titles.length === 0 && /<td\b/i.test(...)),就计入 skipped;runQueryIpsLog 中一旦 parsed.skipped > 0 即抛 FAILED_PRECONDITION。该启发式无法区分“损坏的数据行”与设备页面上常见的合法非数据行,例如空态行(暂无数据)、分页/表尾行、或页面其它 UI 表格中的 行。只要页面任意位置出现一个这样的行,整个 QueryIpsLog 就会失败,而不是返回空列表或正常条目。现有“零数据行”测试只覆盖了纯 表头的空表(无 ),未覆盖更常见的 空态/分页场景;mock 上游也始终返回固定两行数据。考虑到 README 自述“合并前仍需维护者核验实际设备兼容性”,该全局 fail-closed 规则对真机页面(很可能含上述非数据 行)的鲁棒性风险较高。

Problem code:

Changed code at services/venus__ips/src/venus-ips.js:249-281

Recommendation:
将解析范围限定到具体的日志数据表(例如先定位含“名称/源IP/目的IP/时间”表头的

,再只对该表内的行做 fail-closed 校验),并且只对“含 title 但列数不等于 14 或时间列不在索引 6”的数据候选行失败关闭;对完全无 title 的
行(空态、分页、表尾、其它表格)应忽略而非计入 skipped。同时补充“合法空日志页含 空态行”和“页面含分页/表尾行”的回归测试。

Suggested diff:

  while ((m = rowRe.exec(html)) !== null) {
    const titles = rowTitles(m[1]);
-   // Header rows have no data cells. A row containing <td> but no title is a
-   // malformed candidate and must fail closed rather than silently disappearing.
-   if (titles.length === 0 && /<td\b/i.test(m[1])) {
-     structuralRows += 1;
-     skipped += 1;
-     continue;
-   }
    // Header rows have no titled data cells. Any titled row is a candidate log row and
    // must have exactly 14 columns with the timestamp at index 6; fail closed upstream
    // if a candidate is malformed so callers never receive a silently incomplete list.
    if (titles.length === 0) continue;
    structuralRows += 1;
    if (titles.length !== ENTRY_FIELDS.length || !DATETIME_RE.test(titles[6] ?? '')) {
      skipped += 1;
      continue;
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

l2:blocked Service L2 检查被 Draft、冲突或基础条件阻塞

Projects

None yet

Development

Successfully merging this pull request may close these issues.

启明-入侵检测系统IPS

4 participants