Полноценная проверка имени домена
Есть ли быстрый и грязный способ проверки правильности ввода FQDN? Имейте в виду, что DNS-сервер или подключение к Интернету отсутствует, поэтому проверка должна выполняться с помощью regex/awk/sed.
Любые идеи?
Ответы
Ответ 1
Сейчас это сложнее, с интернационализированными доменными именами и несколькими тысячами (!) Новых TLD.
Легкая часть состоит в том, что вы все равно можете разбить компоненты на ".".
Вам нужен список регистрируемых TLD. Там сайт для этого:
https://publicsuffix.org/list/effective_tld_names.dat
Вам нужно только проверить признанные ICANN. Обратите внимание, что регистрируемый TLD может иметь более одного компонента, например, "co.uk".
Тогда есть IDN и punycode. Домены теперь Unicode. Например,
"xn-- nnx388a" эквивалентен "臺灣". Кстати, оба из них являются действительными TLD.
Для кода преобразования punycode см. " Http://golang.org/src/pkg/net/http/cookiejar/punycode.go ".
Проверка синтаксиса каждого компонента домена также содержит новые правила. См. RFC5890 по адресу http://tools.ietf.org/html/rfc5890.
Компонентами могут быть либо A-метки (только ASCII), либо Unicode. Символы ASCII либо следуют за старым синтаксисом, либо начинаются с "xn--", и в этом случае они представляют собой штрафную версию строки Unicode.
Правила для Unicode очень сложны и приведены в RFC5890. Правила предназначены для предотвращения таких вещей, как смешивание символов слева-направо и справа налево.
Извините, нет легкого ответа.
Ответ 2
(?=^.{4,253}$)(^((?!-)[a-zA-Z0-9-]{1,63}(?<!-)\.)+[a-zA-Z]{2,63}$)
regex всегда будет в лучшем случае приблизительным для таких вещей, и правила меняются со временем. указанное выше регулярное выражение было написано с учетом того, что является специфичным для имен хостов -
Hostnames состоят из серии меток, объединенных с точками.
Каждая метка длиной от 1 до 63 символов и может содержать:
- ASCII-буквы a-z (нечувствительным к регистру),
- цифры 0-9,
- и дефис ('-').
Дополнительно:
- метки не могут начинаться или заканчиваться дефисами (RFC 952)
- метки могут начинаться с цифр (RFC 1123)
- максимальная длина имени ascii, включая точки, составляет 253 символа (не считая конечной точки)
(http://blogs.msdn.com/b/oldnewthing/archive/2012/04/12/10292868.aspx)
- подчеркивания недопустимы в именах хостов (но разрешены в других типах DNS)
некоторые предположения:
- TLD имеет не менее 2 символов и только a-z
- мы хотим как минимум 1 уровень выше TLD
results: valid/invalid
- 911.gov - действительный
- 911 - недействительный (без TLD)
- a-.com - недействительный
- -a.com - недействительный
- a.com - действительный
- a.66 - недействительный
- my_host.com - недействительный (undescore)
- standard-hostname33.whatever.co.uk - действительный
EDIT:
Джон Рикс предоставил альтернативный хак регулярного выражения, чтобы уточнить спецификацию TLD:
(?=^.{1,253}$)(^(((?!-)[a-zA-Z0-9-]{1,63}(?<!-))|((?!-)[a-zA-Z0-9-]{1,63}(?<!-)\.)+[a-zA-Z]{2,63})$)
- 911 - действительный
- 911.gov - действительный
ИЗМЕНИТЬ 2:
кто-то попросил версию, которая работает в js.
причина, по которой это не работает в js, состоит в том, что js не поддерживает регулярное выражение.
в частности, код (?<!-)
- который указывает, что предыдущий символ не может быть дефис.
в любом случае, здесь он переписан без lookbehind - немного уродливее, но не намного
(?=^.{4,253}$)(^((?!-)[a-zA-Z0-9-]{0,62}[a-zA-Z0-9]\.)+[a-zA-Z]{2,63}$)
вы также можете сделать аналогичную замену версии John Rix.
РЕДАКТИРОВАТЬ 3: если вы хотите разрешить конечные точки - это технически разрешено:
(?=^.{4,253}$)(^((?!-)[a-zA-Z0-9-]{1,63}(?<!-)\.)+[a-zA-Z]{2,63}\.?$)
Я не был знаком с синтаксисом отстающих точек до тех пор, пока @ChaimKut не указал их, и я провел некоторое исследование
Использование конечных точек, однако, кажется, вызывает несколько непредсказуемых результатов в различных инструментах, с которыми я играл, поэтому я бы посоветовал немного предостережения.
Ответ 3
Это регулярное выражение - это то, что вы хотите:
(?=^.{1,254}$)(^(?:(?!\d+\.)[a-zA-Z0-9_\-]{1,63}\.?)+(?:[a-zA-Z]{2,})$)
Он соответствует вашему примеру домена (groupa-zone1appserver.example.com или cod.eu и т.д.)
Я попытаюсь объяснить:
(?=^.{1,254}$)
соответствует именам доменов (которые могут начинаться с любого char), которые длинные между 1 и 254 char, это также может быть 5 254, если мы предположим, что co.uk - минимальная длина.
(^
начало матча
(?:
определить группу соответствия
(?!\d+\.)
имя домена не должно быть составлено числами, поэтому 1234.co.uk или abc.123.uk не принимаются в то время как 1a.ko.uk да.
[a-zA-Z0-9_\-]
имена доменов должны быть составлены словами только с помощью a-zA-Z0-9 _-
{1,63}
длина любого уровня домена не более 63 char (это может быть 2,63)
+
и
(?:[a-zA-Z]{2,})$)
конечная часть имени домена не должна сопровождаться каким-либо другим словом и должна состоять из слова минимум 2 char a-zA-Z
Ответ 4
РАССМОТРЕНИЕ № 1:
Обратите внимание, что из-за непринужденных требований в RFC-2181 метки DNS могут состоять из почти любой комбинации символов (однако ограничения по длине все еще существуют):
"Любая двоичная строка, которая может использоваться как метка любой записи ресурса. Реализации DNS-протоколов не должны устанавливать ограничений на метки, которые могут быть использованы. В частности, DNS-серверы не должны отказываться от обслуживания зоны, потому что он содержит метки, которые могут быть неприемлемыми для некоторых клиентских программ DNS". (https://tools.ietf.org/html/rfc2181#section-11)
РАССМОТРЕНИЕ # 2:
"Существует дополнительное правило, которое по существу требует, чтобы имена доменов верхнего уровня не были все-числовыми" (https://tools.ietf.org/html/rfc3696#section-2)
Учитывая эти два соображения, правильное регулярное выражение выглядит так:
/^(?!:\/\/)(?=.{1,255}$)((.{1,63}\.){1,127}(?![0-9]*$)[a-z0-9-]+\.?)$/i
См. демонстрацию @http://regexr.com/3g5j0
Ответ 5
Следующее выражение
(^((?=^.{4,253}$)(((http){0,1}|(http){0,1}|(ftp){0,1}|(ws){0,1})(s{0,1}):\/\/){0,1})((((?!-)[\pL0-9\-]{1,63})(?<!-)(\.)){1,})(((?!-)[a-z0-9\-]{1,63})(?<!-)((\/{0,1}[\pL\pN?=\-]*)+){1})$)
будет соответствовать
https://www.tes1t.com/lets/to?878932572
https://www.test.co.uk/lets/to?878932572
http://www.test.com/lets/to?878932572
http://www.test.co.uk/lets/to?878932572
ftp://www.test.com/lets/to?878932572
subdomain.test.com/lets/to?878932572
subdomain.test.com/lets/to?878932572
subdomain.subdomain.test.net/lets/to?878932572
sub-domain.test.net/lets/to?878932572
sub-domain.test.net/lets-go/to?878932572
www.test.net/lets/to?878932572
www.test-test.com/
www.test-test.com
subdomain.subdomainsubdomainsuèdomainsubdomainsubdomainsubdomainsubdomain.net/let2s/to?=878932572
www.test-test.co.uk
http://www.test-test-.com/test
www.test-teèst.co.uk/lets
www.test-test.co.uk/lets/
www.test-test.co.uk/lets/to?
test-test.co.uk/lets/to?
test-test.co.uk/lets/
test-test.co.uk/lets
test-test.co.uk
http://test.com/lets/to?878932572
https://test.com/lets/to?878932572
ftp://test.com/lets/to?878932572
ftps://test.com/lets/to?878932572
ws://test.com/lets/to?878932572aa
wss://test.com/lets/to?=878932572bar
test.com
subdomain.test.test.test.test.test.test.test.test.test.test.test.test.test.test.test.test.test.test.test.test.test.test.test.test.test.test.test.test.test.test.test.test.khbdomainsubdomainsubdomain.test.net/lets/to?87893257
но не совпадают:
www.-test-fail-.com
www.-test-fail.com
-test-fail.com
test-fail-.com
subdomain.subdomainsubdomainsubdomainsubdomainsubdomainsubdomainsubdomainsubdomainsubdomainsubdomainubdomainsubdomainsubdomain.test.net/lets/to?878932572
subdomain.subdomainsubdomainsubdcnvcnvcnofhfhghgfhvnhj-mainsubdomainsubdohhghghghfhgffgjh-gfhfdhfdghmainsubdocgvhngvnbnbmghghghaihgfjgfnfhfdghgsufghgghghhdfjgffsgfbdomainsubdomainsubdomainsubdomainsubdomainsubdomainsubdomain.test.net/lets/to?878932572
subdomain.test.test..test..test..test..test..test..test..test..test..test..test..test..test..test..test..test..test..test..test..test..test..test..test..test..test..test..test..test..test..test..test.khbdomainsubdomainsubdomain.test.net/lets/to?87893257
Ответ 6
Мы используем это регулярное выражение для проверки доменов, которые встречаются в дикой природе. Он охватывает все случаи практического использования, о которых я знаю. Новые приветствуются. Согласно нашим рекомендациям, это позволяет избежать групп захвата и жадного сопоставления.
^(?!.*?_.*?)(?!(?:[\d\w]+?\.)?\-[\w\d\.\-]*?)(?![\w\d]+?\-\.(?:[\d\w\.\-]+?))(?=[\w\d])(?=[\w\d\.\-]*?\.+[\w\d\.\-]*?)(?![\w\d\.\-]{254})(?!(?:\.?[\w\d\-\.]*?[\w\d\-]{64,}\.)+?)[\w\d\.\-]+?(?<![\w\d\-\.]*?\.[\d]+?)(?<=[\w\d\-]{2,})(?<![\w\d\-]{25})$
Доказательство и объяснение: https://regex101.com/r/FLA9Bv/9
При проверке доменов можно выбрать один из двух подходов.
Соответствие полному доменному имени (теоретическое определение, редко встречающееся на практике):
- длина не более 253 символов (согласно RFC-1035/3.1, RFC-2181/11)
- не более 63 символов на этикетку (согласно RFC-1035/3.1, RFC-2181/11)
- разрешены любые символы (согласно RFC-2181/11)
- TLD не могут быть полностью числовыми (согласно RFC-3696/2)
- Полные доменные имена могут быть записаны в полной форме, которая включает корневую зону (конечная точка)
Практическое/консервативное сопоставление FQDN (практическое определение, ожидаемое и поддерживаемое на практике):
- соответствие книг со следующими исключениями/дополнениями
- допустимые символы:
[a-zA-Z0-9.-]
- метки не могут начинаться или заканчиваться дефисами (согласно RFC-952 и RFC-1123/2.1)
- Минимальная длина TLD - 2 символа, максимальная длина - 24 символа в соответствии с текущими записями.
- не соответствует конечной точке