backtrace/bk/ipv6_asn.go
spiritlhl 5369aa16f7
Some checks failed
Sync ASN metadata / sync (push) Has been cancelled
feat: strengthen three-carrier return route detection
2026-07-31 00:31:56 +08:00

97 lines
2.5 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package backtrace
import (
_ "embed"
"net/netip"
"strings"
)
//go:embed prefix/as4809.txt
var as4809Data string
//go:embed prefix/as4134.txt
var as4134Data string
//go:embed prefix/as9929.txt
var as9929Data string
//go:embed prefix/as10099.txt
var as10099Data string
//go:embed prefix/as4837.txt
var as4837Data string
//go:embed prefix/as58807.txt
var as58807Data string
//go:embed prefix/as9808.txt
var as9808Data string
//go:embed prefix/as58453.txt
var as58453Data string
//go:embed prefix/as23764.txt
var as23764Data string
// ASN -> Prefix strings
var asnPrefixes = map[string][]string{
"AS4809": strings.Split(as4809Data, "\n"), // 电信 CN2 GT/GIA
"AS4134": strings.Split(as4134Data, "\n"), // 电信 163 骨干网
"AS9929": strings.Split(as9929Data, "\n"), // 联通 9929 优质国际线路
"AS10099": strings.Split(as10099Data, "\n"), // 联通 CUG 国际网络
"AS4837": strings.Split(as4837Data, "\n"), // 联通 AS4837 普通国际线路
"AS58807": strings.Split(as58807Data, "\n"), // 移动 CMIN2 国际精品网
"AS9808": strings.Split(as9808Data, "\n"), // 移动 CMI中国移动国际公司
"AS58453": strings.Split(as58453Data, "\n"), // 移动国际互联网CMI/HK
"AS23764": strings.Split(as23764Data, "\n"), // 电信 CTGNET/国际出口可能是CN2-B
}
// 判断 IPv6 地址是否匹配 ASN 中的某个前缀
func ipv6Asn(ip string) string {
ip = strings.ToLower(ip)
address, addressErr := netip.ParseAddr(ip)
if addressErr != nil || !address.Is6() {
return ""
}
bestASN := ""
bestSpecificity := -1
for asn, prefixes := range currentASNPrefixes() {
for _, prefix := range prefixes {
prefix = strings.TrimSpace(prefix)
if prefix == "" {
continue
}
if strings.Contains(prefix, "/") {
network, networkErr := netip.ParsePrefix(prefix)
if networkErr == nil && network.Contains(address) &&
(network.Bits() > bestSpecificity || (network.Bits() == bestSpecificity && asn < bestASN)) {
bestASN = asn
bestSpecificity = network.Bits()
}
continue
}
if strings.HasPrefix(ip, prefix) {
specificity := prefixHexBits(prefix)
if specificity > bestSpecificity || (specificity == bestSpecificity && asn < bestASN) {
bestASN = asn
bestSpecificity = specificity
}
}
}
}
return bestASN
}
func prefixHexBits(prefix string) int {
bits := 0
for _, value := range prefix {
switch {
case value >= '0' && value <= '9':
bits += 4
case value >= 'a' && value <= 'f':
bits += 4
}
}
return bits
}