Git Product home page Git Product logo

minidyndns's Introduction

MiniDynDNS

A simple no fuss DNS server with an build in HTTP/HTTPS interface to update IPs. It's build to be compact and simple way to access your home devices via subdomains. Something like DynDNS but just for your private needs. It's not build for performance!

  • Supports IPv4 and IPv6 (A and AAAA records)
  • IPs are saved to and loaded from a YAML database file
  • New names can be added to the YAML file, each with it's own password
  • Send USR1 signal to server to make it pick up changes in the YAML file, otherwise it will overwrite it when the server shuts down.
  • The server should be stared as root so it can bind to privileged ports (like 53 for DNS). It'll then drop privileges.
  • Only requires Ruby 1.9 or newer. No other dependencies.

Stuff to look out for:

  • Only A and AAAA records are supported. CNAME, TXT, MX and so on won't work. Ask me or open an issue if you need that.
  • HTTPS: I'm not sure how stable or reliable Rubys OpenSSL integration actually is. I've had some funny effects I can't pinpoint. Again, let me know if something comes up.
  • FritzBox users: Be aware of the DNS rebind protection (DNS-Rebind-Schutz). The FritzBox will silently drop all DNS responses that contain public IPv6 addresses of devices in your home network. You'll have to add each domain name to a whitelist in your router configuration (see issue #3).

Installation

  • Make sure you have Ruby 1.9 or 2 installed (e.g. the ruby1.9.1 package on Debian Linux).

  • Download dns.rb, config.yml and db.yml. These three files are all you need.

  • Modify config.yml to match your setup, especially the domain, soa โ†’ nameserver and soa โ†’ mail settings.

  • Modify db.yml to contain your subdomains and passwords. For example:

    pi:
      pass: oAKrrpozHCDRLyPp97T7umf648aiYQpL
    pc:
      pass: UjQFD9Vm3nU6uzn7GPDYeHt9xxRURid6
    

    The IP addresses themselfs are best added later on via the HTTP interface. Either by your router or via a command line script (see "Some useful commands" later on).

  • Run the server: sudo ruby dns.rb. To stop it press ctrl+c.

Right now I just leave it running within a screen terminal. But feel free to automatically start it on server boot up. If you want you can also redirect stdout into an access log file and stderr into an error log file.

HTTP/HTTPS interface to update IPs

The HTTP interface is very minimalistic: The server only understands one HTTP request to update or invalidate IP addresses. This isn't a webinterface you can use in your browser! Rather it's the interface your router can use to automatically report a changed IP to the DNS server (look for something like DynDNS in your router configuration). The HTTP interface is inspired by DynDNS and others so routers can easily be configured to report to this DNS server.

HTTP basic auth is used for all HTTP requests. The username and password have to match one configured in the db.yml file. For example with the HTTP user pi and password oAKrrpozHCDRLyPp97T7umf648aiYQpL you can update the IP address of the pi subdomain.

The HTTP request GET /?myip=[ip] where [ip] is either an IPv4 or IPv6 address then assigns a new address to the subdomain matching the authentication.

If [ip] is an empty string (GET /?myip=) both the IPv4 and IPv6 address are invalidated. The server won't return an IP for that subdomain until a new IP is assigned.

You can omit the myip parameter (just GET /). In that case the server will set the subdomain matching the authentication to whatever IP the client is using to connect to the HTTP interface. In the internet this is your public IP. If you use MiniDynDNS in a local network this will probably be a local IP address.

You can use wget on the command line or in scripts to assign a new IP to a subdomain (see "Some useful commands"). Languages like PHP and Ruby can also do HTTP requests directly.

Deleting users and changing passwords

To add or delete a user you can modify the db.yml file. Same for changing passwords: Just change them in db.yml.

But after you did that you have to tell the server to pick up those changes. To do this send it the USR1 signal (see "Some useful commands"). Otherwise the server will ignore the changes and overwrite the db.yml file when the next IP is updated.

When you change an IP in db.yml the server will ignore it. It is designed to receive all IP updates via the HTTP interface.

Some useful commands

All these commands assume that the DNS server is running on 127.0.0.2 with default ports (53 for DNS, 80 for HTTP, 443 for HTTPS).

Update a name with a new IPv4 or IPv6 address:

wget --user foo --password bar -O /dev/null http://127.0.0.2/?myip=192.168.0.1
wget --user foo --password bar -O /dev/null http://127.0.0.2/?myip=ff80::1
wget --user foo --password bar -O /dev/null http://127.0.0.2/  # set the subdomain to the clients IP

Same with curl and over HTTPS:

curl -u foo:bar --cacert server_cert.pem https://127.0.0.2/?myip=192.168.0.2
curl -u foo:bar --cacert server_cert.pem https://127.0.0.2/?myip=ff80::1
curl -u foo:bar --cacert server_cert.pem https://127.0.0.2/  # set the subdomain to the clients IP

Note: Don't use the self-signed certificate of your CA with --cacert. For some reason this causes OpenSSL to freak out and block the entire HTTP/HTTPS interface. Please let me know if you know why.

Send an USR1 signal to the server to make it pick up changes from the YAML database file:

sudo pkill -USR1 -o -f dns.rb

Shutdown the server by sending it the INT signal (like pressing ctrl+c):

sudo pkill -INT -o -f dns.rb

Query IPv4 (A), IPv6 (AAAA) or both (ANY) records from DNS server running on 127.0.0.2:

