云服务器与考试考台网络联通指导手册

本手册面向「云服务器(Linux)+ 考场终端(考试机 / 考台)」的部署形态,覆盖网络规划、端口开放、 安全组配置、双向连通验证、常见故障排查五个环节。按本手册逐项执行,可确保考试管理中心、 考试机考台、平台超管三端稳定联通。

8080 / TCP考试管理系统唯一服务端口
19196 / TCP本机读卡器服务(仅考试机本地)
60 台单考区默认考台规模
v1.7本手册适用版本

1网络拓扑与规划

先定拓扑,再动配置。拓扑不清楚时不要直接改防火墙,否则极易把自己锁在门外。

考场电脑(考官)浏览器访问
https://域名/login.html
→
云服务器 Linux公网 IP / 域名
Node 服务监听 0.0.0.0:8080
←
考试机 × 60考场内网
心跳 / 注册 / 抓拍上传

1.1 三种典型部署形态

形态网络关系适用场景考台如何连服务器
A 全内网 服务器、考试机同处一个考场局域网(如 10.168.99.0/24) 单考场、无外网需求,最稳 直连内网 IP
B 云服务器 + 考场专线 云服务器公网 IP,考场通过 VPN / 专线把 60 台考试机汇入同一网段 多考场统一管理,推荐生产使用 经 VPN 隧道访问云端内网地址
C 云服务器 + 公网直连 考试机直接访问云服务器公网 IP:8080 临时考场、考台数量少 公网 IP + 端口白名单
安全提示:形态 C 下请务必在安全组中把 8080 的入方向限制为考场出口 IP 段, 并把平台超管入口 /platform.html 通过 Nginx 加一层 IP 白名单或二次认证。 裸奔在公网的 8080 会被端口扫描批量探测。

1.2 端口规划表

端口协议所在机器用途
8080TCP云服务器考试管理系统 HTTP 服务(页面 + REST API)
443TCP云服务器Nginx HTTPS(推荐,摄像头抓拍必须 HTTPS 或 localhost)
22TCP云服务器SSH 运维,务必限制来源 IP
19196TCP考试机本地身份证读卡器本地服务,仅 127.0.0.1 监听,不对外
浏览器摄像头限制:Chrome / Edge 只在 HTTPS 或 http://localhost 下允许调用摄像头。 若从 http://公网IP:8080 打开考试界面,监考视频与抓拍会全部失败。 生产环境必须上 HTTPS(Nginx + 证书),这是最容易被忽略的一条。

2云服务器前置准备

以 CentOS 7+/Rocky、Ubuntu 20.04+/Debian 11+ 为例,两套命令都给出。

2.1 确认系统与网络信息

# 系统版本
cat /etc/os-release

# 内网 IP(云厂商分配,注意可能是 172.x / 10.x)
ip -4 addr show | grep inet

# 公网 IP(以云控制台为准)
curl -s ifconfig.me; echo

# 确认 8080 是否被占用
ss -lntp | grep 8080

2.2 时间同步(务必执行)

本系统所有心跳、抓拍、考试成绩都带时间戳。服务器时间漂移会导致考台「假离线」、 成绩单时间错乱。云服务器默认时钟可能偏差数分钟。

# 查看当前时间偏差
timedatectl status

# 开启 NTP 同步(系统自带 chrony 或 systemd-timesyncd)
sudo timedatectl set-ntp true
sudo timedatectl set-timezone Asia/Shanghai
timedatectl status   # 应显示 System clock synchronized: yes

2.3 安装 Node 运行时

系统要求 Node.js 18 及以上(推荐 20 LTS / 22 LTS)。若使用本系统自带的一键安装包, 可跳过本节——安装脚本会内置运行时。

# 方式一:官方二进制包(推荐,免外网源依赖)
cd /tmp
curl -O https://nodejs.org/dist/v20.18.0/node-v20.18.0-linux-x64.tar.xz
sudo mkdir -p /usr/local/lib/nodejs
sudo tar -xJf node-v20.18.0-linux-x64.tar.xz -C /usr/local/lib/nodejs
sudo ln -sf /usr/local/lib/nodejs/node-v20.18.0-linux-x64/bin/node /usr/local/bin/node
node -v

# 方式二:包管理器(Ubuntu / Debian)
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs

