Skip to content

Commit

Permalink
加入geo ip
Browse files Browse the repository at this point in the history
  • Loading branch information
fireinrain committed Apr 21, 2023
1 parent bcc187e commit 79be632
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 2 deletions.
117 changes: 117 additions & 0 deletions location/location.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package location

import (
"encoding/json"
"errors"
"fmt"
"log"
"net"
"net/http"
)

const IpGeoLocationApiKey = "71a993e55ea64df29c3caa7c094f7099"

// https://ipgeolocation.io/ data
// 1k request for per day

type IpgeolocationInfo struct {
IP string `json:"ip"`
Hostname string `json:"hostname"`
ContinentCode string `json:"continent_code"`
ContinentName string `json:"continent_name"`
CountryCode2 string `json:"country_code2"`
CountryCode3 string `json:"country_code3"`
CountryName string `json:"country_name"`
CountryCapital string `json:"country_capital"`
StateProv string `json:"state_prov"`
District string `json:"district"`
City string `json:"city"`
Zipcode string `json:"zipcode"`
Latitude string `json:"latitude"`
Longitude string `json:"longitude"`
IsEu bool `json:"is_eu"`
CallingCode string `json:"calling_code"`
CountryTld string `json:"country_tld"`
Languages string `json:"languages"`
CountryFlag string `json:"country_flag"`
GeonameID string `json:"geoname_id"`
Isp string `json:"isp"`
ConnectionType string `json:"connection_type"`
Organization string `json:"organization"`
Asn string `json:"asn"`
Currency Currency `json:"currency"`
TimeZone TimeZone `json:"time_zone"`
}
type Currency struct {
Code string `json:"code"`
Name string `json:"name"`
Symbol string `json:"symbol"`
}
type TimeZone struct {
Name string `json:"name"`
Offset int `json:"offset"`
CurrentTime string `json:"current_time"`
CurrentTimeUnix float64 `json:"current_time_unix"`
IsDst bool `json:"is_dst"`
DstSavings int `json:"dst_savings"`
}

// GetIpgeolocationInfo
//
// @Description: 使用ipgeolocation 获取geoip信息
// @param ipString
// @return *IpgeolocationInfo
// @return error
func GetIpgeolocationInfo(ipString string) (*IpgeolocationInfo, error) {
normalIpv4Address := CheckStrIsIpAddress(ipString)
if !normalIpv4Address {
return nil, errors.New("args not a valid ipStr address: " + ipString)
}
var requestUrl = fmt.Sprintf("https://api.ipgeolocation.io/ipgeo?apiKey=%s&ip=%s", IpGeoLocationApiKey, ipString)
req, err := http.NewRequest("GET", requestUrl, nil)
if err != nil {
log.Println("get location by ipgeolocation error: ", err)
return nil, errors.New("get location by ipgeolocation error: " + err.Error())
}
req.Header.Add("Accept", "*/*")
req.Header.Add("Accept-Language", "zh,en;q=0.9,zh-TW;q=0.8,zh-CN;q=0.7,ja;q=0.6")
req.Header.Add("Cache-Control", "no-cache")
//req.Header.Add("Origin", "http://ip-api.com")
req.Header.Add("Pragma", "no-cache")
//req.Header.Add("Referer", "http://ip-api.com/")
req.Header.Add("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36")

client := &http.Client{}
resp, err := client.Do(req)
defer resp.Body.Close()

var ipGeoInfo IpgeolocationInfo
err = json.NewDecoder(resp.Body).Decode(&ipGeoInfo)
if err != nil {
log.Println("get location by ipgeolocation error: ", err)
return nil, errors.New("get location by ipgeolocation error: " + err.Error())
}
return &ipGeoInfo, nil
}

// GetLocInfoShort
//
// @Description: 获取地理位置信息
// @receiver receiver
// @return string
func (receiver *IpgeolocationInfo) GetLocInfoShort() string {
if receiver == nil {
return ""
}
return fmt.Sprintf("%s-%s-%s", receiver.CountryCode3, receiver.City, receiver.Organization)
}

// CheckStrIsIpAddress
//
// @Description: 判断str是否为合格的ip str
// @param str
// @return bool
func CheckStrIsIpAddress(str string) bool {
ip := net.ParseIP(str)
return ip != nil
}
16 changes: 16 additions & 0 deletions location/location_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package location

import (
"fmt"
"testing"
)

