@chenpu17/tcpmapping 2.0.0 → 2.1.0

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/README.md CHANGED
@@ -1,103 +1,185 @@
1
- # TCP转发服务器
1
+ # TcpMapping
2
2
 
3
- 一个功能强大、安全可靠的TCP端口转发服务器,支持多端口映射、WebUI管理界面和实时连接监控。
3
+ TCP port forwarding server with WebUI management and real-time connection monitoring.
4
4
 
5
- ## 功能特性
5
+ TCP端口转发服务器,支持WebUI管理界面和实时连接监控。
6
6
 
7
- ### 核心功能
8
- - **TCP协议端口转发** - 将TCP请求转发到后端服务器
9
- - **多端口映射配置** - 同时支持多个端口转发规则
10
- - **动态配置管理** - 通过WebUI实时添加/删除/启动/停止端口映射
11
- - **连接监控** - 实时显示每个映射的连接数和流量统计
7
+ ---
12
8
 
13
- ### WebUI管理界面
14
- - 现代化响应式Web界面
15
- - 实时系统状态监控(映射数、连接数、运行时间)
16
- - 每个端口映射的连接数和流量统计
17
- - 映射的启动/停止控制
9
+ ## Features | 功能特性
18
10
 
19
- ### 安全特性
20
- - 强密码策略(8字符+大小写+数字)
21
- - 登录失败保护(5次失败锁定30分钟)
22
- - 会话管理(24小时自动超时)
23
- - bcrypt 12轮密码哈希加密
24
- - 自动生成的Session Secret
11
+ - **TCP Port Forwarding** - Forward TCP traffic to backend servers | TCP端口转发
12
+ - **Multiple Mappings** - Manage multiple forwarding rules simultaneously | 多端口映射
13
+ - **WebUI Management** - Modern web interface for real-time monitoring | WebUI管理界面
14
+ - **Connection Monitoring** - Real-time connection count and traffic statistics | 实时连接监控
15
+ - **Secure Authentication** - bcrypt password hashing, login protection | 安全认证
25
16
 
26
- ## 快速开始
17
+ ---
18
+
19
+ ## Installation | 安装
20
+
21
+ ### NPM Global Install (Recommended) | NPM全局安装(推荐)
27
22
 
28
- ### 安装
29
23
  ```bash
30
- # 安装依赖
31
- npm install
24
+ npm install -g @chenpu17/tcpmapping
32
25
 
33
- # 设置管理员密码
34
- npm run setup-password
26
+ tcpmapping setup-password # Set admin password | 设置管理员密码
27
+ tcpmapping init # Create config file | 创建配置文件
28
+ tcpmapping start # Start server | 启动服务
29
+ ```
30
+
31
+ ### Local Install | 本地安装
35
32
 
36
- # 启动服务器
33
+ ```bash
34
+ git clone https://github.com/chenpu17/TcpMapping.git
35
+ cd TcpMapping
36
+ npm install
37
+ npm run setup-password
37
38
  npm start
38
39
  ```
39
40
 
40
- ### 访问
41
- 启动后访问 **http://localhost:9999** 进入管理界面。
41
+ ---
42
+
43
+ ## CLI Commands | CLI命令
44
+
45
+ | Command | Description |
46
+ |---------|-------------|
47
+ | `tcpmapping start` | Start server in background | 后台启动服务 |
48
+ | `tcpmapping stop` | Stop server | 停止服务 |
49
+ | `tcpmapping restart` | Restart server | 重启服务 |
50
+ | `tcpmapping status` | Show status and config paths | 查看状态和配置路径 |
51
+ | `tcpmapping logs` | Show recent logs | 查看最近日志 |
52
+ | `tcpmapping logs -f` | Follow logs in real-time | 实时跟踪日志 |
53
+ | `tcpmapping setup-password` | Set admin password | 设置管理员密码 |
54
+ | `tcpmapping init` | Create config file | 创建配置文件 |
55
+
56
+ ---
42
57
 
