Coder Social home page Coder Social logo

cromefire / fritzbox-cloudflare-dyndns Goto Github PK

View Code? Open in Web Editor NEW
28.0 3.0 12.0 3.14 MB

Slim WAN IP updater for AVM FRITZ!Box devices, pushing updates towards CloudFlare DNS using push and poll strategies.

License: MIT License

Go 90.46% Dockerfile 9.54%
golang avm fritzbox dyndns soap

fritzbox-cloudflare-dyndns's Introduction

AVM FRITZ!Box Cloudflare DNS-service

This project has some simple goals:

  • Offer a slim service without any additional service requirements
  • Allow for two different combined strategies: Polling (through FRITZ!Box SOAP-API) and Pushing (FRITZ!Box Custom-DynDns setting).
  • Allow multiple domains to be updated with new A (IPv4) and AAAA (IPv6) records
  • Push those IP changes directly to CloudFlare DNS
  • Deploy in docker compose

If this fits for you, skim over the CNAME workaround if this is a better solution for you, otherwise feel free to visit the appropriate strategy section of this document and find out how to configure it correctly.

CNAME record workaround

Before you try this service evaluate a cheap workaround, as it does not require dedicated hardware to run 24/7:

Have dynamic IP updates by using a CNAME record to your myfritz address, found in Admin > Internet > MyFRITZ-Account. It should look like [hash].myfritz.net.

This basic example of a BIND DNS entry would make intranet.example.com auto update the current IP:

$TTL 60
$ORIGIN example.com.
intranet IN CNAME [hash].myfritz.net

Beware that this will expose your account hash to the outside world and depend on AVMs service availability.

Strategies

FRITZ!Box pushing

You can use this strategy if you have:

  • access to the admin panel of the FRITZ!Box router.
  • this services runs on a public interface towards the router.

In your .env file or your system environment variables you can be configured:

Variable name Description
DYNDNS_SERVER_BIND required, network interface to bind to, i.e. :8080
DYNDNS_SERVER_USERNAME optional, username for the DynDNS service
DYNDNS_SERVER_PASSWORD optional, password for the DynDNS service

Now configure the FRITZ!Box router to push IP changes towards this service. Log into the admin panel and go to Internet > Shares > DynDNS tab and setup a Custom provider:

Property Description / Value
Update-URL http://[server-ip]/ip?v4=<ipaddr>&v6=<ip6addr>&prefix=<ip6lanprefix>
Domain Enter at least one domain name so the router can probe if the update was successfully
Username Enter '_' if DYNDNS_SERVER_USERNAME env is unset
Password Enter '_' if DYNDNS_SERVER_PASSWORD env is unset

If you specified credentials you need to append them as additional GET parameters into the Update-URL like &username=<username>&password=<pass>.

FRITZ!Box polling

You can use this strategy if you have:

  • no access to the admin panel of the FRITZ!Box router.
  • for whatever reasons the router can not push towards this service, but we can poll from it.
  • you do not trust pushing

In your .env file or your system environment variables you can be configured:

Variable name Description
FRITZBOX_ENDPOINT_URL optional, how can we reach the router, i.e. http://fritz.box:49000, the port should be 49000 anyway.
FRITZBOX_ENDPOINT_TIMEOUT optional, a duration we give the router to respond, i.e. 10s.
FRITZBOX_ENDPOINT_INTERVAL optional, a duration how often we want to poll the WAN IPs from the router, i.e. 120s

You can try the endpoint URL in the browser to make sure you have the correct port, you should receive an 404 ERR_NOT_FOUND.

Because FRITZBOX_ENDPOINT_URL is set by default on the docker image, you have to explicitly set it to an empty string to disable polling

Cloudflare setup

To get your API Token do the following: Login to the cloudflare dashboard, go to My Profile > API Tokens > Create Token > Edit zone DNS, give to token some good name (e.g. "DDNS"), add all zones that the DDNS should be used for, click Continue to summary and Create token. Be sure to copy the token and add it to the config, you won't be able to see it again.

In your .env file or your system environment variables you can be configured:

Variable name Description
CLOUDFLARE_API_TOKEN required, your Cloudflare API Token
CLOUDFLARE_ZONES_IPV4 comma-separated list of domains to update with new IPv4 addresses
CLOUDFLARE_ZONES_IPV6 comma-separated list of domains to update with new IPv6 addresses
CLOUDFLARE_API_EMAIL deprecated, your Cloudflare account email
CLOUDFLARE_API_KEY deprecated, your Cloudflare Global API key

