我有一个go中的程序,它接受来自客户端的URL并使用net / http包获取它们。在进行进一步处理之前,我想检查URL是否映射到私有(不可路由/ RFC1918网络)地址空间。
直接的方法是执行显式DNS请求并检查已知私有范围的地址。之后,执行URL的HTTP GET请求。
有没有更好的方法来实现这一目标?最好与http.Client集成,以便它可以作为GET请求的一部分执行。
答案 0 :(得分:15)
您可能还希望包括对环回(IPv4或IPv6)和/或IPv6链接本地或唯一本地地址的检查。下面是一个示例,其中包含RFC1918地址列表以及其他这些地址以及isPrivateIP(ip net.IP)
对它们的简单检查:
var privateIPBlocks []*net.IPNet
func init() {
for _, cidr := range []string{
"127.0.0.0/8", // IPv4 loopback
"10.0.0.0/8", // RFC1918
"172.16.0.0/12", // RFC1918
"192.168.0.0/16", // RFC1918
"::1/128", // IPv6 loopback
"fe80::/10", // IPv6 link-local
"fc00::/7", // IPv6 unique local addr
} {
_, block, _ := net.ParseCIDR(cidr)
privateIPBlocks = append(privateIPBlocks, block)
}
}
func isPrivateIP(ip net.IP) bool {
for _, block := range privateIPBlocks {
if block.Contains(ip) {
return true
}
}
return false
}
答案 1 :(得分:2)
似乎没有比我描述的更好的方法来实现。将@MichaelHausenblas的代码与@JimB的建议结合起来,我的代码就像这样。
func privateIP(ip string) (bool, error) {
var err error
private := false
IP := net.ParseIP(ip)
if IP == nil {
err = errors.New("Invalid IP")
} else {
_, private24BitBlock, _ := net.ParseCIDR("10.0.0.0/8")
_, private20BitBlock, _ := net.ParseCIDR("172.16.0.0/12")
_, private16BitBlock, _ := net.ParseCIDR("192.168.0.0/16")
private = private24BitBlock.Contains(IP) || private20BitBlock.Contains(IP) || private16BitBlock.Contains(IP)
}
return private, err
}
答案 2 :(得分:2)
Go 1.17(2021 年第 4 季度,5 年后)应该更容易做到这一点,因为 reported by Go 101:
<块引用>net
:添加IP.IsPrivate()
添加 IsPrivate()
帮助程序以根据 RFC 1918 和 RFC 4193 检查 IP 是否为私有
修复了 golang issue 29146 提出的 Aaran McGuire:
<块引用>net 包好像有很多helper 来报告什么是IP。例如:
IsLoopback()
IsMulticast()
IsInterfaceLocalMulticast()