Проверка поддоменов

Поддомен представляет собой часть доменной структуры, расположенную слева от основного домена. Например, в api.example.com поддоменом является api, а в v1.api.example.com — уже цепочка поддоменов v1.api.

Структурно доменные имена подчиняются строгим правилам:

  • общая длина домена — до 253 символов;
  • каждая метка (label) — до 63 символов;
  • допустимы буквы, цифры и дефис;
  • нельзя начинать или заканчивать метку дефисом;
  • допускается использование IDN-доменов (Unicode через Punycode).

Подходы к проверке поддоменов

Валидация поддоменов в JavaScript обычно решается не одной функцией, а комбинацией инструментов:

  • проверка корректности доменного имени;
  • выделение хоста из URL;
  • анализ количества уровней домена;
  • проверка допустимых символов;
  • контроль зон доверия (whitelist/blacklist).

Библиотека Validator.js предоставляет базовые функции, которые можно использовать как основу.


Использование isFQDN для проверки домена

Основной инструмент — isFQDN (Fully Qualified Domain Name).

const validator = require('validator');

validator.isFQDN('example.com');

Функция возвращает true для корректных доменов и false для некорректных.

Проверка поддоменов через FQDN

По умолчанию isFQDN не ограничивает наличие поддоменов, но позволяет валидировать всю структуру домена.

validator.isFQDN('api.example.com'); // true
validator.isFQDN('example.com');     // true

Настройки isFQDN

Функция поддерживает параметры, влияющие на строгую проверку:

validator.isFQDN('api.example.com', {
  require_tld: true,
  allow_underscores: false,
  allow_numeric_tld: false,
  allow_trailing_dot: false
});

Значение параметров

require_tld

  • требует наличие зоны (.com, .ru и т.д.)
  • полезно для исключения localhost

allow_underscores

  • разрешает символ _
  • обычно отключается для строгих стандартов DNS

allow_numeric_tld

  • разрешает числовые TLD (редкий случай)

allow_trailing_dot

  • допускает example.com.

Проверка именно поддомена (уровней домена)

Validator.js не предоставляет отдельной функции “isSubdomain”, поэтому используется логика анализа структуры.

Разделение домена на части

const domain = 'api.v1.example.com';
const parts = domain.split('.');

Результат:

['api', 'v1', 'example', 'com']

Проверка количества уровней

function hasSubdomain(domain) {
  const parts = domain.split('.');
  return parts.length > 2;
}

hasSubdomain('example.com');        // false
hasSubdomain('api.example.com');    // true

Проверка через isURL

При работе с URL часто требуется извлечь хост:

const validator = require('validator');

const url = 'https://api.example.com/users';
validator.isURL(url);

Извлечение hostname

Современный способ — использовать встроенный URL:

const hostname = new URL('https://api.example.com/users').hostname;
// api.example.com

Далее применяется валидация:

validator.isFQDN(hostname);

Проверка конкретного поддомена

Иногда требуется убедиться, что поддомен равен определённому значению.

function isApiSubdomain(url) {
  const hostname = new URL(url).hostname;
  return hostname.startsWith('api.');
}

isApiSubdomain('https://api.example.com'); // true

Глубина поддоменов

Для некоторых систем важно количество уровней:

  • example.com — основной домен
  • api.example.com — 1 уровень поддомена
  • v1.api.example.com — 2 уровня
function getSubdomainDepth(domain) {
  return domain.split('.').length - 2;
}

getSubdomainDepth('api.example.com');       // 1
getSubdomainDepth('v1.api.example.com');    // 2

Фильтрация разрешённых поддоменов

Часто используется whitelist:

const allowed = ['api', 'admin', 'cdn'];

function isAllowedSubdomain(domain) {
  const hostname = new URL(domain).hostname;
  const sub = hostname.split('.')[0];
  return allowed.includes(sub);
}

Ограничения и крайние случаи

localhost и тестовые зоны

validator.isFQDN('localhost'); // false (при require_tld: true)

Для разработки:

validator.isFQDN('localhost', { require_tld: false });

IP-адреса вместо домена

validator.isFQDN('192.168.0.1'); // false
validator.isIP('192.168.0.1');    // true

IDN-домены (Unicode)

validator.isFQDN('пример.рф');

Validator.js обрабатывает такие случаи через Punycode-представление:

'xn--e1afmkfd.xn--p1ai'

Регулярные выражения как альтернатива

Иногда применяется ручная проверка:

const subdomainRegex = /^([a-z0-9-]+\.)+[a-z]{2,}$/i;

subdomainRegex.test('api.example.com');

Недостатки:

  • не учитывает IDN без дополнительной обработки;
  • легко ошибиться с краевыми случаями;
  • требует постоянного обновления.

Комбинированная стратегия валидации

На практике используется связка:

function validateSubdomain(url) {
  if (!validator.isURL(url)) return false;

  const hostname = new URL(url).hostname;

  if (!validator.isFQDN(hostname)) return false;

  const parts = hostname.split('.');

  return parts.length >= 3;
}

Типовые сценарии использования

API маршрутизация по поддомену

/api.example.com
/admin.example.com

Проверка:

const sub = new URL(req.url).hostname.split('.')[0];

Мультитенантные системы

client1.app.com
client2.app.com
function getTenant(url) {
  return new URL(url).hostname.split('.')[0];
}

Защита от подмены домена

function isTrustedDomain(url) {
  const hostname = new URL(url).hostname;
  return validator.isFQDN(hostname) && hostname.endsWith('.example.com');
}

Ошибки при проверке поддоменов

Игнорирование глубины домена

example.com       // допустим
evil.example.com  // тоже допустим без проверки уровня

Неполная проверка URL

validator.isFQDN('api.example.com/login'); // ошибка логики

Hostname нужно извлекать отдельно.


Доверие пользовательскому вводу

api.example.com.evil.com

Формально валидный домен, но логически другой. Поэтому важна проверка суффикса:

hostname.endsWith('.example.com')

Практическая модель валидации поддоменов

function isValidSubdomain(url, rootDomain) {
  if (!validator.isURL(url)) return false;

  const hostname = new URL(url).hostname;

  if (!validator.isFQDN(hostname)) return false;

  return hostname === rootDomain || hostname.endsWith('.' + rootDomain);
}

Такой подход позволяет контролировать:

  • структуру домена;
  • допустимые поддомены;
  • защиту от подмен.