正则表达式中的私有 IP 地址标识符

发布于 2024-09-01 08:34:39 字数 173 浏览 3 评论 0原文

我想知道这是否是匹配以私有 IP 地址(Perl 样式正则表达式)开头的字符串的最佳方式:

(^127\.0\.0\.1)|(^192\.168)|(^10\.)|(^172\.1[6-9])|(^172\.2[0-9])|(^172\.3[0-1])

非常感谢!

I'm wondering if this is the best way to match a string that starts with a private IP address (Perl-style Regex):

(^127\.0\.0\.1)|(^192\.168)|(^10\.)|(^172\.1[6-9])|(^172\.2[0-9])|(^172\.3[0-1])

Thanks much!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(15

∞梦里开花 2024-09-08 08:34:39

我假设您想要匹配这些范围:

127.  0.0.0 – 127.255.255.255     127.0.0.0 /8
 10.  0.0.0 –  10.255.255.255      10.0.0.0 /8
172. 16.0.0 – 172. 31.255.255    172.16.0.0 /12
192.168.0.0 – 192.168.255.255   192.168.0.0 /16

您缺少一些点,这些点会导致它接受例如 172.169.0.0 即使这不应该被接受。我已经在下面修复了它。删除新行,只是为了便于阅读。

(^127\.)|
(^10\.)|
(^172\.1[6-9]\.)|(^172\.2[0-9]\.)|(^172\.3[0-1]\.)|
(^192\.168\.)

另请注意,这假设 IP 地址已经过验证 - 它接受诸如 10.foobar 之类的内容。

I'm assuming you want to match these ranges:

127.  0.0.0 – 127.255.255.255     127.0.0.0 /8
 10.  0.0.0 –  10.255.255.255      10.0.0.0 /8
172. 16.0.0 – 172. 31.255.255    172.16.0.0 /12
192.168.0.0 – 192.168.255.255   192.168.0.0 /16

You are missing some dots that would cause it to accept for example 172.169.0.0 even though this should not be accepted. I've fixed it below. Remove the new lines, it's just for readability.

(^127\.)|
(^10\.)|
(^172\.1[6-9]\.)|(^172\.2[0-9]\.)|(^172\.3[0-1]\.)|
(^192\.168\.)

Also note that this assumes that the IP addresses have already been validated - it accepts things like 10.foobar.

这与 Mark 的正确答案相同,但现在包括 IPv6 私有地址。

/(^127\.)|(^192\.168\.)|(^10\.)|(^172\.1[6-9]\.)|(^172\.2[0-9]\.)|(^172\.3[0-1]\.)|(^::1$)|(^[fF][cCdD])/

This is the same as the correct answer by Mark, but now including IPv6 private addresses.

/(^127\.)|(^192\.168\.)|(^10\.)|(^172\.1[6-9]\.)|(^172\.2[0-9]\.)|(^172\.3[0-1]\.)|(^::1$)|(^[fF][cCdD])/
终止放荡 2024-09-08 08:34:39

我已经为 A 类网络生成了这个

正则表达式:

(10)(\.([2]([0-5][0-5]|[01234][6-9])|[1][0 -9][0-9]|[1-9][0-9]|[0-9])){3}

B 类网络的正则表达式:

(172)\.(1 [6-9]|2[0-9]|3[0-1])(\.(2[0-4][0-9]|25[0-5]|[1][0-9 ][0-9]|[1-9][0-9]|[0-9])){2}

C 类网络的正则表达式:

(192)\.(168)( \.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9] )){2}

如果您遇到任何错误,请告诉我

如果您确定自己的输出(例如 netstat)并且您无需检查 IP 地址有效性,因为它已经完成,那么您可以使用以下公式捕获私有 IP 地址

grep -P "(10.|192.168|172.1[6-9].|172.2[0-9].|172.3[01].).* "

I have generated this

REGEXP FOR CLASS A NETWORKS :

(10)(\.([2]([0-5][0-5]|[01234][6-9])|[1][0-9][0-9]|[1-9][0-9]|[0-9])){3}

REGEXP FOR CLASS B NETWORKS :

(172)\.(1[6-9]|2[0-9]|3[0-1])(\.(2[0-4][0-9]|25[0-5]|[1][0-9][0-9]|[1-9][0-9]|[0-9])){2}

