Skip to content

Commit 79be632

Browse files
committed
加入geo ip
1 parent bcc187e commit 79be632

File tree

3 files changed

+163
-2
lines changed

3 files changed

+163
-2
lines changed

location/location.go

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
package location
2+
3+
import (
4+
"encoding/json"
5+
"errors"
6+
"fmt"
7+
"log"
8+
"net"
9+
"net/http"
10+
)
11+
12+
const IpGeoLocationApiKey = "71a993e55ea64df29c3caa7c094f7099"
13+
14+
// https://ipgeolocation.io/ data
15+
// 1k request for per day
16+
17+
type IpgeolocationInfo struct {
18+
IP string `json:"ip"`
19+
Hostname string `json:"hostname"`
20+
ContinentCode string `json:"continent_code"`
21+
ContinentName string `json:"continent_name"`
22+
CountryCode2 string `json:"country_code2"`
23+
CountryCode3 string `json:"country_code3"`
24+
CountryName string `json:"country_name"`
25+
CountryCapital string `json:"country_capital"`
26+
StateProv string `json:"state_prov"`
27+
District string `json:"district"`
28+
City string `json:"city"`
29+
Zipcode string `json:"zipcode"`
30+
Latitude string `json:"latitude"`
31+
Longitude string `json:"longitude"`
32+
IsEu bool `json:"is_eu"`
33+
CallingCode string `json:"calling_code"`
34+
CountryTld string `json:"country_tld"`
35+
Languages string `json:"languages"`
36+
CountryFlag string `json:"country_flag"`
37+
GeonameID string `json:"geoname_id"`
38+
Isp string `json:"isp"`
39+
ConnectionType string `json:"connection_type"`
40+
Organization string `json:"organization"`
41+
Asn string `json:"asn"`
42+
Currency Currency `json:"currency"`
43+
TimeZone TimeZone `json:"time_zone"`
44+
}
45+
type Currency struct {
46+
Code string `json:"code"`
47+
Name string `json:"name"`
48+
Symbol string `json:"symbol"`
49+
}
50+
type TimeZone struct {
51+
Name string `json:"name"`
52+
Offset int `json:"offset"`
53+
CurrentTime string `json:"current_time"`
54+
CurrentTimeUnix float64 `json:"current_time_unix"`
55+
IsDst bool `json:"is_dst"`
56+
DstSavings int `json:"dst_savings"`
57+
}
58+
59+
// GetIpgeolocationInfo
60+
//
61+
// @Description: 使用ipgeolocation 获取geoip信息
62+
// @param ipString
63+
// @return *IpgeolocationInfo
64+
// @return error
65+
func GetIpgeolocationInfo(ipString string) (*IpgeolocationInfo, error) {
66+
normalIpv4Address := CheckStrIsIpAddress(ipString)
67+
if !normalIpv4Address {
68+
return nil, errors.New("args not a valid ipStr address: " + ipString)
69+
}
70+
var requestUrl = fmt.Sprintf("https://api.ipgeolocation.io/ipgeo?apiKey=%s&ip=%s", IpGeoLocationApiKey, ipString)
71+
req, err := http.NewRequest("GET", requestUrl, nil)
72+
if err != nil {
73+
log.Println("get location by ipgeolocation error: ", err)
74+
return nil, errors.New("get location by ipgeolocation error: " + err.Error())
75+
}
76+
req.Header.Add("Accept", "*/*")
77+
req.Header.Add("Accept-Language", "zh,en;q=0.9,zh-TW;q=0.8,zh-CN;q=0.7,ja;q=0.6")
78+
req.Header.Add("Cache-Control", "no-cache")
79+
//req.Header.Add("Origin", "http://ip-api.com")
80+
req.Header.Add("Pragma", "no-cache")
81+
//req.Header.Add("Referer", "http://ip-api.com/")
82+
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")
83+
84+
client := &http.Client{}
85+
resp, err := client.Do(req)
86+
defer resp.Body.Close()
87+
88+
var ipGeoInfo IpgeolocationInfo
89+
err = json.NewDecoder(resp.Body).Decode(&ipGeoInfo)
90+
if err != nil {
91+
log.Println("get location by ipgeolocation error: ", err)
92+
return nil, errors.New("get location by ipgeolocation error: " + err.Error())
93+
}
94+
return &ipGeoInfo, nil
95+
}
96+
97+
// GetLocInfoShort
98+
//
99+
// @Description: 获取地理位置信息
100+
// @receiver receiver
101+
// @return string
102+
func (receiver *IpgeolocationInfo) GetLocInfoShort() string {
103+
if receiver == nil {
104+
return ""
105+
}
106+
return fmt.Sprintf("%s-%s-%s", receiver.CountryCode3, receiver.City, receiver.Organization)
107+
}
108+
109+
// CheckStrIsIpAddress
110+
//
111+
// @Description: 判断str是否为合格的ip str
112+
// @param str
113+
// @return bool
114+
func CheckStrIsIpAddress(str string) bool {
115+
ip := net.ParseIP(str)
116+
return ip != nil
117+
}

