正则表达式中的私有 IP 地址标识符
我想知道这是否是匹配以私有 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(15)
我假设您想要匹配这些范围:
您缺少一些点,这些点会导致它接受例如
172.169.0.0
即使这不应该被接受。我已经在下面修复了它。删除新行,只是为了便于阅读。另请注意,这假设 IP 地址已经过验证 - 它接受诸如
10.foobar
之类的内容。I'm assuming you want to match these ranges:
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.Also note that this assumes that the IP addresses have already been validated - it accepts things like
10.foobar
.这与 Mark 的正确答案相同,但现在包括 IPv6 私有地址。
This is the same as the correct answer by Mark, but now including IPv6 private addresses.
我已经为 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].).* "
这是我在 python 中使用的:
如果您愿意,您可以删除 ^ 和/或 $ 锚点。
我更喜欢上面的正则表达式,因为它会清除无效的八位字节(任何高于 255 的字节)。
用法示例:
here is what I use in python:
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:
这是为了防止您决定接受我的评论,建议您不要使用正则表达式。未经测试(但可能有效,或至少接近),在 Perl 中:
现在请注意
@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:
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.
看起来不错。就我个人而言,我会将第一个更改为:
通过此:
(^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:
With this:
(^127\.0\.0\.1)
you looking for anything that starts with127.0.0.1
and will miss out on127.0.0.2*
,127.0.2.*
,127.0.*
etc.晚了10年。感谢
Mark Byers
、bramp
、Edward
、blueyed
、user3177026
、贾斯汀
、karmakaze
、罗恩·莫平
。回答 TLDR
仅开头
请删除换行符 - 这只是为了更容易阅读:
括号开头的
?:
意味着该括号未被捕获,可能会使其更快一点。请小心反斜杠。例如,在 Postgres 中,您必须使用 E 字符串,并且必须使用反斜杠转义反斜杠 - 或者只使用
[.]
而不是E'\\.'
!整个IP(小数,前导零可选,最多三位)
请删除换行符 - 这只是为了更容易阅读:
https://regex101.com/r/JCLOZL/14(备份:https://etherpad.wikimedia.org/p/JCLOZL)
详细信息
IPv4
示例:
我不确定斜杠后面的部分是否可以有前导零(不太可能),但 IP 可以有前导零。
带有前导零(十进制)的 IPv4
示例:
带有前导零(八进制)的 IPv4
在我的正则表达式中不受支持。为了使您的程序完美,请检查八进制 IP 地址和/或超过三位数字并警告用户!
示例:
是的,
172.017.050.033
在不同工具上与0254.0021.0062.0041
相同。在 macOS 上使用ping
进行测试。当然,您也可以在某些工具中混合十进制(无前导零)和八进制(至少一个前导零)。 :S
IPv6
这可能不完全是您想要的,因为:
私有 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
(有一定限制)分配公共互联网上永远不允许的流量。示例:
不完整的链接列表
当我来到这里时,我不知道:
224.0.0.0/24
)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:
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 ofE'\\.'
!The whole IP (decimal, leading zeros optional, max. three digits)
Please remove the line breaks - this is just to make it easier to read:
https://regex101.com/r/JCLOZL/14 (Backup: https://etherpad.wikimedia.org/p/JCLOZL)
Details
IPv4
Example:
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)
Example:
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!
Example:
Yes,
172.017.050.033
is the same as0254.0021.0062.0041
on different tools. Tested withping
on macOS.Of course, you can also mix decimal (no leading zero) with octal (at least one leading zero) in some tools. :S
IPv6
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::
to3fff: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 fromfd00::/8
with certain limitations) for traffic that will never be allowed on the public Internet.Example:
Incomplete link list
When I came here, I did not know about:
224.0.0.0/24
)如果您正在寻找 system.net defaultProxy 和代理旁路列表配置,该配置使用外部代理,但使用内部主机的直接连接(可以使用一些 ipv6 支持)...
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)...
这是 Mark Byers 解决方案的紧凑形式:
This is the compact form of Mark Byers solution:
您需要一个结束分隔符才能获取整个第 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])$
根据https://en.wikipedia.org/wiki/Reserved_IP_addresses#IPv4,最好的检查方法是将其与 IP 范围一一进行比较。例如,JavaScript 代码:
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:
匹配以私有 IP 地址(包括 ipv6)开头的字符串的最佳方法
The best way to match a string that starts with private IP address (ipv6 included)
试试这个,
此代码纠正了私有 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))
FWIW 使用
pattern.matcher
,此模式速度快了 10% 以上:FWIW this pattern was over 10% faster using
pattern.matcher
: