
简介这份《网络信息安全》课程设计报告面向高校信息安全、计算机相关专业学生及需要完成同类课设的学习者以古典密码体制中的无密钥置换加密为课题记录从选题分工、需求分析、概要设计到源代码实现与调试的完整流程可作为课程设计写作与算法实现的参考范本。资源为单个 doc 文档压缩包约1.28MB篇幅15页左右含目录、正文与附录结构规整、便于对照模仿。报告明确了小组成员职责划分给出明文序列需达1000位的设计要求并附概要设计流程图与基于 Visual C 的 C 源代码涉及 SubKey、DES 两个类的密钥置换、IP 转换、S 变换与 P 置换等关键环节。读者可据此理解古典加密算法的设计思路与实现要点参考调试分析与程序输入、执行验证的写法积累课程设计排版与文档组织经验同时加深对网络信息安全中加解密技术价值的认识。目前已有396人学习下载。1. 《网络信息安全》课程设计报告.doc 到底该写什么先定题再定文档骨架多数人拿到《网络信息安全》课程设计报告.doc 这个题目第一反应是打开 Word 找模板然后被「绪论—相关技术—设计与实现—测试—总结」的骨架牵着走最后交上去的文档里技术含量最高的部分反而是从教材抄来的加密算法定义。真正决定分数的不是排版而是这份文档背后有没有一个能跑起来、能被追问、能复现的最小系统。合理的定位是选一个自己搭得起来的小场景说清它面临哪些具体威胁给出防护措施用可执行的命令或代码证明措施生效。适合刚学完密码学与网络协议、手上没有真实业务系统的学生也适合需要快速产出一份内部安全小项目文档的初级运维与后端开发。后面按「定题—搭环境—做实验—写分析—交材料」推演重点放在每一段能落到命令行和参数上的部分。2. 网络信息安全课程设计的实验环境Python 依赖、拓扑表与参数落盘课程设计最尴尬的场景是报告里写得头头是道答辩老师让你现场跑一遍结果import scapy直接报错。安全类实验依赖系统权限、网卡驱动和密码学库比一般的增删改查项目更容易在换机器时崩掉。把环境当成报告的一部分来写是省时间的做法依赖版本、网卡名称、监听端口、密钥长度这些全部落进文档和脚本评阅人照着做就能得到同一组数据。2.1 用 venv 与 requirements.txt 固定版本避免换机器就跑不起来不要用系统全局 Python 装 scapy 和 cryptography两者都涉及二进制扩展全局环境污染后很难回退。虚拟环境加锁定文件是最小成本方案。# 在项目根目录创建隔离环境.venv 目录跟随项目走 python -m venv .venv # Linux / macOS 激活 source .venv/bin/activate # Windows PowerShell 激活PowerShell 需先执行 Set-ExecutionPolicy -Scope Process RemoteSigned # .venv\Scripts\Activate.ps1 # 按锁定文件安装保证同学和评阅人拿到的是同一批版本 pip install -r requirements.txt # 记录当前实际生效的版本覆盖式写回方便复现 pip freeze requirements.lock.txtpython -m venv比virtualenv少一层依赖.venv放在项目根目录并在提交时排除评审时只提交requirements.txt与requirements.lock.txt。pip freeze输出的是精确版本号形如scapy2.5.0而requirements.txt里通常写宽松约束两者分工不同前者用于复现后者用于说明意图。如果学校机房禁止联网提前用pip download -r requirements.txt -d wheels/把 wheel 包下载下来现场pip install --no-index --find-linkswheels/ -r requirements.txt离线安装这一步写进报告能直接体现工程意识。2.2 抓包与密码学依赖的最小安装清单安全课程设计不需要堆库三个方向各一个就够抓包分析用 scapy口令与摘要用标准库hashlib/hmac配合 cryptography 做对称加密画图用 matplotlib 出实验曲线。# requirements.txt scapy2.5.0 # 抓包与手工构造报文需底层抓包驱动 cryptography42.0.5 # AES-GCM、RSA 等算法实现 matplotlib3.8.3 # 实验数据绘图报告插图直接用它出选 scapy 而不是直接调 libpcap是因为它把报文封装成可读对象报告里贴的代码自解释性强选 cryptography 而不是自己实现 AES是因为课程设计考察的是「会不会用正确参数」不是「会不会写轮函数」自己实现的 S 盒反而容易被追问侧信道问题。安装后先用python -c from scapy.all import conf; print(conf.ifaces)打印可用网卡把输出截图放进报告的环境章节说明你确实确认过抓包接口。2.3 实验拓扑与 IP 规划表把截图变成可核对的数据课程设计常见的大坑是拓扑只放一张截图读者无法判断哪台机器装了什么。用表格把角色、地址、端口、依赖写清楚报告立刻从「作业」变成「方案」。节点角色地址监听端口关键配置host-a客户端192.168.56.10随机高位端口发起 TCP 连接触发握手host-b服务端192.168.56.118443/tcp只开必要端口防火墙默认拒绝host-b抓包点同上无scapy 监听 eth1过滤条件tcp port 8443host-a分析机同上无跑哈希与加密实验不参与网络流量表格里必须写清地址是虚拟网段还是物理网段。用虚拟机做实验时建议选仅主机模式网段避免把实验流量打到公共网络端口一列写「8443/tcp」这种带协议的格式方便后续写防火墙规则时直接对照。实验开始前用ss -lntp核对实际监听状态实际结果与表格不一致时改的是表格不是脑补。2.4 三个高频环境故障的定位顺序抓不到包、装不上库、脚本换机报错这三类问题占掉课程设计一半的调试时间按固定顺序排查比反复重装快得多。第一是权限。Linux 下普通用户无原始套接字权限表现为PermissionError: [Errno 1] Operation not permitted用sudo setcap cap_net_raw,cap_net_admineip $(readlink -f $(which python))给解释器授最小能力比全程 sudo 更安全。Windows 下需要安装抓包驱动安装后重启否则conf.ifaces只列回环。第二是过滤器写错导致空结果。filtertcp port 8443与filterport 8443在存在 UDP 流量时结果不同先用tcpdump -i eth1 -nn port 8443 -c 5交叉验证确认有流量再上 scapy。第三是编码与依赖冲突。报告中文本在 Windows 下默认 GBK读写 JSON 结果时统一加encodingutf-8依赖冲突表现为ImportError: cannot import name ...用pip list --outdated看是否存在旧版本残留必要时删掉.venv从requirements.txt重装别在旧环境里逐个降级。3. 网络信息安全课程设计的三个核心实验握手解析、口令加盐哈希、端口暴露面排查三个实验分别对应网络层、应用层和主机层覆盖面够写满一份课程设计工作量又可控。关键不是把代码跑通而是每一段输出都能回答问题握手过程的哪个字段暴露了信息、口令为什么不能直接存摘要、主机上为什么会有不该开的端口。每个实验都要求保留原始输出文件报告里的表格和插图必须由这些文件生成不能手敲。3.1 用 Scapy 抓一次 TCP 三次握手并解析字段先把服务端跑起来任意一个监听 8443 的最小服务即可再在抓包点执行下面的脚本。一次完整握手加一次挥手足够讲清序列号与标志位。from scapy.all import sniff, TCP, IP def show(pkt): # 只处理带 TCP 层且端口匹配的包避免噪声 if TCP in pkt and (pkt[TCP].sport 8443 or pkt[TCP].dport 8443): flags pkt[TCP].flags # flags 是 FlagValue 对象转成字符串便于写进报告 print(f{pkt[IP].src}:{pkt[TCP].sport} - f{pkt[IP].dst}:{pkt[TCP].dport} fflags{flags} seq{pkt[TCP].seq} ack{pkt[TCP].ack} fwin{pkt[TCP].window}) # iface 按 2.3 表格里的抓包接口填写count8 抓够一个完整会话即退出 sniff(ifaceeth1, filtertcp port 8443, prnshow, count8, storeFalse)iface必须与拓扑表一致写错会静默抓到零个包filter用 BPF 语法交给内核过滤比在prn里写 if 判断效率高得多count设为 8 是为了脚本能自己结束否则会一直挂住。storeFalse防止报文堆积占内存长时间抓包时尤其重要。输出里重点看三行SYN 的seq是客户端初始序列号SYN-ACK 的ack等于它加一第三次 ACK 再确认服务端的初始序列号。报告里把这三行整理成表并补一句「初始序列号可预测会带来会话劫持风险」把协议细节和威胁建模连起来这一节的分就拿到了。3.2 口令存储PBKDF2-HMAC-SHA256 的盐值与迭代次数怎么定课程设计里最常见的错误写法是hashlib.md5(password.encode()).hexdigest()老师一问彩虹表就答不上来。正确做法是加随机盐、用慢哈希、把参数一起存下来。import os, hashlib, hmac, base64 ITERATIONS 600_000 # 迭代次数按硬件可承受的登录延迟调整 SALT_BYTES 16 # 盐长度与哈希输出长度无关16 字节足够 DKLEN 32 # 派生密钥长度32 字节对应 SHA-256 输出 def hash_password(password: str) - str: salt os.urandom(SALT_BYTES) # 每个用户独立随机盐 dk hashlib.pbkdf2_hmac(sha256, password.encode(utf-8), salt, ITERATIONS, dklenDKLEN) # 存储格式算法$迭代次数$盐$派生密钥参数随密文一起保存 return pbkdf2_sha256${}${}${}.format( ITERATIONS, base64.b64encode(salt).decode(), base64.b64encode(dk).decode()) def verify_password(password: str, stored: str) - bool: algo, iters, salt_b64, dk_b64 stored.split($) salt base64.b64decode(salt_b64) expect base64.b64decode(dk_b64) actual hashlib.pbkdf2_hmac(algo.split(_)[1], password.encode(utf-8), salt, int(iters), dklenlen(expect)) # 用常量时间比较避免比较过程本身泄露信息 return hmac.compare_digest(actual, expect)盐值用os.urandom而不是random前者是密码学安全随机源。迭代次数写进存储串而不是写死在代码里将来调高迭代次数时老用户仍能正常登录登录成功后按新参数重新派生即可。hmac.compare_digest做常量时间比较逐字节短路比较会在时间上泄露匹配前缀长度。实验部分建议做一组对照用同一口令生成两条存储串并打印证明盐不同导致结果不同再测一次 600000 次迭代的耗时timeit跑三次取平均把耗时写进报告说明迭代次数是在安全性与登录延迟之间取的折中值。3.3 用 socket 在授权范围内做一次本机端口探测再写防护规则暴露面排查是课程设计里最能体现「攻防一体」的实验但必须限定范围只探测自己搭的虚拟机与回环地址报告中写明授权对象与时间窗口。下面是并发探测的核心逻辑。import socket, concurrent.futures TARGET 127.0.0.1 # 仅限本机或自有实验机 PORTS [22, 80, 443, 3306, 6379, 8443] # 待核查端口清单 def probe(port: int, timeout: float 0.8) - tuple: with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.settimeout(timeout) # 超时过短会误判开放端口 # connect_ex 返回 0 表示端口接受连接不抛异常便于批量处理 code s.connect_ex((TARGET, port)) return port, code 0 with concurrent.futures.ThreadPoolExecutor(max_workers8) as pool: for port, is_open in pool.map(probe, PORTS): print(f{TARGET}:{port} {OPEN if is_open else CLOSED/FILTERED})settimeout设 0.8 秒是本地网络的常用值公网场景要放大到 2 秒以上否则丢包会被误判成关闭connect_ex不抛异常返回错误码适合批量场景。并发线程数控制在 8 以内再多对本地实验没有收益反而让耗时统计失真。拿到开放清单后立刻写防护规则Linux 下用nft的写法是nft add rule inet filter input tcp dport { 3306, 6379 } dropWindows 下用New-NetFirewallRule -DisplayName Block-6379 -Direction Inbound -LocalPort 6379 -Protocol TCP -Action Block。整改后重跑同一脚本把前后两列结果并排贴进报告这就是最好的实验证据。3.4 实验数据怎么落成报告里的表格与插图三组实验的输出格式不统一直接截图贴进 Word 会显得很散。约定一个统一结果文件result.json字段包含实验名、时间戳、参数集、原始输出再由脚本渲染成表格。实验关键参数观测指标结论落点握手解析抓包接口 eth1过滤 tcp port 8443三次握手的 seq/ack/flags明文字段可被中间节点读取口令存储迭代 600000盐 16 字节dklen 32单次派生耗时、两条串是否相同彩虹表与撞库成本显著上升端口排查并发 8超时 0.8s整改前后开放端口数量最小化暴露面可量化验证matplotlib出图时把dpi设到 300、字体设成支持中文的字体避免报告中文字变方块每个图下方写一句「图 X 由 scripts/xxx.py 生成数据源 result.json」评阅人据此能判断数据不是编的。4. 报告主体怎么写得像安全工程STRIDE 威胁建模、风险矩阵与整改前后对照前面三个实验只是素材报告的含金量全靠分析部分。教学里常见的写法是把「安全需求」写成一段形容词什么「保证系统安全可靠」这种句子在答辩时一问就穿。可操作的做法是引入 STRIDE 分类把威胁一条条列出来再给每条威胁打风险分最后把整改措施和验证命令绑在一起。4.1 STRIDE 落到自己那套系统上的填法STRIDE 六个字母分别对应伪装、篡改、抵赖、信息泄露、拒绝服务、权限提升。用它不是为了背名词而是强制自己把「谁对哪个资产做了什么」想清楚。填表时每一行都要指明具体资产和具体入口不能写「整个系统」。威胁类型具体场景受影响资产现有控制缺口伪装攻击者用弱口令登录管理接口8443 管理服务口令哈希存储无失败次数限制篡改传输过程被改写请求参数客户端与服务端会话无未启用完整性校验信息泄露抓包读到明文凭据会话流量无未启用加密传输拒绝服务高频连接耗尽服务线程监听端口无无连接速率限制权限提升服务以高权限运行服务进程无未做权限降级表里的「缺口」一列是重点它直接决定后面整改章节写什么。伪装这一行补上登录失败计数例如同一账号 5 分钟内失败 5 次锁定篡改与信息泄露两行合并处理用 AES-GCM 同时提供机密性与完整性拒绝服务补上iptables/nft的连接速率限制权限提升则检查进程运行账户并在报告里贴出ps -o user,cmd -C python的实际输出。4.2 风险矩阵的取值口径可能性与影响怎么打分风险打分最大的问题是口径不一致同一条威胁有人打 3 有人打 5最后矩阵看起来毫无意义。解决办法是在报告里先定义每一档的含义再打分档位定义本身也是评分点。分值可能性一年内发生概率影响对课程设计系统1需要特定条件且难以满足无数据损失仅日志告警2需要一定条件攻击工具易获取单个账号受影响3条件常见自动化工具可完成服务短时不可用4无需特殊条件公开资料可复现凭据或数据泄露5默认配置即可触发系统被完全控制风险值取可能性与影响的乘积1 到 8 为低、9 到 15 为中、16 及以上为高。以「未启用加密传输」为例可能性打 3同一链路内抓包即可复现影响打 4凭据泄露风险值 12定为中风险并纳入必须整改项。报告里逐条给分时必须给出理由理由要能被实验数据支撑比如可能性打分引用 3.1 节的抓包结果证明流量确实明文可读。4.3 整改效果用命令和代码对照验证整改章节最容易写成「已修复」三个字正确的写法是给出命令与前后对照。以启用 AES-GCM 为例先给出改造后的加解密函数再给出验证脚本。from cryptography.hazmat.primitives.ciphers.aead import AESGCM import os def seal(key: bytes, plaintext: bytes, aad: bytes) - bytes: # 96 位随机 nonce 是 GCM 的推荐取值每次加密都必须重新生成 nonce os.urandom(12) ct AESGCM(key).encrypt(nonce, plaintext, aad) return nonce ct # nonce 与密文一起传输 def open_sealed(key: bytes, blob: bytes, aad: bytes) - bytes: nonce, ct blob[:12], blob[12:] # aad 参与认证但不加密可用于绑定会话标识防止密文被移植 return AESGCM(key).decrypt(nonce, ct, aad)nonce长度 12 字节是 GCM 的推荐值重复使用同一密钥下的同一 nonce 会直接破坏认证安全性这是必须写进报告的注意点。aad用来绑定上下文把会话 ID 放进去攻击者把 A 会话的密文搬到 B 会话就会解密失败。验证脚本做两组测试正常解密返回原文篡改密文最后一个字节后调用open_sealed应抛出InvalidTag异常把异常信息原样贴进报告这是完整性生效的直接证据。同理速率限制的验证用nft list ruleset | grep -A3 limit查看规则是否生效再跑一次高频连接脚本观察是否被丢弃前后对照的数据放进同一张表。5. 从 .doc 到能答辩图表编号、数据留存与复现脚本文档最后一步是把散落的实验、表格和截图收敛成一份自洽的报告。评审看的是三件事结论有没有数据支撑、每个数字能不能追溯到脚本、别人能不能重跑。把这三件事做成习惯比多写两千字更有用。5.1 报告骨架与图表编号规则建议的章节顺序是实验目标与范围、环境与拓扑、实验方法与原始数据、威胁建模与风险矩阵、整改措施与验证、结论与局限。图表编号采用「章号-序号」图题在图下方、表题在表上方正文引用时写「见图 3-1」。所有截图旁边附上生成它的命令例如抓包结果图旁写python scripts/sniff_handshake.py --iface eth1 --port 8443读者能顺着命令找到脚本。局限一节不要写套话写清楚哪些威胁没有覆盖例如「未考虑物理层接触攻击」「仅验证单机场景未做多节点并发」。5.2 一键复现脚本让评阅人三分钟跑出你的数据把三个实验串成一条流水线用 Makefile 或一个 shell 脚本统一入口比让人逐个执行脚本友好得多。#!/usr/bin/env bash # run_all.sh从环境检查到结果生成全程可重复执行 set -euo pipefail # 任一命令失败即中止避免脏数据 python -c import scapy, cryptography, matplotlib # 依赖自检 mkdir -p out python scripts/sniff_handshake.py --iface ${IFACE:-eth1} --port 8443 out/handshake.txt python scripts/hash_bench.py --iterations 600000 out/hash.json python scripts/port_check.py --target 127.0.0.1 out/ports_before.json python scripts/render_report_assets.py --indir out --outdir figures echo 生成完毕out/ 为原始数据figures/ 为报告插图set -euo pipefail里的-u让未定义变量直接报错避免$IFACE写错时静默使用空值IFACE用${IFACE:-eth1}提供默认值评阅人机器上网卡名不同时可临时覆盖。脚本把原始输出重定向到out/绘图脚本只读out/不重新采集保证「数据」与「渲染」分离报告里任何一张图都能追到对应的原始文件。5.3 答辩追问的自检口径提前把可能被追问的点整理成自检表答辩时按表回答比临场组织语言稳得多。自检表建议覆盖四类参数为什么这么取、风险分值依据是什么、整改前后差多少、还有什么没做。追问方向自检问题应答依据参数选择迭代 600000 次是否过慢hash.json 中的平均耗时与登录延迟对比风险打分可能性为何给 3 分3.1 节的抓包复现步骤整改效果速率限制是否真生效nft 规则输出与丢弃计数边界实验是否覆盖横向移动报告中局限一节已声明未覆盖自检表里的每一项都要能指向文件路径答不出路径的项说明数据没留好回去补采一次。把run_all.sh、requirements.lock.txt、out/、figures/和报告放在同一目录下评阅人双击run_all.sh就能得到与报告中完全一致的数字。本文还有配套的精品资源点击获取