43
- ## 配置说明
58
+ ## WebUI
44
59
 
45
- 编辑 `config.json` 配置端口映射:
60
+ After starting, visit **http://localhost:9999**
61
+
62
+ 启动后访问 **http://localhost:9999**
63
+
64
+ Default username | 默认用户名: `admin`
65
+
66
+ ---
67
+
68
+ ## Configuration | 配置
69
+
70
+ Config file location (priority order) | 配置文件位置(优先级):
71
+ 1. `./config.json` - Current directory | 当前目录
72
+ 2. `~/.tcpmapping/config.json` - User data directory | 用户数据目录
73
+
74
+ ### Example | 示例
46
75
 
47
76
  ```json
48
77
  {
49
78
  "mappings": [
50
79
  {
51
- "name": "服务名称",
80
+ "name": "web-server",
52
81
  "listen": { "host": "0.0.0.0", "port": 8080 },
53
82
  "target": { "host": "192.168.1.100", "port": 3000 }
83
+ },
84
+ {
85
+ "name": "database",
86
+ "listen": { "host": "127.0.0.1", "port": 3307 },
87
+ "target": { "host": "db.example.com", "port": 3306 }
54
88
  }
55
89
  ],
56
- "webui": { "enabled": true, "port": 9999, "host": "0.0.0.0" },
57
- "logging": { "enabled": true, "level": "info" }
90
+ "webui": { "port": 9999 },
91
+ "logging": { "level": "info" }
58
92
  }
59
93
  ```
60
94
 
61
- ## 项目结构
95
+ ### Config Options | 配置项
96
+
97
+ | Option | Description |
98
+ |--------|-------------|
99
+ | `mappings[].name` | Mapping name | 映射名称 |
100
+ | `mappings[].listen.host` | Listen address (0.0.0.0 for all) | 监听地址 |
101
+ | `mappings[].listen.port` | Listen port | 监听端口 |
102
+ | `mappings[].target.host` | Target host IP or domain | 目标主机 |
103
+ | `mappings[].target.port` | Target port | 目标端口 |
104
+ | `webui.port` | WebUI port (default: 9999) | WebUI端口 |
105
+ | `logging.level` | Log level: debug/info/warn/error | 日志级别 |
106
+
107
+ ---
108
+
109
+ ## Data Persistence | 数据持久化
110
+
111
+ User configuration is stored in `~/.tcpmapping/`:
112
+
113
+ 用户配置存储在 `~/.tcpmapping/` 目录:
62
114
 
115
+ - `config.json` - Port mapping configuration | 端口映射配置
116
+ - `auth-config.json` - Authentication configuration | 认证配置
117
+ - `tcpmapping.log` - Log file | 日志文件
118
+ - `tcpmapping.pid` - PID file | PID文件
119
+
120
+ **Upgrading will NOT overwrite your configuration.**
121
+
122
+ **升级不会覆盖你的配置文件。**
123
+
124
+ ---
125
+
126
+ ## Security | 安全特性
127
+
128
+ - **Strong Password Policy** - 8+ chars, uppercase, lowercase, numbers | 强密码策略
129
+ - **Login Protection** - Lock after 5 failed attempts for 30 minutes | 登录保护
130
+ - **Session Timeout** - 24 hours auto expiration | 会话超时
131
+ - **Password Encryption** - bcrypt with 12 rounds | bcrypt加密
132
+
133
+ ---
134
+
135
+ ## API
136
+
137
+ See [docs/API.md](docs/API.md) for API documentation.
138
+
139
+ 详细API文档请参阅 [docs/API.md](docs/API.md)
140
+
141
+ ### Quick Reference | 快速参考
142
+
143
+ ```bash
144
+ # Health check (no auth) | 健康检查
145
+ curl http://localhost:9999/api/health
146
+
147
+ # Login | 登录
148
+ curl -X POST http://localhost:9999/api/login \
149
+ -H "Content-Type: application/json" \
150
+ -d '{"username":"admin","password":"YourPassword"}' \
151
+ -c cookies.txt
152
+
153
+ # Get mappings | 获取映射列表
154
+ curl http://localhost:9999/api/mappings -b cookies.txt
63
155
  ```