REGEXP FOR CLASS C NETWORKS :

(192)\.(168)(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])){2}

Let me know if you encounter any error

If you are sure of your output (say for example netstat) and you have no need to check about IP address validity because it is already done, then you can catch private ip addresses with this formula

grep -P "(10.|192.168|172.1[6-9].|172.2[0-9].|172.3[01].).* "

心的位置 2024-09-08 08:34:39

这是我在 python 中使用的:

rfc1918 = re.compile('^(10(\.(25[0-5]|2[0-4][0-9]|1[0-9]{1,2}|[0-9]{1,2})){3}|((172\.(1[6-9]|2[0-9]|3[01]))|192\.168)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{1,2}|[0-9]{1,2})){2})

如果您愿意,您可以删除 ^ 和/或 $ 锚点。

我更喜欢上面的正则表达式,因为它会清除无效的八位字节(任何高于 255 的字节)。

用法示例:

if rfc1918.match(ip):
    print "ip is private"
)

如果您愿意,您可以删除 ^ 和/或 $ 锚点。

我更喜欢上面的正则表达式,因为它会清除无效的八位字节(任何高于 255 的字节)。

用法示例:

here is what I use in python:

rfc1918 = re.compile('^(10(\.(25[0-5]|2[0-4][0-9]|1[0-9]{1,2}|[0-9]{1,2})){3}|((172\.(1[6-9]|2[0-9]|3[01]))|192\.168)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{1,2}|[0-9]{1,2})){2})

You can remove the ^ and/or $ anchors if you wish.

I prefer the above regex because it weeds out invalid octets (anything above 255).

example usage:

if rfc1918.match(ip):
    print "ip is private"
)

You can remove the ^ and/or $ anchors if you wish.

I prefer the above regex because it weeds out invalid octets (anything above 255).

example usage:

强者自强 2024-09-08 08:34:39

这是为了防止您决定接受我的评论,建议您不要使用正则表达式。未经测试(但可能有效,或至少接近),在 Perl 中:

@private = (
    {network => inet_aton('127.0.0.0'),   mask => inet_aton('255.0.0.0')   },
    {network => inet_aton('192.168.0.0'), mask => inet_aton('255.255.0.0') },
    # ...
);

$ip = inet_aton($ip_text);
if (grep $ip & $_->{mask} == $_->{network}, @private) {
    # ip address is private
} else {
    # ip address is not private
}

现在请注意 @private 只是数据,您可以轻松更改它。或者从 Cymru Bogon 参考 即时下载。

编辑:在我看来,要求 Perl 正则表达式并不意味着您了解 Perl,因此关键行是“grep”,它只是在每个私有地址范围上循环。您按位获取 IP 和网络掩码,然后与网络地址进行比较。如果相等,则它是该专用网络的一部分。

This is in case you decide to go with my comment, suggesting you don't use regexps. Untested (but probably works, or at least close), in Perl:

@private = (
    {network => inet_aton('127.0.0.0'),   mask => inet_aton('255.0.0.0')   },
    {network => inet_aton('192.168.0.0'), mask => inet_aton('255.255.0.0') },
    # ...
);

$ip = inet_aton($ip_text);
if (grep $ip & $_->{mask} == $_->{network}, @private) {
    # ip address is private
} else {
    # ip address is not private
}

Note now how @private is just data, which you can easily change. Or download on the fly from the Cymru Bogon Reference.

edit: It occurs to me that asking for a Perl regexp doesn't mean you know Perl, so the key line is there is the 'grep', which just loops over each private address range. You take your IP, bitwise and it with the netmask, and compare to the network address. If equal, its part of that private network.

任性一次 2024-09-08 08:34:39

看起来不错。就我个人而言,我会将第一个更改为:

^127\.0 

通过此:(^127\.0\.0\.1),您可以查找以127.0.0.1开头的任何内容> 并且会错过 127.0.0.2*127.0.2.*127.0.* 等。

Looks right. Personally, I'd change the first one to:

^127\.0 

With this: (^127\.0\.0\.1) you looking for anything that starts with 127.0.0.1 and will miss out on 127.0.0.2*, 127.0.2.*, 127.0.* etc.

