From 4c9cb7eab672c1a46103e1347bd967607767155b Mon Sep 17 00:00:00 2001 From: shats Date: Fri, 23 Jan 2026 19:18:06 +0700 Subject: [PATCH] fix(NetworkConfigManager): improve validation for /30 networks by ensuring local and remote IPs do not conflict with network and broadcast addresses --- frontend/src/NetworkConfigManager.jsx | 41 +++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/frontend/src/NetworkConfigManager.jsx b/frontend/src/NetworkConfigManager.jsx index 2efe412..62c1f49 100644 --- a/frontend/src/NetworkConfigManager.jsx +++ b/frontend/src/NetworkConfigManager.jsx @@ -917,6 +917,16 @@ function NetworkConfigManager() { const networkBase = Math.floor(baseOctet / 4) * 4; const localOffset = baseOctet - networkBase; + // Для сетей /30 проверяем, что Local IP не является сетевым адресом или broadcast + if (prefix >= 30) { + const networkAddress = `${localIpParts[0]}.${localIpParts[1]}.${localIpParts[2]}.${networkBase}`; + const broadcastAddress = `${localIpParts[0]}.${localIpParts[1]}.${localIpParts[2]}.${networkBase + 3}`; + if (pairedLocalIp === networkAddress || pairedLocalIp === broadcastAddress) { + // Local IP является сетевым адресом или broadcast, не можем использовать + return null; + } + } + let remoteOffset; if (localOffset === 1) { remoteOffset = 2; @@ -930,8 +940,21 @@ function NetworkConfigManager() { if (remoteOctet >= 0 && remoteOctet <= 255) { const remoteIp = `${localIpParts[0]}.${localIpParts[1]}.${localIpParts[2]}.${remoteOctet}`; // Проверяем, что Remote IP входит в диапазон пула и отличается от Local IP + // Также проверяем, что не используем сетевой адрес (networkBase) и broadcast (networkBase + 3) if (isIpInCidr(remoteIp, cidr) && !usedIps.has(remoteIp) && remoteIp !== pairedLocalIp) { - return remoteIp; + // Для сетей /30 проверяем, что не используем сетевой адрес и broadcast + if (prefix >= 30) { + const networkAddress = `${localIpParts[0]}.${localIpParts[1]}.${localIpParts[2]}.${networkBase}`; + const broadcastAddress = `${localIpParts[0]}.${localIpParts[1]}.${localIpParts[2]}.${networkBase + 3}`; + if (remoteIp === networkAddress || remoteIp === broadcastAddress) { + // Remote IP является сетевым адресом или broadcast, не используем его + // Продолжаем поиск в общем цикле ниже + } else { + return remoteIp; + } + } else { + return remoteIp; + } } } } @@ -965,11 +988,17 @@ function NetworkConfigManager() { const localIp = `${a}.${b}.${c}.${dVal + 1}`; const remoteIp = `${a}.${b}.${c}.${dVal + 2}`; - // Для сетей /30 проверяем, что не выходим за пределы сети (не используем .0 и .3) + // Для сетей /30 проверяем, что не используем сетевой адрес (базовый) и broadcast (базовый + 3) if (prefix >= 30) { const lastOctet = dVal % 4; if (lastOctet !== 0) continue; // Базовый адрес должен быть кратен 4 if (dVal + 2 > 255) continue; // Проверяем, что remoteIp не превышает 255 + // Проверяем, что не используем сетевой адрес (dVal) и broadcast (dVal + 3) + // Для /30 используем только dVal + 1 и dVal + 2 + const networkAddress = `${a}.${b}.${c}.${dVal}`; + const broadcastAddress = `${a}.${b}.${c}.${dVal + 3}`; + if (localIp === networkAddress || localIp === broadcastAddress) continue; + if (remoteIp === networkAddress || remoteIp === broadcastAddress) continue; } // Проверяем, что IP входят в диапазон пула @@ -1000,6 +1029,14 @@ function NetworkConfigManager() { const localIp = `${a}.${b}.${cVal}.${dVal + 1}`; // Local IP = базовый + 1 const remoteIp = `${a}.${b}.${cVal}.${dVal + 2}`; // Remote IP = базовый + 2 + // Для сетей /30 проверяем, что не используем сетевой адрес (базовый) и broadcast (базовый + 3) + if (prefix >= 30) { + const networkAddress = `${a}.${b}.${cVal}.${dVal}`; + const broadcastAddress = `${a}.${b}.${cVal}.${dVal + 3}`; + if (localIp === networkAddress || localIp === broadcastAddress) continue; + if (remoteIp === networkAddress || remoteIp === broadcastAddress) continue; + } + // Проверяем, что IP входят в диапазон пула и отличаются if (!isIpInCidr(localIp, cidr)) continue; if (localIp === remoteIp) continue;