This service allows to update multiple records, an advanced example would be:

CLOUDFLARE_ZONES_IPV4=ipv4.example.com,ip.example.com,server-01.dev.local
CLOUDFLARE_ZONES_IPV6=ipv6.example.com,ip.example.com,server-01.dev.local

Considering the example call http://192.168.0.2:8080/ip?v4=127.0.0.1&v6=::1 every IPv4 listed zone would be updated to 127.0.0.1 and every IPv6 listed one to ::1.

Register IPv6 for another device (port-forwarding)

IPv6 port-forwarding works differently and so if you want to use it you have to add the following configuration.

Warning: FRITZBOX_ENDPOINT_URL has to be set for this to work.

To access a device via IPv6 you need to add it's global IPv6 address to cloudflare, for this to be calculated you need to find out the local part of it's IP. You can find out the local part of a device's IP, by going to the device's settings and looking at the IPv6 Interface-ID. It should look something like this: ::1234:5678:90ab:cdef. Sometimes the FritzBox seems to use a subnet, so you might need to add change it from something like ::1234:5678:90ab:cdef to ::1:1234:5678:90ab:cdef

Variable name Description
DEVICE_LOCAL_ADDRESS_IPV6 required, enter the local part of the device IP

Docker compose setup

Here is an example docker-compose.yml with all features activated:

version: '3.7'

services:
  updater:
    image: ghcr.io/cromefire/fritzbox-cloudflare-dyndns:1
    network_mode: host
    # build:
    #   context: .
    environment:
      - FRITZBOX_ENDPOINT_URL=http://fritz.box:49000
      - FRITZBOX_ENDPOINT_TIMEOUT=30s
      - FRITZBOX_ENDPOINT_INTERVAL=3s
      - [email protected]
      - CLOUDFLARE_API_KEY=demo
      - CLOUDFLARE_ZONES_IPV4=test.example.com
      - CLOUDFLARE_ZONES_IPV6=test.example.com

Now we could configure the FRITZ!Box to http://[docker-host-ip]:49000/ip?v4=<ipaddr>&v6=<ip6addr>&prefix=<ip6lanprefix> and it should trigger the update process.

Docker build

Note: A pre-built docker image is also available on this GitHub repository.

More raw approach would be to build and run it yourself:

docker build -t fritzbox-cloudflare-dyndns .
docker run --rm -it -p 8888:8080 fritzbox-cloudflare-dyndns

If you leave CLOUDFLARE_* unconfigured, pushing to CloudFlare will be disabled for testing purposes, so try to trigger it by calling http://127.0.0.1:8888/ip?v4=127.0.0.1&v6=::1 and review the logs.

fritzbox-cloudflare-dyndns's People

Contributors

adrianrudnik avatar cromefire avatar kilianyp avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

fritzbox-cloudflare-dyndns's Issues

feature: Add health check endpoint

First of all, great project! This enhancement request should be pretty easy to implement.

For added resiliency, add a health check endpoint to validate that the updater is actually running.
Proposed endpoints could be /health or /alive, with a simple HTTP 200 as the response code. Maybe add an "ok" in the body.

Bonus points: A JSON response which lists if the last communication attempts to the Fritz!Box and Cloudflare were successful. Still keep the 200 response code, even if these connections were not successful.

Add support for ARM-architecture

Hi,
when I try to run the docker container I get an standard_init_linux.go:219: exec user process caused: exec format error. I used it one time with the environment variables for polling and one time for pushing but I get immediately this error.

Possible Issue with TR64?

Is there a change within the Fritzbox TR64?

This Script stopped working for me.

I get the 404 Error Message from the Fritzbox but the log say:


time="2023-11-20T14:52:08Z" level=warning msg="Failed to poll WAN IPv4 from router" error="Post \"http://192.168.99.1:49000/igdupnp/control/WANIPConn1\": context deadline exceeded (Client.Timeout exceeded while awaiting headers)"

Environment Variables defined in compose file not recognized by container