64
- ├── server.js # 主服务器
65
- ├── config.json # 端口映射配置
66
- ├── auth-config.json # 认证配置(敏感)
67
- ├── setup-password.js # 密码设置工具
68
- ├── package.json # 项目配置
69
- ├── .gitignore # Git忽略规则
70
- ├── public/ # Web界面
71
- │ ├── login.html # 登录页面
72
- │ └── dashboard.html # 管理面板
73
- └── docs/ # 文档目录
74
- ├── API.md # API接口文档
75
- ├── 功能总结.md # 功能清单
76
- └── 安全配置说明.md # 安全指南
156
+
157
+ ---
158
+
159
+ ## FAQ | 常见问题
160
+
161
+ ### Forgot password? | 忘记密码?
162
+
163
+ ```bash
164
+ tcpmapping setup-password
165
+ # or | 或
166
+ npm run reset-password
77
167
  ```
78
168
 
79
- ## API接口
169
+ ### Check if running? | 检查运行状态?
80
170
 
81
- 详细API文档请参阅 [docs/API.md](docs/API.md)
171
+ ```bash
172
+ tcpmapping status
173
+ ```
174
+
175
+ ### Port already in use? | 端口被占用?
82
176
 
83
- 主要接口:
84
- - `GET /api/health` - 健康检查(无需认证)
85
- - `POST /api/login` - 登录
86
- - `GET /api/mappings` - 获取映射列表(含连接数统计)
87
- - `POST /api/mappings` - 添加映射
88
- - `PUT /api/mappings/:id` - 更新映射
89
- - `DELETE /api/mappings/:id` - 删除映射
90
- - `POST /api/mappings/:id/start` - 启动映射
91
- - `POST /api/mappings/:id/stop` - 停止映射
92
- - `GET /api/connections` - 获取连接状态
93
- - `GET /api/status` - 获取系统状态
177
+ Edit `webui.port` or `mappings[].listen.port` in config.json.
94
178
 
95
- ## 技术栈
179
+ 修改 config.json 中的 `webui.port` 或 `mappings[].listen.port`。
96
180
 
97
- - **后端**: Node.js, Express.js, bcryptjs
98
- - **前端**: 原生HTML/CSS/JavaScript
99
- - **安全**: bcrypt密码哈希, Session管理
181
+ ---
100
182
 
101
- ## 许可证
183
+ ## License | 许可证
102
184
 
103
- MIT License
185
+ MIT License
package/bin/tcpmapping.js CHANGED
@@ -6,8 +6,9 @@ const fs = require('fs');
6
6
  const os = require('os');
7
7
 
8
8
  const APP_NAME = 'tcpmapping';
9
- const PID_FILE = path.join(os.tmpdir(), 'tcpmapping.pid');
10
- const LOG_FILE = path.join(os.tmpdir(), 'tcpmapping.log');
9
+ const DATA_DIR = path.join(os.homedir(), '.tcpmapping');
10
+ const PID_FILE = path.join(DATA_DIR, 'tcpmapping.pid');
11
+ const LOG_FILE = path.join(DATA_DIR, 'tcpmapping.log');
11
12
  const SERVER_FILE = path.join(__dirname, '..', 'server.js');
12
13
  const SETUP_PASSWORD_FILE = path.join(__dirname, '..', 'setup-password.js');
13
14
 
