mirror of
https://github.com/Jerryplusy/AI-powered-switches.git
synced 2025-07-04 13:19:20 +00:00
Compare commits
No commits in common. "e894ffd3f9ac03f7f6926dff48a94379e1d17caa" and "223d43f0d9c7cbb7209d2b1df3f320473ac801ea" have entirely different histories.
e894ffd3f9
...
223d43f0d9
@ -1,208 +0,0 @@
|
||||
const configEffect = {
|
||||
async generateRealisticConfig(command, devices = []) {
|
||||
const timestamp = new Date().toLocaleString();
|
||||
let config = `! 配置生成于 ${timestamp}\n`;
|
||||
const configTemplates = {
|
||||
vlan: {
|
||||
pattern: /(vlan|虚拟局域网|虚拟网)\s*(\d+)/i,
|
||||
template: (vlanId) =>
|
||||
`vlan ${vlanId}\n` +
|
||||
` name VLAN_${vlanId}\n` +
|
||||
` exit\n` +
|
||||
`interface Vlan${vlanId}\n` +
|
||||
` description ${vlanId === '10' ? '管理VLAN' : '用户VLAN'}\n` +
|
||||
` ip address 192.168.${vlanId}.1 255.255.255.0\n` +
|
||||
` exit\n`,
|
||||
},
|
||||
ssh: {
|
||||
pattern: /(ssh|安全外壳|远程登录)/i,
|
||||
template: () => {
|
||||
const password = Math.random().toString(36).slice(2, 10);
|
||||
return (
|
||||
`ip ssh server\n` +
|
||||
`ip ssh version 2\n` +
|
||||
`username admin privilege 15 secret 0 ${password}\n` +
|
||||
`line vty 0 4\n` +
|
||||
` transport input ssh\n` +
|
||||
` login local\n` +
|
||||
` exit\n`
|
||||
);
|
||||
},
|
||||
},
|
||||
port: {
|
||||
pattern: /(端口|接口|port|interface)\s*(\d+)/i,
|
||||
template: (port) => {
|
||||
const isTrunk = /(trunk|干道)/i.test(command);
|
||||
const isAccess = /(access|接入)/i.test(command) || !isTrunk;
|
||||
const desc = /(上联|uplink)/i.test(command) ? 'Uplink_Port' : 'Access_Port';
|
||||
const vlanId = command.match(/vlan\s*(\d+)/i)?.[1] || '10';
|
||||
|
||||
return (
|
||||
`interface GigabitEthernet0/${port}\n` +
|
||||
` description ${desc}\n` +
|
||||
` switchport mode ${isTrunk ? 'trunk' : 'access'}\n` +
|
||||
` ${isTrunk ? 'switchport trunk allowed vlan all' : `switchport access vlan ${vlanId}`}\n` +
|
||||
` no shutdown\n` +
|
||||
` exit\n`
|
||||
);
|
||||
},
|
||||
},
|
||||
acl: {
|
||||
pattern: /(acl|访问控制|防火墙)/i,
|
||||
template: () => {
|
||||
let targetIP = '192.168.10.10';
|
||||
if (devices.length > 0) {
|
||||
const randomDevice = devices[Math.floor(Math.random() * devices.length)];
|
||||
targetIP = randomDevice.ip;
|
||||
}
|
||||
return (
|
||||
`ip access-list extended PROTECT_SERVERS\n` +
|
||||
` permit tcp any host ${targetIP} eq 22\n` +
|
||||
` permit tcp any host ${targetIP} eq 80\n` +
|
||||
` permit tcp any host ${targetIP} eq 443\n` +
|
||||
` deny ip any any\n` +
|
||||
` exit\n` +
|
||||
`interface Vlan10\n` +
|
||||
` ip access-group PROTECT_SERVERS in\n` +
|
||||
` exit\n`
|
||||
);
|
||||
},
|
||||
},
|
||||
dhcp: {
|
||||
pattern: /(dhcp|动态主机配置)/i,
|
||||
template: () => {
|
||||
const vlanId = command.match(/vlan\s*(\d+)/i)?.[1] || '10';
|
||||
return (
|
||||
`ip dhcp pool VLAN_${vlanId}\n` +
|
||||
` network 192.168.${vlanId}.0 255.255.255.0\n` +
|
||||
` default-router 192.168.${vlanId}.1\n` +
|
||||
` dns-server 8.8.8.8 8.8.4.4\n` +
|
||||
` exit\n` +
|
||||
`ip dhcp excluded-address 192.168.${vlanId}.1 192.168.${vlanId}.10\n`
|
||||
);
|
||||
},
|
||||
},
|
||||
nat: {
|
||||
pattern: /(nat|网络地址转换)/i,
|
||||
template: () => {
|
||||
const publicIp = `203.0.113.${Math.floor(Math.random() * 10) + 1}`;
|
||||
return (
|
||||
`ip access-list standard NAT_ACL\n` +
|
||||
` permit 192.168.0.0 0.0.255.255\n` +
|
||||
` exit\n` +
|
||||
`ip nat inside source list NAT_ACL interface GigabitEthernet0/1 overload\n` +
|
||||
`interface GigabitEthernet0/1\n` +
|
||||
` ip address ${publicIp} 255.255.255.248\n` +
|
||||
` ip nat outside\n` +
|
||||
` exit\n` +
|
||||
`interface Vlan10\n` +
|
||||
` ip nat inside\n` +
|
||||
` exit\n`
|
||||
);
|
||||
},
|
||||
},
|
||||
stp: {
|
||||
pattern: /(stp|生成树|spanning-tree)/i,
|
||||
template: () => {
|
||||
return (
|
||||
`spanning-tree mode rapid-pvst\n` +
|
||||
`spanning-tree vlan 1-4094 priority 4096\n` +
|
||||
`spanning-tree portfast default\n` +
|
||||
`spanning-tree portfast bpduguard default\n`
|
||||
);
|
||||
},
|
||||
},
|
||||
portSecurity: {
|
||||
pattern: /(端口安全|port-security)/i,
|
||||
template: () => {
|
||||
const port = command.match(/端口\s*(\d+)/i)?.[1] || '1';
|
||||
return (
|
||||
`interface GigabitEthernet0/${port}\n` +
|
||||
` switchport port-security\n` +
|
||||
` switchport port-security maximum 5\n` +
|
||||
` switchport port-security violation restrict\n` +
|
||||
` switchport port-security mac-address sticky\n` +
|
||||
` exit\n`
|
||||
);
|
||||
},
|
||||
},
|
||||
qos: {
|
||||
pattern: /(qos|服务质量|流量控制)/i,
|
||||
template: () => {
|
||||
return (
|
||||
`class-map match-all VOICE\n` +
|
||||
` match ip dscp ef\n` +
|
||||
` exit\n` +
|
||||
`policy-map QOS_POLICY\n` +
|
||||
` class VOICE\n` +
|
||||
` priority percent 20\n` +
|
||||
` class class-default\n` +
|
||||
` bandwidth percent 80\n` +
|
||||
` exit\n` +
|
||||
`interface GigabitEthernet0/1\n` +
|
||||
` service-policy output QOS_POLICY\n` +
|
||||
` exit\n`
|
||||
);
|
||||
},
|
||||
},
|
||||
vpn: {
|
||||
pattern: /(vpn|虚拟专用网)/i,
|
||||
template: () => {
|
||||
const vpnId = Math.floor(Math.random() * 1000);
|
||||
return (
|
||||
`crypto isakmp policy ${vpnId}\n` +
|
||||
` encryption aes 256\n` +
|
||||
` hash sha256\n` +
|
||||
` authentication pre-share\n` +
|
||||
` group 14\n` +
|
||||
` exit\n` +
|
||||
`crypto ipsec transform-set VPN_TRANSFORM esp-aes 256 esp-sha256-hmac\n` +
|
||||
` mode tunnel\n` +
|
||||
` exit\n` +
|
||||
`crypto map VPN_MAP 10 ipsec-isakmp\n` +
|
||||
` set peer 203.0.113.5\n` +
|
||||
` set transform-set VPN_TRANSFORM\n` +
|
||||
` match address VPN_ACL\n` +
|
||||
` exit\n`
|
||||
);
|
||||
},
|
||||
},
|
||||
};
|
||||
let matched = false;
|
||||
if (/(完整配置|全部配置|all config)/i.test(command)) {
|
||||
matched = true;
|
||||
config += '! 生成完整校园网络配置\n';
|
||||
Object.values(configTemplates).forEach((template) => {
|
||||
const result = template.template();
|
||||
if (result) {
|
||||
config += result;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
for (const [key, { pattern, template }] of Object.entries(configTemplates)) {
|
||||
const match = command.match(pattern);
|
||||
if (match) {
|
||||
matched = true;
|
||||
config += template(match[2] || match[1] || '');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!matched) {
|
||||
config += 'hostname SCHOOL_SWITCH\n';
|
||||
config += 'ip domain-name school.local\n';
|
||||
config += 'snmp-server community SCHOOL_RO RO\n';
|
||||
config += 'ntp server 192.168.1.1\n';
|
||||
config += 'logging trap informational\n';
|
||||
config += 'logging 192.168.1.10\n';
|
||||
config += 'service password-encryption\n';
|
||||
config += 'enable secret 0 ' + Math.random().toString(36).slice(2, 12) + '\n';
|
||||
config += 'no ip http server\n';
|
||||
config += 'no ip http secure-server\n';
|
||||
}
|
||||
|
||||
return { config };
|
||||
},
|
||||
};
|
||||
|
||||
export default configEffect;
|
@ -1,24 +0,0 @@
|
||||
const scanEffect = {
|
||||
getTestDevices() {
|
||||
return [
|
||||
{ ip: '192.168.1.1', mac: '00:1A:2B:3C:4D:5E', ports: [22, 23, 161] },
|
||||
{ ip: '192.168.1.2', mac: '00:1D:7D:AA:1B:01', ports: [22, 23, 161] },
|
||||
{ ip: '192.168.1.3', mac: '00:0C:29:5A:3B:11', ports: [22, 23, 161, 443] },
|
||||
{ ip: '192.168.1.4', mac: '00:23:CD:FF:10:02', ports: [22, 23] },
|
||||
{ ip: '192.168.1.5', mac: '00:04:4B:AA:BB:CC', ports: [22, 23, 80, 443] },
|
||||
{ ip: '192.168.1.6', mac: '00:11:22:33:44:55', ports: [22, 23, 161] },
|
||||
{ ip: '192.168.1.7', mac: '00:1F:45:67:89:AB', ports: [23] },
|
||||
{ ip: '192.168.1.8', mac: '00:50:56:11:22:33', ports: [22, 443, 8443] },
|
||||
];
|
||||
},
|
||||
|
||||
async fetchLocalInfo({ setLocalIp, subnet, setSubnet }) {
|
||||
setLocalIp('192.168.1.100');
|
||||
if (!subnet) {
|
||||
const ipParts = '192.168.1.0'.split('.');
|
||||
setSubnet(`${ipParts[0]}.${ipParts[1]}.${ipParts[2]}.0/24`);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default scanEffect;
|
@ -20,7 +20,6 @@ import ConfigTool from '@/libs/config/ConfigTool';
|
||||
import { api } from '@/services/api/api';
|
||||
import Notification from '@/libs/system/Notification';
|
||||
import Common from '@/libs/common';
|
||||
import configEffect from '@/libs/script/configPage/configEffect';
|
||||
|
||||
const testMode = ConfigTool.load().testMode;
|
||||
|
||||
@ -45,6 +44,76 @@ const ConfigPage = () => {
|
||||
setDevices(config.devices || []);
|
||||
}, []);
|
||||
|
||||
const generateRealisticConfig = (command, devices = []) => {
|
||||
const timestamp = new Date().toLocaleString();
|
||||
let config = `! 配置生成于 ${timestamp}\n`;
|
||||
const cmd = command.toLowerCase();
|
||||
// VLAN 配置
|
||||
if (cmd.includes('vlan')) {
|
||||
const vlanIdMatch = command.match(/vlan\s*(\d+)/i);
|
||||
const vlanId = vlanIdMatch?.[1] || '10';
|
||||
const isMgmt = cmd.includes('管理') || cmd.includes('mgmt');
|
||||
config +=
|
||||
`vlan ${vlanId}\n` +
|
||||
` name ${isMgmt ? 'MGMT' : 'USER'}_VLAN\n` +
|
||||
` exit\n` +
|
||||
`interface Vlan${vlanId}\n` +
|
||||
` description ${isMgmt ? 'Management VLAN' : 'User VLAN'}\n` +
|
||||
` ip address 192.168.${vlanId}.1 255.255.255.0\n` +
|
||||
` exit\n`;
|
||||
}
|
||||
// SSH 配置
|
||||
if (cmd.includes('ssh') || cmd.includes('安全') || cmd.includes('登录')) {
|
||||
const password = Math.random().toString(36).slice(2, 10);
|
||||
config +=
|
||||
`ip ssh server\n` +
|
||||
`ip ssh version 2\n` +
|
||||
`username admin privilege 15 secret 0 ${password}\n` +
|
||||
`line vty 0 4\n` +
|
||||
` transport input ssh\n` +
|
||||
` login local\n` +
|
||||
` exit\n`;
|
||||
}
|
||||
// 端口配置
|
||||
if (cmd.includes('端口') || cmd.includes('接口') || cmd.includes('port')) {
|
||||
const portMatch = command.match(/端口\s*(\d+)/i) || command.match(/port\s*(\d+)/i);
|
||||
const port = portMatch?.[1] || '1';
|
||||
const isTrunk = cmd.includes('trunk');
|
||||
const isAccess = cmd.includes('access') || !isTrunk;
|
||||
const desc = cmd.includes('上联') || cmd.includes('uplink') ? 'Uplink_Port' : 'Access_Port';
|
||||
const vlanId = '10';
|
||||
config +=
|
||||
`interface GigabitEthernet0/${port}\n` +
|
||||
` description ${desc}\n` +
|
||||
` switchport mode ${isTrunk ? 'trunk' : 'access'}\n` +
|
||||
` ${isTrunk ? 'switchport trunk allowed vlan all' : `switchport access vlan ${vlanId}`}\n` +
|
||||
` no shutdown\n` +
|
||||
` exit\n`;
|
||||
}
|
||||
// ACL 配置
|
||||
if (cmd.includes('acl') || cmd.includes('访问控制') || cmd.includes('防火墙')) {
|
||||
let targetIP = '192.168.10.10';
|
||||
if (devices.length > 0) {
|
||||
const randomDevice = devices[Math.floor(Math.random() * devices.length)];
|
||||
targetIP = randomDevice.ip;
|
||||
}
|
||||
config +=
|
||||
`ip access-list extended PROTECT_SERVERS\n` +
|
||||
` permit tcp any host ${targetIP} eq 22\n` +
|
||||
` permit tcp any host ${targetIP} eq 80\n` +
|
||||
` deny ip any any\n` +
|
||||
` exit\n` +
|
||||
`interface Vlan10\n` +
|
||||
` ip access-group PROTECT_SERVERS in\n` +
|
||||
` exit\n`;
|
||||
}
|
||||
|
||||
if (config.trim() === `! 配置生成于 ${timestamp}`) {
|
||||
config += '! 当前命令未识别到任何可配置项目\n';
|
||||
}
|
||||
return { config };
|
||||
};
|
||||
|
||||
const handleParse = async () => {
|
||||
if (!selectedDevice || !inputText.trim()) {
|
||||
Notification.error({
|
||||
@ -58,7 +127,7 @@ const ConfigPage = () => {
|
||||
const performParse = async () => {
|
||||
if (testMode) {
|
||||
await Common.sleep(800 + Math.random() * 700);
|
||||
return await configEffect.generateRealisticConfig(inputText, devices);
|
||||
return generateRealisticConfig(inputText);
|
||||
}
|
||||
return await api.parseCommand(inputText);
|
||||
};
|
||||
@ -67,7 +136,7 @@ const ConfigPage = () => {
|
||||
promise: performParse(),
|
||||
loading: {
|
||||
title: '正在解析配置',
|
||||
description: '正在分析您的指令..',
|
||||
description: '正在分析您的指令...',
|
||||
},
|
||||
success: {
|
||||
title: '解析完成',
|
||||
|
@ -43,14 +43,13 @@ const DevicesPage = () => {
|
||||
const handleSave = (idx) => {
|
||||
const updated = [...devices];
|
||||
updated[idx].name = editingName;
|
||||
Common.sleep(200).then(() => {
|
||||
setDevices(updated);
|
||||
ConfigTool.save({ ...ConfigTool.load(), devices: updated });
|
||||
Notification.success({
|
||||
title: '设备重命名成功!',
|
||||
});
|
||||
setEditingIndex(null);
|
||||
Common.sleep(200);
|
||||
setDevices(updated);
|
||||
ConfigTool.save({ ...ConfigTool.load(), devices: updated });
|
||||
Notification.success({
|
||||
title: '设备重命名成功!',
|
||||
});
|
||||
setEditingIndex(null);
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -9,8 +9,8 @@ import {
|
||||
Spinner,
|
||||
Badge,
|
||||
HStack,
|
||||
Table,
|
||||
} from '@chakra-ui/react';
|
||||
import { Table } from '@chakra-ui/react';
|
||||
import DocumentTitle from '@/components/system/pages/DocumentTitle';
|
||||
import PageContainer from '@/components/system/PageContainer';
|
||||
import DashboardBackground from '@/components/system/pages/DashboardBackground';
|
||||
@ -19,7 +19,6 @@ import { api } from '@/services/api/api';
|
||||
import ConfigTool from '@/libs/config/ConfigTool';
|
||||
import Common from '@/libs/common';
|
||||
import Notification from '@/libs/system/Notification';
|
||||
import scanEffect from '@/libs/script/scanPage/scanEffect';
|
||||
|
||||
/**
|
||||
* 网络扫描页面
|
||||
@ -36,22 +35,36 @@ const ScanPage = () => {
|
||||
const testMode = config.testMode;
|
||||
|
||||
useEffect(() => {
|
||||
scanEffect
|
||||
.fetchLocalInfo({
|
||||
setLocalIp: setLocalIp,
|
||||
setSubnet: setSubnet,
|
||||
subnet: subnet,
|
||||
})
|
||||
.then();
|
||||
const fetchLocalInfo = async () => {
|
||||
setLocalIp('192.168.1.100');
|
||||
if (!subnet) {
|
||||
const ipParts = '192.168.1.0'.split('.');
|
||||
setSubnet(`${ipParts[0]}.${ipParts[1]}.${ipParts[2]}.0/24`);
|
||||
}
|
||||
};
|
||||
fetchLocalInfo();
|
||||
}, [subnet, Notification]);
|
||||
|
||||
const getTestDevices = () => {
|
||||
return [
|
||||
{ ip: '192.168.1.1', mac: '00:1A:2B:3C:4D:5E', ports: [22, 23, 161] },
|
||||
{ ip: '192.168.1.2', mac: '00:1D:7D:AA:1B:01', ports: [22, 23, 161] },
|
||||
{ ip: '192.168.1.3', mac: '00:0C:29:5A:3B:11', ports: [22, 23, 161, 443] },
|
||||
{ ip: '192.168.1.4', mac: '00:23:CD:FF:10:02', ports: [22, 23] },
|
||||
{ ip: '192.168.1.5', mac: '00:04:4B:AA:BB:CC', ports: [22, 23, 80, 443] },
|
||||
{ ip: '192.168.1.6', mac: '00:11:22:33:44:55', ports: [22, 23, 161] },
|
||||
{ ip: '192.168.1.7', mac: '00:1F:45:67:89:AB', ports: [23] },
|
||||
{ ip: '192.168.1.8', mac: '00:50:56:11:22:33', ports: [22, 443, 8443] },
|
||||
];
|
||||
};
|
||||
|
||||
const handleScan = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
let scanDevices;
|
||||
if (testMode) {
|
||||
await Common.sleep(2000);
|
||||
scanDevices = scanEffect.getTestDevices();
|
||||
scanDevices = getTestDevices();
|
||||
Notification.success({
|
||||
title: '扫描子网设备成功!',
|
||||
});
|
||||
@ -91,7 +104,7 @@ const ScanPage = () => {
|
||||
let scanDevices;
|
||||
if (testMode) {
|
||||
await Common.sleep(500);
|
||||
scanDevices = scanEffect.getTestDevices();
|
||||
scanDevices = getTestDevices();
|
||||
Notification.success({
|
||||
title: '获取上一次扫描记录成功!',
|
||||
});
|
||||
@ -160,7 +173,7 @@ const ScanPage = () => {
|
||||
{loading && (
|
||||
<HStack>
|
||||
<Spinner />
|
||||
<Text>{'正在加载,请稍候..'}</Text>
|
||||
<Text>{'正在加载,请稍候...'}</Text>
|
||||
</HStack>
|
||||
)}
|
||||
|
||||
@ -212,7 +225,7 @@ const ScanPage = () => {
|
||||
)}
|
||||
|
||||
{!loading && devices.length === 0 && (
|
||||
<Text color={'gray.400'}>{'暂无扫描结果,请执行扫描..'}</Text>
|
||||
<Text color={'gray.400'}>{'暂无扫描结果,请执行扫描。'}</Text>
|
||||
)}
|
||||
</Box>
|
||||
</VStack>
|
||||
|
Loading…
x
Reference in New Issue
Block a user