From 7761fa4b0cd6e5a0ba82fc12af639a7fc94e6884 Mon Sep 17 00:00:00 2001 From: Leopold Date: Fri, 25 Apr 2025 00:31:28 +0200 Subject: [PATCH] initial commit --- .woodpecker/build.yaml | 19 ++++++++++ Containerfile | 19 ++++++++++ README.md | 3 ++ go.mod | 3 ++ main.go | 86 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 130 insertions(+) create mode 100644 .woodpecker/build.yaml create mode 100644 Containerfile create mode 100644 README.md create mode 100644 go.mod create mode 100644 main.go diff --git a/.woodpecker/build.yaml b/.woodpecker/build.yaml new file mode 100644 index 0000000..ba83203 --- /dev/null +++ b/.woodpecker/build.yaml @@ -0,0 +1,19 @@ +when: + - event: push + branch: main + +steps: +- name: publish + image: woodpeckerci/plugin-kaniko + settings: + platforms: linux/amd64 + repo: git.sakoma.wang/llamprecht/advent20xx + registry: git.sakoma.wang + tags: ${CI_COMMIT_SHA} + cache: true + username: llamprecht + build_args: + - COMMIT_SHA=${CI_COMMIT_SHA} + - COMMIT_AUTHOR_EMAIL=${CI_COMMIT_AUTHOR_EMAIL} + password: + from_secret: container_registry_token diff --git a/Containerfile b/Containerfile new file mode 100644 index 0000000..1ff8464 --- /dev/null +++ b/Containerfile @@ -0,0 +1,19 @@ +FROM golang:latest AS build + +WORKDIR /build + +COPY go.mod go.sum ./ + +RUN go mod download + +COPY . . + +RUN go build -o /dynv6-update + +FROM scratch + +WORKDIR /app + +COPY --from=build /dynv6-update /app/dynv6-update + +CMD ["/app/dynv6-update"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..647d660 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +## dynv6-update + +A simple client to update the IPv6 Prefix using the dynv6 API diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..85e5c71 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module git.sakoma.wang/llamprecht/dynv6-update + +go 1.24.2 diff --git a/main.go b/main.go new file mode 100644 index 0000000..aaa2cd9 --- /dev/null +++ b/main.go @@ -0,0 +1,86 @@ +package main + +import ( + "errors" + "fmt" + "log" + "net" + "net/http" + "os" + "time" +) + +type conf struct { + zone string + token string + server string +} + +func main() { + conf, err := readConfigVars() + if err != nil { + log.Fatal(err) + } + lastIPv6 := "" + for { + time.Sleep(1 * time.Second) + if newIPv6, ok := checkForNewV6(lastIPv6); ok { + lastIPv6 = newIPv6 + sendNewIP(conf) + } + } +} + +func checkForNewV6(lastIPv6 string) (string, bool) { + interfaces, err := net.Interfaces() + if err != nil { + log.Println(err) + return lastIPv6, false + } + currentIPv6 := "" + for _, inter := range interfaces { + addresses, err := inter.Addrs() + if err != nil { + log.Println(err) + return lastIPv6, false + } + for _, addr := range addresses { + if ip, ok := addr.(*net.IPNet); ok && !ip.IP.IsLoopback() { + if ip.IP.To4() == nil { + currentIPv6 = ip.IP.String() + } + } + } + } + if currentIPv6 != lastIPv6 { + return currentIPv6, true + } + return lastIPv6, false +} + +func sendNewIP(config conf) error { + _, err := http.Get(fmt.Sprintf("https://ipv6.dynv6.com/api/update?ipv6prefix=auto&token=%s&zone=%s", config.token, config.zone)) + if err != nil { + return err + } + return nil +} + +func readConfigVars() (conf, error) { + var zone, token, server string + var present bool + if zone, present = os.LookupEnv("ZONE"); !present { + return conf{}, errors.New("No Zone Specified") + } + if token, present = os.LookupEnv("TOKEN"); !present { + return conf{}, errors.New("No Token Specified") + } + if server, present = os.LookupEnv("SERVER"); !present { + server = "ipv6.dynv6.com" + } + return conf{ + zone: zone, + token: token, + server: server, + }, nil +}