# NetTeach **Repository Path**: xyx199395/net-teach ## Basic Information - **Project Name**: NetTeach - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-10-12 - **Last Updated**: 2026-10-12 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # NetTeach 网络教学系统 本地部署的网络教学系统,专为 **华为 HCIA → HCIP → HCIE** 认证知识教学打造:**理论课件 + 真机命令实验(对接 eNSP / GNS3 模拟器)+ 实验自动判分 + 随堂测验 + 进度跟踪 + 投屏演示模式**。 纯 Python 标准库实现,**无需安装任何第三方依赖**,一条命令即可启动。学员用浏览器打开即可学习,教师可查看班级汇总。 --- ## 1. 快速开始 要求:已安装 **Python 3.8+**,Windows / macOS / Linux 均可。 ```bash cd NetTeach python server.py ``` 启动后: - 本机访问:http://127.0.0.1:8000 - 局域网访问:http://<本机IP>:8000(学员在同一 Wi-Fi/局域网,浏览器打开即可) > 没有 EVE-NG / eNSP?加 `--mock` 参数即可用**内置 VRP 模拟设备**完成全部 13 个实验(见 §3.5): > > ```bash > python server.py --mock > ``` 默认监听 `0.0.0.0`(局域网可访问)。参数可选: ```bash python server.py --host 127.0.0.1 # 仅本机可访问 python server.py --port 9000 # 自定义端口 ``` > 断网可用:所有前端库(marked.js、xterm.js)已内嵌在 `web/vendor/`,课件与题库都在本地,无任何外部请求。 --- ## 2. 功能总览 | 功能 | 说明 | | --- | --- | | 三级课程体系 | 首页课程地图 → HCIA / HCIP / HCIE → 章节树 → 章节详情 | | 理论课件 | Markdown 渲染(表格、代码块、图示),改 `theory.md` 即更新 | | 知识点动画 | 17 个数据驱动 SVG 动画:报文飞行、逐步字幕、状态标注,可重播/单步,课件里写 ```` ```anim 名称 ```` 即嵌入 | | 实验闯关 + 自动判分 | 每章 1~2 个实验,含拓扑图 + 每台设备网页终端 + 目标清单;点击「检查」向设备发送命令,按**真实输出**正则匹配自动判定通过/未通过;内置实验已适配 EVE-NG 中的华为 **CE6800**(VRP8)真机,也可用内置 VRP 模拟设备(--mock)离线完成 | | 随堂测验 | 每章题库,单选 / 多选 / 判断,提交即评分并显示解析,记录最好成绩 | | 学生进度跟踪 | 学员输入学习代号(无需密码)即自动记录已读章节、实验完成度、测验成绩;教师端查看班级汇总 | | 课前演示大屏模式 | 全屏大字课件,键盘翻页,可一键直达实验现场演示 | | 设备连接向导 | Web 页面内添加 / 测试 / 删除模拟器设备(telnet host:port) | --- ## 3. 对接 eNSP / GNS3 模拟器 系统通过 **telnet 控制台中继** 连接模拟器设备:浏览器终端 → 本机 Python 服务 → 设备 console。判分时也走同一通道读取设备真实输出。 ### 3.1 eNSP 中开启设备的 Telnet 在 eNSP 中双击设备(AR / 交换机)进入 CLI,执行: ```text system-view [Huawei] telnet server enable [Huawei] aaa [Huawei-aaa] local-user admin password cipher Admin@123 [Huawei-aaa] local-user admin privilege level 15 [Huawei-aaa] local-user admin service-type telnet [Huawei-aaa] quit [Huawei] user-interface vty 0 4 [Huawei-ui-vty0-4] authentication-mode aaa [Huawei-ui-vty0-4] protocol inbound telnet [Huawei-ui-vty0-4] quit [Huawei] quit ``` ### 3.2 找到每台设备的 console 端口 eNSP 为拓扑中每台设备分配一个 **本地 telnet 端口**,从 **2000 开始**依次递增(第 1 台 2000、第 2 台 2001…)。查看方法: - 设备窗口标题栏 / 设备属性里通常直接显示端口号; - 或命令行确认(Windows): ```bat netstat -ano | findstr LISTEN | findstr 2000 ``` 例如输出 `127.0.0.1:2000` 即为第 1 台设备的 console 端口。 ### 3.3 在系统里登记设备 1. 打开顶部导航 **「实验设备」**; 2. 填写 **设备名(必须与实验 labs.json 中 objectives.device 一致,如 AR1)**、地址 `127.0.0.1`、端口(如 2000)、类型; 3. 点「测试连接」确认,再「保存设备」。 > GNS3 节点将 console 设置为 telnet 类型(如 `telnet://127.0.0.1:5000`)时同样适用。eNSP 里建议先启动设备再测试连接。 > > **EVE-NG** 同样适用(已实测):节点 console 类型选 telnet 时,端口 = **32768 + 节点 ID**(节点 1 → 32769),登记地址填 EVE-NG 服务器 IP。注意:网页终端与判分对任何 telnet console 都有效,但内置实验的判分 patterns 按**华为 VRP** 输出编写;若使用 H3C Comware 镜像(提示符同为 `<名称>`/`[名称]`,命令捕获兼容),个别配置命令与输出格式不同(如 `port access vlan` vs `port default vlan`),需按实际输出微调 patterns。 ### 3.4 当前默认实验环境:EVE-NG + 华为 CE6800(VRP8) 全部 13 个内置实验已适配 EVE-NG 中的**单台华为 CE6800**(V200R005C10,VRP 8.180): - **登记信息**:设备名 `CE6800`,地址 `192.168.100.247`(EVE 服务器),端口 `32770`(= 32768 + 节点 ID); - **管理上联**:GE1/0/0 已 `undo portswitch` 转三层口并配置 `192.168.100.200/24`(已 commit),经 EVE 的 Net 云桥接进**真实局域网**——ping 类判分是真实流量(网关 192.168.100.1、外网 223.5.5.5)。**GE1/0/0 为保留口,实验请勿改动**; - **两阶段提交**:CE 系列配置先进候选区,回到**系统视图**执行 `commit` 才生效(提示符 `[~]`=未提交、`[*]`=已提交未保存);接口/OSPF/ACL 等子视图内不能 commit,所有实验 hint 已按「quit 回系统视图 → commit」编写。三条实测规则:`display current-configuration` 只显示**已提交**配置(未 commit 判分不通过,正好强制养成提交习惯);**未提交的候选在会话断开后被丢弃**(配完尽快 commit);**默认配置不出现在 display 中**(如 access 口的 `port link-type access`、VTY 默认 AAA),判分 patterns 已相应适配; - **能力边界**:VLAN/STP/ACL/DHCP/OSPF/Telnet/SSH 均支持;**NAT、MPLS、WLAN 不支持**——对应章节(8、10、HCIE-1)的实验设计为「实机验证不支持 + 原理推演判分」,顺便讲清设备选型与网络分层; - **分页处理**:判分通道对 `---- More ----` 自动翻页(中继已内置),长输出命令(display current-configuration 等)无需人工干预。 扩展第二台设备(建立真实 OSPF 邻居、ACL 拦截对比):在 EVE 中用同一模板克隆节点(console 端口顺延,如 32771),到「实验设备」页登记后即可按各实验目标中的"扩展推演"提示升级实验。 ### 3.5 内置 VRP 模拟设备(--mock):无需 EVE-NG / eNSP 没有模拟器环境也能把 13 个实验**完整做完并自动判分**——`--mock` 会随服务启动一个内置的华为 CE6800(VRP8)命令行模拟器并自动登记为设备 `CE6800`: ```bash python server.py --mock # 模拟设备监听 127.0.0.1:26180 python server.py --mock 26200 # 自定义端口 ``` - **能力**:视图切换(system-view/interface/acl/ospf/aaa/user-interface/ip pool 等)、两阶段提交(`[~]`/`[*]` 提示符、commit/discard、子视图不能 commit)、`display` 系列输出(按 13 个 labs.json 的判分正则反向校准)、ping 连通性模型(直连/VLANIF/环回/静态路由/缺省路由/NULL0 黑洞/ACL 拦截/不可达)、NAT/WLAN/MPLS 命令按真机行为返回 Unrecognized(推演型实验照常教学); - **交互**:字符回显、退格、`↑/↓` 历史、Tab 命令补全、`?` 帮助、`| include` 过滤、`save` 的 [Y/N] 确认; - **持久化**:commit 即写入 `data/mock_ce6800.json`,重启服务学员配置不丢;删除该文件即恢复出厂; - **保护**:GE1/0/0 为保留管理口,拒绝改动(与真机使用约定一致);STP 出厂默认关闭(便于第 2 章实验,真机默认开启); - **边界**:单机仿真、无真实转发平面,输出为教学近似;未 commit 的候选配置在会话断开后丢弃(F-6 实测规则); - 若已登记同名真机 `CE6800`,启动时**不会覆盖**,会打印提示——想用模拟器请先把真机登记改名(如 CE6800-EVE); - 也可独立部署:`python tools/vrp_simulator.py --port 26180`(模拟设备跑在另一台机器,学员机登记该 IP); - 全部 122 个自动判分目标(HCIA 56 + HCIP/HCIE 新增 66)已在模拟器上完成「反例→正例」翻转验证(`tools/test_vrp_sim.py`)。 --- ## 4. 目录结构 ``` NetTeach/ ├─ server.py # 启动入口(静态 + API + SSE + telnet 中继) ├─ core/ │ ├─ content.py # 课程 / 章节 / 拓扑加载 │ ├─ progress.py # 学员进度持久化(JSON)+ 教师鉴权 │ ├─ quiz.py # 题库加载与判分 │ └─ labs.py # 实验定义与自动判分逻辑 ├─ relay/ │ ├─ telnet_relay.py # telnet 中继(SSE 下行 / POST 上行 / 命令捕获) │ ├─ vrp_sim.py # 内置 VRP(CE6800)模拟设备(--mock,纯标准库) │ └─ devices.py # 设备注册表 ├─ web/ │ ├─ index.html # 应用外壳 │ ├─ css/app.css │ ├─ js/ # 首页 / 章节 / 实验 / 测验 / 大屏 / 设备 / 班级 等视图 │ └─ vendor/ # marked.js、xterm.js(离线内嵌) ├─ content/ │ ├─ _animations/ # 知识点动画定义(17 个 JSON,数据驱动 SVG) │ ├─ HCIA/ # 11 章全部完整(理论 + 动画 + 实验 + 题库) │ ├─ HCIP/ # 10 章全部完整(理论 + 题库 + 实验 + 拓扑) │ └─ HCIE/ # 7 章全部完整(理论 + 题库 + 实验 + 拓扑) ├─ data/ # 运行时数据(学员进度、设备表、教师口令) │ ├─ progress.json │ ├─ devices.json │ ├─ teacher.txt │ ├─ server.log # 运行日志(异步写入,超 5MB 自动轮转) │ └─ mock_ce6800.json # 内置模拟设备的已提交配置(--mock 使用) └─ tools/ ├─ gen_topology.py # 由 .topo 生成拓扑 SVG ├─ vrp_simulator.py # 独立启动内置 VRP 模拟设备(也可 server.py --mock) ├─ test_vrp_sim.py # 模拟设备端到端验证(122 个判分目标反例→正例) ├─ validate_content.py # 内容一致性自检(章节完整性/题库/正则/拓扑引用) └─ mock_vrp_device.py # 旧版最小 mock(测试用,telnet 26000) ``` --- ## 5. 内容结构:如何新增 / 修改章节 内容全部是**纯文件**,不需要改代码。每个章节一个目录: ``` content/HCIA/07-acl/ ├─ chapter.json # 章节元信息 ├─ theory.md # 课件(Markdown) ├─ quiz.json # 题库 ├─ labs.json # 实验定义 ├─ 07-topo.svg # 拓扑图(程序生成) └─ acl-basic-filter.topo # 拓扑源文件 ``` ### 5.1 chapter.json ```json { "id": "07-acl", "title": "访问控制列表 ACL", "order": 7, "summary": "ACL 的作用与分类、基本 ACL / 高级 ACL、通配符口罩、traffic-filter 应用与验证。" } ``` > `id` 即目录名。首页章节排序按 `order`。 ### 5.2 theory.md 标准 Markdown。**用 `---`**(三个以上连字符单独成行)**或 `##` 二级标题分页**,大屏演示会按页翻动。正文内可直接写表格、代码块、引用。 ### 5.3 quiz.json — 题库 ```json { "questions": [ { "id": "q1", "type": "single", // single 单选 | multi 多选 | judge 判断 "stem": "基本 ACL(2000~2999)主要匹配报文的什么字段?", "options": ["目的 IP", "源 IP", "源端口", "目的端口"], "answer": [1], // 正确选项下标(从 0 开始) "explain": "基本 ACL 只能匹配源 IP 地址…" } ] } ``` 判断题用两个选项 `["正确", "错误"]`,answer 填 `[0]` 或 `[1]`。 ### 5.4 labs.json — 实验与自动判分 ```json { "labs": [ { "id": "acl-basic-filter", "title": "实验 7-1:基本 ACL 精确拦截指定源地址", "desc": "…实验背景说明…", "topology": "07-topo.svg", // 与拓扑文件同名 "devices": [ // 实验页显示哪些设备终端 { "name": "AR1", "note": "R1(配置 ACL)" }, { "name": "AR2", "note": "R2" } ], "objectives": [ { "id": "o1", "title": "R1/R2 配好接口地址与静态路由,环回可互访", "device": "AR1", // 必须与「实验设备」里登记的设备名一致 "check": "config", // config | ping | manual "patterns": ["ip address 10\\.0\\.12\\.1", "ip route-static 2\\.2\\.2\\.2"], "mode": "any", // any 任一命中即通过 | all 全部命中 "hint": "提示学生怎么做…" }, { "id": "o4", "title": "验证拦截:从 R1 带源 1.1.1.1 ping 2.2.2.2 失败", "device": "AR1", "check": "ping", "command": "ping -a 1.1.1.1 2.2.2.2", // ping 类型可自定义命令 "patterns": ["Success rate is 0 percent", "100\\.0% packet loss"] }, { "id": "o5", "title": "人工确认项示例", "device": "AR2", "check": "manual" // 前端「我已配置完成」按钮,人工确认 } ] } ] } ``` **三种判分方式:** - `config`:向设备发送 `display current-configuration`(也可用 `command` 覆盖为其他 display 命令),把输出按 patterns 匹配; - `ping`:发送 `ping` 命令并读取结果(如「Success rate is 0 percent」表示被拦截,可用于验证 ACL); - `manual`:不自动判分,学员点「我已配置完成」由教师核对。 `patterns` 是**正则表达式**,`.` 需转义 `\\.`(JSON 中写 `\\.`)。判分只匹配**设备真实输出文本**,与模拟器版本无关。 ### 5.5 拓扑图 - `.topo` 是文本拓扑源文件(节点 / 连线),运行 `tools/gen_topology.py` 可重新生成 `<章号>-topo.svg`; - 直接手写/替换同名 `.svg` 也可以,实验页会自动加载。 ### 5.6 知识点动画(图形化教学) 理论课件与大屏演示中,任何位置写一行围栏代码块即可嵌入动画(动画名 = `content/_animations/` 下的 JSON 文件名): ````text ```anim tcp-handshake ``` ```` 动画是**数据驱动的 SVG**:节点拓扑(pc/server/router/switch/host 五种设备图形)+ 连线 + 报文飞行(支持单播/广播泛洪)+ 逐步字幕 + 节点状态标注/高亮/链路染色,自带「重播 / 上一步 / 暂停 / 下一步」控制,自动循环播放。新建动画复制任一现有 JSON 改 `nodes / links / steps` 即可,无需动代码;格式要点: ```jsonc { "title": "动画标题", "size": { "w": 820, "h": 320 }, // 画布,文字勿超出边界 "nodes": [{ "id": "r1", "label": "R1", "sub": "备注", "kind": "router", "x": 85, "y": 150 }], "links": [{ "from": "r1", "to": "r2", "label": "链路说明" }], "steps": [{ "caption": "① 本步字幕讲解…", "packets": [{ "from": "r1", "to": "r2", "label": "报文名", "color": "#f59e0b", "delay": 0.6 }], "labels": { "r1": { "text": "状态标注", "color": "#2fbf71" } }, // 节点上方状态字 "highlight": ["r2"], // 节点呼吸高亮 "linkTint": [{ "from": "r1", "to": "r2", "color": "#e5484d" }], // 链路染色 "clearLabels": ["r1"] // 清除旧标注 // 广播:packets 里用 "toAll": true, "except": ["入接口节点"] }] } ``` **现有 17 个动画一览:** | 章节 | 动画 | 知识点 | | --- | --- | --- | | HCIA-01 | `tcp-handshake` / `packet-encapsulation` | TCP 三次握手;数据逐层封装与解封装 | | HCIA-02 | `mac-learning` / `stp-blocking` | MAC 学习与转发;广播风暴与 STP 阻塞 | | HCIA-03 | `vlan-tagging` | VLAN 标签的添加、传递与剥离 | | HCIA-04 | `cross-subnet` | 跨网段通信为什么必须经过网关 | | HCIA-05 | `static-route` | 静态路由逐跳转发 | | HCIA-06 | `ospf-neighbor` | OSPF 邻居与邻接建立 | | HCIA-07 | `acl-filter` | ACL 报文过滤:放行与丢弃 | | HCIA-08 | `nat-translation` | NAT 出向转换与回向还原 | | HCIA-09 | `arp-resolution` / `dhcp-dora` / `dns-resolution` | ARP 广播请求单播应答;DHCP 四步;DNS 递归+迭代 | | HCIA-10 | `wlan-join` | 无线接入:扫描→认证→关联→CAPWAP | | HCIA-11 | `telnet-vs-ssh` | 明文与加密的差别(窃听者视角) | | HCIP-01 | `ospf-lsa-flood` | 多区域 LSA 洪泛边界与 ABR Type3 翻译 | | HCIE-01 | `mpls-label-forwarding` | LDP 标签分发与 PUSH/SWAP/POP | > ⚠️ 动画 JSON 修改后需**整页刷新**浏览器才能看到更新(前端有内存缓存,hash 路由切章不重载页面)。 --- ## 6. 教师账号 - 班级进度页默认账号 `teacher`,**密码为空**; - 修改:在 `data/teacher.txt` 里写一行 `账号:密码`,如 `teacher:mypass123`,重启后生效。 --- ## 7. 大屏演示模式(课前投屏) - 首页「教学工具 → 大屏演示」或任一章节页「🖥 大屏演示」进入; - **翻页**:`→`/`空格`/`Enter`/`PageDown` 下一页,`←`/`PageUp`/`Backspace` 上一页,`Esc` 退出; - 章节有实验时,顶部「🧪 打开实验」可直接切到该实验的终端页现场演示命令。 --- ## 8. 两种教学场景建议 **场景一:教师演示 + 学员观摩(推荐离线课堂)** 教师机运行 `python server.py`,接大屏进演示模式;理论讲完打开实验,现场在网页终端里配置 eNSP 设备,点「检查」现场判分,边做边讲。 **场景二:学员人手一台练习(机房 / 同 Wi-Fi)** 教师在教师机启动服务(默认 `0.0.0.0`),学员浏览器打开 `http://<教师机IP>:8000`。学员输入自己的学习代号(如姓名),完成章节 → 实验 → 测验,进度自动回传;教师随时打开「班级进度」查看每位学员的已学章节、实验完成数与测验最高分。 > 实验依赖学员本机(或教师机)运行的 eNSP 设备。若学员各自练习,请在每台学员机上跑自己的 eNSP 拓扑,并把设备 telnet 端口登记到本机 NetTeach(在学员机上启动服务,或教师机 `--port` 分流)。 --- ## 9. 常见问题 - **「无法连接设备,请确认设备已启动」**:eNSP 中设备还没启动,或端口号不对(`netstat -ano | findstr 2000` 核对),或设备未开 telnet 服务(见 3.1)。没有模拟器环境时直接 `python server.py --mock` 用内置模拟设备(见 3.5)。 - **想清空内置模拟设备的配置**:停止服务后删除 `data/mock_ce6800.json`,重启 `--mock` 即恢复出厂。 - **「设备未添加」**:目标里写的设备名与「实验设备」页登记的名字不一致,改为一致即可。 - **判分总是不通过**:先点目标旁的「检查」,展开「查看采集到的设备输出」看设备真实返回,对照 `patterns` 调整(注意正则转义)。 - **学员进度没了**:`data/progress.json` 存放全部进度,手动删除即清空;学员换电脑时输入相同代号即可继续累计(数据在服务端)。 - **排查服务问题**:运行日志在 `data/server.log`(控制台只显示启动横幅)。日志采用后台线程异步写入,Windows 控制台被选中文字(QuickEdit)或冻结时**不会**再拖死服务;若页面异常,先看日志里最近的请求与报错。 --- ## 10. 内容覆盖一览 | 层级 | 章节 | 状态 | | --- | --- | --- | | HCIA | 网络基础、二层交换、VLAN、IP 编址、静态路由、OSPF、ACL、NAT、网络服务、WLAN、网络管理与安全 | ✅ 11 章全部完整(理论 + 动画 + 实验 + 题库) | | HCIP | OSPF 多区域、OSPF 特殊区域、路由过滤/策略、BGP 基础、BGP 选路、IS-IS、VRRP、Eth-Trunk、园区网络、故障排除 | ✅ 10 章全部完整(每章理论 + 题库 + 实验 + 拓扑) | | HCIE | MPLS 基础、MPLS L3VPN、大型网络设计、QoS、SDN/自动化、SRv6、优化与排障 | ✅ 7 章全部完整(每章理论 + 题库 + 实验 + 拓扑) | HCIP/HCIE 各章均含:理论课件(含选型决策/对比表/配置示例)、10 题随堂测验(单选/多选/判断,逐项解析)、1 个内置实验(config/ping 自动判分 + 推演目标,全部适配 CE6800 与内置 VRP 模拟器)。内容一致性可用 `python tools/validate_content.py` 自检;全部 122 个自动判分目标已在内置模拟器上完成「反例→正例」翻转验证(`tools/test_vrp_sim.py`)。