2.4 创建专用运行用户

不要让服务以 root 运行。系统用固定低权限账号 drvexam,数据目录归其所有。

sudo useradd -r -s /usr/sbin/nologin -d /opt/drvexam drvexam
sudo mkdir -p /opt/drvexam
sudo chown -R drvexam:drvexam /opt/drvexam

3安全组与端口开放

云服务器有两层防火墙:云厂商「安全组」(在控制台配)+ 系统「firewalld/ufw」。两层都要放行。

3.1 云控制台安全组规则

方向协议端口来源说明
入方向TCP4430.0.0.0/0HTTPS,考官与考试机访问
入方向TCP8080考场出口 IP 段直连模式必开;有 Nginx 反代时可改为仅 127.0.0.1 监听后关闭本行
入方向TCP22运维固定 IP /32禁止 0.0.0.0/0
出方向全部全部0.0.0.0/0默认允许

3.2 系统防火墙放行

# CentOS / Rocky / Alibaba Cloud Linux(firewalld)
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
sudo firewall-cmd --list-all

# Ubuntu / Debian(ufw)
sudo ufw allow 8080/tcp
sudo ufw allow 443/tcp
sudo ufw reload
sudo ufw status verbose

# 仅内网形态 A/C 需要:从指定网段访问 8080
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.168.99.0/24" port protocol="tcp" port="8080" accept'

3.3 Nginx 反向代理 + HTTPS(推荐)

把 8080 藏在 Nginx 后面,对外只开 443,既能解决摄像头 HTTPS 限制,也便于加 IP 白名单。