∝单色的世界 2024-09-08 08:34:39

晚了10年。感谢 Mark ByersbrampEdwardblueyeduser3177026贾斯汀karmakaze罗恩·莫平

回答 TLDR

仅开头

请删除换行符 - 这只是为了更容易阅读:

^(?:
127\.|
0?10\.|
172\.0?1[6-9]\.|
172\.0?2[0-9]\.|
172\.0?3[01]\.|
192\.168\.|
169\.254\.|
::1|
[fF][cCdD][0-9a-fA-F]{2}:|
[fF][eE][89aAbB][0-9a-fA-F]:
)

括号开头的 ?: 意味着该括号未被捕获,可能会使其更快一点。

请小心反斜杠。例如,在 Postgres 中,您必须使用 E 字符串,并且必须使用反斜杠转义反斜杠 - 或者只使用 [.] 而不是 E'\\.'

整个IP(小数,前导零可选,最多三位)

请删除换行符 - 这只是为了更容易阅读:

\b(
127\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|
0?10\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|
172\.0?1[6-9]\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|
172\.0?2[0-9]\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|
172\.0?3[01]\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|
192\.168\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|
169\.254\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|
::1|
[fF][cCdD][0-9a-fA-F]{2}(?:[:][0-9a-fA-F]{0,4}){0,7}|
[fF][eE][89aAbB][0-9a-fA-F](?:[:][0-9a-fA-F]{0,4}){0,7}
)
(?:\/([789]|1?[0-9]{2}))?
\b

https://regex101.com/r/JCLOZL/14(备份:https://etherpad.wikimedia.org/p/JCLOZL)

详细信息

IPv4

  127.0.0.0 to 127.255.255.255 is   127.0.0.0/8   # localhost, loopback etc.
   10.0.0.0 to  10.255.255.255 is    10.0.0.0/8   # approximately/formerly class A
 172.16.0.0 to  172.31.255.255 is  172.16.0.0/12  # approximately/formerly class B
192.168.0.0 to 192.168.255.255 is 192.168.0.0/16  # approximately/formerly class C
169.254.0.0 to 169.254.255.255 is 169.254.0.0/16  # link-local addresses since 2005

示例:

172.17.50.33 or more explicit:
172.17.50.33/32

我不确定斜杠后面的部分是否可以有前导零(不太可能),但 IP 可以有前导零。

带有前导零(十进制)的 IPv4

127.000.000.000 to 127.255.255.255 is 127.000.000.000/8   # localhost, loopback etc.
010.000.000.000 to 010.255.255.255 is 010.000.000.000/8   # approx/formerly class A
172.016.000.000 to 172.031.255.255 is 172.016.000.000/12  # approx/formerly class B
192.168.000.000 to 192.168.255.255 is 192.168.000.000/16  # approx/formerly class C
169.254.000.000 to 169.254.255.255 is 169.254.000.000/16  # link-local addresses

示例:

172.017.050.033 or more explicit:
172.017.050.033/32

带有前导零(八进制)的 IPv4

在我的正则表达式中不受支持。为了使您的程序完美,请检查八进制 IP 地址和/或超过三位数字并警告用户!

0177.0000.0000.0000 to 0177.0377.0377.0377 is 0177.0000.0000.0000/8   # loopback
0012.0000.0000.0000 to 0012.0377.0377.0377 is 0012.0000.0000.0000/8   # A
0254.0020.0000.0000 to 0254.0037.0377.0377 is 0254.0020.0000.0000/12  # B
0300.0250.0000.0000 to 0300.0250.0377.0377 is 0300.0250.0000.0000/16  # C
0251.0376.0000.0000 to 0251.0376.0377.0377 is 0251.0376.0000.0000/16  # link-local

示例:

0254.0021.0062.0041 or more explicit:
0254.0021.0062.0041/32

是的,172.017.050.033 在不同工具上与 0254.0021.0062.0041 相同。在 macOS 上使用 ping 进行测试。

当然,您也可以在某些工具中混合十进制(无前导零)和八进制(至少一个前导零)。 :S

IPv6

fc00:0000:… to fdff:ffff:… is fc00::/7
fe80:0000:… to febf:ffff:… is fe80::/10  # link-local addresses

