美文网首页go学习我爱编程我的专题
Go实战--golang中获取公网ip、查看内网ip、检测ip类

Go实战--golang中获取公网ip、查看内网ip、检测ip类

作者: 豆瓣奶茶 | 来源:发表于2018-06-02 14:58 被阅读18次

    之前,有介绍过golang提供的标准库:net包

    Go语言学习之net包(The way to go)

    简要回味net包

    func ParseIP

    func ParseIP(s string) IP1
    

    ParseIP parses s as an IP address, returning the result. The string s can be in dotted decimal (“192.0.2.1”) or IPv6 (“2001:db8::68”) form. If s is not a valid textual representation of an IP address, ParseIP returns nil.

    func InterfaceAddrs

    func InterfaceAddrs() ([]Addr, error)1
    

    InterfaceAddrs returns a list of the system’s unicast interface addresses.

    The returned list does not identify the associated interface; use Interfaces and Interface.Addrs for more detail.

    type IPNet
    An IPNet represents an IP network.

    type IPNet struct {
            IP   IP     // network number
            Mask IPMask // network mask
    }1234
    

    type IP

    An IP is a single IP address, a slice of bytes. Functions in this package accept either 4-byte (IPv4) or 16-byte (IPv6) slices as input.

    Note that in this documentation, referring to an IP address as an IPv4 address or an IPv6 address is a semantic property of the address, not just the length of the byte slice: a 16-byte slice can still be an IPv4 address.

    type IP []byte1
    

    func IPv4

    func IPv4(a, b, c, d byte) IP1
    

    IPv4 returns the IP address (in 16-byte form) of the IPv4 address a.b.c.d.

    点到为止,更详细的请看文档:https://golang.org/pkg/net

    什么是外网IP和内网IP?

    tcp/ip协议中,专门保留了三个IP地址区域作为私有地址,其地址范围如下:
    10.0.0.0/8:10.0.0.0~10.255.255.255
    172.16.0.0/12:172.16.0.0~172.31.255.255
    192.168.0.0/16:192.168.0.0~192.168.255.255

    什么是内网IP

    一些小型企业或者学校,通常都是申请一个固定的IP地址,然后通过IP共享(IP Sharing),使用整个公司或学校的机器都能够访问互联网。而这些企业或学校的机器使用的IP地址就是内网IP,内网IP是在规划IPv4协议时,考虑到IP地址资源可能不足,就专门为内部网设计私有IP地址(或称之为保留地址),一般常用内网IP地址都是这种形式的:10.X.X.X、172.16.X.X-172.31.X.X、192.168.X.X等。需要注意的是,内网的计算机可向Internet上的其他计算机发送连接请求,但Internet上其他的计算机无法向内网的计算机发送连接请求。我们平时可能在内网机器上搭建过网站或者FTP服务器,而在外网是不能访问该网站和FTP服务器的,原因就在于此。

    什么是公网IP

    公网IP就是除了保留IP地址以外的IP地址,可以与Internet上的其他计算机随意互相访问。我们通常所说的IP地址,其实就是指的公网IP。互联网上的每台计算机都有一个独立的IP地址,该IP地址唯一确定互联网上的一台计算机。这里的IP地址就是指的公网IP地址。

    怎样理解互联网上的每台计算机都有一个唯一的IP地址

    其实,互联网上的计算机是通过“公网IP+内网IP”来唯一确定的,就像很多大楼都是201房间一样,房间号可能一样,但是大楼肯定是唯一的。公网IP地址和内网IP地址也是同样,不同企业或学校的机器可能有相同的内网IP地址,但是他们的公网IP地址肯定不同。那么这些企业或学校的计算机是怎样IP地址共享的呢?这就需要使用NAT(Network Address Translation,网络地址转换)功能。当内部计算机要连接互联网时,首先需要通过NAT技术,将内部计算机数据包中有关IP地址的设置都设成NAT主机的公共IP地址,然后再传送到Internet,虽然内部计算机使用的是私有IP地址,但在连接Internet时,就可以通过NAT主机的NAT技术,将内网我IP地址修改为公网IP地址,如此一来,内网计算机就可以向Internet请求数据了。

    获取公网ip

    百度ip,即可查看公网ip

    curl命令查看公网ip

    curl ipinfo.io/ip1
    

    通过http://myexternalip.com/raw获取公网ip

    func get_external() string {
        resp, err := http.Get("http://myexternalip.com/raw")
        if err != nil {
            return ""
        }
        defer resp.Body.Close()
        content, _ := ioutil.ReadAll(resp.Body)
        //buf := new(bytes.Buffer)
        //buf.ReadFrom(resp.Body)
        //s := buf.String()
        return string(content)
    }123456789101112
    

    获取本地ip

    func GetIntranetIp() {
        addrs, err := net.InterfaceAddrs()
    
        if err != nil {
            fmt.Println(err)
            os.Exit(1)
        }
    
        for _, address := range addrs {
    
            // 检查ip地址判断是否回环地址
            if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
                if ipnet.IP.To4() != nil {
                    fmt.Println("ip:", ipnet.IP.String())
                }
    
            }
        }
    }12345678910111213141516171819
    

    通过dns服务器8.8.8.8:80获取使用的ip

    func GetPulicIP() string {
        conn, _ := net.Dial("udp", "8.8.8.8:80")
        defer conn.Close()
        localAddr := conn.LocalAddr().String()
        idx := strings.LastIndex(localAddr, ":")
        return localAddr[0:idx]
    }1234567
    

    判断是否是公网ip

    func IsPublicIP(IP net.IP) bool {
        if IP.IsLoopback() || IP.IsLinkLocalMulticast() || IP.IsLinkLocalUnicast() {
            return false
        }
        if ip4 := IP.To4(); ip4 != nil {
            switch true {
            case ip4[0] == 10:
                return false
            case ip4[0] == 172 && ip4[1] >= 16 && ip4[1] <= 31:
                return false
            case ip4[0] == 192 && ip4[1] == 168:
                return false
            default:
                return true
            }
        }
        return false
    }123456789101112131415161718
    

    ip地址string转int

    func inet_aton(ipnr net.IP) int64 {
        bits := strings.Split(ipnr.String(), ".")
    
        b0, _ := strconv.Atoi(bits[0])
        b1, _ := strconv.Atoi(bits[1])
        b2, _ := strconv.Atoi(bits[2])
        b3, _ := strconv.Atoi(bits[3])
    
        var sum int64
    
        sum += int64(b0) << 24
        sum += int64(b1) << 16
        sum += int64(b2) << 8
        sum += int64(b3)
    
        return sum
    }1234567891011121314151617
    

    ip地址int转string

    func inet_ntoa(ipnr int64) net.IP {
        var bytes [4]byte
        bytes[0] = byte(ipnr & 0xFF)
        bytes[1] = byte((ipnr >> 8) & 0xFF)
        bytes[2] = byte((ipnr >> 16) & 0xFF)
        bytes[3] = byte((ipnr >> 24) & 0xFF)
    
        return net.IPv4(bytes[3], bytes[2], bytes[1], bytes[0])
    }123456789
    

    判断ip地址区间

    func IpBetween(from net.IP, to net.IP, test net.IP) bool {
        if from == nil || to == nil || test == nil {
            fmt.Println("An ip input is nil") // or return an error!?
            return false
        }
    
        from16 := from.To16()
        to16 := to.To16()
        test16 := test.To16()
        if from16 == nil || to16 == nil || test16 == nil {
            fmt.Println("An ip did not convert to a 16 byte") // or return an error!?
            return false
        }
    
        if bytes.Compare(test16, from16) >= 0 && bytes.Compare(test16, to16) <= 0 {
            return true
        }
        return false
    }12345678910111213141516171819
    

    通过淘宝接口根据公网ip获取国家运营商等信息

    接口:
    http://ip.taobao.com/service/getIpInfo.php?ip=

    type IPInfo struct {
        Code int `json:"code"`
        Data IP  `json:"data`
    }
    
    type IP struct {
        Country   string `json:"country"`
        CountryId string `json:"country_id"`
        Area      string `json:"area"`
        AreaId    string `json:"area_id"`
        Region    string `json:"region"`
        RegionId  string `json:"region_id"`
        City      string `json:"city"`
        CityId    string `json:"city_id"`
        Isp       string `json:"isp"`
    }
    
    func TabaoAPI(ip string) *IPInfo {
        url := "http://ip.taobao.com/service/getIpInfo.php?ip="
        url += ip
    
        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
    }123456789101112131415161718192021222324252627282930313233343536373839
    

    完整代码

    package main
    
    import (
        "bytes"
        "encoding/json"
        "fmt"
        "io/ioutil"
        "net"
        "net/http"
        "os"
        "strconv"
        "strings"
    )
    
    type IPInfo struct {
        Code int `json:"code"`
        Data IP  `json:"data`
    }
    
    type IP struct {
        Country   string `json:"country"`
        CountryId string `json:"country_id"`
        Area      string `json:"area"`
        AreaId    string `json:"area_id"`
        Region    string `json:"region"`
        RegionId  string `json:"region_id"`
        City      string `json:"city"`
        CityId    string `json:"city_id"`
        Isp       string `json:"isp"`
    }
    
    func main() {
    
        external_ip := get_external()
    
        external_ip = strings.Replace(external_ip, "\n", "", -1)
        fmt.Println("公网ip是: ", external_ip)
    
        fmt.Println("------Dividing Line------")
    
        ip := net.ParseIP(external_ip)
        if ip == nil {
            fmt.Println("您输入的不是有效的IP地址,请重新输入!")
        } else {
            result := TabaoAPI(string(external_ip))
            if result != nil {
                fmt.Println("国家:", result.Data.Country)
                fmt.Println("地区:", result.Data.Area)
                fmt.Println("城市:", result.Data.City)
                fmt.Println("运营商:", result.Data.Isp)
            }
        }
    
        fmt.Println("------Dividing Line------")
    
        GetIntranetIp()
    
        fmt.Println("------Dividing Line------")
    
        ip_int := inet_aton(net.ParseIP(external_ip))
        fmt.Println("Convert IPv4 address to decimal number(base 10) :", ip_int)
    
        ip_result := inet_ntoa(ip_int)
        fmt.Println("Convert decimal number(base 10) to IPv4 address:", ip_result)
    
        fmt.Println("------Dividing Line------")
    
        is_between := IpBetween(net.ParseIP("0.0.0.0"), net.ParseIP("255.255.255.255"), net.ParseIP(external_ip))
        fmt.Println("check result: ", is_between)
    
        fmt.Println("------Dividing Line------")
        is_public_ip := IsPublicIP(net.ParseIP(external_ip))
        fmt.Println("It is public ip: ", is_public_ip)
    
        is_public_ip = IsPublicIP(net.ParseIP("169.254.85.131"))
        fmt.Println("It is public ip: ", is_public_ip)
    
        fmt.Println("------Dividing Line------")
        fmt.Println(GetPulicIP())
    }
    
    func get_external() string {
        resp, err := http.Get("http://myexternalip.com/raw")
        if err != nil {
            return ""
        }
        defer resp.Body.Close()
        content, _ := ioutil.ReadAll(resp.Body)
        buf := new(bytes.Buffer)
        buf.ReadFrom(resp.Body)
        //s := buf.String()
        return string(content)
    }
    
    func GetIntranetIp() {
        addrs, err := net.InterfaceAddrs()
    
        if err != nil {
            fmt.Println(err)
            os.Exit(1)
        }
    
        for _, address := range addrs {
    
            // 检查ip地址判断是否回环地址
            if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
                if ipnet.IP.To4() != nil {
                    fmt.Println("ip:", ipnet.IP.String())
                }
    
            }
        }
    }
    
    func TabaoAPI(ip string) *IPInfo {
        url := "http://ip.taobao.com/service/getIpInfo.php?ip="
        url += ip
    
        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 inet_ntoa(ipnr int64) net.IP {
        var bytes [4]byte
        bytes[0] = byte(ipnr & 0xFF)
        bytes[1] = byte((ipnr >> 8) & 0xFF)
        bytes[2] = byte((ipnr >> 16) & 0xFF)
        bytes[3] = byte((ipnr >> 24) & 0xFF)
    
        return net.IPv4(bytes[3], bytes[2], bytes[1], bytes[0])
    }
    
    func inet_aton(ipnr net.IP) int64 {
        bits := strings.Split(ipnr.String(), ".")
    
        b0, _ := strconv.Atoi(bits[0])
        b1, _ := strconv.Atoi(bits[1])
        b2, _ := strconv.Atoi(bits[2])
        b3, _ := strconv.Atoi(bits[3])
    
        var sum int64
    
        sum += int64(b0) << 24
        sum += int64(b1) << 16
        sum += int64(b2) << 8
        sum += int64(b3)
    
        return sum
    }
    
    func IpBetween(from net.IP, to net.IP, test net.IP) bool {
        if from == nil || to == nil || test == nil {
            fmt.Println("An ip input is nil") // or return an error!?
            return false
        }
    
        from16 := from.To16()
        to16 := to.To16()
        test16 := test.To16()
        if from16 == nil || to16 == nil || test16 == nil {
            fmt.Println("An ip did not convert to a 16 byte") // or return an error!?
            return false
        }
    
        if bytes.Compare(test16, from16) >= 0 && bytes.Compare(test16, to16) <= 0 {
            return true
        }
        return false
    }
    
    func IsPublicIP(IP net.IP) bool {
        if IP.IsLoopback() || IP.IsLinkLocalMulticast() || IP.IsLinkLocalUnicast() {
            return false
        }
        if ip4 := IP.To4(); ip4 != nil {
            switch true {
            case ip4[0] == 10:
                return false
            case ip4[0] == 172 && ip4[1] >= 16 && ip4[1] <= 31:
                return false
            case ip4[0] == 192 && ip4[1] == 168:
                return false
            default:
                return true
            }
        }
        return false
    }
    
    func GetPulicIP() string {
        conn, _ := net.Dial("udp", "8.8.8.8:80")
        defer conn.Close()
        localAddr := conn.LocalAddr().String()
        idx := strings.LastIndex(localAddr, ":")
        return localAddr[0:idx]
    }
    123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
    

    输出:

    公网ip是:  222.128.17*.***
    ------Dividing Line------
    国家: 中国
    地区: 华北
    城市: 北京市
    运营商: 联通
    ------Dividing Line------
    ip: 169.254.85.131
    ip: 169.254.64.29
    ip: 169.254.211.178
    ip: 192.168.106.1
    ip: 192.168.154.1
    ip: 169.254.212.223
    ip: 192.168.10.26
    ip: 169.254.63.20
    ------Dividing Line------
    Convert IPv4 address to decimal number(base 10) : 373297****
    Convert decimal number(base 10) to IPv4 address: 222.128.17*.***
    ------Dividing Line------
    check result:  true
    ------Dividing Line------
    It is public ip:  true
    It is public ip:  false
    ------Dividing Line------
    192.168.10.2612345678910111213141516171819202122232425
    
    这里写图片描述

    相关文章

      网友评论

        本文标题:Go实战--golang中获取公网ip、查看内网ip、检测ip类

        本文链接:https://www.haomeiwen.com/subject/krsrsftx.html