Files
iAOP/docs/采集网只读隔离与网闸配置.md
T

136 lines
5.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 采集网只读隔离与网闸配置
> 对应 EPIC #3「① 边缘采集网关」子任务 **#27**(0.5d,docs):
> 现场勘查拓扑与隔离策略(`docs/网络拓扑与隔离策略.md`,#19)的**网关侧落地**——
> 网闸/防火墙**具体配置**、**规则集**、**验证脚本**。
> 安全红线(PRD 5.1 / 9 章):边缘网关**严格只读、不反控、零控制指令下发**。
---
## 1. 目的与范围
- **目的**:把 #19 的三网隔离策略落为可执行配置(网闸规则 + 驱动只读约束 + 验证方法);
- **范围**:边缘网关(采集侧)与网闸/工业防火墙(边界)的配置;
- **配套**:拓扑与隔离策略总览见 `docs/网络拓扑与隔离策略.md`;
点位/采样率/协议规范见 `docs/DCS点表需求模板.md`(#16)。
---
## 2. 只读隔离设计(网关侧)
1. **驱动层只读**:所有采集驱动(`core/edge-gateway/drivers/`)仅暴露
`connect() / read_points() / close()`,**无任何写/控制方法**
(`base.py` 安全约束;新增驱动必须遵守,测试含「只读约束」用例)。
2. **协议只读会话**:
- OPC UA:只读会话 + 只读账号(如 `iaop_read`,仅授予 Read/Subscribe 权限);
- S7:仅建立只读连接(不绑定写数据块);
- Modbus:仅功能码 01/02/03/04(读),**禁止** 05/06/0F/10(写)。
3. **零反控通道**:网关进程不配置任何到 DCS/PLC 的写寄存器映射,
点位字典 `protocol` 维度不含写指令(`point_dict/validator.py` 校验)。
---
## 3. 单向网闸配置
**拓扑**(详见 #19 §2):`采集网 → 单向网闸 → 工业环网`,仅数据外发。
| 配置项 | 值 | 说明 |
| --- | --- | --- |
| 部署位置 | 采集网出口 / 工业环网入口 | 单向模块(发送) |
| 数据方向 | 采集网 → 工业环网(单向) | 反向物理阻断或规则拒绝 |
| 白名单源 | 边缘网关 IP(如 `10.20.1.100`) | 仅网关可出 |
| 白名单目的 | 数据总线(Kafka)IP/端口 | `10.20.0.10:9093`(mTLS) |
| 允许协议 | TCP(Kafka 9093 / 健康上报 443) | 白名单外全拒绝 |
| 反向规则 | 工业环网 → 采集网:**DROP** | 杜绝远程控制通道 |
> 网闸具体型号规则录入厂商控制台(天融信/网御星云/奇安信等按型号提供 CLI 模板);
> 本表为通用配置语义,实施时按现场设备映射。
---
## 4. 防火墙规则集示例(iptables 风格)
```bash
# ---- 采集网侧(边缘网关主机)----
# 默认拒绝
iptables -P INPUT DROP; iptables -P FORWARD DROP; iptables -P OUTPUT DROP
# 回环与本机管理
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
iptables -A INPUT -s 10.20.1.0/24 -p tcp --dport 22 -j ACCEPT # 运维 SSH(堡垒机)
# 只读采集出站:DCS OPC UA(4840)与 S7(102)
iptables -A OUTPUT -d 10.20.1.10 -p tcp --dport 4840 -j ACCEPT # 和利时 OPC UA
iptables -A OUTPUT -d 10.20.1.20 -p tcp --dport 102 -j ACCEPT # S7-1200 只读
# 数据上行:Kafka(mTLS 9093)与健康上报
iptables -A OUTPUT -d 10.20.0.10 -p tcp --dport 9093 -j ACCEPT
iptables -A OUTPUT -d 10.20.0.20 -p tcp --dport 443 -j ACCEPT
# 入站写控制:全部拒绝(无任何入站控制通道)
# (INPUT 默认 DROP 已覆盖;如需例外必须评审并记录)
```
> 关键点:**出站只放行读采集与数据上行;入站除运维外全拒绝**,
> 从网络层再次封死"反控"路径。
---
## 5. 验证方法
**负向用例(必须零通过)——验证"写不进去"**:
| # | 验证项 | 方法 | 期望 |
| --- | --- | --- | --- |
| V1 | Modbus 写寄存器 | 尝试功能码 05/06/0F/10 写保持寄存器 | 连接被拒/超时/无响应(**零通过**) |
| V2 | OPC UA 写节点 | 尝试 `write_value()` 写测点节点 | 权限拒绝(只读账号) |
| V3 | S7 写数据块 | 尝试写 DB | 连接不支持/异常 |
| V4 | 反向连通性 | 工业环网 → 采集网扫描网关端口 | 全部拒绝 |
| V5 | 控制指令下发 | 全链路模拟下发指令 | 网关无对应实现,零指令出站 |
**正向用例**:
- 采集链路健康:600 点位 1Hz,丢失率 ≤ 0.02%、P99 ≤ 1.8s(`collector/metrics.py`);
- mTLS 双向证书验证通过(Kafka 9093,`upstream/kafka_sink.py`)。
**自检命令**(网关侧):
```bash
python -m unittest discover -s tests -p "test_*.py" # 驱动只读约束用例
python scripts/check_readonly.py --points point_dict.csv # 点位字典写指令扫描(见 §6)
```
---
## 6. 只读自检脚本(check_readonly)
随本任务提供轻量自检:扫描点位字典与驱动实现,确认**零写指令**:
| 检查项 | 实现 |
| --- | --- |
| 点位字典 | 校验 `protocol`/`opcNode` 不含写指令语义(无 `write`/`set`/`control` 关键字) |
| 驱动代码 | 扫描 `drivers/` 源码不含写方法名(`write`/`set_value`/`control`) |
| 配置 | `gateway.yaml` 不含反向/控制通道配置 |
> 落地形式:`docs/_check_isolation_doc.py` 附带代码级自检函数
> (也可作为 CI 检查脚本复用)。
---
## 7. 部署检查清单
- [ ] 网闸规则已录入:单向数据外发、白名单 IP/端口、反向 DROP;
- [ ] 边缘网关 iptables 规则集生效(§4 示例);
- [ ] 驱动只读:无写方法;OPC UA 只读账号、S7 只读连接、Modbus 仅读功能码;
- [ ] 负向用例 V1–V5 全部**零通过**(写不进、连不通);
- [ ] 正向用例:丢失率 ≤ 0.02%、P99 ≤ 1.8s、mTLS 验证通过;
- [ ] 自检脚本(§6)零告警;审计日志记录规则变更。
---
## 8. 关联
- `docs/网络拓扑与隔离策略.md`(#19):本配置的上层策略;
- `core/edge-gateway/`:驱动只读实现(base.py / drivers / validator);
- `docs/DCS点表需求模板.md`(#16):点位/协议字段规范;
- PRD 5.1(只读采集)、9 章安全-网络(零控制指令)、12 章等保三级。