Files
tamakyi e3e59e7c69 chore: baseline snapshot before moderation-strictness feature
Repo .git was damaged (refs/ missing, index truncated, object store near-empty).
Repaired via git init (rebuilt refs), stale index preserved as .git/index.corrupt-20260910.bak,
then full worktree committed as a rollback baseline.
2026-09-10 10:56:27 +08:00

85 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 ipinfo 识别 IP 的网络归属(CDN / 云厂商 / WAF)。
// 基于 projectdiscovery/cdncheck 的离线签名(编译期嵌入,上游每周更新指纹),
// 判定过程零外部网络请求,适合 1C1G 小型服务器与告警链路使用。
// 当前用于安全告警邮件:展示扫描来源的网络归属,帮助管理员判断告警严重性。
package ipinfo
import (
"fmt"
"net"
"strings"
"sync"
"github.com/projectdiscovery/cdncheck"
)
var (
clientOnce sync.Once
client *cdncheck.Client
)
// getClient 懒加载判定客户端(签名数据编译期嵌入,New 无错误返回)。
func getClient() *cdncheck.Client {
clientOnce.Do(func() {
client = cdncheck.New()
})
return client
}
// Lookup 判定 IP 的网络归属。
// 返回:
// - label:展示用标签,如 "Cloudflare(CDN)"、"亚马逊(云厂商)";
// 未命中返回 "未识别(普通网络)",输入非法或判定出错返回 "识别失败"。
// - proxied:IP 是否属于 CDN/WAF/代理网络(用于提示"封禁可能无法拦截真实来源")。
//
// 任何内部错误都被折叠为展示标签,不向调用方传播——告警链路不应因归属识别失败而中断。
func Lookup(ipStr string) (label string, proxied bool) {
ip := net.ParseIP(strings.TrimSpace(ipStr))
if ip == nil {
return "识别失败(IP 格式异常)", false
}
matched, value, itemType, err := getClient().Check(ip)
if err != nil {
return "识别失败", false
}
if !matched || value == "" {
return "未识别(普通网络)", false
}
return fmt.Sprintf("%s(%s)", title(value), typeLabel(itemType)), true
}
// typeLabel 将 cdncheck 的 itemType 翻译为中文展示。
func typeLabel(itemType string) string {
switch itemType {
case "cdn":
return "CDN"
case "waf":
return "WAF"
case "cloud":
return "云厂商"
default:
return "未知类型"
}
}
// acronymProviders 需要保持全大写的提供商缩写(cdncheck 返回全小写,如 aws → AWS)。
var acronymProviders = map[string]bool{
"aws": true, "gcp": true, "oci": true, "gds": true, "ovh": true,
}
// title 将提供商名转为展示形式:缩写全大写(aws → AWS),其余首字母大写
// (cloudflare → Cloudflare)。
func title(s string) string {
if s == "" {
return s
}
lower := strings.ToLower(s)
if acronymProviders[lower] {
return strings.ToUpper(lower)
}
r := []rune(lower)
return strings.ToUpper(string(r[0])) + string(r[1:])
}