/** * Модуль валидации входных данных * Содержит валидаторы для IP, CIDR, доменов, ASN, Community */ /** * Валидация IPv4 адреса * @param {string} ip - IP адрес для валидации * @returns {boolean} */ function isValidIPv4(ip) { if (!ip || typeof ip !== 'string') return false; const octets = ip.trim().split('.'); if (octets.length !== 4) return false; return octets.every(octet => { if (!/^\d{1,3}$/.test(octet)) return false; const num = Number(octet); return num >= 0 && num <= 255; }); } /** * Валидация IPv6 адреса (базовая) * @param {string} ip - IPv6 адрес * @returns {boolean} */ function isValidIPv6(ip) { if (!ip || typeof ip !== 'string') return false; const segments = ip.trim().split(':'); if (segments.length < 3 || segments.length > 8) return false; return segments.every(seg => { if (seg === '') return true; // :: notation return /^[0-9a-fA-F]{1,4}$/.test(seg); }); } /** * Валидация CIDR блока (IPv4) * @param {string} cidr - CIDR блок (например, 192.168.1.0/24) * @returns {boolean} */ function isValidCIDRv4(cidr) { if (!cidr || typeof cidr !== 'string') return false; const parts = cidr.trim().split('/'); if (parts.length !== 2) return false; const [ip, mask] = parts; if (!isValidIPv4(ip)) return false; if (!/^\d{1,2}$/.test(mask)) return false; const maskNum = Number(mask); return maskNum >= 0 && maskNum <= 32; } /** * Валидация CIDR блока (IPv6) * @param {string} cidr - CIDR блок IPv6 * @returns {boolean} */ function isValidCIDRv6(cidr) { if (!cidr || typeof cidr !== 'string') return false; const parts = cidr.trim().split('/'); if (parts.length !== 2) return false; const [ip, mask] = parts; if (!isValidIPv6(ip)) return false; if (!/^\d{1,3}$/.test(mask)) return false; const maskNum = Number(mask); return maskNum >= 0 && maskNum <= 128; } /** * Валидация доменного имени (FQDN) * Поддержка IDN (интернационализированных доменов) * @param {string} domain - доменное имя * @returns {boolean} */ function isValidDomain(domain) { if (!domain || typeof domain !== 'string') return false; const d = domain.trim().toLowerCase(); // Проверка на максимальную длину if (d.length > 253) return false; // Проверка на IP адрес (не должен быть IP) if (isValidIPv4(d) || isValidIPv6(d)) return false; // Базовая проверка структуры домена // Разрешаем буквы, цифры, дефис, точку, и IDN символы const domainRegex = /^([a-z0-9\u00a1-\uffff]([a-z0-9\u00a1-\uffff-]{0,61}[a-z0-9\u00a1-\uffff])?\.)+[a-z\u00a1-\uffff]{2,}$/i; return domainRegex.test(d); } /** * Валидация wildcard домена (*.example.com) * @param {string} domain - wildcard домен * @returns {boolean} */ function isValidWildcardDomain(domain) { if (!domain || typeof domain !== 'string') return false; const d = domain.trim().toLowerCase(); // Проверка на wildcard в начале if (d.startsWith('*.')) { const baseDomain = d.substring(2); return isValidDomain(baseDomain); } return isValidDomain(d); } /** * Валидация номера ASN * @param {string|number} asn - номер ASN * @returns {boolean} */ function isValidASN(asn) { if (!asn) return false; const asnStr = String(asn).trim(); // Формат: AS12345 или просто 12345 const asnRegex = /^(AS)?(\d{1,10})$/i; const match = asnStr.match(asnRegex); if (!match) return false; const num = Number(match[2]); // ASN диапазон: 0-4294967295 (32-bit) return num >= 0 && num <= 4294967295; } /** * Валидация BGP Community * Поддержка форматов: 65000:100, 65000 * @param {string} community - BGP community * @returns {boolean} */ function isValidCommunity(community) { if (!community || typeof community !== 'string') return false; const c = community.trim(); // Формат: N:N или просто N const communityRegex = /^(\d{1,10})(:(\d{1,10}))?$/; const match = c.match(communityRegex); if (!match) return false; const first = Number(match[1]); if (first < 0 || first > 4294967295) return false; if (match[3]) { const second = Number(match[3]); if (second < 0 || second > 65535) return false; } return true; } /** * Валидация gateway имени (для MikroTik) * @param {string} gateway - имя gateway * @returns {boolean} */ function isValidGateway(gateway) { if (!gateway || typeof gateway !== 'string') return false; const g = gateway.trim(); // MikroTik gateway: буквы, цифры, дефис, подчеркивание // Длина: 1-64 символа if (g.length < 1 || g.length > 64) return false; const gatewayRegex = /^[a-zA-Z0-9_-]+$/; return gatewayRegex.test(g); } /** * Санитизация строки от опасных символов * @param {string} str - входная строка * @returns {string} */ function sanitizeString(str) { if (!str || typeof str !== 'string') return ''; // Удаляем управляющие символы let cleaned = str.replace(/[\x00-\x1F\x7F]/g, ''); // Экранируем HTML специальные символы cleaned = cleaned .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') .replace(/'/g, ''') .replace(/\//g, '/'); return cleaned.trim(); } /** * Проверка на SQL injection паттерны * @param {string} str - строка для проверки * @returns {boolean} true если безопасно */ function isSafeSQLString(str) { if (!str || typeof str !== 'string') return true; const dangerousPatterns = [ /(\bSELECT\b|\bINSERT\b|\bUPDATE\b|\bDELETE\b|\bDROP\b|\bCREATE\b)/i, /(\bUNION\b|\bJOIN\b)/i, /(--|;|\/\*|\*\/)/, /(\bOR\b|\bAND\b)\s+\d+\s*=\s*\d+/i, ]; return !dangerousPatterns.some(pattern => pattern.test(str)); } /** * Проверка на XSS паттерны * @param {string} str - строка для проверки * @returns {boolean} true если безопасно */ function isSafeXSSString(str) { if (!str || typeof str !== 'string') return true; const dangerousPatterns = [ /