mirror of
https://github.com/cmur2/dyndnsd.git
synced 2025-12-14 13:48:10 +01:00
Compare commits
28 Commits
dependabot
...
renovate-a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b7e2c58e5d | ||
| 627b1c4dc5 | |||
| da79ef902d | |||
| 8589cf801f | |||
|
|
c743c778bc | ||
|
|
415635f373 | ||
|
|
694a3e4c21 | ||
|
|
74aec5f873 | ||
| 34f2c01543 | |||
| 62e2067e5b | |||
|
|
62df373c77 | ||
| 7a1302082b | |||
|
|
ea3591564d | ||
|
|
bc2262e2bb | ||
|
|
5871ef4c18 | ||
|
|
62e1843365 | ||
|
|
7def8ea8a6 | ||
|
|
9b553eb117 | ||
|
|
5e6f0e1e33 | ||
|
|
01175ec8f9 | ||
|
|
8d2c2f9c90 | ||
|
|
d3522e2c92 | ||
|
|
d92ee500c9 | ||
| 0ddb87cc57 | |||
| 685854aad3 | |||
|
|
3825f57521 | ||
| 8f7a796e9d | |||
| 81dc2aba4c |
2
.github/renovate.json5
vendored
2
.github/renovate.json5
vendored
@@ -40,7 +40,7 @@
|
|||||||
customManagers: [
|
customManagers: [
|
||||||
{
|
{
|
||||||
customType: "regex",
|
customType: "regex",
|
||||||
fileMatch: ["\.rb$", "^Rakefile$"],
|
managerFilePatterns: ["/.rb$/", "/^Rakefile$/"],
|
||||||
matchStrings: [
|
matchStrings: [
|
||||||
"renovate: datasource=(?<datasource>.*?) depName=(?<depName>.*?)\\s.*_version = '(?<currentValue>.*)'\\s"
|
"renovate: datasource=(?<datasource>.*?) depName=(?<depName>.*?)\\s.*_version = '(?<currentValue>.*)'\\s"
|
||||||
]
|
]
|
||||||
|
|||||||
2
.github/workflows/cd.yml
vendored
2
.github/workflows/cd.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
|||||||
release-dockerimage:
|
release-dockerimage:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Extract dyndnsd version from tag name
|
- name: Extract dyndnsd version from tag name
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
7
.github/workflows/ci.yml
vendored
7
.github/workflows/ci.yml
vendored
@@ -18,13 +18,12 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
ruby-version:
|
ruby-version:
|
||||||
- '3.0'
|
|
||||||
- '3.1'
|
- '3.1'
|
||||||
- '3.2'
|
- '3.2'
|
||||||
- '3.3'
|
- '3.3'
|
||||||
- '3.4'
|
- '3.4'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: Set up Ruby ${{ matrix.ruby-version }}
|
- name: Set up Ruby ${{ matrix.ruby-version }}
|
||||||
uses: ruby/setup-ruby@v1
|
uses: ruby/setup-ruby@v1
|
||||||
with:
|
with:
|
||||||
@@ -38,7 +37,7 @@ jobs:
|
|||||||
actionlint:
|
actionlint:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: Check workflow files
|
- name: Check workflow files
|
||||||
run: |
|
run: |
|
||||||
echo "::add-matcher::.github/actionlint-matcher.json"
|
echo "::add-matcher::.github/actionlint-matcher.json"
|
||||||
@@ -51,6 +50,6 @@ jobs:
|
|||||||
image: ghcr.io/renovatebot/renovate
|
image: ghcr.io/renovatebot/renovate
|
||||||
options: --user root
|
options: --user root
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: Check Renovate config
|
- name: Check Renovate config
|
||||||
run: renovate-config-validator --strict
|
run: renovate-config-validator --strict
|
||||||
|
|||||||
3
.github/workflows/vulnscan.yml
vendored
3
.github/workflows/vulnscan.yml
vendored
@@ -1,10 +1,9 @@
|
|||||||
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
|
|
||||||
---
|
---
|
||||||
name: vulnscan
|
name: vulnscan
|
||||||
|
|
||||||
on:
|
on:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '7 4 * * 4' # weekly on thursday morning
|
- cron: '7 4 1 * *' # monthly on first day's morning
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|||||||
11
CHANGELOG.md
11
CHANGELOG.md
@@ -1,12 +1,19 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## 3.11.0
|
## 3.12.0 (December 4th, 2025)
|
||||||
|
|
||||||
|
IMPROVEMENTS:
|
||||||
|
|
||||||
|
- regex instead of hosts list can be used for hostname ownership
|
||||||
|
|
||||||
|
## 3.11.0 (October 2nd, 2025)
|
||||||
|
|
||||||
IMPROVEMENTS:
|
IMPROVEMENTS:
|
||||||
|
|
||||||
- add Ruby 3.4 support
|
- add Ruby 3.4 support
|
||||||
|
- update base of Docker image to Alpine 3.22.1 (from 3.19.0 before)
|
||||||
|
|
||||||
## 3.10.0
|
## 3.10.0 (January 18th, 2024)
|
||||||
|
|
||||||
IMPROVEMENTS:
|
IMPROVEMENTS:
|
||||||
|
|
||||||
|
|||||||
31
README.md
31
README.md
@@ -307,6 +307,37 @@ users:
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Matching with a regular expression
|
||||||
|
|
||||||
|
Instead of relying on `hosts`, you can use `regex` to employ a regular expression, which is very useful for avoiding having to repeatedly edit the configuration file to register a new host name.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
host: "0.0.0.0"
|
||||||
|
port: 5354
|
||||||
|
username: "dyndnsd"
|
||||||
|
group: "dyndnsd"
|
||||||
|
db: "/dyndnsd/db.json"
|
||||||
|
debug: false
|
||||||
|
domain: "dyn.dc-air.home.arpa"
|
||||||
|
updater:
|
||||||
|
name: "command_with_bind_zone"
|
||||||
|
params:
|
||||||
|
zone_file: "/nsd/zones/static/dyn.dc-air.home.arpa.zone"
|
||||||
|
command: "doas service nsd reload"
|
||||||
|
ttl: "5m"
|
||||||
|
dns: "ns.dc-air.home.arpa."
|
||||||
|
email_addr: "admin.example.org"
|
||||||
|
users:
|
||||||
|
myuser:
|
||||||
|
password: "superhypermegas3kurepassword1234"
|
||||||
|
regex: '^[a-z][0-9]\.dyn\.dc\-air\.home\.arpa$'
|
||||||
|
```
|
||||||
|
|
||||||
|
However, when using `regex`, `hosts` is simply ignored if defined, so you must choose one or the other. Recommendation: use `regex` for scripts or programs and `hosts` for regular users.
|
||||||
|
|
||||||
|
**Note**: Please note that when dyndnsd evaluates the regular expression, the `Regexp::EXTENDED` and `Regexp::IGNORECASE` options are used.
|
||||||
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
dyndnsd.rb is licensed under the Apache License, Version 2.0. See LICENSE for more information.
|
dyndnsd.rb is licensed under the Apache License, Version 2.0. See LICENSE for more information.
|
||||||
|
|||||||
4
Rakefile
4
Rakefile
@@ -13,10 +13,10 @@ task :solargraph do
|
|||||||
end
|
end
|
||||||
|
|
||||||
# renovate: datasource=github-tags depName=hadolint/hadolint
|
# renovate: datasource=github-tags depName=hadolint/hadolint
|
||||||
hadolint_version = 'v2.12.0'
|
hadolint_version = 'v2.14.0'
|
||||||
|
|
||||||
# renovate: datasource=github-tags depName=aquasecurity/trivy
|
# renovate: datasource=github-tags depName=aquasecurity/trivy
|
||||||
trivy_version = 'v0.61.0'
|
trivy_version = 'v0.67.0'
|
||||||
|
|
||||||
namespace :docker do
|
namespace :docker do
|
||||||
ci_image = 'cmur2/dyndnsd:ci'
|
ci_image = 'cmur2/dyndnsd:ci'
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
FROM alpine:3.21.3
|
FROM alpine:3.23.0
|
||||||
|
|
||||||
EXPOSE 5353 8080
|
EXPOSE 5353 8080
|
||||||
|
|
||||||
ARG DYNDNSD_VERSION
|
ARG DYNDNSD_VERSION
|
||||||
|
|
||||||
RUN apk --no-cache add openssl ca-certificates && \
|
RUN apk --no-cache add openssl ca-certificates && \
|
||||||
apk --no-cache add ruby ruby-etc ruby-io-console ruby-json ruby-webrick && \
|
apk --no-cache add ruby ruby-webrick && \
|
||||||
apk --no-cache add --virtual .build-deps linux-headers ruby-dev build-base tzdata && \
|
apk --no-cache add --virtual .build-deps linux-headers ruby-dev build-base tzdata && \
|
||||||
gem install --no-document dyndnsd -v ${DYNDNSD_VERSION} && \
|
gem install --no-document dyndnsd -v ${DYNDNSD_VERSION} && \
|
||||||
rm -rf /usr/lib/ruby/gems/*/cache/ && \
|
rm -rf /usr/lib/ruby/gems/*/cache/ && \
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
FROM alpine:3.21.3
|
FROM alpine:3.23.0
|
||||||
|
|
||||||
EXPOSE 5353 8080
|
EXPOSE 5353 8080
|
||||||
|
|
||||||
COPY pkg/dyndnsd-*.gem /tmp/dyndnsd.gem
|
COPY pkg/dyndnsd-*.gem /tmp/dyndnsd.gem
|
||||||
|
|
||||||
RUN apk --no-cache add openssl ca-certificates && \
|
RUN apk --no-cache add openssl ca-certificates && \
|
||||||
apk --no-cache add ruby ruby-etc ruby-io-console ruby-json ruby-webrick && \
|
apk --no-cache add ruby ruby-webrick && \
|
||||||
apk --no-cache add --virtual .build-deps linux-headers ruby-dev build-base tzdata && \
|
apk --no-cache add --virtual .build-deps linux-headers ruby-dev build-base tzdata && \
|
||||||
gem install --no-document /tmp/dyndnsd.gem && \
|
gem install --no-document /tmp/dyndnsd.gem && \
|
||||||
rm -rf /usr/lib/ruby/gems/*/cache/ && \
|
rm -rf /usr/lib/ruby/gems/*/cache/ && \
|
||||||
|
|||||||
@@ -44,8 +44,8 @@ Gem::Specification.new do |s|
|
|||||||
s.add_development_dependency 'rack-test'
|
s.add_development_dependency 'rack-test'
|
||||||
s.add_development_dependency 'rake'
|
s.add_development_dependency 'rake'
|
||||||
s.add_development_dependency 'rspec'
|
s.add_development_dependency 'rspec'
|
||||||
s.add_development_dependency 'rubocop', '~> 1.75.1'
|
s.add_development_dependency 'rubocop', '~> 1.81.1'
|
||||||
s.add_development_dependency 'rubocop-rake', '~> 0.7.1'
|
s.add_development_dependency 'rubocop-rake', '~> 0.7.1'
|
||||||
s.add_development_dependency 'rubocop-rspec', '~> 3.6.0'
|
s.add_development_dependency 'rubocop-rspec', '~> 3.8.0'
|
||||||
s.add_development_dependency 'solargraph', '~> 0.49.0'
|
s.add_development_dependency 'solargraph', '~> 0.55.0'
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -218,9 +218,22 @@ module Dyndnsd
|
|||||||
# we can trust this information since user was authorized by middleware
|
# we can trust this information since user was authorized by middleware
|
||||||
user = env['REMOTE_USER']
|
user = env['REMOTE_USER']
|
||||||
|
|
||||||
# check for hostnames that the user does not own
|
if @users[user].key?('regex')
|
||||||
forbidden_hostnames = hostnames - @users[user].fetch('hosts', [])
|
pattern = @users[user].fetch('regex')
|
||||||
return [422, {'X-DynDNS-Response' => 'host_forbidden'}, []] if forbidden_hostnames.any?
|
begin
|
||||||
|
regex = Regexp.new(pattern, Regexp::IGNORECASE | Regexp::EXTENDED)
|
||||||
|
rescue RegexpError => e
|
||||||
|
Dyndnsd.logger.warn "Invalid regex pattern '#{pattern}': #{e.message}"
|
||||||
|
return [422, {'X-DynDNS-Response' => 'host_forbidden'}, []]
|
||||||
|
end
|
||||||
|
# check for hostnames that match the regex
|
||||||
|
matches = hostnames.any? { |str| regex.match?(str) }
|
||||||
|
return [422, {'X-DynDNS-Response' => 'host_forbidden'}, []] if !matches
|
||||||
|
else
|
||||||
|
# check for hostnames that the user does not own
|
||||||
|
forbidden_hostnames = hostnames - @users[user].fetch('hosts', [])
|
||||||
|
return [422, {'X-DynDNS-Response' => 'host_forbidden'}, []] if forbidden_hostnames.any?
|
||||||
|
end
|
||||||
|
|
||||||
if params['offline'] == 'YES'
|
if params['offline'] == 'YES'
|
||||||
myips = []
|
myips = []
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ module Dyndnsd
|
|||||||
# @return [Array{Array{Object}}]
|
# @return [Array{Array{Object}}]
|
||||||
def self.parse_endpoints(endpoint_list)
|
def self.parse_endpoints(endpoint_list)
|
||||||
endpoint_list.map { |addr_string| addr_string.split('@') }
|
endpoint_list.map { |addr_string| addr_string.split('@') }
|
||||||
.map { |addr_parts| [addr_parts[0], addr_parts[1].to_i || 53] }
|
.map { |addr_parts| [addr_parts[0], addr_parts[1]&.to_i || 53] }
|
||||||
.map { |addr| [:tcp, :udp].map { |type| [type] + addr } }
|
.map { |addr| [:tcp, :udp].map { |type| [type] + addr } }
|
||||||
.flatten(1)
|
.flatten(1)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Dyndnsd
|
module Dyndnsd
|
||||||
VERSION = '3.9.2'
|
VERSION = '3.12.0'
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -18,6 +18,10 @@ describe Dyndnsd::Daemon do
|
|||||||
},
|
},
|
||||||
'test2' => {
|
'test2' => {
|
||||||
'password' => 'ihavenohosts'
|
'password' => 'ihavenohosts'
|
||||||
|
},
|
||||||
|
'test3' => {
|
||||||
|
'password' => 'superhypermegas3kurepassword1234',
|
||||||
|
'regex' => '^[a-z0-9]+-test3\.example\.org$'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -74,6 +78,22 @@ describe Dyndnsd::Daemon do
|
|||||||
expect(last_response.body).to eq("good 2001:db8::1\ngood 2001:db8::1")
|
expect(last_response.body).to eq("good 2001:db8::1\ngood 2001:db8::1")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'supports regex matches for hostnames' do
|
||||||
|
authorize 'test3', 'superhypermegas3kurepassword1234'
|
||||||
|
|
||||||
|
get '/nic/update?hostname=abc123-test3.example.org&myip=1.2.3.4'
|
||||||
|
expect(last_response).to be_ok
|
||||||
|
expect(last_response.body).to eq('good 1.2.3.4')
|
||||||
|
|
||||||
|
get '/nic/update?hostname=foo-test3.example.org,bar-test3.example.org&myip=2001:db8::1'
|
||||||
|
expect(last_response).to be_ok
|
||||||
|
expect(last_response.body).to eq("good 2001:db8::1\ngood 2001:db8::1")
|
||||||
|
|
||||||
|
get '/nic/update?hostname=abc123.example.org'
|
||||||
|
expect(last_response).to be_ok
|
||||||
|
expect(last_response.body).to eq('nohost')
|
||||||
|
end
|
||||||
|
|
||||||
it 'rejects request if one hostname is invalid' do
|
it 'rejects request if one hostname is invalid' do
|
||||||
authorize 'test', 'secret'
|
authorize 'test', 'secret'
|
||||||
|
|
||||||
@@ -120,6 +140,10 @@ describe Dyndnsd::Daemon do
|
|||||||
get '/nic/update?hostname=foo.example.org,notmyhost.example.org'
|
get '/nic/update?hostname=foo.example.org,notmyhost.example.org'
|
||||||
expect(last_response).to be_ok
|
expect(last_response).to be_ok
|
||||||
expect(last_response.body).to eq('nohost')
|
expect(last_response.body).to eq('nohost')
|
||||||
|
|
||||||
|
get '/nic/update?hostname=abc123-test3.example.org'
|
||||||
|
expect(last_response).to be_ok
|
||||||
|
expect(last_response.body).to eq('nohost')
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'updates a host on IP change' do
|
it 'updates a host on IP change' do
|
||||||
|
|||||||
Reference in New Issue
Block a user