feat(NetworkConfigManager): add optional second interface name for dual server configurations; enhance UI to support interface naming for both servers
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m38s
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m38s
This commit is contained in:
@@ -54,6 +54,7 @@
|
||||
{
|
||||
"id": "if-gre-swe-de",
|
||||
"name": "gre-swe-de",
|
||||
"name2": "gre-de-swe",
|
||||
"type": "GRE",
|
||||
"localIp": "10.10.0.1",
|
||||
"remoteIp": "10.10.0.2",
|
||||
@@ -63,6 +64,7 @@
|
||||
{
|
||||
"id": "if-wg-swe-nl",
|
||||
"name": "wg0",
|
||||
"name2": "wg1",
|
||||
"type": "WireGuard",
|
||||
"localIp": "10.20.0.1",
|
||||
"remoteIp": "10.20.0.2",
|
||||
|
||||
@@ -73,6 +73,7 @@ const getEmptyGateway = () => ({
|
||||
const getEmptyInterface = () => ({
|
||||
id: `if-${Date.now()}-${Math.random().toString(16).slice(2, 6)}`,
|
||||
name: '',
|
||||
name2: '', // Имя интерфейса на втором сервере (опционально)
|
||||
type: 'GRE',
|
||||
localIp: '',
|
||||
remoteIp: '',
|
||||
@@ -511,8 +512,10 @@ function NetworkConfigManager() {
|
||||
return '';
|
||||
}
|
||||
|
||||
let code = '\n# === Настройка IP адресов интерфейсов на обоих серверах ===\n';
|
||||
code += '# Эти команды нужно выполнить на соответствующих серверах\n\n';
|
||||
let code = '\n# ====================================================================\n';
|
||||
code += '# === НАСТРОЙКА IP АДРЕСОВ ИНТЕРФЕЙСОВ НА ОБОИХ СЕРВЕРАХ ===\n';
|
||||
code += '# Эти команды нужно выполнить на соответствующих серверах\n';
|
||||
code += '# ====================================================================\n\n';
|
||||
|
||||
// Группируем по серверам
|
||||
const interfacesByServer = {};
|
||||
@@ -524,43 +527,84 @@ function NetworkConfigManager() {
|
||||
|
||||
const server1Name = server1.dns || server1.ip || iface.serverId;
|
||||
const server2Name = server2.dns || server2.ip || iface.serverId2;
|
||||
const interfaceName = iface.name || `${iface.type}-tunnel`;
|
||||
|
||||
// Для первого сервера - используем localIp
|
||||
// Имя интерфейса для первого сервера
|
||||
const interfaceName1 = iface.name || `${iface.type}-tunnel`;
|
||||
// Имя интерфейса для второго сервера (может отличаться)
|
||||
const interfaceName2 = iface.name2 || iface.name || `${iface.type}-tunnel`;
|
||||
|
||||
// Для первого сервера - используем localIp как local, remoteIp как remote
|
||||
if (!interfacesByServer[server1Name]) {
|
||||
interfacesByServer[server1Name] = [];
|
||||
interfacesByServer[server1Name] = {
|
||||
serverInfo: server1,
|
||||
interfaces: []
|
||||
};
|
||||
}
|
||||
interfacesByServer[server1Name].push({
|
||||
interfaceName,
|
||||
ip: iface.localIp,
|
||||
type: iface.type,
|
||||
interfacesByServer[server1Name].interfaces.push({
|
||||
interfaceName: interfaceName1,
|
||||
localIp: iface.localIp,
|
||||
remoteIp: iface.remoteIp,
|
||||
server2Name
|
||||
type: iface.type,
|
||||
server2Name,
|
||||
server2Info: server2
|
||||
});
|
||||
|
||||
// Для второго сервера - используем remoteIp
|
||||
// Для второго сервера - МЕНЯЕМ МЕСТАМИ: remoteIp становится localIp, localIp становится remoteIp
|
||||
if (!interfacesByServer[server2Name]) {
|
||||
interfacesByServer[server2Name] = [];
|
||||
interfacesByServer[server2Name] = {
|
||||
serverInfo: server2,
|
||||
interfaces: []
|
||||
};
|
||||
}
|
||||
interfacesByServer[server2Name].push({
|
||||
interfaceName,
|
||||
ip: iface.remoteIp,
|
||||
interfacesByServer[server2Name].interfaces.push({
|
||||
interfaceName: interfaceName2,
|
||||
localIp: iface.remoteIp, // На втором сервере remoteIp первого становится localIp
|
||||
remoteIp: iface.localIp, // На втором сервере localIp первого становится remoteIp
|
||||
type: iface.type,
|
||||
remoteIp: iface.localIp, // Для второго сервера remoteIp - это localIp первого
|
||||
server2Name: server1Name
|
||||
server2Name: server1Name,
|
||||
server2Info: server1
|
||||
});
|
||||
});
|
||||
|
||||
Object.entries(interfacesByServer).forEach(([serverName, interfaces]) => {
|
||||
code += `\n# --- Команды для сервера: ${serverName} ---\n`;
|
||||
interfaces.forEach(iface => {
|
||||
code += `# Интерфейс: ${iface.interfaceName} (${iface.type}) - связь с ${iface.server2Name}\n`;
|
||||
code += `/ip address add address=${iface.ip}/32 interface="${iface.interfaceName}" comment="Interface: ${iface.interfaceName} (${iface.type}) to ${iface.server2Name}"\n`;
|
||||
// Сортируем серверы по имени для консистентности
|
||||
const sortedServers = Object.entries(interfacesByServer).sort(([a], [b]) => a.localeCompare(b));
|
||||
|
||||
sortedServers.forEach(([serverName, serverData], index) => {
|
||||
const server = serverData.serverInfo;
|
||||
|
||||
// Отдельный блок для каждого сервера
|
||||
code += '\n';
|
||||
code += '# ' + '='.repeat(70) + '\n';
|
||||
code += `# СЕРВЕР ${index + 1}: ${serverName}\n`;
|
||||
if (server.provider) {
|
||||
code += `# Провайдер: ${server.provider}\n`;
|
||||
}
|
||||
if (server.country) {
|
||||
code += `# Страна: ${server.country}\n`;
|
||||
}
|
||||
if (server.ip && server.ip !== serverName) {
|
||||
code += `# IP: ${server.ip}\n`;
|
||||
}
|
||||
code += '# ' + '='.repeat(70) + '\n';
|
||||
code += '\n';
|
||||
|
||||
serverData.interfaces.forEach((iface, ifaceIndex) => {
|
||||
code += `# Интерфейс ${ifaceIndex + 1}: ${iface.interfaceName} (${iface.type})\n`;
|
||||
code += `# Связь с сервером: ${iface.server2Name}\n`;
|
||||
code += `# Local IP: ${iface.localIp}\n`;
|
||||
code += `# Remote IP: ${iface.remoteIp}\n`;
|
||||
code += `/ip address add address=${iface.localIp}/32 interface="${iface.interfaceName}" comment="Interface: ${iface.interfaceName} (${iface.type}) to ${iface.server2Name}"\n`;
|
||||
code += '\n';
|
||||
});
|
||||
|
||||
code += '# Проверка настроенных адресов на этом сервере:\n';
|
||||
code += '# /ip address print\n';
|
||||
code += '\n';
|
||||
});
|
||||
|
||||
code += '\n# Проверка настроенных адресов:\n';
|
||||
code += '# /ip address print\n';
|
||||
code += '# ' + '='.repeat(70) + '\n';
|
||||
code += '# КОНЕЦ КОНФИГУРАЦИИ IP АДРЕСОВ ИНТЕРФЕЙСОВ\n';
|
||||
code += '# ' + '='.repeat(70) + '\n';
|
||||
|
||||
return code;
|
||||
};
|
||||
@@ -967,6 +1011,7 @@ function NetworkConfigManager() {
|
||||
<IconServer size={12} className="text-muted" />
|
||||
<span className="text-muted">Сервер 1:</span>
|
||||
<span>{server.dns || server.ip}</span>
|
||||
{iface.name && <span className="text-muted ms-1">({iface.name})</span>}
|
||||
</div>
|
||||
)}
|
||||
{server2 && (
|
||||
@@ -974,6 +1019,9 @@ function NetworkConfigManager() {
|
||||
<IconServer size={12} className="text-muted" />
|
||||
<span className="text-muted">Сервер 2:</span>
|
||||
<span>{server2.dns || server2.ip}</span>
|
||||
{(iface.name2 || iface.name) && (
|
||||
<span className="text-muted ms-1">({iface.name2 || iface.name})</span>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -1714,7 +1762,7 @@ function NetworkConfigManager() {
|
||||
</div>
|
||||
<div className="col-md-6">
|
||||
<FormField
|
||||
label="Имя интерфейса"
|
||||
label="Имя интерфейса (сервер 1)"
|
||||
name="name"
|
||||
value={editingInterface.name}
|
||||
onChange={(val) => setEditingInterface({ ...editingInterface, name: val })}
|
||||
@@ -1722,6 +1770,18 @@ function NetworkConfigManager() {
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
{editingInterface.serverId2 && (
|
||||
<div className="col-md-6">
|
||||
<FormField
|
||||
label="Имя интерфейса (сервер 2)"
|
||||
name="name2"
|
||||
value={editingInterface.name2 || ''}
|
||||
onChange={(val) => setEditingInterface({ ...editingInterface, name2: val })}
|
||||
placeholder="gre-tunnel2"
|
||||
/>
|
||||
<div className="form-text">Если не указано, будет использовано имя с сервера 1</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="col-md-6">
|
||||
<FormField
|
||||
label="Тип"
|
||||
|
||||
Reference in New Issue
Block a user