diff --git a/frontend/src/NetworkConfigManager.jsx b/frontend/src/NetworkConfigManager.jsx
index 17f356d..93fd29e 100644
--- a/frontend/src/NetworkConfigManager.jsx
+++ b/frontend/src/NetworkConfigManager.jsx
@@ -982,15 +982,13 @@ function NetworkConfigManager() {
// Проверяем, что IP входят в диапазон пула и отличаются
if (!isIpInCidr(localIp, cidr)) continue;
- if (isIpInCidr(remoteIp, cidr) && localIp !== remoteIp) {
- if (prefix >= 30) {
- if (!usedIps.has(localIp) && !usedIps.has(remoteIp)) {
- return forRemote ? remoteIp : localIp;
- }
- } else {
- if (!usedIps.has(localIp)) {
- return localIp;
- }
+ if (localIp === remoteIp) continue;
+
+ // Для всех префиксов проверяем, что оба IP свободны (для туннелей нужны пары)
+ if (!usedIps.has(localIp) && !usedIps.has(remoteIp)) {
+ // Проверяем, что Remote IP тоже входит в пул (для префиксов >= 30 это всегда true)
+ if (prefix >= 30 || isIpInCidr(remoteIp, cidr)) {
+ return forRemote ? remoteIp : localIp;
}
}
}
@@ -3696,129 +3694,85 @@ function NetworkConfigManager() {
>
);
})()}
- {templateServer1 && templateServer2 && templateServer1 !== templateServer2 && (() => {
- const server1 = getServerInfo(templateServer1);
- const server2 = getServerInfo(templateServer2);
- if (!server1 || !server2) return null;
-
- const autoName1 = generateInterfaceName(server1, server2, templateType, templateNamePrefix);
- const autoName2 = generateInterfaceName(server2, server1, templateType, templateNamePrefix);
- const previewName1 = templateName1.trim() || autoName1;
- const previewName2 = templateName2.trim() || autoName2;
- const previewLocalIp = generateFreePrivateIp(null, false, null, templateIpPoolId || null);
- const previewRemoteIp = previewLocalIp ? generateFreePrivateIp(null, true, previewLocalIp, templateIpPoolId || null) : null;
-
- return (
- <>
-
-
-
setTemplateName1(e.target.value)}
- placeholder={autoName1}
- />
-
Оставьте пустым для автогенерации
-
-
-
-
setTemplateName2(e.target.value)}
- placeholder={autoName2}
- />
-
Оставьте пустым для автогенерации
-
- {(templateType === 'IPSec' || templateType === 'GRE') && (
-
-
-
-
-
-
-
- Выберите сохраненный IPSec пароль или создайте новый (опционально для GRE)
-
-
- )}
-
-
-
-
- Выберите IP пул для подбора адресов или оставьте автоматический подбор
-
-
-
-
-
-
Предпросмотр интерфейса:
-
-
-
Сервер 1 ({server1.dns || server1.ip}):
-
Имя: {previewName1}
-
Local IP: {previewLocalIp || '—'}
-
-
-
Сервер 2 ({server2.dns || server2.ip}):
-
Имя: {previewName2}
-
Local IP: {previewRemoteIp || '—'}
-
- {previewLocalIp && previewRemoteIp && (
-
-
- {previewLocalIp} ↔ {previewRemoteIp}
+ {templateTunnelCount > 1 && templateServerPairs.length === templateTunnelCount && (
+
+
+
+ {templateServerPairs.map((pair, index) => {
+ const server1 = getServerInfo(pair.server1);
+ const server2 = getServerInfo(pair.server2);
+ if (!server1 || !server2 || !pair.server1 || !pair.server2 || pair.server1 === pair.server2) {
+ return null;
+ }
+
+ const baseName1 = generateInterfaceName(server1, server2, templateType, templateNamePrefix);
+ const baseName2 = generateInterfaceName(server2, server1, templateType, templateNamePrefix);
+ const previewName1 = pair.name1?.trim() || baseName1;
+ const previewName2 = pair.name2?.trim() || baseName2;
+
+ // Используем настройки из пары или глобальные для предпросмотра
+ const pairIpPoolId = pair.ipPoolId || templateIpPoolId;
+
+ // Генерируем предпросмотр IP (используем временный Set для предпросмотра)
+ const previewUsedIps = new Set(getAllUsedIpsSet);
+ // Добавляем IP из предыдущих туннелей в предпросмотре
+ for (let i = 0; i < index; i++) {
+ const prevPair = templateServerPairs[i];
+ if (prevPair.server1 && prevPair.server2) {
+ const prevPairIpPoolId = prevPair.ipPoolId || templateIpPoolId;
+ const prevPreviewLocal = generateFreePrivateIp(null, false, null, prevPairIpPoolId || null, previewUsedIps);
+ if (prevPreviewLocal) {
+ const prevPreviewRemote = generateFreePrivateIp(null, true, prevPreviewLocal, prevPairIpPoolId || null, previewUsedIps);
+ if (prevPreviewRemote && prevPreviewRemote !== prevPreviewLocal) {
+ previewUsedIps.add(prevPreviewLocal);
+ previewUsedIps.add(prevPreviewRemote);
+ }
+ }
+ }
+ }
+
+ const previewLocalIp = generateFreePrivateIp(null, false, null, pairIpPoolId || null, previewUsedIps);
+ const previewRemoteIp = previewLocalIp ? generateFreePrivateIp(null, true, previewLocalIp, pairIpPoolId || null, previewUsedIps) : null;
+
+ return (
+
+
+ Туннель {index + 1}:
+
+
+
+
+
+
Сервер 1 ({server1.dns || server1.ip}):
+
+
Имя: {previewName1}
+
Local IP: {previewLocalIp || '—'}
+
- )}
+
+
+
Сервер 2 ({server2.dns || server2.ip}):
+
+
Имя: {previewName2}
+
Local IP: {previewRemoteIp || '—'}
+
+
+
+ {previewLocalIp && previewRemoteIp && (
+
+
+ {previewLocalIp} ↔ {previewRemoteIp}
+
+ )}
+
-
-
- >
- );
- })()}
+ );
+ })}
+
+
+ )}