Compare commits

..

14 Commits

Author SHA1 Message Date
6d2366d929 更新readme 2024-09-19 12:27:57 +08:00
f10fe2843e 断线重连 2024-09-12 22:39:20 +08:00
bc6936def1 2 2024-08-12 16:03:35 +08:00
107dc62e40 add color 2024-08-12 16:00:55 +08:00
a8857e40d4 test 2024-08-12 15:38:58 +08:00
b27eceb18c test3 2024-08-10 20:43:16 +08:00
54c19ffe9c test 2024-08-10 20:41:34 +08:00
1f9557df61 test 2024-08-10 19:22:26 +08:00
56d28ad939 fix ipread 2024-08-10 17:59:58 +08:00
68b87a9956 add sort 2024-08-05 21:52:58 +08:00
be8a8fc2b5 fix bug 2024-08-05 21:36:45 +08:00
236e781d22 10 2024-08-05 21:31:39 +08:00
ebfc12e8b4 9 2024-08-05 21:27:53 +08:00
70ee170f58 8 2024-08-05 21:24:44 +08:00
9 changed files with 98 additions and 48 deletions

4
.gitignore vendored
View File

@@ -174,6 +174,4 @@ dist
# Finder (MacOS) folder config
.DS_Store
.prettierrc
package-lock.json
.prettierrc

View File

@@ -1,8 +1,9 @@
FROM oven/bun:latest
WORKDIR /usr/src/app
RUN mkdir -p /config
COPY ./config.json /config
COPY . .
RUN bun install --production
RUN bun install --frozen-lockfile --production
ENV NODE_ENV=production
EXPOSE 7000/tcp

View File

@@ -1,15 +1,23 @@
# netgate-switch
# ROS 网段切换器
To install dependencies:
基于 bun 运行的 RouterOS 网段切换器前/后端。局域网环境下经常使用网段划分不同用途、类型的设备,以便利用 DHCP 下发不同的网关、DNS、NTP 等信息。直接使用 ros 前端或者 winbox 进行修改是个好方法,然而不是所有设备都能方便地登入以及操作(如移动设备),同时对 ros 的完全访问可能带来额外的安全风险。本项目旨在使局域网中各种设备都能快速便捷切换所在网段。
# 使用方法
1.在 ROS 中创建一个可读写账户
2.准备两个网段,如 10.0.0.0/16、10.1.0.0/16。CRID 数字形式表达,仅支持/8 /16 /24。各设备主机号将被保留。
3.安装依赖:
```bash
bun install
```
To run:
4.运行:
```bash
bun run index.ts
```
This project was created using `bun init` in bun v1.1.18. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime.
5.填写网关、账密信息登入后即可运行

BIN
bun.lockb

Binary file not shown.

View File

@@ -2,6 +2,7 @@ services:
netgate-switch:
build: .
pull_policy: build
container_name: NetgateSwitch
ports:
- '7000:7000'
restart: unless-stopped

View File

@@ -1 +1,9 @@
{"port":7000,"login":false,"host":"","user":"","password":"","maincidr":"","proxycidr":""}
{
"port": 7000,
"login": false,
"host": "",
"user": "",
"password": "",
"maincidr": "",
"proxycidr": ""
}

View File

