GoBroke/tunnelbroker/funcs_tunnel.go
2025-02-04 12:14:08 -05:00

103 lines
2.4 KiB
Go

package tunnelbroker
import (
`fmt`
`net`
`strings`
`github.com/go-resty/resty/v2`
"r00t2.io/clientinfo/server"
)
// Has48 returns true if this Tunnel has a /48 assigned.
func (t *Tunnel) Has48() (has48 bool) {
if t.Routed48 != nil {
has48 = true
}
return
}
/*
Update checks the current (or explicit) client IPv4 address, compares it against the Tunnel's configuration,
and updates itself on change.
*/
func (t *Tunnel) Update() (updated bool, err error) {
var myInfo *server.R00tInfo
var resp *resty.Response
var req *resty.Request
var targetIp net.IP
var respStrs []string
if t.TunCfg.ExplicitAddr != nil {
targetIp = *t.TunCfg.ExplicitAddr
} else {
// Fetch the current client IP.
// Teeechnically we don't need to do this, as it by default uses client IP, but we wanna be as considerate as we can.
req = t.client.R()
// Force the response to JSON; because we pass "Linux" in the UA, it thinks it's graphical...
req.SetHeader("Accept", "application/json")
req.SetResult(&myInfo)
if resp, err = req.Get(wanIpUrl); err != nil {
return
}
if !resp.IsSuccess() {
err = respToErr(resp)
return
}
targetIp = myInfo.IP
}
if !t.ClientIPv4.Equal(targetIp) {
// It's different, so update.
req = t.client.R()
req.SetBasicAuth(*t.TunCfg.Username, t.TunCfg.UpdateKey)
req.SetQueryParam(updateTidParam, fmt.Sprintf("%d", t.TunCfg.TunnelID))
req.SetQueryParam(updateIpParam, targetIp.To4().String())
if resp, err = req.Get(updateBaseUrl); err != nil {
return
}
if !resp.IsSuccess() {
err = respToErr(resp)
return
}
respStrs = strings.Fields(resp.String())
if respStrs == nil || len(respStrs) == 0 {
// I... don't know what would result in this, but let's assume it succeeded.
updated = true
return
}
switch len(respStrs) {
case 1:
if respStrs[0] == "abuse" {
err = ErrHERateLimit
return
}
case 2:
switch respStrs[0] {
case "nochg":
// No update; existing value is the same
return
case "good":
switch respStrs[1] {
case "127.0.0.1":
// If the second returned word is "127.0.0.1", it's a "soft fail".
// This tends to happen if the specified address is in RFC 1918,
// or RFC 5737, or 66.220.2.74 can't ping the address, etc.
err = ErrHEInvalid
return
case targetIp.To4().String():
updated = true
return
}
}
}
}
return
}