完全合格的域名验证

时间:2012-08-04 15:09:22

标签: regex bash fqdn

是否有快速而肮脏的方法来验证是否输入了正确的FQDN?请记住,没有DNS服务器或Internet连接,因此必须通过regex / awk / sed进行验证。

有什么想法吗?

6 个答案:

答案 0 :(得分:37)

(?=^.{4,253}$)(^((?!-)[a-zA-Z0-9-]{1,63}(?<!-)\.)+[a-zA-Z]{2,63}$)

正则表达式总是充其量只是这样的事情的近似,规则会随着时间的推移而变化。以上正则表达式的编写考虑了以下内容,特定于主机名 -

主机名由一系列与点连接的标签组成。 每个标签长度为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
  • 我们希望至少比TLD高1级

结果:有效/无效

  • 911.gov - 有效
  • 911 - 无效(无TLD)
  • a-.com - 无效
  • -a.com - 无效
  • a.com - 有效
  • a.66 - 无效
  • my_host.com - 无效(非挑剔)
  • typical-hostname33.whatever.co.uk - 有效

编辑: John Rix提供了正则表达式的替代方法,以使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不支持正则表达式。 具体来说,代码(?<!-) - 指定前一个字符不能是连字符。

无论如何,在这里它被重写而没有外观 - 有点丑陋但不是很多

(?=^.{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指出它们并且我做了一些研究

然而,使用尾随点似乎会在我使用的各种工具中产生一些不可预测的结果,所以我会建议谨慎。

答案 1 :(得分:11)

现在更难了,国际化域名和数千个(!)新顶级域名。

简单的一点是,您仍然可以在&#34;。&#34;上拆分组件。

您需要一份可注册的TLD列表。有一个网站:

https://publicsuffix.org/list/effective_tld_names.dat

您只需要查看ICANN认可的内容。请注意,可注册TLD可以包含多个组件,例如&#34; co.uk&#34;。

然后是IDN和punycode。域名现在是Unicode。例如,

&#34; XN - nnx388a&#34;相当于&#34;台湾&#34;。顺便提一下,这两个都是有效的顶级域名。

对于punycode转换代码,请参阅&#34; http://golang.org/src/pkg/net/http/cookiejar/punycode.go&#34;。

检查每个域组件的语法也有新规则。请参阅RFC5890 at  http://tools.ietf.org/html/rfc5890

组件可以是A标签(仅限ASCII)或Unicode。 ASCII标签要么遵循旧语法,要么开始&#34; xn - &#34;,在这种情况下它们是punycode Unicode字符串的版本。

Unicode规则非常复杂,在RFC5890中给出。这些规则旨在防止从左到右和从右到左集合混合字符。

很抱歉,没有简单的答案。

答案 2 :(得分:6)

这个正则表达式是你想要的:

(?=^.{1,254}$)(^(?:(?!\d+\.)[a-zA-Z0-9_\-]{1,63}\.?)+(?:[a-zA-Z]{2,})$)

它符合您的示例域名(groupa-zone1appserver.example.com或cod.eu等...)

我会试着解释一下:

(?=^.{1,254}$)匹配长度在1到254个字符之间的域名(可以以任何字符开头),如果我们假设co.uk是最小长度,则它也可以是5,254。

(^开始比赛

(?:定义匹配组

(?!\d+\.)域名不应由数字组成,因此不接受1234.co.uk或abc.123.uk,而1a.ko.uk是。

[a-zA-Z0-9_\-]域名应由仅包含a-zA-Z0-9的单词组成_-

{1,63}任何域级别的长度最多为63个字符,(可能是2,63)

+

(?:[a-zA-Z]{2,})$)域名的最后部分不应该跟任何其他单词,并且必须由最少2个字符a-zA-Z

组成。

答案 3 :(得分:2)

考虑因素#1:

请注意,由于RFC-2181中的宽松要求,DNS标签可以包含几乎任何符号组合(但是,长度限制仍然存在):

&#34; 任何二进制字符串,可以用作任何资源记录的标签。 DNS协议的实现不得对可以使用的标签施加任何限制。特别是,DNS服务器不得拒绝为区域提供服务,因为它包含某些DNS客户端程序可能无法接受的标签。&#34; (https://tools.ietf.org/html/rfc2181#section-11

考虑因素#2:

&#34;还有一条额外规则,基本上要求顶级域名不是全数字&#34; https://tools.ietf.org/html/rfc3696#section-2

考虑到这两个考虑因素,正确的正则表达式如下所示:

/^(?!:\/\/)(?=.{1,255}$)((.{1,63}\.){1,127}(?![0-9]*$)[a-z0-9-]+\.?)$/i

参见demo @ http://regexr.com/3g5j0

答案 4 :(得分:0)

以下表达式

(^((?=^.{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

答案 5 :(得分:0)

We use此正则表达式可验证野外出现的域。它涵盖了我所知道的所有实际用例。欢迎新的。根据{{​​3}},它避免了非捕获组和贪婪匹配。

^(?!.*?_.*?)(?!(?:[\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})$

证明和解释:our guidelines

验证域时,有两种方法可供选择。

按书中的FQDN匹配(理论上的定义,在实践中很少遇到):

实用/保守的FQDN匹配(实践定义,在实践中应得到预期和支持):

  • 按书进行匹配,但具有以下例外/补充内容
  • 有效字符:[a-zA-Z0-9.-]
  • 标签不能以连字符开头或结尾(根据RFC-3696/2RFC-952
  • TLD的最小长度为2个字符,根据当前现有记录的最大长度为24个字符
  • 不匹配尾随点