dyndnsd 2.3.0 → 3.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5c036941ee751a468f225791fae3b73150db3a8a3e011917e27a9ceb742276c6
4
- data.tar.gz: 88217f0be901b27cf7cc018a29c3e5dc56165d4badcecb7d792e36b5f7cbf6fb
3
+ metadata.gz: b1de3798acde309897c5cb51cafa24c21f0f8911a0afeb9679695d71770044da
4
+ data.tar.gz: d2f24081ea363e8bac4d2381bb98d1664b297dd0ef29881ae0975323e20e2275
5
5
  SHA512:
6
- metadata.gz: b2fda9af8940e3ce39f0b45e27fd6ac39e9e1168b8bb0fcf38f968bbe61786adb4a073b6da360b62b4f14cafe1b5c08ec8e1b3e66d4fb5a2f51ca6238b5ecd61
7
- data.tar.gz: 951ee197de794a9600ab3773f49d71d65a597572dab563af770a2374942c1d4f5fcef4d59fb3ec316990938e28ba6e1244c8c50bf8fc37a5047c5f8452fe9d36
6
+ metadata.gz: 017c83474f5ae3d2b93b8d6c8436bc11fbc9cf8b2daa46f94476f24347d4a6c004ab3d03200b3f007132b77740643a8be0c6dfecb93994505b4145c10082e6a2
7
+ data.tar.gz: e5667934714bee01305c72be600378c88d7f8bdb56f1c70829971d0bdabd2afed732df7f1840f3fa2a4f62edc851d6424a318942b4ea71ad0389183e1aee32f8
@@ -1,5 +1,29 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.1.1 (october 3, 2020)
4
+
5
+ IMPROVEMENTS:
6
+
7
+ - Use webrick gem which contains fixes against [CVE-2020-25613](https://www.ruby-lang.org/en/news/2020/09/29/http-request-smuggling-cve-2020-25613/)
8
+
9
+ ## 3.1.0 (August 19, 2020)
10
+
11
+ IMPROVEMENTS:
12
+
13
+ - Add officially maintained [Docker image for dyndnsd](https://hub.docker.com/r/cmur2/dyndnsd)
14
+
15
+ ## 3.0.0 (July 29, 2020)
16
+
17
+ IMPROVEMENTS:
18
+
19
+ - Drop EOL Ruby 2.4 and lower support, now minimum version supported is Ruby 2.5
20
+
21
+ ## 2.3.1 (July 27, 2020)
22
+
23
+ IMPROVEMENTS:
24
+
25
+ - Fix annoying error message `log writing failed. can't be called from trap context` on shutdown by not attempting to log redundant information there
26
+
3
27
  ## 2.3.0 (July 20, 2020)
4
28
 
5
29
  IMPROVEMENTS:
data/README.md CHANGED
@@ -64,7 +64,42 @@ users:
64
64
 
65
65
  Run dyndnsd.rb by:
66
66
 
67
- dyndnsd /path/to/config.yaml
67
+ ```bash
68
+ dyndnsd /path/to/config.yml
69
+ ```
70
+
71
+
72
+ ### Docker image
73
+
74
+ There is an officially maintained [Docker image for dyndnsd](https://hub.docker.com/r/cmur2/dyndnsd) available at Dockerhub. The goal is to have a minimal secured image available (currently based on Alpine) that works well for the `zone_transfer_server` updater use case.
75
+
76
+ Users can make extensions by deriving from the official Docker image or building their own.
77
+
78
+ The Docker image consumes the same configuration file in YAML format as the gem, inside the container it needs to be mounted/available as `/etc/dyndnsd/config.yml`. the following YAML should be used as a base and extended with user's settings:
79
+
80
+ ```yaml
81
+ host: "0.0.0.0"
82
+ port: 8080
83
+ # omit the logfile: option so logging to STDOUT will happen automatically
84
+ db: "/var/lib/dyndnsd/db.json"
85
+
86
+ # User's settings for updater and permissions follow here!
87
+ ```
88
+
89
+ more ports might be needed depending on if DNS zone transfer is needed
90
+
91
+ Run the Docker image exposing the DynDNS-API on host port 8080 via:
92
+
93
+ ```bash
94
+ docker run -d --name dyndnsd \
95
+ -p 8080:8080 \
96
+ -v /host/path/to/dyndnsd/config.yml:/etc/dyndnsd/config.yml \
97
+ -v /host/ptherpath/to/dyndnsd/datadir:/var/lib/dyndnsd \
98
+ cmur2/dyndnsd:vX.Y.Z
99
+ ```
100
+
101
+ *Note*: You may need to expose more then just port 8080 e.g. if you use the `zone_transfer_server` which can be done by appending additional `-p 5353:5353` flags to the `docker run` command.
102
+
68
103
 
69
104
 
70
105
  ## Using dyndnsd.rb with any nameserver via DNS zone transfers (AXFR)
@@ -187,9 +222,11 @@ If you want to provide an additional IPv6 address as myip6 parameter, the myip p
187
222
  Use a webserver as a proxy to handle SSL and/or multiple listen addresses and ports. DynDNS.com provides HTTP on port 80 and 8245 and HTTPS on port 443.
188
223
 
189
224
 
190
- ### Init scripts
225
+ ### Startup
226
+
227
+ There is a [Dockerfile](docs/Dockerfile) that can be used to build a Docker image for running dyndnsd.rb.
191
228
 
192
- The [Debian 6 init.d script](init.d/debian-6-dyndnsd) assumes that dyndnsd.rb is installed into the system ruby (no RVM support) and the config.yaml is at /opt/dyndnsd/config.yaml. Modify to your needs.
229
+ The [Debian 6 init.d script](docs/debian-6-init-dyndnsd) assumes that dyndnsd.rb is installed into the system ruby (no RVM support) and the config.yaml is at /opt/dyndnsd/config.yaml. Modify to your needs.
193
230
 
194
231
 
195
232
  ### Monitoring
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'date'
3
4
  require 'etc'
4
5
  require 'logger'
5
6
  require 'ipaddr'
@@ -80,7 +81,7 @@ module Dyndnsd
80
81
  end
81
82
 
82
83
  # @param env [Hash{String => String}]
83
- # @return [Array{Integer,Hash{String => String},Array{String}}]
84
+ # @return [Array{Integer,Hash{String => String},Array<String>}]
84
85
  def call(env)
85
86
  return [422, {'X-DynDNS-Response' => 'method_forbidden'}, []] if env['REQUEST_METHOD'] != 'GET'
86
87
  return [422, {'X-DynDNS-Response' => 'not_found'}, []] if env['PATH_INFO'] != '/nic/update'
@@ -134,7 +135,7 @@ module Dyndnsd
134
135
  private
135
136
 
136
137
  # @param params [Hash{String => String}]
137
- # @return [Array{String}]
138
+ # @return [Array<String>]
138
139
  def extract_v4_and_v6_address(params)
139
140
  return [] if !(params['myip'])
140
141
  begin
@@ -148,7 +149,7 @@ module Dyndnsd
148
149
 
149
150
  # @param env [Hash{String => String}]
150
151
  # @param params [Hash{String => String}]
151
- # @return [Array{String}]
152
+ # @return [Array<String>]
152
153
  def extract_myips(env, params)
153
154
  # require presence of myip parameter as valid IPAddr (v4) and valid myip6
154
155
  return extract_v4_and_v6_address(params) if params.key?('myip6')
@@ -164,8 +165,8 @@ module Dyndnsd
164
165
  end
165
166
 
166
167
  # @param hostnames [String]
167
- # @param myips [Array{String}]
168
- # @return [Array{Symbol}]
168
+ # @param myips [Array<String>]
169
+ # @return [Array<Symbol>]
169
170
  def process_changes(hostnames, myips)
170
171
  changes = []
171
172
  Helper.span('process_changes') do |span|
@@ -200,7 +201,7 @@ module Dyndnsd
200
201
  end
201
202
 
202
203
  # @param env [Hash{String => String}]
203
- # @return [Array{Integer,Hash{String => String},Array{String}}]
204
+ # @return [Array{Integer,Hash{String => String},Array<String>}]
204
205
  def handle_dyndns_request(env)
205
206
  params = Rack::Utils.parse_query(env['QUERY_STRING'])
206
207
 
@@ -245,7 +246,7 @@ module Dyndnsd
245
246
  if config['logfile']
246
247
  Dyndnsd.logger = Logger.new(config['logfile'])
247
248
  else
248
- Dyndnsd.logger = Logger.new(STDOUT)
249
+ Dyndnsd.logger = Logger.new($stdout)
249
250
  end
250
251
 
251
252
  Dyndnsd.logger.progname = 'dyndnsd'
@@ -256,11 +257,9 @@ module Dyndnsd
256
257
  # @return [void]
257
258
  private_class_method def self.setup_traps
258
259
  Signal.trap('INT') do
259
- Dyndnsd.logger.info 'Quitting...'
260
260
  Rack::Handler::WEBrick.shutdown
261
261
  end
262
262
  Signal.trap('TERM') do
263
- Dyndnsd.logger.info 'Quitting...'
264
263
  Rack::Handler::WEBrick.shutdown
265
264
  end
266
265
  end
@@ -27,7 +27,7 @@ module Dyndnsd
27
27
  ips.each do |ip|
28
28
  ip = IPAddr.new(ip).native
29
29
  type = ip.ipv6? ? 'AAAA' : 'A'
30
- name = hostname.chomp('.' + @domain)
30
+ name = hostname.chomp(".#{@domain}")
31
31
  out << "#{name} IN #{type} #{ip}"
32
32
  end
33
33
  end
@@ -9,7 +9,7 @@ module Dyndnsd
9
9
  end
10
10
 
11
11
  # @param env [Hash{String => String}]
12
- # @return [Array{Integer,Hash{String => String},Array{String}}]
12
+ # @return [Array{Integer,Hash{String => String},Array<String>}]
13
13
  def call(env)
14
14
  @app.call(env).tap do |status_code, headers, body|
15
15
  if headers.key?('X-DynDNS-Response')
@@ -24,30 +24,32 @@ module Dyndnsd
24
24
 
25
25
  # @param status_code [Integer]
26
26
  # @param headers [Hash{String => String}]
27
- # @param body [Array{String}]
28
- # @return [Array{Integer,Hash{String => String},Array{String}}]
27
+ # @param body [Array<String>]
28
+ # @return [Array{Integer,Hash{String => String},Array<String>}]
29
29
  def decorate_dyndnsd_response(status_code, headers, body)
30
- if status_code == 200
30
+ case status_code
31
+ when 200
31
32
  [200, {'Content-Type' => 'text/plain'}, [get_success_body(body[0], body[1])]]
32
- elsif status_code == 422
33
+ when 422
33
34
  error_response_map[headers['X-DynDNS-Response']]
34
35
  end
35
36
  end
36
37
 
37
38
  # @param status_code [Integer]
38
39
  # @param headers [Hash{String => String}]
39
- # @param _body [Array{String}]
40
- # @return [Array{Integer,Hash{String => String},Array{String}}]
40
+ # @param _body [Array<String>]
41
+ # @return [Array{Integer,Hash{String => String},Array<String>}]
41
42
  def decorate_other_response(status_code, headers, _body)
42
- if status_code == 400
43
+ case status_code
44
+ when 400
43
45
  [status_code, headers, ['Bad Request']]
44
- elsif status_code == 401
46
+ when 401
45
47
  [status_code, headers, ['badauth']]
46
48
  end
47
49
  end
48
50
 
49
- # @param changes [Array{Symbol}]
50
- # @param myips [Array{String}]
51
+ # @param changes [Array<Symbol>]
52
+ # @param myips [Array<String>]
51
53
  # @return [String]
52
54
  def get_success_body(changes, myips)
53
55
  changes.map { |change| "#{change} #{myips.join(' ')}" }.join("\n")
@@ -9,7 +9,7 @@ module Dyndnsd
9
9
  end
10
10
 
11
11
  # @param env [Hash{String => String}]
12
- # @return [Array{Integer,Hash{String => String},Array{String}}]
12
+ # @return [Array{Integer,Hash{String => String},Array<String>}]
13
13
  def call(env)
14
14
  @app.call(env).tap do |status_code, headers, body|
15
15
  if headers.key?('X-DynDNS-Response')
@@ -24,30 +24,32 @@ module Dyndnsd
24
24
 
25
25
  # @param status_code [Integer]
26
26
  # @param headers [Hash{String => String}]
27
- # @param body [Array{String}]
28
- # @return [Array{Integer,Hash{String => String},Array{String}}]
27
+ # @param body [Array<String>]
28
+ # @return [Array{Integer,Hash{String => String},Array<String>}]
29
29
  def decorate_dyndnsd_response(status_code, headers, body)
30
- if status_code == 200
30
+ case status_code
31
+ when 200
31
32
  [200, {'Content-Type' => 'text/plain'}, [get_success_body(body[0], body[1])]]
32
- elsif status_code == 422
33
+ when 422
33
34
  error_response_map[headers['X-DynDNS-Response']]
34
35
  end
35
36
  end
36
37
 
37
38
  # @param status_code [Integer]
38
39
  # @param headers [Hash{String => String}]
39
- # @param _body [Array{String}]
40
- # @return [Array{Integer,Hash{String => String},Array{String}}]
40
+ # @param _body [Array<String>]
41
+ # @return [Array{Integer,Hash{String => String},Array<String>}]
41
42
  def decorate_other_response(status_code, headers, _body)
42
- if status_code == 400
43
+ case status_code
44
+ when 400
43
45
  [status_code, headers, ['Bad Request']]
44
- elsif status_code == 401
46
+ when 401
45
47
  [status_code, headers, ['Unauthorized']]
46
48
  end
47
49
  end
48
50
 
49
- # @param changes [Array{Symbol}]
50
- # @param myips [Array{String}]
51
+ # @param changes [Array<Symbol>]
52
+ # @param myips [Array<String>]
51
53
  # @return [String]
52
54
  def get_success_body(changes, myips)
53
55
  changes.map { |change| change == :good ? "Changed to #{myips.join(' ')}" : "No change needed for #{myips.join(' ')}" }.join("\n")
@@ -28,11 +28,9 @@ module Dyndnsd
28
28
  sleep @interval
29
29
 
30
30
  Thread.new do
31
- begin
32
- write
33
- rescue StandardError => e
34
- @on_error[e] rescue nil
35
- end
31
+ write
32
+ rescue StandardError => e
33
+ @on_error[e] rescue nil
36
34
  end
37
35
  end
38
36
  end
@@ -96,8 +94,8 @@ module Dyndnsd
96
94
  # @param file [String]
97
95
  # @param base_name [String]
98
96
  # @param metric [Object]
99
- # @param keys [Array{Symbol}]
100
- # @param snapshot_keys [Array{Symbol}]
97
+ # @param keys [Array<Symbol>]
98
+ # @param snapshot_keys [Array<Symbol>]
101
99
  # @return [void]
102
100
  def write_metric(file, base_name, metric, keys, snapshot_keys = [])
103
101
  time = Time.now.to_i
@@ -85,7 +85,7 @@ module Dyndnsd
85
85
 
86
86
  # converts into suitable parameter form for Async::DNS::Resolver or Async::DNS::Server
87
87
  #
88
- # @param endpoint_list [Array{String}]
88
+ # @param endpoint_list [Array<String>]
89
89
  # @return [Array{Array{Object}}]
90
90
  def self.parse_endpoints(endpoint_list)
91
91
  endpoint_list.map { |addr_string| addr_string.split('@') }
@@ -139,7 +139,7 @@ module Dyndnsd
139
139
 
140
140
  # @param name [String]
141
141
  # @param resource_class [Resolv::DNS::Resource]
142
- # @param transaction [Async::DNS::Transaction]
142
+ # Since solargraph cannot parse this: param transaction [Async::DNS::Transaction]
143
143
  # @return [void]
144
144
  def process(name, resource_class, transaction)
145
145
  if name != @domain || resource_class != Resolv::DNS::Resource::Generic::Type252_Class1
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dyndnsd
4
- VERSION = '2.3.0'
4
+ VERSION = '3.1.1'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dyndnsd
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.0
4
+ version: 3.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christian Nicolai
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-07-20 00:00:00.000000000 Z
11
+ date: 2020-10-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async-dns
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.10.0
33
+ version: 1.1.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 0.10.0
40
+ version: 1.1.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: metriks
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -94,6 +94,20 @@ dependencies:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
96
  version: 0.9.0
97
+ - !ruby/object:Gem::Dependency
98
+ name: webrick
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: 1.6.1
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: 1.6.1
97
111
  - !ruby/object:Gem::Dependency
98
112
  name: bundler
99
113
  requirement: !ruby/object:Gem::Requirement
@@ -170,14 +184,14 @@ dependencies:
170
184
  requirements:
171
185
  - - "~>"
172
186
  - !ruby/object:Gem::Version
173
- version: 0.81.0
187
+ version: 0.92.0
174
188
  type: :development
175
189
  prerelease: false
176
190
  version_requirements: !ruby/object:Gem::Requirement
177
191
  requirements:
178
192
  - - "~>"
179
193
  - !ruby/object:Gem::Version
180
- version: 0.81.0
194
+ version: 0.92.0
181
195
  - !ruby/object:Gem::Dependency
182
196
  name: solargraph
183
197
  requirement: !ruby/object:Gem::Requirement
@@ -207,7 +221,6 @@ files:
207
221
  - LICENSE
208
222
  - README.md
209
223
  - exe/dyndnsd
210
- - init.d/debian-6-dyndnsd
211
224
  - lib/dyndnsd.rb
212
225
  - lib/dyndnsd/database.rb
213
226
  - lib/dyndnsd/generator/bind.rb
@@ -233,7 +246,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
233
246
  requirements:
234
247
  - - ">="
235
248
  - !ruby/object:Gem::Version
236
- version: '2.3'
249
+ version: '2.5'
237
250
  required_rubygems_version: !ruby/object:Gem::Requirement
238
251
  requirements:
239
252
  - - ">="
@@ -1,43 +0,0 @@
1
- #! /bin/sh
2
- ### BEGIN INIT INFO
3
- # Provides: dyndnsd
4
- # Required-Start: $remote_fs $syslog
5
- # Required-Stop: $remote_fs $syslog
6
- # Default-Start: 2 3 4 5
7
- # Default-Stop: 0 1 6
8
- # Short-Description: Handle dyndnsd.rb gem
9
- ### END INIT INFO
10
-
11
- # using the system ruby's gem binaries directory
12
- DAEMON="/var/lib/gems/1.8/bin/dyndnsd"
13
-
14
- CONFIG_FILE="/opt/dyndnsd/config.yaml"
15
-
16
- DAEMON_OPTS="$CONFIG_FILE"
17
-
18
- test -x $DAEMON || exit 0
19
-
20
- . /lib/lsb/init-functions
21
-
22
- case "$1" in
23
- start)
24
- log_daemon_msg "Starting dyndnsd.rb" "dyndnsd"
25
- start-stop-daemon --start --quiet --oknodo --make-pidfile --pidfile "/var/run/dyndnsd.pid" --background --exec $DAEMON -- $DAEMON_OPTS
26
- log_end_msg $?
27
- ;;
28
- stop)
29
- log_daemon_msg "Stopping dyndnsd.rb" "dyndnsd"
30
- start-stop-daemon --stop --quiet --oknodo --pidfile "/var/run/dyndnsd.pid"
31
- log_end_msg $?
32
- ;;
33
- restart|force-reload)
34
- log_daemon_msg "Restarting dyndnsd.rb" "dyndnsd"
35
- start-stop-daemon --stop --quiet --oknodo --retry 30 --pidfile "/var/run/dyndsd.pid"
36
- start-stop-daemon --start --quiet --oknodo --make-pidfile --pidfile "/var/run/dyndnsd.pid" --background --exec $DAEMON -- $DAEMON_OPTS
37
- log_end_msg $?
38
- ;;
39
- *)
40
- log_action_msg "Usage: $0 {start|stop|restart|force-reload}"
41
- exit 2
42
- ;;
43
- esac