radd 1.4.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f9fddd23ad9d4e45fcfef31f6e5d976b13511fc6089a3f77267395ff8d62bfb6
4
- data.tar.gz: 530c66e7a340a9709de98025c4cc697b50d1358371d7ef7e351cd756a30611f8
3
+ metadata.gz: 84f6d38880accb181b5d1976dd49f1492e45cbd69a5e7c93ca3727b131a00698
4
+ data.tar.gz: 6fcd72a269a6f52b99810912620ba7a243680827c01b43e9579efbeb4962d4d2
5
5
  SHA512:
6
- metadata.gz: f0a3ff47b7c18794df7a34972dacc6ec4434c9dc1b749797655518e79d5509fbc4d01326d34906c3904c22498663cce5224d4214b593cf91588398c3c29ab6cf
7
- data.tar.gz: 431664ea22d21ba782c577c940746bfd43083855054cf60befb9b6414d52d3ba281524448eb8639b19a77549440749f43a0528564c6fa0e22992146eaf00175b
6
+ metadata.gz: 7dac0c7f9dd9b61b1a28d47276be853867cb3055d0720bffcfe41028dae4a29d2f4b7ca930c35756206de76aaedcf4680b42c5af3e601491b3179a2660168a1e
7
+ data.tar.gz: 41db151db1e4d9cdd156a71ea4ccb1e3abb16b63659a974bc98a35d48fb38269f1ad8308234a0b4b023634ee7fe457857ead1fdfeb1935b9661a968ff07dc605
data/README.md CHANGED
@@ -1,3 +1,5 @@
1
+ [![Gem Version](https://badge.fury.io/rb/radd.svg)](http://badge.fury.io/rb/radd)
2
+
1
3
  # radd
2
4
 
3
5
  Minimal dynamic DNS service
@@ -13,15 +15,41 @@ gem install radd
13
15
 
14
16
  ```yaml
15
17
  # radd.yml
18
+ origin: domains.example.com
16
19
  ip: 10.1.2.3
17
- http: 127.0.0.1:3000
18
- dns: 0.0.0.0:53
19
- domain: example.com
20
20
  mname: ns.example.com
21
21
  rname: hostmaster.example.com
22
+ ttl: 300
23
+ http: 127.0.0.1:3000
24
+ dns: 0.0.0.0:53
22
25
  db: radd.sqlite3
23
26
  ```
24
27
 
28
+ #### origin
29
+ Your domain where subdomains are the dynamic hostnames
30
+
31
+ #### ip
32
+ The nameserver's public IP
33
+
34
+ #### mname
35
+ Hostname of the nameserver, must not be a subdomain of `origin`
36
+
37
+ #### rname
38
+ Email address of the nameserver contact, default: `hostmaster.ORIGIN`
39
+
40
+ #### ttl
41
+ TTL of the dynamic A records, default: `300`
42
+
43
+ #### http
44
+ `ÌP:port` the HTTP server should listen on, default: `127.0.0.1:3003`
45
+
46
+ #### dns
47
+ `IP:port` the DNS server should listen on, default: `0.0.0.0:53`
48
+
49
+ #### db
50
+ Path to the zone db, default: `radd.sqlite3`
51
+
52
+
25
53
  ## Usage
26
54
 
27
55
  ```
@@ -37,3 +65,37 @@ delete Delete record
37
65
  list List available records
38
66
  start Run the server
39
67
  ```
68
+
69
+ ## Deployment
70
+
71
+ ### Webserver
72
+ The HTTP server should be exposed via a reverse proxy like Nginx, which provides SSL encryption.
73
+
74
+ ### Nameserver
75
+ The DNS ports (53/udp, 53/tcp) can be exposed directly when using `systemd` to run `radd`.
76
+ The provided unit file (`radd.service`) includes the necessary directives which enable an unprivileged user
77
+ to access port 53.
78
+
79
+ ### DNS configuration
80
+ You need to set your dynamic DNS server as the authoritative nameserver for the used (sub)domain:
81
+
82
+ ```
83
+ NS ddns.example.com ns.example.com. 86400
84
+ ```
85
+
86
+ ## Updating a record via HTTP
87
+
88
+ In order to update a record, an authorized request must be made to the `/update` endpoint.
89
+
90
+ The hostname is determined by the HTTP user name.
91
+ The IP address can be supplied by the `ip` parameter, otherwise, the remote IP of the request will be used:
92
+
93
+ ```
94
+ # use remote IP
95
+ curl --user "hostname:password" https://ddns.example.com/update
96
+ ```
97
+
98
+ ```
99
+ # use given IP
100
+ curl --user "hostname:password" https://ddns.example.com/update?ip=10.20.30.40
101
+ ```
data/lib/radd/cli.rb CHANGED
@@ -100,7 +100,7 @@ module Radd::Cli
100
100
 
101
101
  def start
102
102
  load_config
103
- puts "Starting Radd server for #{Radd.domain}"
103
+ puts "Starting Radd server for #{Radd.origin}"
104
104
 
105
105
  dns, http = Radd::Nameserver.new, Radd::Webserver.new
106
106
 
data/lib/radd/config.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  module Radd
2
2
 
3
3
  class << self
4
- attr_reader :domain, :ip, :db, :http_host, :http_port, :dns_host, :dns_port, :ttl,
4
+ attr_reader :origin, :ip, :db, :http_host, :http_port, :dns_host, :dns_port, :ttl,
5
5
  :mname, :rname
6
6
 
7
7
  def configure!(file, skip_models: false, skip_db: false)
@@ -9,8 +9,8 @@ module Radd
9
9
  file_path = Radd.root + file_path unless file_path.absolute?
10
10
  raise ConfigurationError, "could not open config file #{file_path}" unless file_path.file?
11
11
  config = YAML.load(file_path.read)
12
- raise ConfigurationError, 'domain missing' unless config['domain']
13
- @domain = config['domain']
12
+ raise ConfigurationError, 'origin missing' unless config['origin']
13
+ @origin = config['origin']
14
14
  raise ConfigurationError, 'invalid IP' unless Radd.valid_ip?(config['ip'])
15
15
  @ip = config['ip']
16
16
  uri = URI.parse("http://#{config['http']}")
@@ -22,8 +22,8 @@ module Radd
22
22
  raise ConfigurationError, 'invalid TTL' if config['ttl'] && config['ttl'] < 1
23
23
  @ttl = config['ttl'] || 300
24
24
  raise ConfigurationError, 'master name missing' unless config['mname']
25
- @mname = config['mname']
26
- @rname = config['rname'] || "hostmaster.#{domain}"
25
+ @mname = Resolv::DNS::Name.create(config['mname'])
26
+ @rname = Resolv::DNS::Name.create(config['rname'] || "hostmaster@#{origin}")
27
27
  db_path = Pathname.new(config['db'] || 'radd.sqlite3')
28
28
  db_path = Radd.root + db_path unless db_path.absolute?
29
29
  @db = db_path
@@ -40,5 +40,5 @@ module Radd
40
40
  !!(ip && ip.match(Resolv::IPv4::Regex))
41
41
  end
42
42
  end
43
-
43
+
44
44
  end
@@ -1,17 +1,23 @@
1
- class Radd::Nameserver < Async::DNS::Server
2
- def initialize
3
- super(Async::DNS::Endpoint.for(Radd.dns_host, port: Radd.dns_port))
4
- end
5
-
6
- def process(name, resource_class, transaction)
7
- name = name.downcase
8
- case resource_class
9
- when Resolv::DNS::Resource::IN::A
10
- ip = Radd.domain == name ? Radd.ip : Radd.query(name)
11
- return transaction.respond!(ip, ttl: Radd.ttl) if ip
12
- when Resolv::DNS::Resource::IN::SOA
13
- return transaction.respond!(Radd.mname, Radd.rname, Radd.serial, 10800, 1800, 604800, 1800)
1
+ module Radd
2
+ class Nameserver < Async::DNS::Server
3
+
4
+ def initialize
5
+ super(Async::DNS::Endpoint.for(Radd.dns_host, port: Radd.dns_port))
6
+ end
7
+
8
+ def process(name, resource_class, transaction)
9
+ name = name.downcase
10
+ # NOTE: do not use case..when, as resource classes are not identical
11
+ if Resolv::DNS::Resource::IN::A == resource_class
12
+ ip = Radd.mname == name ? Radd.ip : Radd.query(name)
13
+ return transaction.respond!(ip, ttl: Radd.ttl) if ip
14
+ elsif resource_class <= Resolv::DNS::Resource::SOA && Radd.origin == name
15
+ # mname, rname, serial, refresh, retry_, expire, minimum
16
+ return transaction.respond!(Radd.mname, Radd.rname, Radd.serial, 10800, 1800, 604800, 1800)
17
+ elsif resource_class <= Resolv::DNS::Resource::NS && Radd.origin == name
18
+ return transaction.respond!(Radd.mname)
19
+ end
20
+ transaction.fail!(:NXDomain)
14
21
  end
15
- transaction.fail!(:NXDomain)
16
22
  end
17
23
  end
data/lib/radd/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Radd
2
- VERSION = '1.4.0'
2
+ VERSION = '1.5.0'
3
3
  end
data/lib/radd.rb CHANGED
@@ -63,7 +63,7 @@ module Radd
63
63
  end
64
64
 
65
65
  def fqdn2name(fqdn)
66
- if match = fqdn.downcase.match(/\A([a-z0-9-]{1,63})\.#{Regexp.escape(domain)}\z/)
66
+ if match = fqdn.downcase.match(/\A([a-z0-9-]{1,63})\.#{Regexp.escape(origin)}\z/)
67
67
  match.captures[0]
68
68
  end
69
69
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: radd
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthias Grosser