server {
    listen 443 ssl http2;
    server_name exam.example.com;

    ssl_certificate     /etc/nginx/ssl/exam.crt;
    ssl_certificate_key /etc/nginx/ssl/exam.key;

    # 抓拍图片可能较大,放宽上传体积
    client_max_body_size 20m;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Host              $host;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout 120s;
    }

    # 平台超管入口加 IP 白名单(可选但强烈建议)
    location = /platform.html {
        allow 10.168.99.0/24;
        allow 203.0.113.10;
        deny  all;
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
server {
    listen 80;
    server_name exam.example.com;
    return 301 https://$host$request_uri;
}
关键:服务端识别客户端 IP 依赖 X-Forwarded-For。Nginx 反代后, 登录限流按真实 IP 计,不会把整个考场当成一个 IP 而误伤。 若不做反代直接暴露 8080,请确认没开云厂商的「七层负载均衡」,否则同样会丢失真实 IP。

4考场侧网络接入

60 台考试机要能稳定访问云端,考场侧的三件事:网段、DHCP/固定 IP、出口带宽。

4.1 网段与 IP 规划

项目建议
考场内网网段10.168.99.0/24(本项目默认示例),至少预留 /24,容纳 60 台 + 网关 + 服务器
考试机地址优先 DHCP 保留绑定(按 MAC 固定),避免 DHCP 租约变化导致考台错位
考台号与 IP建议末段与考台号对应,如 A-001 → 10.168.99.11,便于现场排查
网关/DNS网关指向考场出口路由器;DNS 至少配两个(如 223.5.5.5 / 114.114.114.114)

4.2 出口带宽估算

单台考试机日常开销:心跳约 2 KB / 3 秒,考试中抓拍 3 张约 300 KB / 场, 交卷成绩单约 10 KB。60 台同时开考的总带宽需求很低(< 2 Mbps), 真正的瓶颈在考场出口 NAT 的并发连接数与链路的丢包率。

实测建议:考场出口至少 10 Mbps 上行,并且用 ping 测丢包—— 丢包率超过 1% 时,考试机心跳会成片超时,表现为监控页大面积「离线」。

4.3 VPN / 专线接入(形态 B)

  1. 在云服务器与考场出口路由器之间建立 IPsec / WireGuard 隧道;
  2. 把考场 60 台机器所在网段与云端 VPC 网段打通,注意两边网段不能重叠;
  3. 在隧道配置中放行 TCP 8080,其余端口一律拒绝;
  4. 隧道断开要能自动重连,并在考场网关做保活探测;
  5. 考试机配置文件里的 server 填写云端 VPC 内网地址(如 http://172.16.0.10:8080),不写公网 IP。

4.4 代理与 DNS 干扰排查

考场机器若装过「上网加速」「安全卫士」类软件,常会写入系统代理,导致 API 请求被劫持到代理服务器。

# Windows 考试机:检查代理
netsh winhttp show proxy
reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v ProxyEnable

# Linux 服务器:检查环境变量(本项目启动脚本会清理)
env | grep -i proxy
服务端启动脚本已处理「http_proxy 与 HTTP_PROXY 同时存在导致 Start-Process 报错」的问题;Linux 侧同样建议在 systemd 单元中用 Environment= 显式清空代理变量。

5双向连通验证

按「服务器自检 → 考场到云端 → 云端到考场」三步走,每步都有明确判定标准。

5.1 第一步:服务器本机自检

# 服务是否在监听(应为 0.0.0.0:8080 或 127.0.0.1:8080)
ss -lntp | grep 8080

# 本机回环访问(必须 200)
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8080/api/health

# 健康检查返回内容(应含 ok:true 与 version)
curl -s http://127.0.0.1:8080/api/health | head -c 300; echo

# 用内网 IP 再验一次(验证不是只听 127.0.0.1)
curl -s -o /dev/null -w "%{http_code}\n" http://$(hostname -I | awk '{print $1}'):8080/
现象判定下一步
ss 无输出服务未启动查 journalctl -u drvexam -n 100
ss 只显示 127.0.0.1:8080只听回环启动参数需 0.0.0.0(本系统默认已是 0.0.0.0)
curl 返回 200 且 ok:true通过进入第二步

5.2 第二步:考场 → 云端(考官与考试机视角)

在考场任意一台考试机上执行。Windows 与 Linux 命令都给:

# Windows 考试机
ping exam.example.com
curl.exe -s -o NUL -w "%{http_code}\n" http://exam.example.com/api/health

# Linux / macOS 考场机
ping -c 4 exam.example.com
curl -s -o /dev/null -w "%{http_code}\n" http://exam.example.com/api/health

# 端口层探测(判断是防火墙丢包还是应用没响应)
telnet exam.example.com 8080
# 或
nc -zv exam.example.com 8080

5.3 第三步:云端 → 考场(考台测试视角)

登录考试管理中心 → 考台测试 → 「全部考台测试」,或点「联网小助手」一键诊断。 云端主动探测考台的连通性,用于确认反向链路(如抓拍图片回传、远程锁屏指令下发)。

若只做「考试机单向上报」的部署,第三步可以为「部分通过」——系统不会因此阻塞开考, 但远程锁屏 / 远程下发考生将不可用。管理中心会在考台测试结果里标出「仅单向连通」。

5.4 抓包定位(终极手段)

# 服务器侧抓 8080 包,看是否有 SYN 进来
sudo tcpdump -i any -nn 'tcp port 8080' -c 50

# 只看 SYN(有 SYN 无 SYN-ACK 说明回包被拦)
sudo tcpdump -i any -nn 'tcp[tcpflags] & tcp-syn != 0 and port 8080' -c 20

6考试机端配置

考试机安装后,配置存放在安装目录的 config.json,改完需重启考试机程序。

6.1 配置文件字段

字段类型说明
serverstring考试管理系统地址,含协议与端口,如 http://10.168.99.10:8080。不要带结尾斜杠
seatNostring考台号,如 A-001,必须与后台分配一致
tokenstring考台安装令牌(X-Exam-Token),由管理中心「考台分配」生成
heartbeatSecnumber心跳间隔,默认 3 秒,不建议大于 10
cameraboolean是否启用摄像头抓拍
kioskboolean全屏锁定模式(考试机专用)

6.2 示例配置

{
  "server": "https://exam.example.com",
  "seatNo": "A-001",
  "token": "安装时由管理中心下发",
  "heartbeatSec": 3,
  "camera": true,
  "kiosk": true
}

6.3 批量修改 60 台

考试机包内附带 config.example.json。批量部署时可用一条命令改完全部:

# Windows 批量(在考试机安装目录执行,改完重启程序)
powershell -NoProfile -Command ^
  "$f='config.json'; $j=Get-Content $f -Raw | ConvertFrom-Json; $j.server='https://exam.example.com'; $j | ConvertTo-Json -Depth 5 | Set-Content $f -Encoding UTF8"

6.4 验证考试机已连上

  1. 考试机启动后,管理中心 → 考试机监控,对应考台变蓝(空闲);
  2. 「最后心跳」在 10 秒内持续刷新;
  3. 「考台测试」该行为 通过;
  4. 断开网线,10 秒内该考台变红(离线),重新插回 5 秒内恢复蓝——说明心跳机制正常。

7常见故障排查

按「现象 → 原因 → 处理」对照表逐条排查,覆盖现场 90% 的联通问题。

Q1 考试机一直显示「未注册」,管理中心看不到考台
① 检查 config.json 的 server 是否写错(常见多写结尾斜杠、端口写成 80); ② 在考试机上 curl http://服务器地址:8080/api/health,返回非 200 说明网络不通; ③ 检查考台号 seatNo 是否与后台分配的考台号一致,不一致会被拒绝注册; ④ 检查令牌是否已失效(考台被后台删除后,旧令牌失效)。
Q2 监控页大面积「离线」,但考试机能上网
最常见的两个原因:心跳超时阈值太小(考场网络抖动)或出口 NAT 并发连接被打满。 先在服务器 ss -s 看 connections 数量;再看考场出口路由器会话数上限。 现场应急:把 heartbeatSec 调到 5、后台「考试参数」里心跳超时调到 60 秒。
Q3 摄像头打开失败 / 监考视频黑屏
首要原因浏览器安全策略:页面不是 HTTPS 且不是 localhost。 解决:上 Nginx + 证书走 443。其次是摄像头被其他程序(如钉钉、腾讯会议)占用, 或 Windows 隐私设置里「允许应用访问摄像头」被关闭。
Q4 登录提示「归属地、用户名或密码不正确」
归属地是登录三要素之一。管理员账号绑定了省份,选错省份即使密码正确也会被拒(这是设计如此, 避免跨考区误登)。请确认账号所属考区的省份。连续失败 8 次会锁定 10 分钟。
Q5 登录后立刻被踢回登录页
① 服务端重启且未设置固定 SECRET → 旧令牌签名失效。生产环境务必在 systemd 中固定 Environment=SECRET=一长串随机值; ② 考区被平台停用 → 该考区会话被强制注销; ③ 服务器时间跳变 → 令牌 exp 判定异常,检查 NTP。
Q6 考台测试全部「未注册」,但考试机进程在跑
多半是考试机连到了另一台服务器(比如之前测试留下的配置)。 在考试机浏览器打开 http://当前配置地址:8080/api/health, 对比返回的 hostname 是否为预期的云服务器主机名。
Q7 抓拍图片上传失败 / 成绩单缺照片
检查 Nginx 的 client_max_body_size(默认 1m 会截断); 检查服务器磁盘空间 df -h;抓拍失败时系统会如实计数并在成绩单上标注,不会伪造。
Q8 页面能打开但所有操作提示「未登录或登录已过期」
反向代理没有透传 Authorization 头,或浏览器缓存了旧前端 JS。 确认 Nginx 未设置 proxy_set_header Authorization "";, 并在浏览器强制刷新(Ctrl+F5)。

8开考前检查清单

建议打印张贴在考场控制台,每场考试前逐项打勾。

#检查项判定标准
1云服务器服务运行systemctl status drvexam 为 active (running)
2健康检查/api/health 返回 ok:true,version 与预期一致
3磁盘空间df -h 根分区使用率 < 80%
4时间同步timedatectl 显示 synchronized: yes
5考台在线率考试机监控页在线数 = 实际考台数(100%)
6考台测试全部考台结果为「通过」,无「仅单向连通」
7摄像头随机抽 3 台看监考画面正常
8题库就绪考试中心「题库就绪情况」科目一/科目四题量均达标
9考生数据考生人数 = 应考人数,抽 2 人核对姓名与身份证号
10权限确认当前账号「考区管理员」及以上,科目已授权
11应急通道记录云服务器 SSH 与重启命令,确认手机可联系运维
建议:把第 1–6 项固化到「联网小助手」一键诊断里,每场开考前点一次, 全部绿色再开考。诊断结果可截图存档,作为考试组织的留痕材料。
机动车驾驶人考试系统 · 网络联通指导手册 · 适用版本 v1.7