Giter Site home page Giter Site logo

dhcp.io's Introduction

DHCP.io

This repository contains the code behind the DHCP.io service, which provides a self-hosted Dynamic-DNS system.

Users can register up to five hostnames beneath a given DNS zone, and easily update those names to point to arbitrary IPv4 or IPv6 addresses.

For example if you deployed the code with the hostname "example.io", then a user "bob" would control the hostname "bob.example.io", and could also claim four more names.

Overview

The code is written in Perl, using the CGI::Application framework.

The logins and record-associations for all users are stored in an SQLite database, making deployment nice and simple.

A Redis instance is used for session-storage, throttle-control, and similar things.

For serving the actual Dynamic-DNS entries Amazon's Route53 service is used.

Requirements

To deploy this code you'll need:

  • A domain name, beneath which you'll let users register accounts.
  • A working Perl installation.
  • A Redis server.
  • An account with Amazon's Route53 DNS service.
    • You'll need to update the configuration module with your secret key, access token, and zone identifier.

Installation

The code relies upon the following modules being present and installed:

  • CGI::Application
    • apt-get install libcgi-application-perl
  • CGI::Application::Plugin::Throttle
    • Bundled into the distribution, as it isn't packaged for Debian.
  • Data::UUID
    • apt-get install libtie-ixhash-perl libdata-uuid-libuuid-perl
  • DBI
    • apt-get install libdbi-perl libdbd-sqlite3-perl
  • HTML::Template
    • apt-get install libhtml-template-perl
  • JSON
    • apt-get install libjson-perl
  • Net::SMTP::SSL
    • apt-get install libnet-smtp-ssl-perl
  • Redis
    • apt-get install libredis-perl
  • WebService::Amazon::Route53
    • Bundled into the distribution, as it isn't packaged for Debian.

These modules have other dependencies which you might not have present. To test you have all the required packages please run:

make test

or:

perl t/00-load.t

Finally you'll also need a Redis server running on the same host as the application, as this is used to store login sessions.

Clone the code, and rename "lib/DHCP/Config.pm.example" to be lib/DHCP/Config.pm, updating it to contain your credentials.

Running/Testing Locally

The installation section should be complete enough that you're able to run the application for real.

However for testing purposes a sample lighttpd configuration file is also included within this repository. The configuration file contains all the required "rewrite rules", for example:

^/create/?        -> /cgi-bin/index.cgi?mode=create

If you have lighttpd installed then you should be able to launch the application on your local system via:

$ make local
..
Launching lighttpd on http://localhost:2000/
lighttpd -f conf/lighttpd.conf -D

Press Ctrl-c to terminate, otherwise open http://localhost:2000 in your browser.

NOTE: You'll need to have Redis installed locally too.

Steve

dhcp.io's People

Contributors

skx 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dhcp.io's Issues

IPv6 AAAA record missing.

That makes it hard, but not impossible, to set an IPv6 address to a specific value.

It can be done with curl, but it's only documented via the source-code.

(The record was dropped, but I didn't appreciate that would cause breakage. Dropped because the docker setup wasn't working with IPv6 at the time I handled the migration and I forgot to track it as a TODO)

MX records?

This might involve a world of pain - but should we allow users to set an MX record too?

Again this is easy for a free v.s. paid discussion. Free users can have an A/AAAA record, but you must pay for MX.

Since we're not really going down that path ..

UI: Profile-Change

The profile page shows the following fields which are directly editable:

  • Login-name.
  • Email-address.
  • Password.

Rather than allowing these to be edited in-place we should make the profile page just show the details, and add two new routes for making changes:

  • Change password
    • This must have confirmation.
  • Change email.
    • This must have confirmation, and validity-checking done. (i.e. mx-record, or similar).

The specific problem we're trying to solve is twofold:

  • Make the UI look better.
  • Ensure we don't allow bogus updates - i.e. typos to be persisted - by forcing confirmation.

Logging is broken. (Shows wrong hostname).

Assume you have the user-account "skx", which has the following records:

  • deagol
  • smeagol
  • shelob

(Manually) edit the records for shelob, and it is logged deagol. Suspect this is an artefact of earlier releases where a single account was available - which in this case would be skx.

Logs not updating sometimes/always?

A twitter user reports that logs aren't showing updates some/all of the time.

Secondly they say that they "can't connect". There are no details on that, so I assume that means the dynamic hostname they've set isn't reachable - that would be outside the scope of this issue and code.

Migrate to bcrypt passwords.

We don't expect a compromise, but using something better is absolutely 100% essential.

  • Create a new passwords table, keyed on user_id.
  • Update the login-code to query against the new table.
    • If there is no match use the old login code.
    • If the login succeeds create a bcrypt entry.