@@ -21,11 +22,52 @@ const colors = {
21
22
  red: (text) => `\x1b[31m${text}\x1b[0m`,
22
23
  yellow: (text) => `\x1b[33m${text}\x1b[0m`,
23
24
  blue: (text) => `\x1b[34m${text}\x1b[0m`,
24
- cyan: (text) => `\x1b[36m${text}\x1b[0m`
25
+ cyan: (text) => `\x1b[36m${text}\x1b[0m`,
26
+ gray: (text) => `\x1b[90m${text}\x1b[0m`
25
27
  };
26
28
 
29
+ // 确保数据目录存在
30
+ function ensureDataDir() {
31
+ if (!fs.existsSync(DATA_DIR)) {
32
+ fs.mkdirSync(DATA_DIR, { recursive: true });
33
+ }
34
+ }
35
+
36
+ // 获取配置文件路径(按优先级)
37
+ function getConfigPath() {
38
+ // 优先级1: 当前工作目录
39
+ const cwdPath = path.join(process.cwd(), 'config.json');
40
+ if (fs.existsSync(cwdPath)) {
41
+ return cwdPath;
42
+ }
43
+
44
+ // 优先级2: 用户数据目录
45
+ const dataPath = path.join(DATA_DIR, 'config.json');
46
+ if (fs.existsSync(dataPath)) {
47
+ return dataPath;
48
+ }
49
+
50
+ return null;
51
+ }
52
+
53
+ // 获取认证配置文件路径
54
+ function getAuthConfigPath() {
55
+ const cwdPath = path.join(process.cwd(), 'auth-config.json');
56
+ if (fs.existsSync(cwdPath)) {
57
+ return cwdPath;
58
+ }
59
+
60
+ const dataPath = path.join(DATA_DIR, 'auth-config.json');
61
+ if (fs.existsSync(dataPath)) {
62
+ return dataPath;
63
+ }
64
+
65
+ return null;
66
+ }
67
+
27
68
  // 检查进程是否运行
