Code Monkey home page Code Monkey logo

python-dyndnsc's Introduction

Dyndnsc - dynamic dns update client

image

image

image

image

Code coverage

Dyndnsc is a command line client for sending updates to dynamic dns (ddns, dyndns) services. It supports multiple protocols and services, and it has native support for ipv6. The configuration file allows using foreign, but compatible services. Dyndnsc ships many different IP detection mechanisms, support for configuring multiple services in one place and it has a daemon mode for running unattended. It has a plugin system to provide external notification services.

Quickstart / Documentation

See the Quickstart section of the https://dyndnsc.readthedocs.io/

Installation

# from pypi:
pip install dyndnsc

# using docker:
docker pull infothrill/dyndnsc-x86-alpine

# from downloaded source:
python setup.py install

# directly from github:
pip install https://github.com/infothrill/python-dyndnsc/zipball/develop

Requirements

  • Python 3.6+

Status

Dyndnsc is still in alpha stage, which means that any interface can still change at any time. For this to change, it shall be sufficient to have documented use of this package which will necessitate stability (i.e. community process).

python-dyndnsc's People

Contributors

do3cc avatar infothrill avatar pyup-bot avatar renovate[bot] avatar stettberger avatar thomaswaldmann 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

python-dyndnsc's Issues

make webcheck url configurable per service

it currently uses some random(?) service.

there are 3 issues with that:

a) it is a bit unpretty if you use service A to also depend on the webchecker of service B

b) if it would use the configured checker of the service, one could make 2 different services to separate ipv4 and ipv6 stuff.

c) it currently checks the ipv4 from the webchecker and then compares it to the ipv6 of the interface - leading to lots of nochg updates.

more labels on github issue tracker

maybe some more labels would be useful:

