IP属地信息如何获取?用Go语言来实现一个

3,037 阅读5分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路

引言

近日,社交网络平台纷纷宣布展示用户的IP属地,这意味着,今后所有用户在网络上发言或评论时,自己在现实生活中的IP归属地将被公开显示,并且用户无法开启或关闭此功能。用户的IP信息,平台是怎么知道的?平台如何通过IP查询属地信息?本文将对这些问题一一阐述,并用Go语言来实现获取IP属地信息。

用户的IP信息,平台是怎么知道的?

其大致流程是这样的:

  • 用户的手机、电脑等设备必须通过网络运营商(电信、移动等)进行联网服务,这个连接网络的过程中,基站、路由器将为该设备动态分配一个IP
  • 用户发布一篇文章或微博,或者进行评论时,就会向平台服务器发送一个HTTP请求。而IP信息,就包含在这个HTTP请求头里;
  • 平台服务器接收到请求信息,就可以通过HTTP请求(Request请求)信息解析出该用户的IP

在这个过程中,请求信息只包含IP,并不包含用户的属地信息

另外,对于交互式平台来说,《互联网交互式服务安全管理要求》(GA 1277.1-2020)的第1部分 基本要求第8.3条 日志与用户数据记录明确,平台必须记录用户的活动、信息发布等操作的IP地址及源端口。详见:www.beian.gov.cn/portal/down… 。

平台如何通过IP查询到属地信息?

一种方案是请求第三方IP属地信息服务的API,通过该接口查询用户的IP属地信息。比如免费的ip-api.com、百度、太平洋等等。但这种方案实现的前提时有API或者数据开放。

另外一种方案是使用离线的IP地址数据库,该数据库通常是一个文件,甚至可能是cvs文件、txt文件。 该数据库一般是由专业人士通过专业技术人工生成,其中记录了大量的IP地址(段),并记录了该IP地址(段)所属的国家省份城市运营商名称邮政编码经纬度等信息。

比如Golang有一个比较常用的库叫 Ip2region,库地址:github.com/lionsoul201… 但这也依赖于API提供的数据,如果API或者数据都不给开放数据时,ip2region将停止数据的更新服务。

免费的IP归属地信息查询接口

1 ip-api.com

url := "http://ip-api.com/json/"+ip+"?lang=zh-CN"

例如:ip-api.com/json/74.206…

2 百度

url := "http://opendata.baidu.com/api.php?query="+ip+"&co=&resource_id=6006&oe=utf8"

例如:opendata.baidu.com/api.php?que…

3 太平洋

url := "http://whois.pconline.com.cn/ipJson.jsp?ip="+ip+"&json=true"

例如: whois.pconline.com.cn/ipJson.jsp?…

实战:Go实现查询本地IP & 根据IP查询归属地信息

接下来,将基于Golangip-api.comAPI,讲解如何实现通过IP获取属地信息

直接看代码吧,除去定义结构体和打印信息,代码也就10行左右

完整代码:

/*
* @Author: starine
* @Date:   2022/5/2 14:04
 */
package main
import (
   "encoding/json"
   "fmt"
   "io/ioutil"
   "net/http"
)

type IPInfo struct {
   Status     string `json:"status"`
   Country    string `json:"country"`
   CountryCode string `json:"countryCode"`
   Region     string `json:"region"`
   RegionName  string `json:"regionName"`
   City       string `json:"city"`
   Zip          string `json:"zip"`
   Lat          float64 `json:"lat"`
   Lon          float64 `json:"lon"`
   Timezone   string `json:"timezone"`
   ISP        string `json:"isp"`
   Org          string `json:"org"`
   AS       string `json:"as"`
   QueryIp       string `json:"query"`
}

// GetMyPublicIP 通过访问http://myexternalip.com/raw获取公网ip
func GetMyPublicIP() string {
   resp, err := http.Get("http://myexternalip.com/raw")
   if err != nil {
      return ""
   }
   defer resp.Body.Close()
   content, _ := ioutil.ReadAll(resp.Body)
   return string(content)
}

// OnlineIpInfo 通过ip-api.com接口查询IP信息
// 返回:IP地址的信息(格式:字符串的json)
func OnlineIpInfo(ip string) *IPInfo {
   url := "http://ip-api.com/json/"+ip+"?lang=zh-CN"
   resp, err := http.Get(url)
   if err != nil {
      return nil
   }
   defer resp.Body.Close()

   out, err := ioutil.ReadAll(resp.Body)
   if err != nil {
      return nil
   }
   var result IPInfo
   if err := json.Unmarshal(out, &result); err != nil {
      return nil
   }
   return &result
}

//测试
func main() {
   myIP := GetMyPublicIP()
   fmt.Println("本机的公网ip是: ", myIP)

   fmt.Println("------查询指定ip的归属地信息------")
   result := OnlineIpInfo(myIP)
   if result != nil {
      fmt.Println("查询的ip是: ", result.QueryIp)
      fmt.Println("国家:", result.Country)
      fmt.Println("省份:", result.RegionName)
      fmt.Println("城市:", result.City)
      fmt.Println("纬度:", result.Lat)
      fmt.Println("经度:", result.Lon)
      fmt.Println("时区:", result.Timezone)
      fmt.Println("运营商:", result.ISP)
      fmt.Println("AS自治域:", result.AS)
   }
}

结果展示:

image.png

如何看待这件事?

显示用户IP属地,对于打击网络暴力、恶意造谣、带节奏蹭热度等人们深恶痛绝的网络行为而言,的确迈出了重要一步。长期以来,社交平台的匿名性让部分不怀好意的群体或是发表不实言论、散布有害信息,又或是在热点事件爆发后冒充事发地当事人造谣传谣、带歪舆论节奏,网络空间变得乌烟瘴气,事件真相也因此难以展现在公众面前。在尤其是今年以来,俄乌冲突、上海疫情等热点事件更让不少别有用心的境外网络用户“现出原形”,斩断在网线背后操弄舆论的黑手已变得刻不容缓。从某种程度而言,显示IP属地加强了用户网络行为与现实世界的联结,进一步提升了网络发声的门槛,也让网民在发言时更加慎重。对于以往那些习惯于肆无忌惮辱骂造谣的“键盘侠”而言,这无疑是一种强有力的震慑。

然而要真正杜绝网络不良行为、创造健康有序的网络环境,除不断加强更多技术层面的探索和约束之外,更重要的是规范一个个IP背后人的行为。提高全体网民的网络素养、加大对违法违规网络行为的惩治力度,才能从根本上遏制网络不良之风,让网络空间清朗起来。