这可能不完全是您想要的,因为:

私有 IPv4 地址是由 RFC 1918“私有互联网地址分配”定义的,并且这些地址在多个网络中使用。 IPv6 ULA 地址应该是唯一的(ULA 中的“U”),不能在多个地方重复使用,这就是它们需要在全局 ID 中具有 40 个随机位的原因,从而对唯一性抱有很高的期望。

来自公共互联网的所有地址都在 2000::3fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff (2000::/3)。
您需要正确屏蔽地址以查看它是否在公共范围内,然后对公共范围内的非公共范围执行相同的操作。如果它通过了公共范围测试,则它必须无法通过公共范围内的非公共范围。如果它通过了所有这些,那么它就是一个公共地址。
IOT 设备还获得全球(公共)IPv6 地址。 IPv6 的要点在于,有足够的地址,每个设备上的每个接口都可以获得全局 IPv6 地址,恢复了 IP 最初设计的方式(不再需要解决 NAT 混乱问题)。

您的网络服务器内部的某些地址将是链接本地地址 (fe80::/10),并且可以分配 ULA 地址 (fc00::/7 其中您可以从fd00::/8(有一定限制)分配公共互联网上永远不允许的流量。

示例:

fdff:1234:abcd:5678:effe:9098:dcba:7654 or more explicit:
fdff:1234:abcd:5678:effe:9098:dcba:7654/128

不完整的链接列表

当我来到这里时,我不知道:

10 years late. Credits to Mark Byers, bramp, Edward, blueyed, user3177026, Justin, karmakaze, Ron Maupin.

Answer TLDR

Beginning only

Please remove the line breaks - this is just to make it easier to read:

^(?:
127\.|
0?10\.|
172\.0?1[6-9]\.|
172\.0?2[0-9]\.|
172\.0?3[01]\.|
192\.168\.|
169\.254\.|
::1|
[fF][cCdD][0-9a-fA-F]{2}:|
[fF][eE][89aAbB][0-9a-fA-F]:
)

The ?: at the beginning of the parenthesis means that this parenthesis is not captured and may make it a bit faster.

Please be careful with the backslash. In Postgres e.g. you have to use an E string and have to escape the backslash with a backslash - or just use [.] instead of E'\\.'!

The whole IP (decimal, leading zeros optional, max. three digits)

Please remove the line breaks - this is just to make it easier to read:

\b(
127\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|
0?10\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|
172\.0?1[6-9]\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|
172\.0?2[0-9]\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|
172\.0?3[01]\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|
192\.168\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|
169\.254\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|
::1|
[fF][cCdD][0-9a-fA-F]{2}(?:[:][0-9a-fA-F]{0,4}){0,7}|
[fF][eE][89aAbB][0-9a-fA-F](?:[:][0-9a-fA-F]{0,4}){0,7}
)
(?:\/([789]|1?[0-9]{2}))?
\b

https://regex101.com/r/JCLOZL/14 (Backup: https://etherpad.wikimedia.org/p/JCLOZL)

Details

IPv4

  127.0.0.0 to 127.255.255.255 is   127.0.0.0/8   # localhost, loopback etc.
   10.0.0.0 to  10.255.255.255 is    10.0.0.0/8   # approximately/formerly class A
 172.16.0.0 to  172.31.255.255 is  172.16.0.0/12  # approximately/formerly class B
192.168.0.0 to 192.168.255.255 is 192.168.0.0/16  # approximately/formerly class C
169.254.0.0 to 169.254.255.255 is 169.254.0.0/16  # link-local addresses since 2005

Example:

172.17.50.33 or more explicit:
172.17.50.33/32

I'm not sure if the part behind the slash can have leading zeros (unlikely), but the IP can have leading zeros.

IPv4 with leading zeros (decimal)

127.000.000.000 to 127.255.255.255 is 127.000.000.000/8   # localhost, loopback etc.
010.000.000.000 to 010.255.255.255 is 010.000.000.000/8   # approx/formerly class A
172.016.000.000 to 172.031.255.255 is 172.016.000.000/12  # approx/formerly class B
192.168.000.000 to 192.168.255.255 is 192.168.000.000/16  # approx/formerly class C
169.254.000.000 to 169.254.255.255 is 169.254.000.000/16  # link-local addresses

Example:

172.017.050.033 or more explicit:
172.017.050.033/32

IPv4 with leading zeros (octal)

Not supported in my regex. To make your program perfect, check and warn the user about octal IP addresses and/or more than three digits!

0177.0000.0000.0000 to 0177.0377.0377.0377 is 0177.0000.0000.0000/8   # loopback
0012.0000.0000.0000 to 0012.0377.0377.0377 is 0012.0000.0000.0000/8   # A
0254.0020.0000.0000 to 0254.0037.0377.0377 is 0254.0020.0000.0000/12  # B
0300.0250.0000.0000 to 0300.0250.0377.0377 is 0300.0250.0000.0000/16  # C
0251.0376.0000.0000 to 0251.0376.0377.0377 is 0251.0376.0000.0000/16  # link-local

Example:

0254.0021.0062.0041 or more explicit:
0254.0021.0062.0041/32

Yes, 172.017.050.033 is the same as 0254.0021.0062.0041 on different tools. Tested with ping on macOS.

Of course, you can also mix decimal (no leading zero) with octal (at least one leading zero) in some tools. :S

IPv6

fc00:0000:… to fdff:ffff:… is fc00::/7
fe80:0000:… to febf:ffff:… is fe80::/10  # link-local addresses

This might not exactly what you want because:

Private IPv4 addresses are defined by RFC 1918, Address Allocation for Private Internets, and the addresses are used in multiple networks all over. IPv6 ULA addresses are meant to be unique (the "U" in ULA), not to be reused in multiple places, which is the reason they are required to have 40 random bits in the Global ID, giving a high expectation of uniqueness.

All the addresses from the public Internet will be in the range from 2000:: to 3fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff (2000::/3).
You need to properly mask an address to see if it is in the public range, then do the same thing for the non-public ranges in the public range. If it passes the public range test, it must fail the non-public ranges within the public range. If it passes all that, it is a public address.
IOT devices also get Global (public) IPv6 addresses. The point of IPv6 is that there are enough addresses that every interface on every device gets a Global IPv6 address, restoring the way IP was originally designed (no more NAT kludge to work around).

Some addresses internal to your webserver will be Link-Local addresses (fe80::/10), and it is possible to assign ULA addresses (fc00::/7 of which you can assign from fd00::/8 with certain limitations) for traffic that will never be allowed on the public Internet.

Example:

fdff:1234:abcd:5678:effe:9098:dcba:7654 or more explicit:
fdff:1234:abcd:5678:effe:9098:dcba:7654/128

Incomplete link list

When I came here, I did not know about:

客…行舟 2024-09-08 08:34:39

如果您正在寻找 system.net defaultProxy 和代理旁路列表配置,该配置使用外部代理,但使用内部主机的直接连接(可以使用一些 ipv6 支持)...

<system.net>
  <defaultProxy enabled="true">
    <proxy proxyaddress="http://proxycluster.privatedomain.net:8080" bypassonlocal="True"  />
    <bypasslist>
      <!-- exclude local host -->
      <add address="^(http|https)://localhost$" />
      <!-- excludes *.privatedomain.net -->
      <add address="^(http|https)://.*\.privatedomain\.net$" />
      <!-- excludes simple host names -->
      <add address="^(http|https)://[a-z][a-z0-9\-_]*$" />
      <!-- exclude private network addresses 192.168, 172.16..31 through 31, 127.* etc. -->
      <add address="^(http|https)://((((127)|(10))\.[0-9]+\.[0-9]+\.[0-9]+)|(((172\.(1[6-9]|2[0-9]|3[0-1]))|(192\.168))\.[0-9]+\.[0-9]+))$"/>
    </bypasslist>
  </defaultProxy>
  <connectionManagement>
    <add address="*" maxconnection="10" />
  </connectionManagement>
</system.net>

If you're looking for system.net defaultProxy and proxy bypasslist config that uses a proxy for external but uses direct connections for internal hosts (could do with some ipv6 support)...

<system.net>
  <defaultProxy enabled="true">
    <proxy proxyaddress="http://proxycluster.privatedomain.net:8080" bypassonlocal="True"  />
    <bypasslist>
      <!-- exclude local host -->
      <add address="^(http|https)://localhost$" />
      <!-- excludes *.privatedomain.net -->
      <add address="^(http|https)://.*\.privatedomain\.net$" />
      <!-- excludes simple host names -->
      <add address="^(http|https)://[a-z][a-z0-9\-_]*$" />
      <!-- exclude private network addresses 192.168, 172.16..31 through 31, 127.* etc. -->
      <add address="^(http|https)://((((127)|(10))\.[0-9]+\.[0-9]+\.[0-9]+)|(((172\.(1[6-9]|2[0-9]|3[0-1]))|(192\.168))\.[0-9]+\.[0-9]+))$"/>
    </bypasslist>
  </defaultProxy>
  <connectionManagement>
    <add address="*" maxconnection="10" />
  </connectionManagement>
</system.net>
归属感 2024-09-08 08:34:39

这是 Mark Byers 解决方案的紧凑形式:

^(172\.(1[6-9]\.|2[0-9]\.|3[0-1]\.)|192\.168\.|10\.|127\.)

This is the compact form of Mark Byers solution:

^(172\.(1[6-9]\.|2[0-9]\.|3[0-1]\.)|192\.168\.|10\.|127\.)
仅此而已 2024-09-08 08:34:39
     //RegEx to check for the following ranges. IPv4 only
         //172.16-31.xxx.xxx
         //10.xxx.xxx.xxx
         //169.254.xxx.xxx
         //192.168.xxx.xxx

     var regex = /(^127\.)|(^(0)?10\.)|(^172\.(0)?1[6-9]\.)|(^172\.(0)?2[0-9]\.)|(^172\.(0)?3[0-1]\.)|(^169\.254\.)|(^192\.168\.)/;
     //RegEx to check for the following ranges. IPv4 only
         //172.16-31.xxx.xxx
         //10.xxx.xxx.xxx
         //169.254.xxx.xxx
         //192.168.xxx.xxx

     var regex = /(^127\.)|(^(0)?10\.)|(^172\.(0)?1[6-9]\.)|(^172\.(0)?2[0-9]\.)|(^172\.(0)?3[0-1]\.)|(^169\.254\.)|(^192\.168\.)/;
〗斷ホ乔殘χμё〖 2024-09-08 08:34:39

您需要一个结束分隔符才能获取整个第 4 个八位字节,以防它超过一位数字。

^(10.([0-9][0-9]?|[0-1][0-9]?[0-9]?|2[0-4]?[0-9]?|25 [0-5])|172.(1[6-9]|2[0-9]|3[0-1])|192.168).([0-9][0-9]?|[0 -1][0-9]?[0-9]?|2[0-4]?[0-9]?|25[0-5]).([0-9][0-9]? |[0-1][0-9]?[0-9]?|2[0-4]?[0-9]?|25[0-5])$

You need an end separator in order to get the whole 4-th octet in case it is more than one digit.

^(10.([0-9][0-9]?|[0-1][0-9]?[0-9]?|2[0-4]?[0-9]?|25[0-5])|172.(1[6-9]|2[0-9]|3[0-1])|192.168).([0-9][0-9]?|[0-1][0-9]?[0-9]?|2[0-4]?[0-9]?|25[0-5]).([0-9][0-9]?|[0-1][0-9]?[0-9]?|2[0-4]?[0-9]?|25[0-5])$

緦唸λ蓇 2024-09-08 08:34:39

根据https://en.wikipedia.org/wiki/Reserved_IP_addresses#IPv4,最好的检查方法是将其与 IP 范围一一进行比较。例如,JavaScript 代码:

/**
 * Check if IPv4 is reserved
 *
 * Reserved IPv4
 * ```
 * 0.0.0.0/8         : 0.0.0.0      - 0.255.255.255
 * 10.0.0.0/8        : 10.0.0.0     - 10.255.255.255
 * 100.64.0.0/10     : 100.64.0.0   - 100.127.255.255
 * 127.0.0.0/8       : 127.0.0.0    - 127.255.255.255
 * 169.254.0.0/16    : 169.254.0.0  - 169.254.255.255
 * 172.16.0.0/12     : 172.16.0.0   - 172.31.255.255
 * 192.0.0.0/24      : 192.0.0.0    - 192.0.0.255
 * 192.0.2.0/24      : 192.0.2.0    - 192.0.2.255
 * 192.88.99.0/24    : 192.88.99.0  - 192.88.99.255
 * 192.168.0.0/16    : 192.168.0.0  - 192.168.255.255
 * 198.18.0.0/15     : 198.18.0.0   - 198.19.255.255
 * 198.51.100.0/24   : 198.51.100.0 - 198.51.100.255
 * 203.0.113.0/24    : 203.0.113.0  - 203.0.113.255
 * 224.0.0.0/4       : 224.0.0.0    - 239.255.255.255
 * 233.252.0.0/24    : 233.252.0.0  - 233.252.0.255
 * 240.0.0.0/4       : 240.0.0.0    - 255.255.255.254
 * 255.255.255.255/32: 255.255.255.255
 * ```
 *
 * @param {string} ip
 */
function reservedIPv4(ip) {
  const [a, b, c, d] = ip.split('.').map(n => +n);

  if (a === 0 || a === 10 || a === 127 ) return true;
  if (a === 100 && b >= 64 && b <= 127) return true;
  if (a === 169 && b === 254) return true;
  if (a === 172 && b >= 16 && b <= 31) return true;
  if (a === 192) {
    if (b === 0 && (c === 0 || c === 2)) return true;
    if (b === 88 && c === 99) return true;
    if (b === 168) return true;
  }
  if (a === 198) {
    if (b >= 18 && b <= 19) return true;
    if (b === 51 && c === 100) return true;
  }
  if (a === 203 && b === 0 && c === 113) return true;
  if (a >= 224 && a <= 239) return true;
  if (a === 233 && b === 252 && c === 0) return true;
  if (a >= 240 && a <= 255 && d != 255) return true;
  if (a === 255 &&  b === 255 && c === 255 && d === 255) return true;

  return false;
}

As per https://en.wikipedia.org/wiki/Reserved_IP_addresses#IPv4, the best way to check is comparing it with IP ranges one by one. For example, JavaScript code:

/**
 * Check if IPv4 is reserved
 *
 * Reserved IPv4
 * ```
 * 0.0.0.0/8         : 0.0.0.0      - 0.255.255.255
 * 10.0.0.0/8        : 10.0.0.0     - 10.255.255.255
 * 100.64.0.0/10     : 100.64.0.0   - 100.127.255.255
 * 127.0.0.0/8       : 127.0.0.0    - 127.255.255.255
 * 169.254.0.0/16    : 169.254.0.0  - 169.254.255.255
 * 172.16.0.0/12     : 172.16.0.0   - 172.31.255.255
 * 192.0.0.0/24      : 192.0.0.0    - 192.0.0.255
 * 192.0.2.0/24      : 192.0.2.0    - 192.0.2.255
 * 192.88.99.0/24    : 192.88.99.0  - 192.88.99.255
 * 192.168.0.0/16    : 192.168.0.0  - 192.168.255.255
 * 198.18.0.0/15     : 198.18.0.0   - 198.19.255.255
 * 198.51.100.0/24   : 198.51.100.0 - 198.51.100.255
 * 203.0.113.0/24    : 203.0.113.0  - 203.0.113.255
 * 224.0.0.0/4       : 224.0.0.0    - 239.255.255.255
 * 233.252.0.0/24    : 233.252.0.0  - 233.252.0.255
 * 240.0.0.0/4       : 240.0.0.0    - 255.255.255.254
 * 255.255.255.255/32: 255.255.255.255
 * ```
 *
 * @param {string} ip
 */
function reservedIPv4(ip) {
  const [a, b, c, d] = ip.split('.').map(n => +n);

  if (a === 0 || a === 10 || a === 127 ) return true;
  if (a === 100 && b >= 64 && b <= 127) return true;
  if (a === 169 && b === 254) return true;
  if (a === 172 && b >= 16 && b <= 31) return true;
  if (a === 192) {
    if (b === 0 && (c === 0 || c === 2)) return true;
    if (b === 88 && c === 99) return true;
    if (b === 168) return true;
  }
  if (a === 198) {
    if (b >= 18 && b <= 19) return true;
    if (b === 51 && c === 100) return true;
  }
  if (a === 203 && b === 0 && c === 113) return true;
  if (a >= 224 && a <= 239) return true;
  if (a === 233 && b === 252 && c === 0) return true;
  if (a >= 240 && a <= 255 && d != 255) return true;
  if (a === 255 &&  b === 255 && c === 255 && d === 255) return true;

  return false;
}
九歌凝 2024-09-08 08:34:39

匹配以私有 IP 地址(包括 ipv6)开头的字符串的最佳方法

   private_ip_identifier("127.0.0.1");
   private_ip_identifier("47.29.161.118");
    
    function private_ip_identifier(ip) {
      const regex_exp = /(^127\.)|(^192\.168\.)|(^10\.)|(^172\.1[6-9]\.)|(^172\.2[0-9]\.)|(^172\.3[0-1]\.)|(^::1$)|(^[fF][cCdD])/;
          const test_result =  regex_exp.test(ip);
          console.log(test_result);
          // true for 127.0.0.1 and false for 47.29.161.118
    }

The best way to match a string that starts with private IP address (ipv6 included)

   private_ip_identifier("127.0.0.1");
   private_ip_identifier("47.29.161.118");
    
    function private_ip_identifier(ip) {
      const regex_exp = /(^127\.)|(^192\.168\.)|(^10\.)|(^172\.1[6-9]\.)|(^172\.2[0-9]\.)|(^172\.3[0-1]\.)|(^::1$)|(^[fF][cCdD])/;
          const test_result =  regex_exp.test(ip);
          console.log(test_result);
          // true for 127.0.0.1 and false for 47.29.161.118
    }

笑梦风尘 2024-09-08 08:34:39

试试这个,
此代码纠正了私有 IP 范围中的一些错误,在某些示例中,范围的最后三位数字可能超过 255。

(^10\.(\b(?:(?:25[0-5]|2 ?[0-4][0-9]|[01]?[0-9][0-9]?)\.){2})\b(\b(25[0-5]|2[ 0-4][0-9]|[01]?[0-9][0-9]?)\b))|(^172\.1[6-9]\.(\b(?: (?:25[0-5]|2?[0-4][0-9]|[01]?[0-9][0-9]?)\.)\b)(\b(25 [0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b))|(^172\.2[0-9] \.(\b(?:(?:25[0-5]|2?[0-4][0-9]|[01]?[0-9][0-9]?)\.) \b)(\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b))|(^172 \.3[0-1]\.(\b(?:(?:25[0-5]|2?[0-4][0-9]|[01]?[0-9][0 -9]?)\.)\b)(\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?) \b))|(^192\.168\.(\b(?:(?:25[0-5]|2?[0-4][0-9]|[01]?[0-9 ][0-9]?)\.)\b)(\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9 ]?)\b))