func TestGetIpgeolocationInfo(t *testing.T) {

info, err := GetIpgeolocationInfo("128.14.140.254")
if err != nil {
fmt.Println(err)
}
fmt.Println(info)

}
32 changes: 30 additions & 2 deletions utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"net/netip"
"proxy-node2more/cdn"
"proxy-node2more/config"
"proxy-node2more/location"
"regexp"
"strconv"
"strings"
Expand Down Expand Up @@ -197,9 +198,21 @@ func CaculateNodesResult(configSet *config.AllConfig) (*config.AllConfig, error)
}

}
//
var ipResultGeo = make(map[string]string)
for _, ip := range ipResult {
//获取位置信息
info, err := location.GetIpgeolocationInfo(ip)
if err != nil {
fmt.Println("Get ip geolocation info error: ", err)
}
infoShort := info.GetLocInfoShort()
ipResultGeo[ip] = infoShort
}

var results []string
for _, node := range inputNodes {
replaceCDNIpSet, err := DoReplaceCDNIpSet(node, ipResult)
replaceCDNIpSet, err := DoReplaceCDNIpSet(node, ipResultGeo)
if err != nil {
return &config.AllConfig{
InputNodeStr: nil,
Expand All @@ -217,7 +230,11 @@ func CaculateNodesResult(configSet *config.AllConfig) (*config.AllConfig, error)
return configSet, nil
}

func DoReplaceCDNIpSet(inputNode string, ipResult []string) ([]string, error) {
func DoReplaceCDNIpSet(inputNode string, ipResultGeo map[string]string) ([]string, error) {
ipResult := make([]string, 0, len(ipResultGeo))
for k := range ipResultGeo {
ipResult = append(ipResult, k)
}
output := inputNode

output = strings.ReplaceAll(output, " ", "")
Expand Down Expand Up @@ -262,6 +279,8 @@ func DoReplaceCDNIpSet(inputNode string, ipResult []string) ([]string, error) {
vmessInfo.Aid = 0
for i := 0; i < len(ipResult); i++ {
var newNode = vmessInfo.CloneNew()
locationInfo := ipResultGeo[ipResult[i]]
newNode.Ps = locationInfo + "@" + newNode.Ps
newNode.Add = ipResult[i]
replacedNode, err := json.Marshal(newNode)
HandleError(err)
Expand Down Expand Up @@ -311,10 +330,15 @@ func DoReplaceCDNIpSet(inputNode string, ipResult []string) ([]string, error) {
re = regexp.MustCompile(`(@)(.*?)(:)`)
subStrPart1 := re.FindStringSubmatch(sampleNode)[1]
subStrPart3 := re.FindStringSubmatch(sampleNode)[3]
nodeNameIndex := strings.LastIndex(sampleNode, "#")
nodeName := sampleNode[nodeNameIndex:]
locationInfo := ipResultGeo[ip]
sampleNode = strings.ReplaceAll(sampleNode, nodeName, locationInfo+"@"+nodeName)
nodes = append(nodes, re.ReplaceAllString(sampleNode, subStrPart1+ip+subStrPart3)+"\r")
}
return nodes, nil
}
//trojan协议
if strings.HasPrefix(sampleNode, trojanPre) {
//trojan trojan://aNbwlRsdsasdasr8N@a.b.tk:48857?type=tcp&security=tls&sni=a.b.tk&flow=xtls-rprx-direct#a.b.tk-trojan-2
re := regexp.MustCompile(`@(.*?):`)
Expand Down Expand Up @@ -354,6 +378,10 @@ func DoReplaceCDNIpSet(inputNode string, ipResult []string) ([]string, error) {
re = regexp.MustCompile(`(@)(.*?)(:)`)
subStrPart1 := re.FindStringSubmatch(sampleNode)[1]
subStrPart3 := re.FindStringSubmatch(sampleNode)[3]
nodeNameIndex := strings.LastIndex(sampleNode, "#")
nodeName := sampleNode[nodeNameIndex:]
locationInfo := ipResultGeo[ip]
sampleNode = strings.ReplaceAll(sampleNode, nodeName, locationInfo+"@"+nodeName)
nodes = append(nodes, re.ReplaceAllString(sampleNode, subStrPart1+ip+subStrPart3)+"\r")
}
return nodes, nil
Expand Down

0 comments on commit 79be632

Please sign in to comment.