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 +4 -4
- data/README.md +65 -3
- data/lib/radd/cli.rb +1 -1
- data/lib/radd/config.rb +6 -6
- data/lib/radd/nameserver.rb +20 -14
- data/lib/radd/version.rb +1 -1
- data/lib/radd.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 84f6d38880accb181b5d1976dd49f1492e45cbd69a5e7c93ca3727b131a00698
|
|
4
|
+
data.tar.gz: 6fcd72a269a6f52b99810912620ba7a243680827c01b43e9579efbeb4962d4d2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7dac0c7f9dd9b61b1a28d47276be853867cb3055d0720bffcfe41028dae4a29d2f4b7ca930c35756206de76aaedcf4680b42c5af3e601491b3179a2660168a1e
|
|
7
|
+
data.tar.gz: 41db151db1e4d9cdd156a71ea4ccb1e3abb16b63659a974bc98a35d48fb38269f1ad8308234a0b4b023634ee7fe457857ead1fdfeb1935b9661a968ff07dc605
|
data/README.md
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
[](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
data/lib/radd/config.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module Radd
|
|
2
2
|
|
|
3
3
|
class << self
|
|
4
|
-
attr_reader :
|
|
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, '
|
|
13
|
-
@
|
|
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
|
|
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
|
data/lib/radd/nameserver.rb
CHANGED
|
@@ -1,17 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
data/lib/radd.rb
CHANGED