Hi,
I was trying to set up your container as part of a compose (v 3.7) with the following config:

  dyndns:
    container_name: propaganda
    image: adrianrudnik/fritzbox-cloudflare-dyndns
    environment:
      - CLOUDFLARE_API_TOKEN=<API_TOKEN Redacted>
      - CLOUDFLARE_ZONES_IPV6=redacted.domain.com
      - DYNDNS_SERVER_BIND=:8081
      - DYNDNS_SERVER_USERNAME=<user>
      - DYNDNS_SERVER_PASSWORD=<redacted>
    labels:
      - traefik.enable=true
      - traefik.frontend.rule=Host:<redacted>
    networks:
      - srv

Running this results in the following error:

propaganda | time="2022-12-06T10:19:52Z" level=panic msg="Failed to parse env FRITZBOX_ENDPOINT_URL" error="parse \"http://fritz.box:49000     FRITZBOX_ENDPOINT_TIMEOUT 30s     DYNDNS_SERVER_BIND :8080     DYNDNS_SERVER_USERNAME      DYNDNS_SERVER_PASSWORD      CLOUDFLARE_API_EMAIL      CLOUDFLARE_API_KEY      CLOUDFLARE_ZONES_IPV4      CLOUDFLARE_ZONES_IPV6      CLOUDFLARE_LOCAL_ADDRESS_IPV6 \": invalid port \":8080     DYNDNS_SERVER_USERNAME      DYNDNS_SERVER_PASSWORD      CLOUDFLARE_API_EMAIL      CLOUDFLARE_API_KEY      CLOUDFLARE_ZONES_IPV4      CLOUDFLARE_ZONES_IPV6      CLOUDFLARE_LOCAL_ADDRESS_IPV6 \" after host"
propaganda | panic: (*logrus.Entry) 0xc000317dc0
propaganda |
propaganda | goroutine 1 [running]:
propaganda | github.com/sirupsen/logrus.Entry.log(0xc000172000, 0xc0003f9650, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
propaganda | 	/appbuild/vendor/github.com/sirupsen/logrus/entry.go:239 +0x2ea
propaganda | github.com/sirupsen/logrus.(*Entry).Log(0xc000317d50, 0x0, 0xc00019fe40, 0x1, 0x1)
propaganda | 	/appbuild/vendor/github.com/sirupsen/logrus/entry.go:268 +0xf0
propaganda | github.com/sirupsen/logrus.(*Entry).Panic(0xc000317d50, 0xc00019fe40, 0x1, 0x1)
propaganda | 	/appbuild/vendor/github.com/sirupsen/logrus/entry.go:306 +0x55
propaganda | main.newFritzBox(0x0)
propaganda | 	/appbuild/main.go:61 +0x136
propaganda | main.startPollServer(0xc0000662a0, 0xc0002e2860)
propaganda | 	/appbuild/main.go:158 +0x26
propaganda | main.main()
propaganda | 	/appbuild/main.go:38 +0x125
propaganda exited with code 2

It seems like the environment variables are not recognized, is there a known workaround?

Support retry

I recently had the problem that when restarting the FritzBox after the new IP was discovered, the API call still failed because the internet still wasn't online. Some retry might be good here or maybe some improvement in the polling / saving the last set IP.

Cloudflare proxy status

When the service updates the cloudflare dns record it resets the proxy status to false even when it was set to true manually before the update.

It would be great if it keeps the existing value or if it was a configurable setting.

CLOUDFLARE_API_TOKEN not found

Hey, why aren't there any issues, yet? Nobody using it am I just to stupid? :-(
I think I set the API token successfully, still the log states that the token is missing. Looking at the code this can only happen, when the token is not set.

Further you are writing in the description that the token should be set in the .env file. From what I understand the .env file only sets variables for the compose file, but does not reach the container: environment variables defined in the .env file are not automatically visible inside containers.
So I set the var in the environment: area of the compose-file, see below: no change

updater_1  | time="2020-11-24T19:45:18Z" level=info msg="Env CLOUDFLARE_API_TOKEN not found, disabling CloudFlare updates"
$ docker/cloudflare-dns-update$ docker exec -it cloudflare-dns-update_updater_1 sh -c 'echo $CLOUDFLARE_API_TOKEN'
y......................................_

What did I do wrong?

Disable strategy

Is it possible to disable e.g. the polling strategy if I only want to use the pushing strategy?

Implementation

Hi,
I have a FritzBox and i need to give up my static ip nr, i have my own DNS at a hosting provider, is it possible by using your code on a pi to update the dns with new dynamic ipnrs?

regards
Eelco

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.