easy (for people new to the project who want to help)
needs help (stuff that main devs can't / won't do on their own)
security (for security improvements or security issues) - in RED :)
task (stuff that is clear and just needs to be done)
docs (any documentation task that doesn't require coding)

docs tree reordering

just some ideas:

example.ini -> docs/user/examples/...
README.rst - include this from docs/user/about.rst (or intro.rst) [see also #33 ]
docs/api.rst -> docs/dev/api.rst
docs/user/intro.rst philosophy -> docs/dev/...
docs/user/intro.rst goals -> docs/user/about.rst or history.rst?
docs/user/intro.rst license -> docs/user/license.rst
docs/dev/todo.rst -> docs/dev/contribute.rst
docs/community/faq.rst -> docs/user/...
docs/community/updates.rst updates -> docs/user/changelog.rst

document guidelines for SSL issues

I immediately ran into SSL certificate checking issues when trying to use it with nsupdate.info due to:

https://github.com/kennethreitz/requests/issues/749

We need SNI for nsupdate.info, trying it with requests on python2.7 failed, even after installing some dependencies mentioned in that issue.

But there is an easy way:

I installed python3.2 and the SSL / SNI issues were just GONE (without needing to install anything special).

So, if there is nothing speaking against it, it maybe should be recommended to use python >= 3.2 with dyndnsc. Or at least if one is seeing SSL cert issues.

AttributeError: 'IPDetectorWebCheck' object has no attribute 'names'

I am having problems keeping the ip addresses updated on one of my Raspberry Pi setups. Sometimes they do not even get updated at all, the easiest way for me is to trigger a reboot of the device, so that I am able to access it from the outside again. This usually works, but I noticed some errors in the logs. I am calling dyndnsc via dhcpd hooks, to react directly on any changes on my networking interfaces, but also via crontab as a fallback every 11th minute of every hour.
I assume the errors occur because the interfaces have no IP at the time that I am calling dyndnsc, but even in that case the dyndns entry should be updated as well and set to no IP/delete the IP.

/etc/dyndnsc.ini:

[dyndnsc]
configs = myconf_ipv4, myconf_ipv6

[myconf_ipv4]
# this will update your ipv4 address to the address
# the detector dnswanip returns:
use_preset = nsupdate.info:ipv4
updater-url = https://ipv4.mynsupdateinfosetup.tld/nic/update
updater-hostname = myclient.mynsupdateinfosetup.tld
updater-userid = myclient.mynsupdateinfosetup.tld
updater-password = mypassword
detector = webcheck4
detector-url = http://ipv4.mynsupdateinfosetup.tld/myip
#detector-parser = plain

[myconf_ipv6]
# this will update your ipv6 address to the address
# the detector dnswanip returns:
use_preset = nsupdate.info:ipv6
updater-url = https://ipv6.mynsupdateinfosetup.tld/nic/update
updater-hostname = myclient.mynsupdateinfosetup.tld
updater-userid = myclient.mynsupdateinfosetup.tld
updater-password = mypassword
detector = socket
detector-family = INET6
#detector = webcheck6
#detector-url = http://ipv6.mynsupdateinfosetup.tld/myip
#detector-parser = plain

I used the webcheck6 detector before, but that yielded different errors, so I commented that and tried the socket detector. Logs are from that very config right there.

/etc/dhcp/dhclient-exit-hooks.d/dyndns:

/usr/local/bin/dyndnsc --config /etc/dyndnsc.ini

crontab:

# m h  dom mon dow   command
11 * * * * /usr/local/bin/dyndnsc --config /etc/dyndnsc.ini

journalctl:

Mär 29 11:17:06 server dhcpcd[343]: Traceback (most recent call last):
Mär 29 11:17:06 server dhcpcd[343]:   File "/usr/local/bin/dyndnsc", line 10, in <module>
Mär 29 11:17:06 server dhcpcd[343]:     sys.exit(main())
Mär 29 11:17:06 server dhcpcd[343]:   File "/usr/local/lib/python3.7/dist-packages/dyndnsc/cli.py", line 189, in main
Mär 29 11:17:06 server dhcpcd[343]:     dyndnsclient.sync()
Mär 29 11:17:06 server dhcpcd[343]:   File "/usr/local/lib/python3.7/dist-packages/dyndnsc/core.py", line 71, in sync
Mär 29 11:17:06 server dhcpcd[343]:     LOG.debug("Couldn't detect the current IP using detector %r", self.detector.names()[-1])
Mär 29 11:17:06 server dhcpcd[343]: AttributeError: 'IPDetectorWebCheck' object has no attribute 'names'

support update services that provide IP auto-detection

Currently, we can't update services if no detector is present. This is counter-intuitive, since many dynamic dns services offer some form of fallback automatic IP detection if none was specified. We should support this behaviour. This would also simplify the usage, since there would be one thing less to configure / think about.
If you want support for this, add a "++" comment below - support for additional services will be added on-demand.

no good way yet to detect IPv6 addresses when using privacy extensions (which is probably the default)

I am using Ubuntu 14.04 with a fritzbox router and an internet provider that provides native V6.
I can configure the router to allow specific machines to be accessible from the internet via V6, then no natting in any way is necessary.

I get a bunch of ip address, local ones and global ones.
I get a temporary one, which is one generated because of privacy extensions. This ip is used for outgoing connections.
I get my global one, this one is used for incoming connections.
I get multiple deprecated ones, this is because telcos suck and want to make your life miserable by changing your ip every 24 hours so that you can't put your ip in a normal dns entry.

All ip addresses have the same netmask, so I can't filter them by netmask, they are all on the same interface. ipaddresses does not provide information if an address is a privacy extended one.

Web services do not work, because they see my privacy ip, but Fritzbox does not forward my privacy ip to me.

I don't know what the answer can be. I opened a feature request for ipaddresses package: https://bitbucket.org/al45tair/netifaces/issue/11/provide-a-way-to-access-flags-for-ip

In the meantime, I started to use the command detector:

dyndnsc --debug --updater-nsupdate --updater-nsupdate-hostname=xxx.nsupdate.info --updater-nsupdate-userid=xxx.nsupdate.info --updater-nsupdate-password=xxx --detector=command,command:'ip addr | grep inet6 | grep -v deprecated | grep -v temporary | grep global | perl -pe '"'s/.?inet6 ([0-9a-f:]+[0-9a-f:]).*/\1/'"

Only Update IPv6

Hi,

is it possible only to update the AAAA record? I have a connection without a real IPv4 connectivity.
Updating the v6 address usung --method webcheck6 works fine, but dyndnsc alway sends an update, because it also compares the A record from the DNS which is not defined in my case.

The result is the following warning:
2014-10-18 12:48:58,251 INFO Current dns IP 'None' does not match detected IP '2a02:xx::yy', updating

This lead to an abuse report from nsupdate.info because dyndnsc regularly updates because of this.

EDIT: probably this --debug output is relatet to this issue:
2014-10-19 16:33:50,007 DEBUG socket.getaddrinfo() raised an exception
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/dyndnsc/detector/dns.py", line 30, in resolve
addrinfo = socket.getaddrinfo(hostname, None)
gaierror: [Errno -5] No address associated with hostname

use own useragent string

currently the code sends the default User-Agent from "requests".

it should be replaced by something that says "python-dyndnsc" and the version number.

service definition

From @ThomasWaldmann : dyndnsc seems to have no concept of a service definition (that would contain checkip url(s), update url(s), infos whether tls is possible, whether v4 and/or v6 are supported). because of that, checkers and updaters live an independent life and are just coupled together via the cmdline options.

suggestions about how to improve tests

the tests are currently not very usable, they emit a lot of information (warnings, errors, debug stuff) even for tests that are considered successful.

for my projects, I have looked at misc. test frameworks and I am a happy user of py.test currently - I guess you could also use it and have much more usable tests, more pretty and more helpful test output (silent when it is not needed, verbose and helpful when it is needed).

tests are also much easier to write with it and involve less typing even. :)

have a look at it and decide. if you like py.test, I can help you migrating to it.

add http proxy support

It should be possible to configure all HTTP client connections to go through an http proxy server. This should be configurable.
If you want support for this, add a "++" comment below - support for additional services will be added on-demand.

config file documentation

Since we have config file support now, we should provide some easy to understand examples in the documentation.

IP Updater executing a shell command

Hi,

similar to IPDetector_Command an UpdateProtocolCommand would be quite helpful. Atm I 'added' a new builtin (symlinked to my module and changed builtin.py) to update A and AAAA entries in gandi using its cli client.

typo?

plugins/base.py:9: ENV_PREFIX = "DYNDNC_WITH_"
and also line 35

Is there an S missing?

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

dockerfile
packaging/docker/arm32v7-ubuntu/Dockerfile
packaging/docker/x86-alpine/Dockerfile
  • alpine 3.19
  • alpine 3.19
packaging/docker/x86-ubuntu/Dockerfile
github-actions
.github/workflows/tests.yml
  • actions/checkout v4
  • actions/setup-python v5
pip_requirements
docs/requirements.txt
  • Sphinx ==7.2.6
requirements-style.txt
  • flake8 >=3.7.5
  • pydocstyle ==6.3.0
  • flake8-bandit >=1.0.1
  • flake8-bugbear >=17.12.0
  • flake8-comprehensions >=1.4.1
  • flake8_docstrings >=1.1.0
  • flake8-tidy-imports >=1.1.0
  • flake8-rst-docstrings >=0.0.8
  • Pygments >=2.2.0
  • flake8-quotes >=0.13.0
  • flake8-print >=3.0.1
  • flake8-mutable >=1.2.0
  • flake8-string-format >=0.2.3
  • check-manifest >=0.36
  • safety >=1.6.1
requirements.txt
  • dnsimple-dyndns ==0.1
  • coverage ==7.2.7
pip_setup
setup.py
  • daemonocle >=1.0.1
  • dnspython >=1.15.0
  • netifaces >=0.10.5
  • requests >=2.0.1
  • pytest >=4.0.0
  • responses >=0.19.0

  • Check this box to trigger a request for Renovate to run again on this repository

fix exception handling

some places catch "Exception" (e.g. IPDetector_Iface._detect) - this is EVIL in almost all cases.

it rather should catch more specific exceptions or even just NOT catch the exception there, so it can be dealt with at a higher level.

while running the tests on linux, you get quite some stuff like:

"netifaces choked while trying to get inet6 interface information for interface 'tun0'"

if it just raised some sane exception, one could handle it in the test and just skip the test if there is no such interface.

config file additionally to or instead of commandline options

currently, using dyndnsc requires assembling a quite long commandline.

i think for making it easier deployable and enable creation of packages (e.g. for misc. linux distributions), a config file that is read from some specific place (e.g. /etc/dyndnsc.d/*.conf) would be better.

packagers could then create startup scripts that start automatically dyndnsc daemons for each config file and users could just edit the config file(s). there could be multiple daemons, e.g. for ipv4 dyndns, ipv6 dyndns and other services. (see also #35 about how many daemons are wanted)

note: ddclient does it that way and e.g. getting it to work with nsupdate.info is just a matter of copy&pasting the ddclient configuration shown on the service into /etc/ddclient.conf and issuing a service ddclient restart - done! I'ld like to have a similarly quick procedure for dyndnsc (esp. since it now likely is the only updater that has sane v6 support).

No class named 'webcheck4' could be found

Hey Ho

when i try to run dyndnsc --config dyndnsc.conf
I get the follwoing error

Traceback (most recent call last):
File "/usr/local/bin/dyndnsc", line 11, in
load_entry_point('dyndnsc==0.5.dev0', 'console_scripts', 'dyndnsc')()
File "/usr/local/lib/python2.7/dist-packages/dyndnsc-0.5.dev0-py2.7.egg/dyndnsc/cli.py", line 171, in main
collected_configs[thisconfig], plugins=plugins)
File "/usr/local/lib/python2.7/dist-packages/dyndnsc-0.5.dev0-py2.7.egg/dyndnsc/core.py", line 184, in getDynDnsClientForConfig
klass = get_detector_class(detector_name)
File "/usr/local/lib/python2.7/dist-packages/dyndnsc-0.5.dev0-py2.7.egg/dyndnsc/detector/manager.py", line 16, in get_detector_class
return find_class(name, detector_classes())
File "/usr/local/lib/python2.7/dist-packages/dyndnsc-0.5.dev0-py2.7.egg/dyndnsc/common/load.py", line 32, in find_class
raise ValueError("No class named '%s' could be found" % name)
ValueError: No class named 'webcheck4' could be found

I installed dyndnsc fresh from repo. Can anybody tell me whats wrong?

drop iface detector and netifaces dependency?

reasons:
a) maintainer seems uninterested in or too busy for fixing python3 showstopper bugs, see https://bitbucket.org/al45tair/netifaces/issue/13/0104-install-is-broken-on-python-3x
b) because of a), we have travis complications, see issue #15
c) we have a "socket" detector now, that does quite a similar thing, without any external dependency
d) maybe we also run into troubles with too old or broken netifaces packages when building linux packages, see #38.

remove ip.arix.com

2014-11-08 20:25:08,425 DEBUG Querying IP address from 'http://ip.arix.com/'
2014-11-08 20:25:08,650 DEBUG webcheck failed for url 'http://ip.arix.com/'
...
ConnectionRefusedError: [Errno 111] Connection refused

It's offline. Maybe check again in a while and if still offline, remove it.

Exit code is 0 even if auth failed

Description

When using a wrong password (or even a wrong user) the process exit with a code 0 letting think that everything ran smoothly. Which is not the case.

dyndnsc 0.6.1

Example to reproduce:

The demo.conf file

[dyndnsc]
configs = myconf_ipv4, myconf_ipv6

[myconf_ipv4]
# this will update your ipv4 address to the address
# the detector dnswanip returns:
use_preset = nsupdate.info:ipv4
updater-hostname = test-demo.nsupdate.info
updater-userid = test-demo.nsupdate.info
updater-password = NotAValidPassword
detector = webcheck4

[myconf_ipv6]
# this will update your ipv6 address to the address
# the detector dnswanip returns:
use_preset = nsupdate.info:ipv6
updater-hostname = test-demo.nsupdate.info
updater-userid = test-demo.nsupdate.info
updater-password = NotAValidPassword
detector = webcheck6

The commands:

dyndnsc -vvv -c ./demo.conf
echo $?

differentiate between service and update protocol?

many services follow the dyndns2 protocol, so the question is whether one really needs one support module per service just for the sake of the different update url.

many routers (e.g. the fritzbox) offer generic support and you can just give the update url, so it'll work with any service compatible to the selected protocol (which i think is even hardcoded dyndns2 in the case of this router).

to make it even more flexible, you can give multiple update urls to e.g. update the v4 and the v6 address, e.g.:

https://ipv4.nsupdate.info/nic/update https://ipv6.nsupdate.info/nic/update

as there is no querystring with placeholders given (for ip address and hostname), it just uses the url "as is" (and does the required http basic auth taken from username and password params).

in our case, this is all that is needed, as username == hostname for nsupdate.info service and the IP is just the remote address seen by the service.

btw, we intentionally did NOT use the service login username/password as many routers do http, so we did not want to risk disclosure of the more important login password. so we just have the hostname as "username" for updates and a separate, autogenerated random secret as "password".

ipv4.nsupdate.info is v4 only, ipv6.nsupdate.info is v6 only, so this just works as it will for sure see the right remote IP (assuming you want the router ip in dns).

Output '123.123.12.34' could not be parsed

2014-11-08 20:21:33,940 DEBUG IPDetector_DNS.set_current_value(123.123.12.34)
2014-11-08 20:21:33,941 DEBUG Querying IP address from 'http://dynamic.zoneedit.com/checkip.html'
2014-11-08 20:21:34,329 DEBUG Output '123.123.12.34' could not be parsed
2014-11-08 20:21:34,329 INFO Could not detect IP using webcheck! Offline?
2014-11-08 20:21:34,330 DEBUG DNS out of sync, but detector returned None

netifaces latest version (0.10.4) is not Python 3 compatible

This is an upstream issue.
I created a pull request but did not validate if this is enough:
https://bitbucket.org/al45tair/netifaces/pull-request/2/fix-error-preventing-to-install-netifaces/diff

This is the reason why tox can't do python 3 tests.
If it works locally, this is because on pypi are also binary packages of netifaces, these do not have the setup.py any more. Don't know when binary packages get used by installers, I never use them.

Error when using DuckDNS: TypeError: __init__() takes at least 4 arguments (3 given)

When trying to sue DuckDNS, I get the following error:

2016-08-28 00:38:59,403 DEBUG ArgumentParser(prog='dyndnsc', usage=None, description=None, version=None, formatter_class=<class 'argparse.HelpFormatter'>, conflict_handler='error', add_help=True)
2016-08-28 00:38:59,404 DEBUG Attempting to read configuration from ['/usr/lib/python2.7/site-packages/dyndnsc/resources/presets.ini', 'dyndnsc.cfg']
2016-08-28 00:38:59,407 DEBUG Successfully read configuration from ['/usr/lib/python2.7/site-packages/dyndnsc/resources/presets.ini', 'dyndnsc.cfg']
2016-08-28 00:38:59,408 DEBUG config file sections: ['preset:no-ip.com', 'preset:freedns.afraid.com', 'preset:nsupdate.info:ipv4', 'preset:nsupdate.info:ipv6', 'preset:dns.he.net', 'preset:dnsimple.com', 'preset:dnsdynamic.org', 'preset:hopper.pw:ipv4', 'preset:hopper.pw:ipv6', 'preset:dyn.com', 'preset:duckdns.org', 'dyndnsc', 'duckdns_ipv4']
2016-08-28 00:38:59,408 DEBUG raw config for 'duckdns_ipv4': {'detector-iface': 'ppp0', 'updater-password': '[removed]', 'use_preset': 'duckdns.org', 'updater': 'duckdns', 'detector-iface-family': 'INET4', 'detector': 'iface', 'updater-hostname': '[removed]', 'updater-url': 'https://www.duckdns.org/update'}
2016-08-28 00:38:59,408 DEBUG Available plugins: []
2016-08-28 00:38:59,409 DEBUG Enabled plugins: []
2016-08-28 00:38:59,409 DEBUG collected_configs: {'duckdns_ipv4': {'detector': [('iface', {'iface': 'ppp0', 'iface-family': 'INET4'})], 'updater': [('duckdns', {'url': 'https://www.duckdns.org/update', 'password': '[removed]', 'hostname': '[removed]'})]}}
2016-08-28 00:38:59,409 DEBUG Initializing client for 'duckdns_ipv4'
Traceback (most recent call last):
  File "/usr/bin/dyndnsc", line 11, in <module>
    load_entry_point('dyndnsc==0.4.2', 'console_scripts', 'dyndnsc')()
  File "/usr/lib/python2.7/site-packages/dyndnsc/cli.py", line 144, in main
    collected_configs[thisconfig], plugins=plugins)
  File "/usr/lib/python2.7/site-packages/dyndnsc/core.py", line 182, in getDynDnsClientForConfig
    initparams['updater'] = get_updater_class(updater_name)(**updater_options)
TypeError: __init__() takes at least 4 arguments (3 given)

My config file:

[dyndnsc]
configs = duckdns_ipv4

[duckdns_ipv4]
use_preset = duckdns.org
updater-hostname = [removed]
updater-password = [removed]
detector = iface
detector-iface = ppp0
detector-iface-family = INET4

better docs

quickstart section misses quite some infos.

add support for inwx / docker config

Hi,
since I can't get it really how to use dyndns2 to update my inwx domain in a config file.
I would like to see support for inwx. https://www.inwx.de/de/

The update url looks like this.
https://dyndns.inwx.com/nic/update?myip=<ipaddr>&myipv6=<ip6addr>


I use the docker container with a mounted .ini file as config from the host.
docker run -d --name='dyndns' --net='bridge' -e TZ="Europe/Berlin" -e HOST_OS="Unraid" -v '/mnt/xxx/dnydnsc/dyndnsc.ini':'/etc/dyndnsc.ini':'rw' 'infothrill/dyndnsc-x86-alpine'

Maybe add as post arguments in the doc.
--config /etc/dyndnsc.ini --loop

An other question would be how to define the intervall and so in the .ini file ?
Does the docker container produce any kind of logs in the docker log for the container ?

man page

"make man" uses sphinx to create a man page. but it is the complete docs (like what we have in html).

is this intended or should it be something shorter?

support multiple services in daemon mode

dyndnsc supports updating multiple services in one go now, but according to the docs not in daemon mode:

"added: running against multiple services in one go (not supported in daemon mode yet)"

add 'Strato.com' to presets.ini

New feature request:

Please add a new entry to presets.ini as follows:

[preset:strato.com:ipv4]
updater = dyndns2
updater-url = https://dyndns.strato.com/nic/update
detector = webcheck4

[preset:strato.com:ipv6]
updater = dyndns2
updater-url = https://dyndns.strato.com/nic/update
detector = webcheck6

I have successfully tested this config for my local machine and can confirm that it works.

Thank you!

unify command line and config file

It should be easy to understand where what goes and be syntactically a low burden, especially for new users. Code-wise, it should optimally allow a nice automatic cascade of config,env,args.

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.