dig @127.0.0.2 foo.dyn.example.com A
dig @127.0.0.2 foo.dyn.example.com AAAA
dig @127.0.0.2 foo.dyn.example.com ANY

Query the servers start of authority (SOA) record:

dig @127.0.0.2 dyn.example.com SOA

Running the test suite

cd tests
./gen_https_cert.sh
ruby test.rb
sudo ruby test.rb   # Tests dropping privileges

minidyndns's People

Contributors

arkanis 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  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  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

minidyndns's Issues

Not working

2017-03-22 04:43:21 DNS: A @ -> not found

Why?

My settings:

# The domain hosted by this DNS server. It will only reply to requests
# regarding subdomains of this domain. Everything is ignored completely.
domain: lepreip.censured.it
# Time to live (TTL) of replies send by the DNS server. This is the time
# in seconds an reply stays valid. The higher the value the longer clients
# might take to figure out that an IP address has changed. Small values
# will force a DNS request on every page access. This is ok for seldomly
# used sites but a very bad idea for high traffic sites.
ttl: 15

# IP and port the DNS server runs on
dns:
  port: 5352
  ip: 0.0.0.0
# IP and port the HTTP server runs on
http:
  port: 8082
  ip: 0.0.0.0
https:
  port: 443
  ip: 0.0.0.0
  cert: server_cert.pem
  priv_key: server_priv_key.key
# To disable HTTPS set it to false
https: false

# Maximum number of seconds the server waits for clients to send
# the entire HTTP request (to kill requests from stupid routers that
# keep the connections open forever).
http_timeout: 5.0

# The server needs to be started as root to bind to privileged ports
# (everything below 1024). In that case it will drop privileges after
# startup and run under the user and group specified here.
# Make sure that this user can write the database file (default db.yml),
# otherwise the server can't update the database.
user: mauro
group: nogroup

# Start of authority information. This is stuff others like to know about
# this DNS server. The serial is taken from the DB.
soa:
  # The domain name of our DNS server itself
  nameserver: ddns.censured.it
  # Mail address of the person responsible for the DNS server
  mail: [email protected]
  # Time to live in seconds of this SOA record. It won't change often so
  # it can be a rather large value (e.g. 86400 = 1 day).
  ttl: 86400
  # Stuff for secondary DNS servers. Since we're just a small DNS server
  # secondaries don't make sense. So just the default values.
  refresh_time: 86400
  retry_time: 7200
  expire_time: 3600000
  # Time not found responses (NXDOMAIN) can be cached. This is the maximum
  # time a newly added domain might need to be available world wide.
  negative_caching_ttl: 172800

Server hangs every few days

Hi,

unfortunately the ruby process seems to hang every few days and needs to be restarted. Do you have some kind of init.d service script, so that I could just run /etc/init.d/minidyndns restart every night?

Ruby server stops unexpectedly due to strange request parsing error

Here is the message error:

2018-08-13 23:59:29 HTTP: GET http://www.bing.com -> not authorized
2018-08-13 23:59:55 DNS: ANY com -> wrong domain, ignoring
2018-08-14 00:52:58 DNS: Failed to parse request: undefined method `>>' for false:FalseClass
        dns.rb:269:in `parse_dns_question'
        dns.rb:186:in `handle_dns_packet'
        dns.rb:692:in `block in <main>'
        dns.rb:689:in `loop'
        dns.rb:689:in `<main>'
dns.rb:193:in `handle_dns_packet': undefined method `end_with?' for nil:NilClass (NoMethodError)
        from dns.rb:692:in `block in <main>'
        from dns.rb:689:in `loop'
        from dns.rb:689:in `<main>'

Any idea how to solve this? Thank you.

ivp6 request times out

Hi,
I did a git pull today, and since then ipv6 requests seem to time out

When I try dig home.dyn.xxx.org A it works perfectly fine. If I try AAAA i get:

dig home.dyn.xxx.org AAAA

; <<>> DiG 9.10.3-P4-Ubuntu <<>> home.dyn.xxx.org AAAA
;; global options: +cmd
;; connection timed out; no servers could be reached

weirdly the request seems to reach the server and is being answered, at least that's what the log says:

2017-01-10 13:57:16 DNS: AAAA home -> 2a02:xx:xx:xx:xx:xx:xx:xx
2017-01-10 13:57:17 DNS: AAAA home -> 2a02:xx:xx:xx:xx:xx:xx:xx
2017-01-10 13:57:22 DNS: AAAA home -> 2a02:xx:xx:xx:xx:xx:xx:xx
2017-01-10 13:57:29 DNS: AAAA home -> 2a02:xx:xx:xx:xx:xx:xx:xx

Do you see any reason for this? It worked fine before

Consider checking if current IP in record had changed or remained the same and thus avoid unnecessary disk writes to db.yml file

I have noticed that the db.yml file is updated every time an update request is sent to the server, even if the IP in record had not changed. Maybe it is better to check if the IP had changed or not and only if it has a new value write it to the disk and update the db.yml file.

Here is a code modification suggestion inside handle_http_connection method, needs review:

	if ip.ipv4? and $db[user]["A"] != ip_as_string
		log "New IP address detected, updating the database file.."
		$db["SERIAL"] += 1
		save_db
	elsif ip.ipv6? and $db[user]["AAAA"] != ip_as_string
		log "New IP address detected, updating the database file.."
		$db["SERIAL"] += 1
		save_db
	else
	end

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.