Compare commits
16 Commits
d67c94bcdc
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 6d2366d929 | |||
| f10fe2843e | |||
| bc6936def1 | |||
| 107dc62e40 | |||
| a8857e40d4 | |||
| b27eceb18c | |||
| 54c19ffe9c | |||
| 1f9557df61 | |||
| 56d28ad939 | |||
| 68b87a9956 | |||
| be8a8fc2b5 | |||
| 236e781d22 | |||
| ebfc12e8b4 | |||
| 70ee170f58 | |||
| 71c0f225d0 | |||
| a32e2db264 |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -174,6 +174,4 @@ dist
|
|||||||
# Finder (MacOS) folder config
|
# Finder (MacOS) folder config
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
.prettierrc
|
.prettierrc
|
||||||
|
|
||||||
package-lock.json
|
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
FROM oven/bun:1
|
FROM oven/bun:latest
|
||||||
WORKDIR /usr/src/app
|
WORKDIR /usr/src/app
|
||||||
COPY . .
|
RUN mkdir -p /config
|
||||||
COPY ./config.json /config
|
COPY ./config.json /config
|
||||||
|
COPY . .
|
||||||
RUN bun install --frozen-lockfile --production
|
RUN bun install --frozen-lockfile --production
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
|
|
||||||
EXPOSE 7000/tcp
|
EXPOSE 7000/tcp
|
||||||
VOLUME [ "/config"]
|
VOLUME [ "/config"]
|
||||||
ENTRYPOINT [ "bun", "run", "index.ts" ]
|
ENTRYPOINT [ "bun", "run", "index.ts" ]
|
||||||
16
README.md
16
README.md
@@ -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
|
```bash
|
||||||
bun install
|
bun install
|
||||||
```
|
```
|
||||||
|
|
||||||
To run:
|
4.运行:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bun run index.ts
|
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.填写网关、账密信息登入后即可运行
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ services:
|
|||||||
netgate-switch:
|
netgate-switch:
|
||||||
build: .
|
build: .
|
||||||
pull_policy: build
|
pull_policy: build
|
||||||
|
container_name: NetgateSwitch
|
||||||
ports:
|
ports:
|
||||||
- '7000:7000'
|
- '7000:7000'
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|||||||
10
config.json
10
config.json
@@ -1 +1,9 @@
|
|||||||
{"port":7000,"login":false,"host":"","user":"","password":"","maincidr":"","proxycidr":""}
|
{
|
||||||
|
"port": 7000,
|
||||||
|
"login": false,
|
||||||
|
"host": "",
|
||||||
|
"user": "",
|
||||||
|
"password": "",
|
||||||
|
"maincidr": "",
|
||||||
|
"proxycidr": ""
|
||||||
|
}
|
||||||
|
|||||||
12
index.html
12
index.html
@@ -54,6 +54,14 @@
|
|||||||
background-color: #dfdfdf;
|
background-color: #dfdfdf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.device {
|
||||||
|
background-color: #ffff00;
|
||||||
|
}
|
||||||
|
|
||||||
|
.online {
|
||||||
|
color: #00ff00;
|
||||||
|
}
|
||||||
|
|
||||||
.btn:hover {
|
.btn:hover {
|
||||||
background-color: #b9b9b9;
|
background-color: #b9b9b9;
|
||||||
}
|
}
|
||||||
@@ -144,7 +152,9 @@
|
|||||||
tb.append(trn);
|
tb.append(trn);
|
||||||
for (let i in list) {
|
for (let i in list) {
|
||||||
trn = document.createElement('tr');
|
trn = document.createElement('tr');
|
||||||
|
trn.setAttribute('class', list[i].device === true ? 'device' : '');
|
||||||
td1 = document.createElement('td');
|
td1 = document.createElement('td');
|
||||||
|
td1.setAttribute('class', list[i].status === 'bound' ? 'online' : '');
|
||||||
td2 = document.createElement('td');
|
td2 = document.createElement('td');
|
||||||
td3 = document.createElement('td');
|
td3 = document.createElement('td');
|
||||||
td4 = document.createElement('td');
|
td4 = document.createElement('td');
|
||||||
@@ -158,7 +168,7 @@
|
|||||||
btn2.setAttribute('cidrgroup', 'proxy');
|
btn2.setAttribute('cidrgroup', 'proxy');
|
||||||
btn2.setAttribute('deviceid', list[i].id);
|
btn2.setAttribute('deviceid', list[i].id);
|
||||||
btn2.append('切换至Proxy');
|
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);
|
td2.append(list[i].address);
|
||||||
td3.append(list[i].mac);
|
td3.append(list[i].mac);
|
||||||
td4.append(btn1);
|
td4.append(btn1);
|
||||||
|
|||||||
69
index.ts
69
index.ts
@@ -4,7 +4,6 @@ import { RouterOSAPI } from 'node-routeros';
|
|||||||
const path = '/config/config.json';
|
const path = '/config/config.json';
|
||||||
const cfgfile = Bun.file(path);
|
const cfgfile = Bun.file(path);
|
||||||
let cfg = await cfgfile.json();
|
let cfg = await cfgfile.json();
|
||||||
console.log(cfg);
|
|
||||||
|
|
||||||
let api = new RouterOSAPI({
|
let api = new RouterOSAPI({
|
||||||
host: cfg.host,
|
host: cfg.host,
|
||||||
@@ -12,9 +11,8 @@ let api = new RouterOSAPI({
|
|||||||
password: cfg.password,
|
password: cfg.password,
|
||||||
});
|
});
|
||||||
|
|
||||||
const maincidr = cfg.maincidr;
|
let maincidr = cfg.maincidr;
|
||||||
const proxycidr = cfg.proxycidr;
|
let proxycidr = cfg.proxycidr;
|
||||||
|
|
||||||
let haslogin = cfg.login;
|
let haslogin = cfg.login;
|
||||||
type Device = {
|
type Device = {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -34,7 +32,7 @@ if (haslogin) {
|
|||||||
|
|
||||||
const server = serve({
|
const server = serve({
|
||||||
port: cfg.port,
|
port: cfg.port,
|
||||||
async fetch(request) {
|
async fetch(request, server) {
|
||||||
const url = new URL(request.url);
|
const url = new URL(request.url);
|
||||||
if (url.pathname === '/') {
|
if (url.pathname === '/') {
|
||||||
let file = haslogin
|
let file = haslogin
|
||||||
@@ -61,6 +59,8 @@ const server = serve({
|
|||||||
data.main,
|
data.main,
|
||||||
data.proxy
|
data.proxy
|
||||||
);
|
);
|
||||||
|
maincidr = data.main;
|
||||||
|
proxycidr = data.proxy;
|
||||||
console.log('配置文件已更新');
|
console.log('配置文件已更新');
|
||||||
return new Response('登入成功');
|
return new Response('登入成功');
|
||||||
} else {
|
} else {
|
||||||
@@ -71,7 +71,13 @@ const server = serve({
|
|||||||
if (url.pathname === '/core/get/') {
|
if (url.pathname === '/core/get/') {
|
||||||
if (!haslogin)
|
if (!haslogin)
|
||||||
return new Response('ROS配置未设置', { status: 401 });
|
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/') {
|
if (url.pathname === '/core/switch/') {
|
||||||
@@ -99,6 +105,9 @@ const server = serve({
|
|||||||
if (group !== 'main' && group !== 'proxy') {
|
if (group !== 'main' && group !== 'proxy') {
|
||||||
return new Response('group错误', { status: 401 });
|
return new Response('group错误', { status: 401 });
|
||||||
}
|
}
|
||||||
|
if (maincidr === '' || proxycidr === '') {
|
||||||
|
return new Response('配置文件错误', { status: 401 });
|
||||||
|
}
|
||||||
if (await switchNetgate(id, addr, group)) {
|
if (await switchNetgate(id, addr, group)) {
|
||||||
return new Response('切换成功');
|
return new Response('切换成功');
|
||||||
} else {
|
} else {
|
||||||
@@ -128,18 +137,38 @@ async function connectAPI() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getDHCPList() {
|
async function getDHCPList(addr: string | null) {
|
||||||
const result = await api.write('/ip/dhcp-server/lease/print');
|
|
||||||
list = [];
|
list = [];
|
||||||
for (let eq in result) {
|
try {
|
||||||
list.push({
|
const result = await api.write('/ip/dhcp-server/lease/print');
|
||||||
id: result[eq]['.id'],
|
for (let eq in result) {
|
||||||
address: result[eq]['address'],
|
let format = {
|
||||||
mac: result[eq]['mac-address'],
|
id: result[eq]['.id'],
|
||||||
status: result[eq]['status'],
|
address: result[eq]['address'],
|
||||||
host: result[eq]['host-name'],
|
mac: result[eq]['mac-address'],
|
||||||
comment: result[eq]['comment'],
|
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;
|
return list;
|
||||||
}
|
}
|
||||||
@@ -150,11 +179,7 @@ async function switchNetgate(id: string, addr: string, group: string) {
|
|||||||
let targetcidr = (group === 'proxy' ? proxycidr : maincidr)
|
let targetcidr = (group === 'proxy' ? proxycidr : maincidr)
|
||||||
.split('/')[0]
|
.split('/')[0]
|
||||||
.split('.');
|
.split('.');
|
||||||
console.log(proxycidr);
|
|
||||||
console.log(maincidr);
|
|
||||||
console.log(targetcidr);
|
|
||||||
let address = addr.split('.');
|
let address = addr.split('.');
|
||||||
console.log(address);
|
|
||||||
let num = 2;
|
let num = 2;
|
||||||
if (mask == 16) {
|
if (mask == 16) {
|
||||||
num = 1;
|
num = 1;
|
||||||
@@ -192,7 +217,7 @@ async function writeConfig(
|
|||||||
cfg.proxycidr = pcidr;
|
cfg.proxycidr = pcidr;
|
||||||
|
|
||||||
haslogin = true;
|
haslogin = true;
|
||||||
await Bun.write('/config/config.json', JSON.stringify(cfg));
|
await Bun.write(path, JSON.stringify(cfg));
|
||||||
}
|
}
|
||||||
|
|
||||||
async function cleanConfig() {
|
async function cleanConfig() {
|
||||||
@@ -203,5 +228,5 @@ async function cleanConfig() {
|
|||||||
cfg.password = '';
|
cfg.password = '';
|
||||||
cfg.maincidr = '';
|
cfg.maincidr = '';
|
||||||
cfg.proxycidr = '';
|
cfg.proxycidr = '';
|
||||||
await Bun.write('/config/config.json', JSON.stringify(cfg));
|
await Bun.write(path, JSON.stringify(cfg));
|
||||||
}
|
}
|
||||||
|
|||||||
31
package.json
31
package.json
@@ -1,18 +1,17 @@
|
|||||||
{
|
{
|
||||||
"name": "netgate-switch",
|
"name": "netgate-switch",
|
||||||
"module": "index.ts",
|
"module": "index.ts",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bun": "latest"
|
"@types/bun": "latest"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"typescript": "^5.0.0"
|
"typescript": "^5.0.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "bun run index.ts"
|
"dev": "bun run index.ts"
|
||||||
},
|
},
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"netgate-switch": "file:",
|
"node-routeros": "^1.6.9"
|
||||||
"node-routeros": "^1.6.9"
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user