Giter Club home page Giter Club logo

tinydns-dynamic-dns-updater's Introduction

tinydns-dynamic-dns-updater

Tool to generate and keep tinydns (resolver daemon from djbdns) zone file with dynamic dns entries for remote hosts.

It consists of "client" part that sends (several) UDP packets with signing key id and signed current timestamp to "server", which matches key to a name that should be updated and makes sure timestamp is newer than that of the last update there, and if so, uses source address of the packet to update djbdns database name-ip binding.

All configuration for server is contained within djbdns zone file itself, client only needs commandline parameters for server and path to the client key.

This approach differs from solutions for same task I've seen in that it doesn't involve php, http server, passwords (usually passed in plaintext over net), tls, querying random net hosts for your IP or similar stuff, but requires running simple python scripts on both client and server instead.

Usage

See --help output for each command for full args/opts reference.

Example ("S" is for server terminal, "C" - client):

S% ./tddu-client.py -g

S: Signing key (for this script only):
S:    1k_Nf7FSEWHC2I65DfI2SAhtk1q0Ps9RcLy9PinyDLs=
S:
S: Verify key (to use on server):
S:    jLxAZY-vnJfubHr8srYy3mIN2_mCi_OExUwHOluOlLY=
S:

[...these keys are used in zone_file.example and with tddu-client.py...]

S% cat zone_file.example

S: +some.static.name:213.180.193.3
S:
S: # dynamic: 0 jLxAZY-vnJfubHr8srYy3mIN2_mCi_OExUwHOluOlLY=
S: +some.random.name:37.98.242.143
S: +extra.random.name:37.98.242.143
S: 6some.random.name:2a00145040100c080000000000000066
S:
S: +another.static.name:93.158.134.3
S: 6another.static.name:2a0206b8000000000000000000000003

S% cp zone_file.example zone_file.example.tmp && ./tddu-server.py --debug zone_file.example.tmp

S: DEBUG:root:Resolving addr: '::' (params: [5533, 0, 2, 0])
S: DEBUG:root:Binding to: '::' (port: 5533, af: 10, socktype: 2)

C% ./tddu-client.py --debug ::1:5533 1k_Nf7FSEWHC2I65DfI2SAhtk1q0Ps9RcLy9PinyDLs=

C: DEBUG:root:Resolving addr: '::1' (params: [5533, 0, 2, 0])
C: DEBUG:root:Sending 1 update msg(s) to: '::1' (port: 5533, af: 10, socktype: 2)

S: DEBUG:root:Updating zone entry for name 'some.random.name' (type: 6): 2a00:1450:4010:c08::66 -> ::1
S: DEBUG:root:Updating zone block (line: 4) ts: 0.00 -> 1405421249.89

[...it's a BAD idea to pass keys on cli like that, so store it to "./client.key" file...]

C% ./tddu-client.py --debug 127.0.0.1:5533 ./client.key

C: DEBUG:root:Resolving addr: '127.0.0.1' (params: [5533, 0, 2, 0])
C: DEBUG:root:Sending 1 update msg(s) to: '127.0.0.1' (port: 5533, af: 2, socktype: 2)

S: DEBUG:root:Updating zone entry for name 'extra.random.name' (type: +): 37.98.242.143 -> 127.0.0.1
S: DEBUG:root:Updating zone entry for name 'some.random.name' (type: +): 37.98.242.143 -> 127.0.0.1
S: DEBUG:root:Updating zone block (line: 4) ts: 1405421249.89 -> 1405421540.03

C% ./tddu-client.py 127.0.0.1:5533 ./client.key

S: DEBUG:root:No address changes in valid update packet: key_id=QlH0RDCxXrI2OvL2OUA4DBeDY79X ts=1405423510.34 addr=127.0.0.1

Requirements

  • Python 2.7 (not 3.X)

  • PyNaCl or libnacl - either one will work, interoperable with each other (and use same libsodium), no difference whatsoever.

  • netaddr - for the server part.

  • (optional) python-systemd - to use systemd socket activation for server (--systemd option).

"test.py" script also needs plumbum, but shouldn't be necessary by itself (runs test server + clients, checks that all sent updates were applied correctly).

Operation details

  • Payload of sent UDP packets is fixed 100 bytes in size.

    28B key_id (pubkey hash) || 8B timestamp (double) || 64B Ed25519 signature.

  • Client doesn't get any confirmation and is expected to just send as much redundant data (and as often), as required by tolerance for stale data and network reliability.

  • It makes sense (and is safe) to send any number of UDP update packets, old ones and non-changes are ignored server-side, as well as any otherwise invalid packets in general.

  • Since address is determined from UDP packet source, it matters whether it gets sent over IPv4 or IPv6, and whether there's any SNAT translation in-between.

  • If hostname is passed anywhere instead of address, it is resolved by getaddrinfo(3), and if there are several different results, error is raised to prevent ambiguity, esp. wrt IPv4/IPv6 resolution (see also /etc/gai.conf).

  • Signatures are used as a simple means of client id and authentication.

    Ed25519 public-key signature system is used (as implemented in libsodium).

  • Timestamps are sent to discard obsolete updates and replay attacks.

    They are not considered to be worth hiding, and are cheaper to check on server before validating signature when sent in plaintext.

  • It's safe to change zone files when tddu-server.py script is running, as it always checks mtime (and does reload) before building new files, and then again right before replacing (tempfile-rename) old file with a new one.

  • It's also safe to run several server pids from the same file, as they do proper locking on reading/writing to it and update old files as well as replace them with new ones, but no idea if doing that might ever be useful.

Links

tinydns-dynamic-dns-updater's People

Contributors

mk-fg avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

Forkers

jeimerson

tinydns-dynamic-dns-updater's Issues

TTL?

Hey there, just tried this out, it's a neat idea - but if I set a TTL on the records, the server app dies with 'ValueError: too many values to unpack'.

Without a TTL, one is forced to wait on djb's default TTL's, which are much too long to respond to a dynamic change.

Is there a workaround -- a way to force a lower TTL?

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.