thinkeridea / go-extend

go语言扩展包,收集一些常用的操作函数,辅助更快的完成开发工作,并减少重复代码
https://pkg.go.dev/github.com/thinkeridea/go-extend
MIT License
1.33k stars 160 forks source link

加快内网地址检查,172.16~31.0.0/12 其掩码地址均为 172.16.0.0/12 存在重复 #2

Closed thinkeridea closed 4 years ago

thinkeridea commented 4 years ago
"10.0.0.0/8",
"169.254.0.0/16",
"172.16.0.0/12",
"172.17.0.0/12",
"172.18.0.0/12",
"172.19.0.0/12",
"172.20.0.0/12",
"172.21.0.0/12",
"172.22.0.0/12",
"172.23.0.0/12",
"172.24.0.0/12",
"172.25.0.0/12",
"172.26.0.0/12",
"172.27.0.0/12",
"172.28.0.0/12",
"172.29.0.0/12",
"172.30.0.0/12",
"172.31.0.0/12",
"192.168.0.0/16",   

172.16~31.0.0/12 其掩码地址均为 172.16.0.0/12 存在重复。

使用直接对比ip段前两段数据检查,不使用 network.Contains 判断,在暂时不支持IPV6 的前提下,这种方法更加高效。

thinkeridea commented 4 years ago
package exnet

import (
    "net"
    "testing"
)

// HasLocalIPddr 检测 IP 地址字符串是否是内网地址
func HasLocalIPddr(ip string) bool {
    return HasLocalIP(net.ParseIP(ip))
}

// HasLocalIP 检测 IP 地址是否是内网地址
// 通过直接对比ip段范围效率更高,详见:https://github.com/thinkeridea/go-extend/issues/2
func HasLocalIP(ip net.IP) bool {
    if ip.IsLoopback() {
        return true
    }

    ip4 := ip.To4()
    if ip4 == nil {
        return false
    }

    return ip4[0] == 10 || // 10.0.0.0/8
        (ip4[0] == 172 && ip4[1] >= 16 && ip4[1] <= 31) || // 172.16.0.0/12
        (ip4[0] == 169 && ip4[1] == 254) || // 169.254.0.0/16
        (ip4[0] == 192 && ip4[1] == 168) // 192.168.0.0/16
}

// 收集的内网网络地址 IP 段
var localNetworks []*net.IPNet

func init() {
    localNetworks = make([]*net.IPNet, 4)
    for i, sNetwork := range []string{
        "10.0.0.0/8",
        "169.254.0.0/16",
        "172.16.0.0/12",
        "192.168.0.0/16",
    } {
        _, network, _ := net.ParseCIDR(sNetwork)
        localNetworks[i] = network
    }
}

// HasLocalIPddr 检测 IP 地址字符串是否是内网地址
func HasLocalIPddr_test(ip string) bool {
    return HasLocalIP_test(net.ParseIP(ip))
}

// HasLocalIP 检测 IP 地址是否是内网地址
func HasLocalIP_test(ip net.IP) bool {
    for _, network := range localNetworks {
        if network.Contains(ip) {
            return true
        }
    }

    return ip.IsLoopback()
}

func BenchmarkHasLocalIP(b *testing.B) {
    for i := 0; i < b.N; i++ {
        for _, ip := range []string{
            "192.168.9.18",
            "10.168.9.18",
            "172.16.9.18",
            "172.17.9.18",
            "172.18.9.18",
            "172.19.9.18",
            "172.20.9.18",
            "172.21.9.18",
            "172.22.9.18",
            "172.23.9.18",
            "172.24.9.18",
            "172.25.9.18",
            "172.26.9.18",
            "172.27.9.18",
            "172.28.9.18",
            "172.29.9.18",
            "172.30.9.18",
            "172.31.9.18",
        } {
            if !HasLocalIPddr_test(ip) {
                b.Fatal(ip)
            }
        }
    }
}

func BenchmarkHasLocalIP2(b *testing.B) {
    for i := 0; i < b.N; i++ {
        for _, ip := range []string{
            "192.168.9.18",
            "10.168.9.18",
            "172.16.9.18",
            "172.17.9.18",
            "172.18.9.18",
            "172.19.9.18",
            "172.20.9.18",
            "172.21.9.18",
            "172.22.9.18",
            "172.23.9.18",
            "172.24.9.18",
            "172.25.9.18",
            "172.26.9.18",
            "172.27.9.18",
            "172.28.9.18",
            "172.29.9.18",
            "172.30.9.18",
            "172.31.9.18",
        } {
            if !HasLocalIPddr(ip) {
                b.Fatal(ip)
            }
        }
    }
}

测试结果:

$ go test -benchmem -bench="." ip*.go
goos: darwin
goarch: amd64
BenchmarkHasLocalIP-8             441862              2273 ns/op             288 B/op         18 allocs/op
BenchmarkHasLocalIP2-8            801446              1502 ns/op             288 B/op         18 allocs/op
PASS
ok      command-line-arguments  2.268s