This commit is contained in:
parent
4b89a2d18f
commit
063f32fcbb
@ -17,8 +17,8 @@ jobs:
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Install Docker
|
||||
run: curl -fsSL https://get.docker.com | sh
|
||||
# - name: Install Docker
|
||||
# run: curl -fsSL https://get.docker.com | sh
|
||||
|
||||
- name: Deploy with Docker
|
||||
run: docker compose up --build --force-recreate -d
|
||||
|
5
go.mod
5
go.mod
@ -5,6 +5,7 @@ go 1.22
|
||||
require (
|
||||
github.com/bytedance/sonic v1.12.1 // 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/iasm v0.2.0 // 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/klauspost/cpuid/v2 v2.2.8 // 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/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
@ -31,4 +35,5 @@ require (
|
||||
golang.org/x/text v0.17.0 // indirect
|
||||
google.golang.org/protobuf v1.34.2 // 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.2.0 h1:zNprn+lsIP06C/IqCHs3gPQIvnvpKbbxyXQP1iU4kWM=
|
||||
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/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
||||
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/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/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/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
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=
|
||||
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 {
|
||||
Address string `json:"address"`
|
||||
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
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"ipv6-test-node/internal/pkg/protocol"
|
||||
"net"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
IPv4 = 4
|
||||
IPv6 = 6
|
||||
)
|
||||
|
||||
func GetIPVersion(ip string) (int, error) {
|
||||
parsedIP := net.ParseIP(ip)
|
||||
if parsedIP == nil {
|
||||
func GetIPVersion(ip net.IP) (protocol.IPVersion, error) {
|
||||
if ip == nil {
|
||||
return 0, errors.New("invalid IP address")
|
||||
}
|
||||
if parsedIP.To4() != nil {
|
||||
return IPv4, nil
|
||||
} else if parsedIP.To16() != nil {
|
||||
return IPv6, nil
|
||||
if ip.To4() != nil {
|
||||
return protocol.IPv4, nil
|
||||
} else if ip.To16() != nil {
|
||||
return protocol.IPv6, nil
|
||||
} else {
|
||||
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.GET("myip", ip.MyIP)
|
||||
ipGroup.GET("isp", ip.ISP)
|
||||
|
||||
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 (
|
||||
"github.com/gin-gonic/gin"
|
||||
"ipv6-test-node/internal/pkg/response"
|
||||
"ipv6-test-node/internal/pkg/protocol"
|
||||
"ipv6-test-node/internal/pkg/utils"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func MyIP(c *gin.Context) {
|
||||
version, err := utils.GetIPVersion(c.ClientIP())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, response.MyIPResponse{
|
||||
ip := utils.ToIP(net.ParseIP(c.ClientIP()))
|
||||
|
||||
c.JSON(http.StatusOK, protocol.MyIPResponse{
|
||||
Address: c.ClientIP(),
|
||||
Version: strconv.Itoa(version),
|
||||
Version: strconv.Itoa(int(ip.Version)),
|
||||
})
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user