tanyu_admin 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.dockerignore ADDED
@@ -0,0 +1,16 @@
1
+ node_modules
2
+ .git
3
+ .gitignore
4
+ *.md
5
+ archive
6
+ design-system
7
+ design-output.txt
8
+ design-system-output.md
9
+ design-system-result.md
10
+ design-system.md
11
+ .cookie_cache.json
12
+ page.html
13
+ test.js
14
+ nul
15
+ *.log
16
+ .cache
@@ -0,0 +1,52 @@
1
+ name: Build and Push Docker Image
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+
8
+ env:
9
+ REGISTRY: ghcr.io
10
+ IMAGE_NAME: ${{ github.repository }}
11
+
12
+ jobs:
13
+ build-and-push:
14
+ runs-on: ubuntu-latest
15
+ permissions:
16
+ contents: read
17
+ packages: write
18
+
19
+ steps:
20
+ - name: Checkout repository
21
+ uses: actions/checkout@v4
22
+
23
+ - name: Set up Docker Buildx
24
+ uses: docker/setup-buildx-action@v3
25
+
26
+ - name: Log in to GitHub Container Registry
27
+ uses: docker/login-action@v3
28
+ with:
29
+ registry: ${{ env.REGISTRY }}
30
+ username: ${{ github.actor }}
31
+ password: ${{ secrets.GITHUB_TOKEN }}
32
+
33
+ - name: Extract metadata (tags, labels)
34
+ id: meta
35
+ uses: docker/metadata-action@v5
36
+ with:
37
+ images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
38
+ tags: |
39
+ type=ref,event=branch
40
+ type=sha,prefix={{branch}}-
41
+ type=raw,value=latest,enable={{is_default_branch}}
42
+
43
+ - name: Build and push Docker image
44
+ uses: docker/build-push-action@v5
45
+ with:
46
+ context: .
47
+ platforms: linux/amd64,linux/arm64
48
+ push: true
49
+ tags: ${{ steps.meta.outputs.tags }}
50
+ labels: ${{ steps.meta.outputs.labels }}
51
+ cache-from: type=gha
52
+ cache-to: type=gha,mode=max
package/CLAUDE.md ADDED
@@ -0,0 +1,85 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ This is a modem/router virtual host (port forwarding) management system for China Unicom modems. It provides both a REST API server and a CLI tool to manage port forwarding rules on the modem at 192.168.1.1.
8
+
9
+ ## Commands
10
+
11
+ ```bash
12
+ # Install dependencies
13
+ pnpm install
14
+
15
+ # Start the API server (with nodemon for auto-reload)
16
+ pnpm start
17
+
18
+ # Run the HTML parser directly
19
+ pnpm run parse
20
+
21
+ # Fetch page from modem
22
+ pnpm run fetch
23
+
24
+ # CLI tool for listing port mappings
25
+ node cli.js list
26
+ node cli.js list -v # verbose mode
27
+
28
+ # CLI tool for adding port forwarding (external port = internal port)
29
+ node cli.js add <ip> <port> <name>
30
+ # Example: node cli.js add 192.168.1.100 8080 "Web Server"
31
+
32
+ # CLI tool for deleting port forwarding by index
33
+ node cli.js del <index>
34
+ # Example: node cli.js del 0
35
+
36
+ # Disable proxy for debugging
37
+ ENABLE_PROXY=false node cli.js list
38
+ ```
39
+
40
+ ## Architecture
41
+
42
+ ### Core Modules
43
+
44
+ - **server.js** - Express REST API server (port 3000) providing CRUD endpoints for virtual host configurations
45
+ - **modem-api.js** - Modem communication layer handling authentication, encryption (RSA + AES-256-CBC), and configuration submission
46
+ - **index.js** - Login/session management with cookie caching, handles modem authentication flow
47
+ - **parser.js** - Parses modem HTML responses to extract virtual host configurations
48
+ - **cli.js** - Commander-based CLI tool for listing configurations
49
+ - **axios-interceptor.js** - Custom axios instance with request/response logging
50
+
51
+ ### Data Flow
52
+
53
+ 1. **Authentication**: `index.js` handles login to modem using SHA256 password hashing with random number
54
+ 2. **Session Management**: Cookies and session tokens are cached in `.cookie_cache.json` (30 min expiry)
55
+ 3. **API Encryption**: `modem-api.js` encrypts requests using RSA (for AES key exchange) + AES-256-CBC (for parameters)
56
+ 4. **HTML Parsing**: Modem returns HTML with `Transfer_meaning()` calls containing config data, parsed by `parser.js`
57
+
58
+ ### Key Files
59
+
60
+ - `virtual_hosts.json` - Local cache of port forwarding configurations
61
+ - `.cookie_cache.json` - Session cookie and token cache
62
+ - `.cache/page.html` - Cached HTML response from modem
63
+
64
+ ### API Endpoints
65
+
66
+ - `GET /api/hosts` - List all virtual hosts (refreshes from modem)
67
+ - `GET /api/hosts/:id` - Get single host by index
68
+ - `POST /api/hosts` - Add new port forwarding rule
69
+ - `PUT /api/hosts/:id` - Update existing rule
70
+ - `DELETE /api/hosts/:id` - Delete rule
71
+ - `POST /api/hosts/refresh` - Force refresh from modem
72
+
73
+ ## Configuration
74
+
75
+ Modem credentials are hardcoded in `index.js` and `modem-api.js`:
76
+ - Base URL: `http://192.168.1.1`
77
+ - Account type: `admin`
78
+
79
+ ## Docker
80
+
81
+ ```bash
82
+ docker-compose up -d
83
+ ```
84
+
85
+ Runs on host network mode with 128MB memory limit.
package/DEPLOY.md ADDED
@@ -0,0 +1,367 @@
1
+ # OpenWrt Docker 部署指南(直接在 OpenWrt 上操作)
2
+
3
+ ## 前置要求
4
+
5
+ ### 1. 在 OpenWrt 上安装 Docker
6
+
7
+ SSH 登录到你的 OpenWrt 路由器:
8
+
9
+ ```bash
10
+ ssh root@192.168.1.1 # 替换为你的路由器 IP
11
+ ```
12
+
13
+ 安装 Docker:
14
+
15
+ ```bash
16
+ # 更新软件包列表
17
+ opkg update
18
+
19
+ # 安装 Docker(注意:需要足够的存储空间,建议至少 500MB 可用空间)
20
+ opkg install dockerd
21
+
22
+ # 启动 Docker 服务
23
+ /etc/init.d/dockerd start
24
+ /etc/init.d/dockerd enable
25
+ ```
26
+
27
+ ### 2. 检查 Docker 是否正常运行
28
+
29
+ ```bash
30
+ docker --version
31
+ docker info
32
+ ```
33
+
34
+ ## 部署步骤(推荐方案)
35
+
36
+ ### 步骤 1:上传项目文件到 OpenWrt
37
+
38
+ 在你的电脑上打包项目(排除不必要的文件):
39
+
40
+ ```bash
41
+ # Windows PowerShell
42
+ tar -czf admin.tar.gz --exclude=node_modules --exclude=.git --exclude=archive --exclude=design-system .
43
+
44
+ # 或者使用 7-Zip 等工具手动打包
45
+ ```
46
+
47
+ 上传到 OpenWrt:
48
+
49
+ ```bash
50
+ # 使用 SCP 上传(替换 IP 地址)
51
+ scp admin.tar.gz root@192.168.1.1:/root/
52
+ ```
53
+
54
+ ### 步骤 2:在 OpenWrt 上解压并构建
55
+
56
+ SSH 登录到 OpenWrt 后:
57
+
58
+ ```bash
59
+ # 创建项目目录
60
+ mkdir -p /root/admin
61
+ cd /root
62
+
63
+ # 解压项目文件
64
+ tar -xzf admin.tar.gz -C /root/admin
65
+
66
+ # 进入项目目录
67
+ cd /root/admin
68
+
69
+ # 查看文件是否正确
70
+ ls -la
71
+ ```
72
+
73
+ ### 步骤 3:构建 Docker 镜像
74
+
75
+ ```bash
76
+ # 构建镜像(这个过程可能需要 5-15 分钟,取决于设备性能)
77
+ docker build -t modem-admin .
78
+
79
+ # 查看构建的镜像
80
+ docker images
81
+ ```
82
+
83
+ **注意**:如果构建过程中出现内存不足错误,请参考下面的"性能优化建议"部分。
84
+
85
+ ### 步骤 4:运行容器
86
+
87
+ ```bash
88
+ # 运行容器
89
+ docker run -d \
90
+ --name modem-admin \
91
+ --restart unless-stopped \
92
+ --network host \
93
+ -v /root/admin/virtual_hosts.json:/app/virtual_hosts.json \
94
+ -v /root/admin/.cookie_cache.json:/app/.cookie_cache.json \
95
+ -v /root/admin/.cache:/app/.cache \
96
+ -m 128m \
97
+ --cpus 0.5 \
98
+ modem-admin
99
+
100
+ # 查看容器状态
101
+ docker ps
102
+
103
+ # 查看日志
104
+ docker logs -f modem-admin
105
+ ```
106
+
107
+ ### 步骤 5:验证服务
108
+
109
+ ```bash
110
+ # 检查服务是否正常运行
111
+ curl http://localhost:3000/api/hosts
112
+
113
+ # 或者在浏览器访问
114
+ # http://你的路由器IP:3000
115
+ ```
116
+
117
+ ## 性能优化建议
118
+
119
+ ### 如果构建过程中内存不足
120
+
121
+ OpenWrt 设备通常内存较小,构建 Docker 镜像时可能会遇到内存不足的问题。解决方案:
122
+
123
+ #### 方案 1:增加 swap 空间
124
+
125
+ ```bash
126
+ # 创建 512MB swap 文件
127
+ dd if=/dev/zero of=/root/swapfile bs=1M count=512
128
+ chmod 600 /root/swapfile
129
+ mkswap /root/swapfile
130
+ swapon /root/swapfile
131
+
132
+ # 验证 swap 是否生效
133
+ free -m
134
+
135
+ # 构建完成后可以关闭 swap
136
+ swapoff /root/swapfile
137
+ rm /root/swapfile
138
+ ```
139
+
140
+ #### 方案 2:使用预构建镜像(推荐)
141
+
142
+ 如果你有其他安装了 Docker 的设备(朋友的电脑、云服务器等),可以:
143
+
144
+ 1. 在其他设备上构建镜像
145
+ 2. 导出镜像文件
146
+ 3. 传输到 OpenWrt
147
+ 4. 导入并运行
148
+
149
+ ```bash
150
+ # 在其他设备上
151
+ docker build -t modem-admin .
152
+ docker save modem-admin | gzip > modem-admin.tar.gz
153
+
154
+ # 传输到 OpenWrt
155
+ scp modem-admin.tar.gz root@192.168.1.1:/root/
156
+
157
+ # 在 OpenWrt 上导入
158
+ gunzip -c /root/modem-admin.tar.gz | docker load
159
+
160
+ # 运行容器
161
+ cd /root/admin
162
+ docker run -d \
163
+ --name modem-admin \
164
+ --restart unless-stopped \
165
+ --network host \
166
+ -v /root/admin/virtual_hosts.json:/app/virtual_hosts.json \
167
+ -v /root/admin/.cookie_cache.json:/app/.cookie_cache.json \
168
+ -v /root/admin/.cache:/app/.cache \
169
+ -m 128m \
170
+ --cpus 0.5 \
171
+ modem-admin
172
+ ```
173
+
174
+ ### 镜像优化说明
175
+
176
+ - **镜像大小**:使用 Alpine Linux,最终镜像约 50-80MB
177
+ - **内存限制**:限制为 128MB,适合低内存设备
178
+ - **CPU 限制**:限制为 0.5 核心,避免占用过多资源
179
+ - **网络模式**:使用 host 模式,减少网络开销
180
+ - **生产依赖**:只安装生产环境依赖,减少体积
181
+
182
+ ## 常用管理命令
183
+
184
+ ```bash
185
+ # 查看容器状态
186
+ docker ps
187
+
188
+ # 查看容器详细信息
189
+ docker inspect modem-admin
190
+
191
+ # 查看日志(实时)
192
+ docker logs -f modem-admin
193
+
194
+ # 查看最近 100 行日志
195
+ docker logs --tail 100 modem-admin
196
+
197
+ # 停止服务
198
+ docker stop modem-admin
199
+
200
+ # 启动服务
201
+ docker start modem-admin
202
+
203
+ # 重启服务
204
+ docker restart modem-admin
205
+
206
+ # 删除容器(需要先停止)
207
+ docker stop modem-admin
208
+ docker rm modem-admin
209
+
210
+ # 删除镜像
211
+ docker rmi modem-admin
212
+
213
+ # 查看资源占用
214
+ docker stats modem-admin
215
+ ```
216
+
217
+ ## 访问服务
218
+
219
+ 服务启动后,在浏览器访问:
220
+
221
+ ```
222
+ http://你的路由器IP:3000
223
+ ```
224
+
225
+ 例如:`http://192.168.1.1:3000`
226
+
227
+ ## 故障排查
228
+
229
+ ### 1. Docker 服务未启动
230
+
231
+ ```bash
232
+ # 检查 Docker 服务状态
233
+ /etc/init.d/dockerd status
234
+
235
+ # 启动 Docker 服务
236
+ /etc/init.d/dockerd start
237
+ ```
238
+
239
+ ### 2. 存储空间不足
240
+
241
+ ```bash
242
+ # 查看磁盘空间
243
+ df -h
244
+
245
+ # 清理 Docker 缓存
246
+ docker system prune -a
247
+
248
+ # 删除未使用的镜像
249
+ docker image prune -a
250
+ ```
251
+
252
+ ### 3. 内存不足
253
+
254
+ 如果设备内存极小(<256MB),可以进一步降低限制:
255
+
256
+ ```bash
257
+ docker update --memory 64m modem-admin
258
+ ```
259
+
260
+ ### 4. 容器无法启动
261
+
262
+ ```bash
263
+ # 查看详细错误日志
264
+ docker logs modem-admin
265
+
266
+ # 进入容器调试
267
+ docker exec -it modem-admin sh
268
+
269
+ # 检查端口是否被占用
270
+ netstat -tuln | grep 3000
271
+ ```
272
+
273
+ ### 5. 无法访问服务
274
+
275
+ ```bash
276
+ # 检查容器是否运行
277
+ docker ps
278
+
279
+ # 检查防火墙规则
280
+ iptables -L -n | grep 3000
281
+
282
+ # 测试本地访问
283
+ curl http://localhost:3000/api/hosts
284
+ ```
285
+
286
+ ### 6. 构建失败
287
+
288
+ ```bash
289
+ # 查看构建日志
290
+ docker build -t modem-admin . --progress=plain
291
+
292
+ # 如果是网络问题,可以配置镜像加速
293
+ # 编辑 /etc/docker/daemon.json
294
+ {
295
+ "registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"]
296
+ }
297
+
298
+ # 重启 Docker
299
+ /etc/init.d/dockerd restart
300
+ ```
301
+
302
+ ## 开机自启动
303
+
304
+ Docker 容器已配置 `--restart unless-stopped`,会在系统重启后自动启动。
305
+
306
+ 确保 Docker 服务开机自启:
307
+
308
+ ```bash
309
+ /etc/init.d/dockerd enable
310
+ ```
311
+
312
+ 验证开机自启是否配置成功:
313
+
314
+ ```bash
315
+ ls /etc/rc.d/ | grep dockerd
316
+ ```
317
+
318
+ ## 更新服务
319
+
320
+ 当代码有更新时:
321
+
322
+ ```bash
323
+ # 停止并删除旧容器
324
+ docker stop modem-admin
325
+ docker rm modem-admin
326
+
327
+ # 删除旧镜像
328
+ docker rmi modem-admin
329
+
330
+ # 上传新代码并重新构建
331
+ cd /root/admin
332
+ # ... 上传新文件 ...
333
+ docker build -t modem-admin .
334
+
335
+ # 运行新容器
336
+ docker run -d \
337
+ --name modem-admin \
338
+ --restart unless-stopped \
339
+ --network host \
340
+ -v /root/admin/virtual_hosts.json:/app/virtual_hosts.json \
341
+ -v /root/admin/.cookie_cache.json:/app/.cookie_cache.json \
342
+ -v /root/admin/.cache:/app/.cache \
343
+ -m 128m \
344
+ --cpus 0.5 \
345
+ modem-admin
346
+ ```
347
+
348
+ ## 卸载
349
+
350
+ 完全卸载服务和 Docker:
351
+
352
+ ```bash
353
+ # 停止并删除容器
354
+ docker stop modem-admin
355
+ docker rm modem-admin
356
+
357
+ # 删除镜像
358
+ docker rmi modem-admin
359
+
360
+ # 删除项目文件
361
+ rm -rf /root/admin
362
+
363
+ # 卸载 Docker(可选)
364
+ /etc/init.d/dockerd stop
365
+ /etc/init.d/dockerd disable
366
+ opkg remove dockerd
367
+ ```
package/Dockerfile ADDED
@@ -0,0 +1,27 @@
1
+ # 使用 Alpine Linux 最小化镜像大小
2
+ FROM node:20-alpine
3
+
4
+ # 设置工作目录
5
+ WORKDIR /app
6
+
7
+ # 只复制依赖文件
8
+ COPY package.json pnpm-lock.yaml ./
9
+
10
+ # 安装 pnpm 并安装生产依赖
11
+ RUN npm install -g pnpm && \
12
+ pnpm install --prod --frozen-lockfile && \
13
+ npm cache clean --force && \
14
+ pnpm store prune
15
+
16
+ # 复制应用代码
17
+ COPY index.js server.js parser.js modem-api.js jsencrypt.min.js axios-interceptor.js ./
18
+ COPY public ./public
19
+
20
+ # 创建缓存目录
21
+ RUN mkdir -p .cache
22
+
23
+ # 暴露端口
24
+ EXPOSE 3000
25
+
26
+ # 启动服务
27
+ CMD ["node", "server.js"]
@@ -0,0 +1,124 @@
1
+ const crypto = require('crypto');
2
+
3
+ // 1. 定义从父页面获取的公钥
4
+ const pubKey = `-----BEGIN PUBLIC KEY-----
5
+ MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAodPTerkUVCYmv28SOfRV
6
+ 7UKHVujx/HjCUTAWy9l0L5H0JV0LfDudTdMNPEKloZsNam3YrtEnq6jqMLJV4ASb
7
+ 1d6axmIgJ636wyTUS99gj4BKs6bQSTUSE8h/QkUYv4gEIt3saMS0pZpd90y6+B/9
8
+ hZxZE/RKU8e+zgRqp1/762TB7vcjtjOwXRDEL0w71Jk9i8VUQ59MR1Uj5E8X3WIc
9
+ fYSK5RWBkMhfaTRM6ozS9Bqhi40xlSOb3GBxCmliCifOJNLoO9kFoWgAIw5hkSIb
10
+ GH+4Csop9Uy8VvmmB+B3ubFLN35qIa5OG5+SDXn4L7FeAA5lRiGxRi8tsWrtew8w
11
+ nwIDAQAB
12
+ -----END PUBLIC KEY-----`;
13
+
14
+ /**
15
+ * 生成 16 位随机字符串
16
+ */
17
+ function generateRandomString(len = 16) {
18
+ const chars = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678";
19
+ let str = "";
20
+ for (let i = 0; i < len; i++) {
21
+ str += chars.charAt(Math.floor(Math.random() * chars.length));
22
+ }
23
+ return str;
24
+ }
25
+
26
+ /**
27
+ * 对应 EncodeKey(key, iv)
28
+ * 使用 RSA 公钥加密 "key+iv"
29
+ */
30
+ function encodeKey(key, iv, publicKey) {
31
+ const data = Buffer.from(key + "+" + iv);
32
+ const encrypted = crypto.publicEncrypt(
33
+ {
34
+ key: publicKey,
35
+ padding: crypto.constants.RSA_PKCS1_PADDING, // JSEncrypt 默认填充
36
+ },
37
+ data
38
+ );
39
+ return encrypted.toString('base64');
40
+ }
41
+
42
+ /**
43
+ * 处理 ZeroPadding (Node.js 原生不直接支持 ZeroPadding,需要手动处理数据长度)
44
+ */
45
+ function zeroPad(data, blockSize) {
46
+ const buffer = Buffer.from(data, 'utf8');
47
+ const padLen = blockSize - (buffer.length % blockSize);
48
+ if (padLen === blockSize) return buffer;
49
+ return Buffer.concat([buffer, Buffer.alloc(padLen, 0)]);
50
+ }
51
+
52
+ /**
53
+ * 对应 EncodePara(data, key, iv)
54
+ * 1. 对 key 和 iv 进行 SHA256
55
+ * 2. 使用 AES-256-CBC 加密
56
+ * 3. 填充模式为 ZeroPadding
57
+ */
58
+ function encodePara(data, key, iv) {
59
+ // 步骤1: 哈希处理 Key 和 IV
60
+ // 注意:CryptoJS.SHA256 返回的是 256 位(32字节),所以 AES 会自动识别为 AES-256
61
+ const hashedKey = crypto.createHash('sha256').update(key).digest();
62
+ const hashedIv = crypto.createHash('sha256').update(iv).digest();
63
+
64
+ // 步骤2: AES-256-CBC 加密
65
+ // CryptoJS 在 IV 过长时会取前 16 字节 (128bit)
66
+ const realIv = hashedIv.slice(0, 16);
67
+
68
+ // 手动处理 ZeroPadding
69
+ const paddedData = zeroPad(data, 16);
70
+
71
+ const cipher = crypto.createCipheriv('aes-256-cbc', hashedKey, realIv);
72
+ cipher.setAutoPadding(false); // 关闭默认的 PKCS7,使用我们手动做的 ZeroPadding
73
+
74
+ let encrypted = cipher.update(paddedData, null, 'base64');
75
+ encrypted += cipher.final('base64');
76
+
77
+ return encrypted;
78
+ }
79
+
80
+ /**
81
+ * 对应 DecodePara (用于解析服务器返回的加密数据)
82
+ */
83
+ function decodePara(encryptedStr, key, iv) {
84
+ const hashedKey = crypto.createHash('sha256').update(key).digest();
85
+ const hashedIv = crypto.createHash('sha256').update(iv).digest().slice(0, 16);
86
+
87
+ const decipher = crypto.createDecipheriv('aes-256-cbc', hashedKey, hashedIv);
88
+ decipher.setAutoPadding(false);
89
+
90
+ let decrypted = decipher.update(encryptedStr, 'base64', 'utf8');
91
+ decrypted += decipher.final('utf8');
92
+
93
+ // 移除 ZeroPadding 产生的末尾空字符
94
+ return decrypted.replace(/\0+$/, '');
95
+ }
96
+
97
+ // --- 使用示例 ---
98
+ function setDecodePara() {
99
+ var tokenObj = getObj("_SESSION_TOKEN");
100
+ if (tokenObj == null) {
101
+ document.key = null;
102
+ document.iv = null;
103
+ return;
104
+ }
105
+ var key = tokenObj.value;
106
+ var iv = key.substr(5, 10);
107
+ document.key = key;
108
+ document.iv = iv;
109
+ }
110
+ const myKey = generateRandomString(16);
111
+ const myIv = generateRandomString(16);
112
+ const rawData = "IF_ACTION=Apply&IF_ERRORSTR=SUCC&IF_ERRORPARAM=SUCC"; // 示例提交参数
113
+
114
+
115
+ // 实际编辑接口的参数 'ViewName=NULL&WANCViewName=IGD.WD1.WCD2.WCPPP1&WANCName=NULL&Enable=1&Protocol=2&Name=%E8%BF%9C%E7%A8%8B&MinExtPort=6565&MaxExtPort=6565&InternalHost=192.168.1.17&MinIntPort=6565&MaxIntPort=6565&Description=NULL&LeaseDuration=NULL&PortMappCreator=NULL&MinRemoteHost=0.0.0.0&MaxRemoteHost=0.0.0.0&InternalMacHost=NULL&MacEnable=0&IF_ACTION=apply&IF_ERRORSTR=SUCC&IF_ERRORPARAM=SUCC&IF_ERRORTYPE=-1&IF_INDEX=2&IF_INSTNUM=10&ViewName0=IGD.WD1.WCD2.WCPPP1.FWPM1&WANCViewName0=IGD.WD1.WCD2.WCPPP1&WANCName0=2_INTERNET_R_VID_637&Enable0=1&Protocol0=2&Name0=%E8%B7%AF%E7%94%B1%E5%99%A8&MinExtPort0=5700&MaxExtPort0=5700&InternalHost0=192.168.1.125&MinIntPort0=5700&MaxIntPort0=5700&Description0=&LeaseDuration0=0&PortMappCreator0=&MinRemoteHost0=0.0.0.0&MaxRemoteHost0=0.0.0.0&InternalMacHost0=e0%3Ab6%3A68%3A2e%3A2d%3A5b&MacEnable0=0&WANCName0=&ViewName1=IGD.WD1.WCD2.WCPPP1.FWPM2&WANCViewName1=IGD.WD1.WCD2.WCPPP1&WANCName1=2_INTERNET_R_VID_637&Enable1=1&Protocol1=2&Name1=route&MinExtPort1=23831&MaxExtPort1=23831&InternalHost1=192.168.1.125&MinIntPort1=23831&MaxIntPort1=23831&Description1=&LeaseDuration1=0&PortMappCreator1=&MinRemoteHost1=0.0.0.0&MaxRemoteHost1=0.0.0.0&InternalMacHost1=d8%3Ac8%3Ae9%3A1b%3A0a%3A79&MacEnable1=0&WANCName1=&ViewName2=IGD.WD1.WCD2.WCPPP1.FWPM3&WANCViewName2=IGD.WD1.WCD2.WCPPP1&WANCName2=2_INTERNET_R_VID_637&Enable2=0&Protocol2=2&Name2=%E8%BF%9C%E7%A8%8B&MinExtPort2=6565&MaxExtPort2=6565&InternalHost2=192.168.1.17&MinIntPort2=6565&MaxIntPort2=6565&Description2=&LeaseDuration2=0&PortMappCreator2=&MinRemoteHost2=0.0.0.0&MaxRemoteHost2=0.0.0.0&InternalMacHost2=c8%3A7f%3A54%3A70%3Aee%3Abc&MacEnable2=0&WANCName2=&ViewName3=IGD.WD1.WCD2.WCPPP1.FWPM4&WANCViewName3=IGD.WD1.WCD2.WCPPP1&WANCName3=2_INTERNET_R_VID_637&Enable3=1&Protocol3=0&Name3=tv&MinExtPort3=4567&MaxExtPort3=4567&InternalHost3=192.168.1.125&MinIntPort3=4567&MaxIntPort3=4567&Description3=&LeaseDuration3=0&PortMappCreator3=&MinRemoteHost3=0.0.0.0&MaxRemoteHost3=0.0.0.0&InternalMacHost3=00%3A00%3A00%3A00%3A00%3A00&MacEnable3=0&WANCName3=&ViewName4=IGD.WD1.WCD2.WCPPP1.FWPM6&WANCViewName4=IGD.WD1.WCD2.WCPPP1&WANCName4=2_INTERNET_R_VID_637&Enable4=1&Protocol4=0&Name4=panso&MinExtPort4=7123&MaxExtPort4=7123&InternalHost4=192.168.1.125&MinIntPort4=7123&MaxIntPort4=7123&Description4=&LeaseDuration4=0&PortMappCreator4=&MinRemoteHost4=0.0.0.0&MaxRemoteHost4=0.0.0.0&InternalMacHost4=00%3A00%3A00%3A00%3A00%3A00&MacEnable4=0&WANCName4=&ViewName5=IGD.WD1.WCD2.WCPPP1.FWPM7&WANCViewName5=IGD.WD1.WCD2.WCPPP1&WANCName5=2_INTERNET_R_VID_637&Enable5=1&Protocol5=0&Name5=frp&MinExtPort5=7001&MaxExtPort5=7001&InternalHost5=192.168.1.125&MinIntPort5=7001&MaxIntPort5=7001&Description5=&LeaseDuration5=0&PortMappCreator5=&MinRemoteHost5=0.0.0.0&MaxRemoteHost5=0.0.0.0&InternalMacHost5=00%3A00%3A00%3A00%3A00%3A00&MacEnable5=0&WANCName5=&ViewName6=IGD.WD1.WCD2.WCPPP1.FWPM8&WANCViewName6=IGD.WD1.WCD2.WCPPP1&WANCName6=2_INTERNET_R_VID_637&Enable6=1&Protocol6=0&Name6=frp_25000&MinExtPort6=25000&MaxExtPort6=25000&InternalHost6=192.168.1.125&MinIntPort6=25000&MaxIntPort6=25000&Description6=&LeaseDuration6=0&PortMappCreator6=&MinRemoteHost6=0.0.0.0&MaxRemoteHost6=0.0.0.0&InternalMacHost6=00%3A00%3A00%3A00%3A00%3A00&MacEnable6=0&WANCName6=&ViewName7=IGD.WD1.WCD2.WCPPP1.FWPM9&WANCViewName7=IGD.WD1.WCD2.WCPPP1&WANCName7=2_INTERNET_R_VID_637&Enable7=1&Protocol7=0&Name7=v2_33786&MinExtPort7=33786&MaxExtPort7=33786&InternalHost7=192.168.1.125&MinIntPort7=33786&MaxIntPort7=33786&Description7=&LeaseDuration7=0&PortMappCreator7=&MinRemoteHost7=0.0.0.0&MaxRemoteHost7=0.0.0.0&InternalMacHost7=00%3A00%3A00%3A00%3A00%3A00&MacEnable7=0&WANCName7=&ViewName8=IGD.WD1.WCD2.WCPPP1.FWPM10&WANCViewName8=IGD.WD1.WCD2.WCPPP1&WANCName8=2_INTERNET_R_VID_637&Enable8=1&Protocol8=2&Name8=ai&MinExtPort8=7138&MaxExtPort8=7138&InternalHost8=192.168.1.125&MinIntPort8=8317&MaxIntPort8=8317&Description8=&LeaseDuration8=0&PortMappCreator8=&MinRemoteHost8=0.0.0.0&MaxRemoteHost8=0.0.0.0&InternalMacHost8=00%3A00%3A00%3A00%3A00%3A00&MacEnable8=0&WANCName8=&ViewName9=IGD.WD1.WCD2.WCPPP1.FWPM11&WANCViewName9=IGD.WD1.WCD2.WCPPP1&WANCName9=2_INTERNET_R_VID_637&Enable9=1&Protocol9=2&Name9=clash&MinExtPort9=16412&MaxExtPort9=16412&InternalHost9=192.168.1.125&MinIntPort9=16412&MaxIntPort9=16412&Description9=&LeaseDuration9=0&PortMappCreator9=&MinRemoteHost9=0.0.0.0&MaxRemoteHost9=0.0.0.0&InternalMacHost9=00%3A00%3A00%3A00%3A00%3A00&MacEnable9=0&WANCName9=&_SESSION_TOKEN=8IPkBg7krYYsnHID77YNaDKo'
116
+ // 生成发送给接口的两个参数
117
+ const IF_ENCODE = encodeKey(myKey, myIv, pubKey);
118
+ const IF_ENCODEPARAM = encodePara(rawData, myKey, myIv);
119
+
120
+ console.log("Key:", myKey);
121
+ console.log("IV:", myIv);
122
+ console.log("\n--- 请提交以下参数 ---");
123
+ console.log("IF_ENCODE:", IF_ENCODE);
124
+ console.log("IF_ENCODEPARAM:", IF_ENCODEPARAM);