Try this,
This code corrects some errors in the range of private IPs, in some examples the last three digits the range could exceed 255.

(^10\.(\b(?:(?:25[0-5]|2?[0-4][0-9]|[01]?[0-9][0-9]?)\.){2})\b(\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b))|(^172\.1[6-9]\.(\b(?:(?:25[0-5]|2?[0-4][0-9]|[01]?[0-9][0-9]?)\.)\b)(\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b))|(^172\.2[0-9]\.(\b(?:(?:25[0-5]|2?[0-4][0-9]|[01]?[0-9][0-9]?)\.)\b)(\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b))|(^172\.3[0-1]\.(\b(?:(?:25[0-5]|2?[0-4][0-9]|[01]?[0-9][0-9]?)\.)\b)(\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b))|(^192\.168\.(\b(?:(?:25[0-5]|2?[0-4][0-9]|[01]?[0-9][0-9]?)\.)\b)(\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b))

dawn曙光 2024-09-08 08:34:39

FWIW 使用 pattern.matcher,此模式速度快了 10% 以上:

^1((0)|(92\\.168)|(72\\.((1[6-9])|(2[0-9])|(3[0-1])))|(27))\\.

FWIW this pattern was over 10% faster using pattern.matcher:

^1((0)|(92\\.168)|(72\\.((1[6-9])|(2[0-9])|(3[0-1])))|(27))\\.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文