This will buy us per-user salting, and if we ever are compromised that'll reduce the risk of exposure.

Not possible to delete accounts.

There is no ability to delete a user-account from the web-interface.

The site-admin can use bin/delete-user --username=foo to delete a user, and their associated records, manually though.

Not possible to delete hostnames

Once you've claimed a sub-domain you cannot release it, or delete it.

You can delete the existing IP which is associated with the name, if any, though.

Redis: We don't use you as much.

As a result of #14 we no longer fetch the current value(s) of the complete hosted zone from Amazon.

Because we don't fetch the complete zone we no longer cache it in memory.

This means we can drop some of the redis-usage, as it is orphaned.

NOTE: We still use redis, we just use it for rate-limiting/throttling, and for storing transient password-reset tokens, etc. So while we can remove it in some places it does continue to be necessary (and awesome)!

Edit via web-page

Currently there are two ways to change the value of a record:

  • For the admin, via bin/set-name.
  • For a user, via curl.

It might be nice to add an Edit Record page. I've added a stub link in the live version - repository is out of date - but it is a NOP.

Set both IPv4 and IPv6 at once.

It would be nice to be able to set IPv4 and IPv6 addresses for a record in one call.

This cannot be done unless both are specified though, because if no address is specified then the source is used - clearly a request may arrive at the dhcp.io host on either IPv4 or IPv6 but not both a once.

If we restrict ourselves to the case where both addresses are specified then it becomes a simple enough job. Something like :

  curl http://dhcp.io/set/$token/$ipv4/$ipv6

Or via the post:

 curl -X POST -data 'token=xx&ip4=1.2.3.4&ipv6=fe80::1'

The only thing to note is that we need to handle the case where the endpoint might receive only one argument, ip, as is currently the case. That means to set both they must be named appropriately (i.e. ipv4 + ipv6.)

Shouldn't be a big change, but no rush ..

We should cache the zone lookups.

Currently we pull the complete zone out, to get the most current records, for the /edit/ operation.

By contrast at /home/ we just use Net::DNS. At the time I considered this too expensive to lookup constantly, but Net::DNS isn't responsive enough.

Suggestion:

  • Drop the use of Net::DNS.
  • Update DHCP::Records to cache, in Redis, the return value of getRecords - with TTL of 60 seconds.

Invalidate on hits to /edit/ + /set obviously. (Or wait for cache to expire via TTL, if the cache-time is the same as the zone..?)

Be more explicit about the state of the project.

At the moment:

  • Updates are capped a little.
    • Partly because of the overhead.
    • Partly because we're using the old API and all changes are heavyweight.
    • When we use the new API #14 we can just use UPSERT.
  • Account registration(s) are closed.
    • Though I've given a few people new accounts on a one-off-basis.
  • We have too many orphans.
    • Need to write a tool to identify accounts that haven't changed IP in months.
    • Consider marking such accounts as read-only unless/until they are changed.
  • We don't have a good way of contacting users, because emails are option.
    • Disable all acounts without emails? Until they complain? Horrid, but workable ..

Sub-records should be supported.

A common request is the support for sub-records.

For example rather than restricting names to things such as skx.dhcp.io, me.dhcp.io users would like the ability to have names of the form:

  • gateway.office.dhcp.io.
  • printer.office.dhcp.io.

I won't add this support, and explicitly do not support sub-records.

Pull requests implementing this will be accepted providing the behaviour can be disabled via the configuration file lib/DHCP/Config.pm[.example].

(This issue just created for reference.)

You cannot edit the value of a record which is empty.

This is regression, but if there is no value set for a given name you cannot edit it.

e.g. Create a new record foo.dhcp.io and it will be empty. After you run a curl command to set (any) value you can then edit it. But until then it is impossible.

Password reset.

The deployed code uses hashed passwords - this repository is a little out of date.

If a user forgets their password and has a registered email address we should allow a reset operation.

If the user has no registered email address they are out of luck. Or must mail me.

Multiple names?

It might be the case that we want to allow users to have more than one name.

If so that requires a redesign of the home-page - perhaps a dropdown that will change the text in the home panel.

Alternatively we could use a tab-interface running across the top, with one tab for each name.

Implementation of either would be simple. I just need to decide whether it should be supported or not.

Were this commercial it would be easy to say "One domain for free, if you want more pay". Though I guess the obvious concern would be people registering N-accounts..

Create an `orphaned` record, & use it for bogus accounts.

We're moving to a situation where several users are going to need to be updated because their details are wrong, and we can't contact them.

Suggest we create:

All the records owned by bogus users will be remapped into CNAME records pointing to that, unless/until they update themselves. If they never update themselves we can delete the accounts after a month or two.

UI: Password reset

The password-reset process is ugly and can be improved via more bootstrap.

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.