mirror of
https://github.com/qdm12/ddns-updater.git
synced 2026-03-31 06:24:00 -04:00
fix(google): removed since no longer functional
- Logs error if provider google is used - Documentation updated - Fixes #605
This commit is contained in:
@@ -52,7 +52,6 @@ Light container updating DNS A and/or AAAA records periodically for multiple DNS
|
||||
- Gandi
|
||||
- GCP
|
||||
- GoDaddy
|
||||
- Google
|
||||
- He.net
|
||||
- Hetzner
|
||||
- Infomaniak
|
||||
@@ -191,7 +190,6 @@ Check the documentation for your DNS provider:
|
||||
- [Gandi](https://github.com/qdm12/ddns-updater/blob/master/docs/gandi.md)
|
||||
- [GCP](https://github.com/qdm12/ddns-updater/blob/master/docs/gcp.md)
|
||||
- [GoDaddy](https://github.com/qdm12/ddns-updater/blob/master/docs/godaddy.md)
|
||||
- [Google](https://github.com/qdm12/ddns-updater/blob/master/docs/google.md)
|
||||
- [He.net](https://github.com/qdm12/ddns-updater/blob/master/docs/he.net.md)
|
||||
- [Infomaniak](https://github.com/qdm12/ddns-updater/blob/master/docs/infomaniak.md)
|
||||
- [INWX](https://github.com/qdm12/ddns-updater/blob/master/docs/inwx.md)
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
# Google
|
||||
|
||||
## Configuration
|
||||
|
||||
### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"settings": [
|
||||
{
|
||||
"provider": "google",
|
||||
"domain": "domain.com",
|
||||
"host": "@",
|
||||
"username": "username",
|
||||
"password": "password",
|
||||
"ip_version": "ipv4"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Compulsory parameters
|
||||
|
||||
- `"domain"`
|
||||
- `"host"` is your host and can be a subdomain or `"@"` or `"*"`
|
||||
- `"username"`
|
||||
- `"password"`
|
||||
|
||||
### Optional parameters
|
||||
|
||||
- `"ip_version"` can be `ipv4` (A records) or `ipv6` (AAAA records), defaults to `ipv4 or ipv6`
|
||||
|
||||
## Domain setup
|
||||
|
||||
Thanks to [@gauravspatel](https://github.com/gauravspatel) for #124
|
||||
|
||||
1. Enable dynamic DNS in the *synthetic records* section of DNS management.
|
||||
1. The username and password is generated once you create the dynamic DNS entry.
|
||||
|
||||
### Wildcard entries
|
||||
|
||||
If you want to create a **wildcard entry**, you have to create a custom **CNAME** record with key `"*"` and value `"@"`.
|
||||
@@ -130,8 +130,16 @@ func extractAllSettings(jsonBytes []byte) (
|
||||
return allProviders, warnings, nil
|
||||
}
|
||||
|
||||
var (
|
||||
ErrProviderNoLongerSupported = errors.New("provider no longer supported")
|
||||
)
|
||||
|
||||
func makeSettingsFromObject(common commonSettings, rawSettings json.RawMessage) (
|
||||
providers []provider.Provider, warnings []string, err error) {
|
||||
if common.Provider == "google" {
|
||||
return nil, nil, fmt.Errorf("%w: %s", ErrProviderNoLongerSupported, common.Provider)
|
||||
}
|
||||
|
||||
providerName := models.Provider(common.Provider)
|
||||
if providerName == constants.DuckDNS { // only hosts, no domain
|
||||
if common.Domain != "" { // retro compatibility
|
||||
|
||||
@@ -25,7 +25,6 @@ const (
|
||||
Gandi models.Provider = "gandi"
|
||||
GCP models.Provider = "gcp"
|
||||
GoDaddy models.Provider = "godaddy"
|
||||
Google models.Provider = "google"
|
||||
HE models.Provider = "he"
|
||||
Hetzner models.Provider = "hetzner"
|
||||
Infomaniak models.Provider = "infomaniak"
|
||||
@@ -72,7 +71,6 @@ func ProviderChoices() []models.Provider {
|
||||
Gandi,
|
||||
GCP,
|
||||
GoDaddy,
|
||||
Google,
|
||||
HE,
|
||||
Hetzner,
|
||||
Infomaniak,
|
||||
|
||||
@@ -31,7 +31,6 @@ import (
|
||||
"github.com/qdm12/ddns-updater/internal/provider/providers/gandi"
|
||||
"github.com/qdm12/ddns-updater/internal/provider/providers/gcp"
|
||||
"github.com/qdm12/ddns-updater/internal/provider/providers/godaddy"
|
||||
"github.com/qdm12/ddns-updater/internal/provider/providers/google"
|
||||
"github.com/qdm12/ddns-updater/internal/provider/providers/he"
|
||||
"github.com/qdm12/ddns-updater/internal/provider/providers/hetzner"
|
||||
"github.com/qdm12/ddns-updater/internal/provider/providers/infomaniak"
|
||||
@@ -116,8 +115,6 @@ func New(providerName models.Provider, data json.RawMessage, domain, host string
|
||||
return gcp.New(data, domain, host, ipVersion)
|
||||
case constants.GoDaddy:
|
||||
return godaddy.New(data, domain, host, ipVersion)
|
||||
case constants.Google:
|
||||
return google.New(data, domain, host, ipVersion)
|
||||
case constants.HE:
|
||||
return he.New(data, domain, host, ipVersion)
|
||||
case constants.Hetzner:
|
||||
|
||||
@@ -1,171 +0,0 @@
|
||||
package google
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/netip"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/qdm12/ddns-updater/internal/models"
|
||||
"github.com/qdm12/ddns-updater/internal/provider/constants"
|
||||
"github.com/qdm12/ddns-updater/internal/provider/errors"
|
||||
"github.com/qdm12/ddns-updater/internal/provider/headers"
|
||||
"github.com/qdm12/ddns-updater/internal/provider/utils"
|
||||
"github.com/qdm12/ddns-updater/pkg/ipextract"
|
||||
"github.com/qdm12/ddns-updater/pkg/publicip/ipversion"
|
||||
)
|
||||
|
||||
type Provider struct {
|
||||
domain string
|
||||
host string
|
||||
ipVersion ipversion.IPVersion
|
||||
username string
|
||||
password string
|
||||
useProviderIP bool
|
||||
}
|
||||
|
||||
func New(data json.RawMessage, domain, host string,
|
||||
ipVersion ipversion.IPVersion) (p *Provider, err error) {
|
||||
extraSettings := struct {
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
UseProviderIP bool `json:"provider_ip"`
|
||||
}{}
|
||||
err = json.Unmarshal(data, &extraSettings)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p = &Provider{
|
||||
domain: domain,
|
||||
host: host,
|
||||
ipVersion: ipVersion,
|
||||
username: extraSettings.Username,
|
||||
password: extraSettings.Password,
|
||||
useProviderIP: extraSettings.UseProviderIP,
|
||||
}
|
||||
err = p.isValid()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func (p *Provider) isValid() error {
|
||||
switch {
|
||||
case p.username == "":
|
||||
return fmt.Errorf("%w", errors.ErrUsernameNotSet)
|
||||
case p.password == "":
|
||||
return fmt.Errorf("%w", errors.ErrPasswordNotSet)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Provider) String() string {
|
||||
return utils.ToString(p.domain, p.host, constants.Google, p.ipVersion)
|
||||
}
|
||||
|
||||
func (p *Provider) Domain() string {
|
||||
return p.domain
|
||||
}
|
||||
|
||||
func (p *Provider) Host() string {
|
||||
return p.host
|
||||
}
|
||||
|
||||
func (p *Provider) IPVersion() ipversion.IPVersion {
|
||||
return p.ipVersion
|
||||
}
|
||||
|
||||
func (p *Provider) Proxied() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *Provider) BuildDomainName() string {
|
||||
return utils.BuildDomainName(p.host, p.domain)
|
||||
}
|
||||
|
||||
func (p *Provider) HTML() models.HTMLRow {
|
||||
return models.HTMLRow{
|
||||
Domain: fmt.Sprintf("<a href=\"http://%s\">%s</a>", p.BuildDomainName(), p.BuildDomainName()),
|
||||
Host: p.Host(),
|
||||
Provider: "<a href=\"https://domains.google.com/m/registrar\">Google</a>",
|
||||
IPVersion: p.ipVersion.String(),
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Provider) Update(ctx context.Context, client *http.Client, ip netip.Addr) (newIP netip.Addr, err error) {
|
||||
u := url.URL{
|
||||
Scheme: "https",
|
||||
Host: "domains.google.com",
|
||||
Path: "/nic/update",
|
||||
User: url.UserPassword(p.username, p.password),
|
||||
}
|
||||
values := url.Values{}
|
||||
fqdn := utils.BuildURLQueryHostname(p.host, p.domain)
|
||||
values.Set("hostname", fqdn)
|
||||
if !p.useProviderIP {
|
||||
values.Set("myip", ip.String())
|
||||
}
|
||||
u.RawQuery = values.Encode()
|
||||
|
||||
request, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil)
|
||||
if err != nil {
|
||||
return netip.Addr{}, fmt.Errorf("creating http request: %w", err)
|
||||
}
|
||||
headers.SetUserAgent(request)
|
||||
|
||||
response, err := client.Do(request)
|
||||
if err != nil {
|
||||
return netip.Addr{}, fmt.Errorf("doing http request: %w", err)
|
||||
}
|
||||
defer response.Body.Close()
|
||||
|
||||
b, err := io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return netip.Addr{}, fmt.Errorf("reading response body: %w", err)
|
||||
}
|
||||
s := string(b)
|
||||
|
||||
switch s {
|
||||
case "":
|
||||
return netip.Addr{}, fmt.Errorf("%w: %d: %s", errors.ErrHTTPStatusNotValid, response.StatusCode, s)
|
||||
case constants.Nohost, constants.Notfqdn:
|
||||
return netip.Addr{}, fmt.Errorf("%w", errors.ErrHostnameNotExists)
|
||||
case constants.Badauth:
|
||||
return netip.Addr{}, fmt.Errorf("%w", errors.ErrAuth)
|
||||
case constants.Badagent:
|
||||
return netip.Addr{}, fmt.Errorf("%w", errors.ErrBannedUserAgent)
|
||||
case constants.Abuse:
|
||||
return netip.Addr{}, fmt.Errorf("%w", errors.ErrBannedAbuse)
|
||||
case constants.Nineoneone:
|
||||
return netip.Addr{}, fmt.Errorf("%w", errors.ErrDNSServerSide)
|
||||
case "conflict constants.A", "conflict constants.AAAA":
|
||||
return netip.Addr{}, fmt.Errorf("%w", errors.ErrConflictingRecord)
|
||||
}
|
||||
|
||||
if !strings.Contains(s, "nochg") && !strings.Contains(s, "good") {
|
||||
return netip.Addr{}, fmt.Errorf("%w: %s", errors.ErrUnknownResponse, s)
|
||||
}
|
||||
|
||||
var ips []netip.Addr
|
||||
if ip.Is4() {
|
||||
ips = ipextract.IPv4(s)
|
||||
} else {
|
||||
ips = ipextract.IPv6(s)
|
||||
}
|
||||
|
||||
if len(ips) == 0 {
|
||||
return netip.Addr{}, fmt.Errorf("%w", errors.ErrReceivedNoIP)
|
||||
}
|
||||
|
||||
newIP = ips[0]
|
||||
if !p.useProviderIP && ip.Compare(newIP) != 0 {
|
||||
return netip.Addr{}, fmt.Errorf("%w: sent ip %s to update but received %s",
|
||||
errors.ErrIPReceivedMismatch, ip, newIP)
|
||||
}
|
||||
return newIP, nil
|
||||
}
|
||||
Reference in New Issue
Block a user