This commit is contained in:
parent
4b89a2d18f
commit
063f32fcbb
@ -17,8 +17,8 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
|
|
||||||
- name: Install Docker
|
# - name: Install Docker
|
||||||
run: curl -fsSL https://get.docker.com | sh
|
# run: curl -fsSL https://get.docker.com | sh
|
||||||
|
|
||||||
- name: Deploy with Docker
|
- name: Deploy with Docker
|
||||||
run: docker compose up --build --force-recreate -d
|
run: docker compose up --build --force-recreate -d
|
||||||
|
5
go.mod
5
go.mod
@ -5,6 +5,7 @@ go 1.22
|
|||||||
require (
|
require (
|
||||||
github.com/bytedance/sonic v1.12.1 // indirect
|
github.com/bytedance/sonic v1.12.1 // indirect
|
||||||
github.com/bytedance/sonic/loader v0.2.0 // indirect
|
github.com/bytedance/sonic/loader v0.2.0 // indirect
|
||||||
|
github.com/c-robinson/iplib/v2 v2.0.5 // indirect
|
||||||
github.com/cloudwego/base64x v0.1.4 // indirect
|
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||||
github.com/cloudwego/iasm v0.2.0 // indirect
|
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||||
github.com/gabriel-vasile/mimetype v1.4.5 // indirect
|
github.com/gabriel-vasile/mimetype v1.4.5 // indirect
|
||||||
@ -18,6 +19,9 @@ require (
|
|||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
|
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
|
||||||
github.com/leodido/go-urn v1.4.0 // indirect
|
github.com/leodido/go-urn v1.4.0 // indirect
|
||||||
|
github.com/likexian/gokit v0.25.15 // indirect
|
||||||
|
github.com/likexian/whois v1.15.4 // indirect
|
||||||
|
github.com/likexian/whois-parser v1.24.19 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
@ -31,4 +35,5 @@ require (
|
|||||||
golang.org/x/text v0.17.0 // indirect
|
golang.org/x/text v0.17.0 // indirect
|
||||||
google.golang.org/protobuf v1.34.2 // indirect
|
google.golang.org/protobuf v1.34.2 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
lukechampine.com/uint128 v1.3.0 // indirect
|
||||||
)
|
)
|
||||||
|
10
go.sum
10
go.sum
@ -3,6 +3,8 @@ github.com/bytedance/sonic v1.12.1/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKz
|
|||||||
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||||
github.com/bytedance/sonic/loader v0.2.0 h1:zNprn+lsIP06C/IqCHs3gPQIvnvpKbbxyXQP1iU4kWM=
|
github.com/bytedance/sonic/loader v0.2.0 h1:zNprn+lsIP06C/IqCHs3gPQIvnvpKbbxyXQP1iU4kWM=
|
||||||
github.com/bytedance/sonic/loader v0.2.0/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
github.com/bytedance/sonic/loader v0.2.0/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||||
|
github.com/c-robinson/iplib/v2 v2.0.5 h1:puzVVzXBv9HjZqj8muiSoQwiMvkMwE9dLUaWCZ52S0g=
|
||||||
|
github.com/c-robinson/iplib/v2 v2.0.5/go.mod h1:ZfjJB+pR8Guy++ylL+OgGzN9dd4jWAE1CszvwVrjlJI=
|
||||||
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
|
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
|
||||||
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
||||||
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
|
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
|
||||||
@ -35,6 +37,12 @@ github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZY
|
|||||||
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||||
|
github.com/likexian/gokit v0.25.15 h1:QjospM1eXhdMMHwZRpMKKAHY/Wig9wgcREmLtf9NslY=
|
||||||
|
github.com/likexian/gokit v0.25.15/go.mod h1:S2QisdsxLEHWeD/XI0QMVeggp+jbxYqUxMvSBil7MRg=
|
||||||
|
github.com/likexian/whois v1.15.4 h1:r5En62c+S9HKFgJtdh2WsdmRGTcxE4WUtGBdZkSBXmM=
|
||||||
|
github.com/likexian/whois v1.15.4/go.mod h1:rXFTPcQdNlPQBJCQpPWTSIDGzzmgKBftmhdOOcLpwXk=
|
||||||
|
github.com/likexian/whois-parser v1.24.19 h1:vT8lWhnV8ogkdaYLyef6IvE5VTHVCwlUDG5BUXCx06k=
|
||||||
|
github.com/likexian/whois-parser v1.24.19/go.mod h1:rAtaofg2luol09H+ogDzGIfcG8ig1NtM5R16uQADDz4=
|
||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
@ -141,5 +149,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
|
|||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
lukechampine.com/uint128 v1.3.0 h1:cDdUVfRwDUDovz610ABgFD17nXD4/uDgVHl2sC3+sbo=
|
||||||
|
lukechampine.com/uint128 v1.3.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
|
||||||
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
||||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||||
|
5
internal/pkg/protocol/requests.go
Normal file
5
internal/pkg/protocol/requests.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package protocol
|
||||||
|
|
||||||
|
type ISPRequest struct {
|
||||||
|
Address string `json:"address"`
|
||||||
|
}
|
@ -1,6 +1,10 @@
|
|||||||
package response
|
package protocol
|
||||||
|
|
||||||
type MyIPResponse struct {
|
type MyIPResponse struct {
|
||||||
Address string `json:"address"`
|
Address string `json:"address"`
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ISPResponse struct {
|
||||||
|
ISP string `json:"isp"`
|
||||||
|
}
|
17
internal/pkg/protocol/types.go
Normal file
17
internal/pkg/protocol/types.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package protocol
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
type IPVersion int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
IPv4 IPVersion = 4
|
||||||
|
IPv6 IPVersion = 6
|
||||||
|
)
|
||||||
|
|
||||||
|
type IP struct {
|
||||||
|
Address net.IP
|
||||||
|
Version IPVersion
|
||||||
|
}
|
@ -1,25 +1,87 @@
|
|||||||
package utils
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"ipv6-test-node/internal/pkg/protocol"
|
||||||
"net"
|
"net"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
func GetIPVersion(ip net.IP) (protocol.IPVersion, error) {
|
||||||
IPv4 = 4
|
if ip == nil {
|
||||||
IPv6 = 6
|
|
||||||
)
|
|
||||||
|
|
||||||
func GetIPVersion(ip string) (int, error) {
|
|
||||||
parsedIP := net.ParseIP(ip)
|
|
||||||
if parsedIP == nil {
|
|
||||||
return 0, errors.New("invalid IP address")
|
return 0, errors.New("invalid IP address")
|
||||||
}
|
}
|
||||||
if parsedIP.To4() != nil {
|
if ip.To4() != nil {
|
||||||
return IPv4, nil
|
return protocol.IPv4, nil
|
||||||
} else if parsedIP.To16() != nil {
|
} else if ip.To16() != nil {
|
||||||
return IPv6, nil
|
return protocol.IPv6, nil
|
||||||
} else {
|
} else {
|
||||||
return 0, errors.New("invalid IP address")
|
return 0, errors.New("invalid IP address")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetASN(ip protocol.IP) (string, error) {
|
||||||
|
var query string
|
||||||
|
if ip.Version == 4 {
|
||||||
|
query = fmt.Sprintf("%sorigin.asn.cymru.com", reverseIPv4(ip.Address))
|
||||||
|
} else if ip.Version == 6 {
|
||||||
|
query = fmt.Sprintf("%sorigin6.asn.cymru.com", reverseIPv6(ip.Address))
|
||||||
|
}
|
||||||
|
|
||||||
|
txtRecords, err := net.LookupTXT(query)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(txtRecords) > 0 {
|
||||||
|
parts := strings.Split(txtRecords[0], " | ")
|
||||||
|
if len(parts) > 0 {
|
||||||
|
return "AS" + parts[0], nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf("ASN not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetISPName(asn string) (string, error) {
|
||||||
|
query := fmt.Sprintf("%s.asn.cymru.com", asn)
|
||||||
|
txtRecords, err := net.LookupTXT(query)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(txtRecords) > 0 {
|
||||||
|
parts := strings.Split(txtRecords[0], " | ")
|
||||||
|
if len(parts) > 0 {
|
||||||
|
return parts[4], nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf("ISP not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToIP(address net.IP) protocol.IP {
|
||||||
|
version, err := GetIPVersion(address)
|
||||||
|
if err != nil {
|
||||||
|
return protocol.IP{}
|
||||||
|
}
|
||||||
|
return protocol.IP{Address: address, Version: version}
|
||||||
|
}
|
||||||
|
|
||||||
|
func reverseIPv4(ip net.IP) string {
|
||||||
|
return fmt.Sprintf("%d.%d.%d.%d.", ip[3], ip[2], ip[1], ip[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
func reverseIPv6(ip net.IP) string {
|
||||||
|
var dst []byte
|
||||||
|
dst = make([]byte, hex.EncodedLen(len(ip)))
|
||||||
|
hex.Encode(dst, ip)
|
||||||
|
|
||||||
|
var reversed string
|
||||||
|
for i := len(dst) - 1; i >= 0; i-- {
|
||||||
|
reversed = reversed + string(dst[i]) + "."
|
||||||
|
}
|
||||||
|
return reversed
|
||||||
|
}
|
||||||
|
@ -12,6 +12,7 @@ func Register() *gin.Engine {
|
|||||||
|
|
||||||
ipGroup := g.Group("ip")
|
ipGroup := g.Group("ip")
|
||||||
ipGroup.GET("myip", ip.MyIP)
|
ipGroup.GET("myip", ip.MyIP)
|
||||||
|
ipGroup.GET("isp", ip.ISP)
|
||||||
|
|
||||||
return g
|
return g
|
||||||
}
|
}
|
||||||
|
29
internal/router/routes/ip/isp.go
Normal file
29
internal/router/routes/ip/isp.go
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package ip
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"ipv6-test-node/internal/pkg/protocol"
|
||||||
|
"ipv6-test-node/internal/pkg/utils"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ISP(c *gin.Context) {
|
||||||
|
var req *protocol.ISPRequest
|
||||||
|
err := c.BindJSON(&req)
|
||||||
|
if err != nil {
|
||||||
|
c.AbortWithStatus(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
asn, err := utils.GetASN(utils.ToIP(net.ParseIP(req.Address)))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
name, err := utils.GetISPName(asn)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, protocol.ISPResponse{ISP: name})
|
||||||
|
}
|
@ -2,19 +2,18 @@ package ip
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"ipv6-test-node/internal/pkg/response"
|
"ipv6-test-node/internal/pkg/protocol"
|
||||||
"ipv6-test-node/internal/pkg/utils"
|
"ipv6-test-node/internal/pkg/utils"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
func MyIP(c *gin.Context) {
|
func MyIP(c *gin.Context) {
|
||||||
version, err := utils.GetIPVersion(c.ClientIP())
|
ip := utils.ToIP(net.ParseIP(c.ClientIP()))
|
||||||
if err != nil {
|
|
||||||
return
|
c.JSON(http.StatusOK, protocol.MyIPResponse{
|
||||||
}
|
|
||||||
c.JSON(http.StatusOK, response.MyIPResponse{
|
|
||||||
Address: c.ClientIP(),
|
Address: c.ClientIP(),
|
||||||
Version: strconv.Itoa(version),
|
Version: strconv.Itoa(int(ip.Version)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user