location/location_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package location
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
)
7+
8+
func TestGetIpgeolocationInfo(t *testing.T) {
9+
10+
info, err := GetIpgeolocationInfo("128.14.140.254")
11+
if err != nil {
12+
fmt.Println(err)
13+
}
14+
fmt.Println(info)
15+
16+
}

utils/utils.go

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"net/netip"
1111
"proxy-node2more/cdn"
1212
"proxy-node2more/config"
13+
"proxy-node2more/location"
1314
"regexp"
1415
"strconv"
1516
"strings"
@@ -197,9 +198,21 @@ func CaculateNodesResult(configSet *config.AllConfig) (*config.AllConfig, error)
197198
}
198199

199200
}
201+
//
202+
var ipResultGeo = make(map[string]string)
203+
for _, ip := range ipResult {
204+
//获取位置信息
205+
info, err := location.GetIpgeolocationInfo(ip)
206+
if err != nil {
207+
fmt.Println("Get ip geolocation info error: ", err)
208+
}
209+
infoShort := info.GetLocInfoShort()
210+
ipResultGeo[ip] = infoShort
211+
}
212+
200213
var results []string
201214
for _, node := range inputNodes {
202-
replaceCDNIpSet, err := DoReplaceCDNIpSet(node, ipResult)
215+
replaceCDNIpSet, err := DoReplaceCDNIpSet(node, ipResultGeo)
203216
if err != nil {
204217
return &config.AllConfig{
205218
InputNodeStr: nil,
@@ -217,7 +230,11 @@ func CaculateNodesResult(configSet *config.AllConfig) (*config.AllConfig, error)
217230
return configSet, nil
218231
}
219232

220-
func DoReplaceCDNIpSet(inputNode string, ipResult []string) ([]string, error) {
233+
func DoReplaceCDNIpSet(inputNode string, ipResultGeo map[string]string) ([]string, error) {
234+
ipResult := make([]string, 0, len(ipResultGeo))
235+
for k := range ipResultGeo {
236+
ipResult = append(ipResult, k)
237+
}
221238
output := inputNode
222239

223240
output = strings.ReplaceAll(output, " ", "")
@@ -262,6 +279,8 @@ func DoReplaceCDNIpSet(inputNode string, ipResult []string) ([]string, error) {
262279
vmessInfo.Aid = 0
263280
for i := 0; i < len(ipResult); i++ {
264281
var newNode = vmessInfo.CloneNew()
282+
locationInfo := ipResultGeo[ipResult[i]]
283+
newNode.Ps = locationInfo + "@" + newNode.Ps
265284
newNode.Add = ipResult[i]
266285
replacedNode, err := json.Marshal(newNode)
267286
HandleError(err)
@@ -311,10 +330,15 @@ func DoReplaceCDNIpSet(inputNode string, ipResult []string) ([]string, error) {
311330
re = regexp.MustCompile(`(@)(.*?)(:)`)
312331
subStrPart1 := re.FindStringSubmatch(sampleNode)[1]
313332
subStrPart3 := re.FindStringSubmatch(sampleNode)[3]
333+
nodeNameIndex := strings.LastIndex(sampleNode, "#")
334+
nodeName := sampleNode[nodeNameIndex:]
335+
locationInfo := ipResultGeo[ip]
336+
sampleNode = strings.ReplaceAll(sampleNode, nodeName, locationInfo+"@"+nodeName)
314337
nodes = append(nodes, re.ReplaceAllString(sampleNode, subStrPart1+ip+subStrPart3)+"\r")
315338
}
316339
return nodes, nil
317340
}
341+
//trojan协议
318342
if strings.HasPrefix(sampleNode, trojanPre) {
319343
//trojan trojan://[email protected]:48857?type=tcp&security=tls&sni=a.b.tk&flow=xtls-rprx-direct#a.b.tk-trojan-2
320344
re := regexp.MustCompile(`@(.*?):`)
@@ -354,6 +378,10 @@ func DoReplaceCDNIpSet(inputNode string, ipResult []string) ([]string, error) {
354378
re = regexp.MustCompile(`(@)(.*?)(:)`)
355379
subStrPart1 := re.FindStringSubmatch(sampleNode)[1]
356380
subStrPart3 := re.FindStringSubmatch(sampleNode)[3]
381+
nodeNameIndex := strings.LastIndex(sampleNode, "#")
382+
nodeName := sampleNode[nodeNameIndex:]
383+
locationInfo := ipResultGeo[ip]
384+
sampleNode = strings.ReplaceAll(sampleNode, nodeName, locationInfo+"@"+nodeName)
357385
nodes = append(nodes, re.ReplaceAllString(sampleNode, subStrPart1+ip+subStrPart3)+"\r")
358386
}
359387
return nodes, nil

0 commit comments

Comments
 (0)