Compare commits

...

1 Commits

Author SHA1 Message Date
dkeven
0fb498fa7a feat(daemon): use unified remote api env to query external ip 2026-03-03 20:52:44 +08:00
2 changed files with 83 additions and 84 deletions

View File

@@ -43,11 +43,12 @@ type state struct {
Disk string `json:"disk"` Disk string `json:"disk"`
// network info // network info
WikiConnected bool `json:"wifiConnected"` WikiConnected bool `json:"wifiConnected"`
WifiSSID *string `json:"wifiSSID,omitempty"` WifiSSID *string `json:"wifiSSID,omitempty"`
WiredConnected bool `json:"wiredConnected"` WiredConnected bool `json:"wiredConnected"`
HostIP string `json:"hostIp"` HostIP string `json:"hostIp"`
ExternalIP string `json:"externalIp"` ExternalIP string `json:"externalIp"`
ExternalIPProbeTime time.Time `json:"-"`
// installing / uninstalling / upgrading state // installing / uninstalling / upgrading state
InstallingState ProcessingState `json:"installingState"` InstallingState ProcessingState `json:"installingState"`
@@ -255,7 +256,10 @@ func CheckCurrentStatus(ctx context.Context) error {
} }
CurrentState.HostIP = hostIp CurrentState.HostIP = hostIp
CurrentState.ExternalIP = nets.GetMyExternalIPAddr() if time.Since(CurrentState.ExternalIPProbeTime) > 1*time.Minute {
CurrentState.ExternalIP = nets.GetMyExternalIPAddr()
CurrentState.ExternalIPProbeTime = time.Now()
}
// get olares state // get olares state

View File

@@ -4,14 +4,17 @@ import (
"crypto/tls" "crypto/tls"
"encoding/json" "encoding/json"
"errors" "errors"
"io/ioutil" "io"
"net" "net"
"net/http" "net/http"
"net/netip" "net/netip"
"net/url"
"os" "os"
"strings" "strings"
"time" "time"
"github.com/beclab/Olares/daemon/pkg/commands"
"github.com/gofiber/fiber/v2/log"
"github.com/libp2p/go-netroute" "github.com/libp2p/go-netroute"
pkg_errors "github.com/pkg/errors" pkg_errors "github.com/pkg/errors"
"github.com/txn2/txeh" "github.com/txn2/txeh"
@@ -267,15 +270,7 @@ func GetHostIpFromHostsFile(domain string) (string, error) {
return ip, nil return ip, nil
} }
// GetMyExternalIPAddr get my network outgoing ip address
func GetMyExternalIPAddr() string { func GetMyExternalIPAddr() string {
sites := map[string]string{
"httpbin": "https://httpbin.org/ip",
"ifconfigme": "https://ifconfig.me/all.json",
"externalip": "https://myexternalip.com/json",
"joinolares": "https://myip.joinolares.cn/ip",
}
type httpBin struct { type httpBin struct {
Origin string `json:"origin"` Origin string `json:"origin"`
} }
@@ -295,80 +290,80 @@ func GetMyExternalIPAddr() string {
IP string `json:"ip"` IP string `json:"ip"`
} }
var unmarshalFuncs = map[string]func(v []byte) string{ type siteConfig struct {
"httpbin": func(v []byte) string { url string
var hb httpBin unmarshalFunc func(v []byte) string
if err := json.Unmarshal(v, &hb); err == nil && hb.Origin != "" {
return hb.Origin
}
return ""
},
"ifconfigme": func(v []byte) string {
var ifMe ifconfigMe
if err := json.Unmarshal(v, &ifMe); err == nil && ifMe.IPAddr != "" {
return ifMe.IPAddr
}
return ""
},
"externalip": func(v []byte) string {
var extip externalIP
if err := json.Unmarshal(v, &extip); err == nil && extip.IP != "" {
return extip.IP
}
return ""
},
"joinolares": func(v []byte) string {
return strings.TrimSpace(string(v))
},
} }
ch := make(chan any, len(sites)) externalIPServiceURL, err := url.JoinPath(commands.OLARES_REMOTE_SERVICE, "/myip/ip")
if err != nil {
for site := range sites { klog.Error("failed to parse external IP service URL, ", err)
go func(name string) { return ""
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
c := http.Client{Timeout: 5 * time.Second}
resp, err := c.Get(sites[name])
if err != nil {
ch <- err
return
}
defer resp.Body.Close()
respBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
ch <- err
return
}
ip := unmarshalFuncs[name](respBytes)
//println(name, site, ip)
ch <- ip
}(site)
} }
tr := time.NewTimer(time.Duration(5*len(sites)+3) * time.Second) sites := []siteConfig{
{
LOOP: url: externalIPServiceURL,
for i := 0; i < len(sites); i++ { unmarshalFunc: func(v []byte) string {
select { return strings.TrimSpace(string(v))
case r, ok := <-ch: },
if !ok { },
continue {
} url: "https://httpbin.org/ip",
unmarshalFunc: func(v []byte) string {
switch v := r.(type) { var hb httpBin
case string: if err := json.Unmarshal(v, &hb); err == nil && hb.Origin != "" {
ip := net.ParseIP(v) return hb.Origin
if ip != nil && ip.To4() != nil && !ip.IsLoopback() && !ip.IsMulticast() {
return v
} }
case error: return ""
klog.Warningf("got an error, %v", v) },
} },
case <-tr.C: {
tr.Stop() url: "https://ifconfig.me/all.json",
klog.Warning("timed out") unmarshalFunc: func(v []byte) string {
break LOOP var ifMe ifconfigMe
if err := json.Unmarshal(v, &ifMe); err == nil && ifMe.IPAddr != "" {
return ifMe.IPAddr
}
return ""
},
},
{
url: "https://myexternalip.com/json",
unmarshalFunc: func(v []byte) string {
var extip externalIP
if err := json.Unmarshal(v, &extip); err == nil && extip.IP != "" {
return extip.IP
}
return ""
},
},
}
client := http.Client{
Timeout: 3 * time.Second,
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
},
}
for _, site := range sites {
resp, err := client.Get(site.url)
if err != nil {
log.Warnf("failed to get external ip from %s, %v", site.url, err)
continue
}
respBytes, readErr := io.ReadAll(resp.Body)
resp.Body.Close()
if readErr != nil {
log.Warnf("failed to read response from %s, %v", site.url, readErr)
continue
}
ipStr := site.unmarshalFunc(respBytes)
ip := net.ParseIP(ipStr)
if ip != nil && ip.To4() != nil && !ip.IsLoopback() && !ip.IsMulticast() {
return ipStr
} }
} }