@@ -54,6 +54,14 @@
background-color: #dfdfdf;
}
.device {
background-color: #ffff00;
}
.online {
color: #00ff00;
}
.btn:hover {
background-color: #b9b9b9;
}
@@ -144,7 +152,9 @@
tb.append(trn);
for (let i in list) {
trn = document.createElement('tr');
trn.setAttribute('class', list[i].device === true ? 'device' : '');
td1 = document.createElement('td');
td1.setAttribute('class', list[i].status === 'bound' ? 'online' : '');
td2 = document.createElement('td');
td3 = document.createElement('td');
td4 = document.createElement('td');
@@ -158,7 +168,7 @@
btn2.setAttribute('cidrgroup', 'proxy');
btn2.setAttribute('deviceid', list[i].id);
btn2.append('切换至Proxy');
td1.append(list[i].host);
td1.append(list[i].comment === undefined ? list[i].host : list[i].comment);
td2.append(list[i].address);
td3.append(list[i].mac);
td4.append(btn1);

View File

@@ -4,7 +4,6 @@ import { RouterOSAPI } from 'node-routeros';
const path = '/config/config.json';
const cfgfile = Bun.file(path);
let cfg = await cfgfile.json();
console.log(cfg);
let api = new RouterOSAPI({
host: cfg.host,
@@ -12,9 +11,8 @@ let api = new RouterOSAPI({
password: cfg.password,
});
const maincidr = cfg.maincidr;
const proxycidr = cfg.proxycidr;
let maincidr = cfg.maincidr;
let proxycidr = cfg.proxycidr;
let haslogin = cfg.login;
type Device = {
id: string;
@@ -34,7 +32,7 @@ if (haslogin) {
const server = serve({
port: cfg.port,
async fetch(request) {
async fetch(request, server) {
const url = new URL(request.url);
if (url.pathname === '/') {
let file = haslogin
@@ -61,6 +59,8 @@ const server = serve({
data.main,
data.proxy
);
maincidr = data.main;
proxycidr = data.proxy;
console.log('配置文件已更新');
return new Response('登入成功');
} else {
@@ -71,7 +71,13 @@ const server = serve({
if (url.pathname === '/core/get/') {
if (!haslogin)
return new Response('ROS配置未设置', { status: 401 });
return new Response(JSON.stringify(await getDHCPList()));
const sockaddr = server.requestIP(request);
let ipinfo = sockaddr === null ? '' : sockaddr.address;
let ipaddr = ipinfo.split(':');
console.log(sockaddr);
return new Response(
JSON.stringify(await getDHCPList(ipaddr[ipaddr.length - 1]))
);
}
if (url.pathname === '/core/switch/') {
@@ -99,6 +105,9 @@ const server = serve({
if (group !== 'main' && group !== 'proxy') {
return new Response('group错误', { status: 401 });
}
if (maincidr === '' || proxycidr === '') {
return new Response('配置文件错误', { status: 401 });
}
if (await switchNetgate(id, addr, group)) {
return new Response('切换成功');
} else {
@@ -128,18 +137,38 @@ async function connectAPI() {
}
}
async function getDHCPList() {
const result = await api.write('/ip/dhcp-server/lease/print');
async function getDHCPList(addr: string | null) {
list = [];
for (let eq in result) {
list.push({
id: result[eq]['.id'],
address: result[eq]['address'],
mac: result[eq]['mac-address'],
status: result[eq]['status'],
host: result[eq]['host-name'],
comment: result[eq]['comment'],
try {
const result = await api.write('/ip/dhcp-server/lease/print');
for (let eq in result) {
let format = {
id: result[eq]['.id'],
address: result[eq]['address'],
mac: result[eq]['mac-address'],
status: result[eq]['status'],
host: result[eq]['host-name'],
comment: result[eq]['comment'],
device: false,
};
if (addr !== null || addr !== undefined || addr !== '') {
if (addr === format.address) {
format.device = true;
list.unshift(format);
} else {
list.push(format);
}
continue;
}
list.push(format);
}
} catch (e) {
api = new RouterOSAPI({
host: cfg.host,
user: cfg.user,
password: cfg.password,
});
api.connect();
}
return list;
}
@@ -150,11 +179,7 @@ async function switchNetgate(id: string, addr: string, group: string) {
let targetcidr = (group === 'proxy' ? proxycidr : maincidr)
.split('/')[0]
.split('.');
console.log(proxycidr);
console.log(maincidr);
console.log(targetcidr);
let address = addr.split('.');
console.log(address);
let num = 2;
if (mask == 16) {
num = 1;
@@ -192,7 +217,7 @@ async function writeConfig(
cfg.proxycidr = pcidr;
haslogin = true;
await Bun.write('/config/config.json', JSON.stringify(cfg));
await Bun.write(path, JSON.stringify(cfg));
}
async function cleanConfig() {
@@ -203,5 +228,5 @@ async function cleanConfig() {
cfg.password = '';
cfg.maincidr = '';
cfg.proxycidr = '';
await Bun.write('/config/config.json', JSON.stringify(cfg));
await Bun.write(path, JSON.stringify(cfg));
}

View File

@@ -1,18 +1,17 @@
{
"name": "netgate-switch",
"module": "index.ts",
"devDependencies": {
"@types/bun": "latest"
},
"peerDependencies": {
"typescript": "^5.0.0"
},
"scripts": {
"dev": "bun run index.ts"
},
"type": "module",
"dependencies": {
"netgate-switch": "file:",
"node-routeros": "^1.6.9"
}
"name": "netgate-switch",
"module": "index.ts",
"devDependencies": {
"@types/bun": "latest"
},
"peerDependencies": {
"typescript": "^5.0.0"
},
"scripts": {
"dev": "bun run index.ts"
},
"type": "module",
"dependencies": {
"node-routeros": "^1.6.9"
}
}