2021-03-22 09:40:50 -04:00
package monitor
import (
"fmt"
"io/ioutil"
2022-03-31 10:45:26 -04:00
"math/rand"
2021-03-22 09:40:50 -04:00
"net/http"
2021-07-12 22:59:13 -04:00
"strings"
2021-03-22 09:40:50 -04:00
"time"
2021-05-21 23:28:43 -04:00
2021-06-21 09:30:42 -04:00
"github.com/naiba/nezha/pkg/utils"
2021-03-22 09:40:50 -04:00
)
type geoIP struct {
CountryCode string ` json:"country_code,omitempty" `
IP string ` json:"ip,omitempty" `
2021-07-08 12:01:58 -04:00
Query string ` json:"query,omitempty" `
2021-03-22 09:40:50 -04:00
}
2021-05-21 23:28:43 -04:00
var (
2021-07-08 12:01:58 -04:00
geoIPApiList = [ ] string {
2021-07-05 01:44:21 -04:00
"https://api.ip.sb/geoip" ,
2021-06-21 09:30:42 -04:00
"https://ipapi.co/json" ,
2021-07-08 12:01:58 -04:00
"https://freegeoip.app/json/" ,
"http://ip-api.com/json/" ,
"https://extreme-ip-lookup.com/json/" ,
2022-03-31 10:45:26 -04:00
// "https://ip.seeip.org/geoip",
2021-05-21 23:28:43 -04:00
}
cachedIP , cachedCountry string
2021-06-21 09:30:42 -04:00
httpClientV4 = utils . NewSingleStackHTTPClient ( time . Second * 20 , time . Second * 5 , time . Second * 10 , false )
httpClientV6 = utils . NewSingleStackHTTPClient ( time . Second * 20 , time . Second * 5 , time . Second * 10 , true )
2021-05-21 23:28:43 -04:00
)
2021-03-22 09:40:50 -04:00
func UpdateIP ( ) {
for {
2021-07-08 12:01:58 -04:00
ipv4 := fetchGeoIP ( geoIPApiList , false )
ipv6 := fetchGeoIP ( geoIPApiList , true )
2021-09-29 07:58:02 -04:00
if ipv4 . IP == "" && ipv6 . IP == "" {
time . Sleep ( time . Minute )
continue
}
if ipv4 . IP == "" || ipv6 . IP == "" {
cachedIP = fmt . Sprintf ( "%s%s" , ipv4 . IP , ipv6 . IP )
} else {
cachedIP = fmt . Sprintf ( "%s/%s" , ipv4 . IP , ipv6 . IP )
}
2021-03-22 09:40:50 -04:00
if ipv4 . CountryCode != "" {
cachedCountry = ipv4 . CountryCode
} else if ipv6 . CountryCode != "" {
cachedCountry = ipv6 . CountryCode
}
2021-09-29 07:58:02 -04:00
time . Sleep ( time . Minute * 30 )
2021-03-22 09:40:50 -04:00
}
}
2021-05-21 23:28:43 -04:00
func fetchGeoIP ( servers [ ] string , isV6 bool ) geoIP {
2021-03-22 09:40:50 -04:00
var ip geoIP
2021-05-21 23:28:43 -04:00
var resp * http . Response
var err error
2022-03-31 10:45:26 -04:00
if isV6 {
resp , err = httpGetWithUA ( httpClientV6 , servers [ rand . Intn ( len ( servers ) ) ] )
} else {
resp , err = httpGetWithUA ( httpClientV4 , servers [ rand . Intn ( len ( servers ) ) ] )
}
if err != nil {
return ip
}
body , err := ioutil . ReadAll ( resp . Body )
if err != nil {
return ip
}
resp . Body . Close ( )
err = utils . Json . Unmarshal ( body , & ip )
if err != nil {
return ip
}
if ip . IP == "" && ip . Query != "" {
ip . IP = ip . Query
}
// 没取到 v6 IP
if isV6 && ! strings . Contains ( ip . IP , ":" ) {
return ip
}
// 没取到 v4 IP
if ! isV6 && ! strings . Contains ( ip . IP , "." ) {
return ip
2021-03-22 09:40:50 -04:00
}
return ip
}
2022-03-31 10:45:26 -04:00
func httpGetWithUA ( client * http . Client , url string ) ( * http . Response , error ) {
req , err := http . NewRequest ( "GET" , url , nil )
if err != nil {
return nil , err
}
req . Header . Add ( "User-Agent" , "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36" )
return client . Do ( req )
}