28
69
  function isRunning() {
70
+ ensureDataDir();
29
71
  if (!fs.existsSync(PID_FILE)) {
30
72
  return false;
31
73
  }
@@ -50,6 +92,17 @@ function start() {
50
92
  return;
51
93
  }
52
94
 
95
+ // 检查是否已初始化
96
+ const configPath = getConfigPath();
97
+ const authPath = getAuthConfigPath();
98
+
99
+ if (!authPath) {
100
+ console.log(colors.yellow('未设置管理员密码,请先运行:'));
101
+ console.log(colors.cyan(' tcpmapping setup-password'));
102
+ return;
103
+ }
104
+
105
+ ensureDataDir();
53
106
  console.log(colors.blue(`Starting ${APP_NAME}...`));
54
107
 
55
108
  const out = fs.openSync(LOG_FILE, 'a');
@@ -58,7 +111,7 @@ function start() {
58
111
  const child = spawn('node', [SERVER_FILE], {
59
112
  detached: true,
60
113
  stdio: ['ignore', out, err],
61
- cwd: path.dirname(SERVER_FILE)
114
+ cwd: process.cwd() // 使用当前目录,以便server可以找到当前目录的config
62
115
  });
63
116
 
64
117
  fs.writeFileSync(PID_FILE, child.pid.toString());
@@ -66,7 +119,10 @@ function start() {
66
119
 
67
120
  console.log(colors.green(`${APP_NAME} started successfully (PID: ${child.pid})`));
68
121
  console.log(colors.cyan(`WebUI: http://localhost:9999`));
69
- console.log(colors.cyan(`Log file: ${LOG_FILE}`));
122
+ console.log(colors.gray(`Log file: ${LOG_FILE}`));
123
+ if (configPath) {
124
+ console.log(colors.gray(`Config: ${configPath}`));
125
+ }
70
126
  }
71
127
 
72
128
  // 停止服务
@@ -126,8 +182,14 @@ function restart() {
126
182
  // 查看状态
127
183
  function status() {
128
184
  const pid = isRunning();
185
+ const configPath = getConfigPath();
186
+ const authPath = getAuthConfigPath();
187
+
188
+ console.log(colors.cyan('=== TcpMapping Status ===\n'));
189
+
190
+ // 服务状态
129
191
  if (pid) {
130
- console.log(colors.green(`${APP_NAME} is running (PID: ${pid})`));
192
+ console.log(colors.green(`Service: Running (PID: ${pid})`));
131
193
 
132
194
  // 尝试获取健康状态
133
195
  try {
@@ -138,23 +200,36 @@ function status() {
138
200
  res.on('end', () => {
139
201
  try {
140
202
  const health = JSON.parse(data);
141
- console.log(colors.cyan(` Status: ${health.status}`));
142
- console.log(colors.cyan(` Uptime: ${Math.floor(health.uptime / 60)} minutes`));
143
- console.log(colors.cyan(` Active Mappings: ${health.activeMappings}`));
144
- console.log(colors.cyan(` Active Connections: ${health.activeConnections}`));
203
+ console.log(` Uptime: ${Math.floor(health.uptime / 60)} minutes`);
204
+ console.log(` Active Mappings: ${health.activeMappings}`);
205
+ console.log(` Active Connections: ${health.activeConnections}`);
145
206
  } catch (e) {}
207
+ showPaths();
146
208
  });
147
209
  });
148
- req.on('error', () => {});
149
- req.on('timeout', () => req.destroy());
150
- } catch (e) {}
210
+ req.on('error', () => showPaths());
211
+ req.on('timeout', () => { req.destroy(); showPaths(); });
212
+ } catch (e) {
213
+ showPaths();
214
+ }
151
215
  } else {
152
- console.log(colors.red(`${APP_NAME} is not running`));
216
+ console.log(colors.red('Service: Stopped'));
217
+ showPaths();
218
+ }
219
+
220
+ function showPaths() {
221
+ console.log('');
222
+ console.log(colors.cyan('=== Configuration ===\n'));
223
+ console.log(`Data Dir: ${DATA_DIR}`);
224
+ console.log(`Config: ${configPath || colors.yellow('Not found (run: tcpmapping init)')}`);
225
+ console.log(`Auth: ${authPath || colors.yellow('Not found (run: tcpmapping setup-password)')}`);
226
+ console.log(`Log: ${LOG_FILE}`);
153
227
  }
154
228
  }
155
229
 
156
230
  // 查看日志
157
231
  function logs(follow = false) {
232
+ ensureDataDir();
158
233
  if (!fs.existsSync(LOG_FILE)) {
159
234
  console.log(colors.yellow('No log file found'));
160
235
  return;
@@ -176,10 +251,15 @@ function logs(follow = false) {
176
251
 
177
252
  // 设置密码
178
253
  function setupPassword() {
254
+ ensureDataDir();
179
255
  console.log(colors.blue('Setting up password...'));
256
+ console.log(colors.gray(`Config will be saved to: ${DATA_DIR}`));
257
+ console.log('');
258
+
180
259
  const child = spawn('node', [SETUP_PASSWORD_FILE], {
181
260
  stdio: 'inherit',
182
- cwd: path.dirname(SETUP_PASSWORD_FILE)
261
+ cwd: DATA_DIR, // 在数据目录运行,使auth-config.json保存到数据目录
262
+ env: { ...process.env, TCPMAPPING_DATA_DIR: DATA_DIR }
183
263
  });
184
264
 
185
265
  child.on('exit', (code) => {
@@ -189,29 +269,41 @@ function setupPassword() {
189
269
 
190
270
  // 初始化配置
191
271
  function init() {
192
- const configDir = process.cwd();
193
- const configFile = path.join(configDir, 'config.json');
272
+ ensureDataDir();
273
+
274
+ // 检查当前目录和数据目录是否已有配置
275
+ const cwdConfig = path.join(process.cwd(), 'config.json');
276
+ const dataConfig = path.join(DATA_DIR, 'config.json');
277
+
278
+ if (fs.existsSync(cwdConfig)) {
279
+ console.log(colors.yellow(`config.json already exists in current directory`));
280
+ console.log(colors.gray(` ${cwdConfig}`));
281
+ return;
282
+ }
194
283
 
195
- if (fs.existsSync(configFile)) {
196
- console.log(colors.yellow('config.json already exists'));
284
+ if (fs.existsSync(dataConfig)) {
285
+ console.log(colors.yellow(`config.json already exists in data directory`));
286
+ console.log(colors.gray(` ${dataConfig}`));
287
+ console.log('');
288
+ console.log('To create a local config, copy it to current directory:');
289
+ console.log(colors.cyan(` cp ${dataConfig} ./config.json`));
197
290
  return;
198
291
  }
199
292
 
200
293
  const defaultConfig = {
201
- mappings: [
202
- {
203
- name: "Example",
204
- listen: { host: "0.0.0.0", port: 8080 },
205
- target: { host: "127.0.0.1", port: 3000 }
206
- }
207
- ],
208
- webui: { enabled: true, port: 9999, host: "0.0.0.0" },
209
- logging: { enabled: true, level: "info" }
294
+ mappings: [],
295
+ webui: { port: 9999 },
296
+ logging: { level: "info" }
210
297
  };
211
298
 
212
- fs.writeFileSync(configFile, JSON.stringify(defaultConfig, null, 2));
299
+ // 保存到数据目录
300
+ fs.writeFileSync(dataConfig, JSON.stringify(defaultConfig, null, 2));
213
301
  console.log(colors.green('Created config.json'));
214
- console.log(colors.cyan('Edit config.json to configure your port mappings'));
302
+ console.log(colors.gray(` ${dataConfig}`));
303
+ console.log('');
304
+ console.log('Edit the config file to add your port mappings.');
305
+ console.log('Or copy it to current directory for project-specific config:');
306
+ console.log(colors.cyan(` cp ${dataConfig} ./config.json`));
215
307
  }
216
308
 
217
309
  // 显示版本
@@ -232,7 +324,7 @@ ${colors.yellow('Commands:')}
232
324
  ${colors.green('start')} Start the server in background
233
325
  ${colors.green('stop')} Stop the server
234
326
  ${colors.green('restart')} Restart the server
235
- ${colors.green('status')} Show server status
327
+ ${colors.green('status')} Show server status and config paths
236
328
  ${colors.green('logs')} Show recent logs
237
329
  ${colors.green('logs -f')} Follow logs in real-time
238
330
  ${colors.green('setup-password')} Set up admin password
@@ -240,10 +332,15 @@ ${colors.yellow('Commands:')}
240
332
  ${colors.green('version')} Show version
241
333
  ${colors.green('help')} Show this help message
242
334
 
335
+ ${colors.yellow('Config Paths (priority order):')}
336
+ 1. ./config.json (current directory - project config)
337
+ 2. ~/.tcpmapping/ (user data directory - global config)
338
+
243
339
  ${colors.yellow('Examples:')}
244
- tcpmapping start # Start server
245
- tcpmapping status # Check if server is running
246
- tcpmapping logs -f # Follow logs
340
+ tcpmapping init # Create config file
341
+ tcpmapping setup-password # Set admin password
342
+ tcpmapping start # Start server
343
+ tcpmapping status # Check status and config paths
247
344
 
248
345
  ${colors.yellow('WebUI:')}
249
346
  After starting, visit http://localhost:9999
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chenpu17/tcpmapping",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "TCP端口转发服务器,支持多端口映射、WebUI管理界面和实时连接监控",
5
5
  "main": "server.js",
6
6
  "bin": {
@@ -16,8 +16,7 @@
16
16
  "bin/",
17
17
  "public/",
18
18
  "server.js",
19
- "setup-password.js",
20
- "config.json"
19
+ "setup-password.js"
21
20
  ],
22
21
  "keywords": [
23
22
  "tcp",