Build your own DynDNS - Arkanis DevelopmentStuff about programming, technology, life… err… how about the universe?http://arkanis.de/weblog.xml2024-02-14T17:00:22+01:00Comment by SörenSörenhttp://arkanis.de/weblog/2015-11-27-build-your-own-dyndns#comment-2024-02-14-17-00-22-s%C3%B6ren2024-02-14T17:00:22+01:00
<p>Hi Stephan</p>
<p>I did not try to use TLS so far but I configured fail2ban for your mini DynDNS.</p>
<p>To do that, I run the ruby script as a service. With systemd on AlmaLinux 9 (or similar), create a file for the service:</p>
<pre><code># /etc/systemd/system/dyndns.service
[Unit]
Description=Service for Mini DynDNS
[Service]
User=root
# change 'var/dyndns' to the path where the dns.rb and related files live
WorkingDirectory=/var/dyndns
# change '/usr/bin/ruby' to path where the ruby interpreter is located
ExecStart=/usr/bin/ruby dns.rb
ExecReload=kill -USR1 $MAINPID
ExecStop=kill -INT $MAINPID
# change log files as desired (folder must exist)
StandardOutput=append:/var/log/dyndns/standard.log
StandardError=append:/var/log/dyndns/error.log
[Install]
WantedBy=multi-user.target</code></pre>
<p>Enable, start and check new service:</p>
<pre><code>systemctl enable dyndns
systemctl start dyndns
systemctl status dyndns</code></pre>
<p>I assume that fail2ban is already running. Create filter:</p>
<pre><code># /etc/fail2ban/filter.d/dyndns.conf
[Definition]
# don't forget to edit the ruby script to log host ip as well!
failregex = <HOST>.*not authorized</code></pre>
<p>Create a jail for dyndns:</p>
<pre><code># /etc/fail2ban/jail.d/dyndns.local
[dyndns] # this must match with the name of the service
enabled = true
banaction = iptables # ban is applied only for port defined below
filter = dyndns
# make sure the log path matches the set path in dyndns.service file
logpath = /var/log/dyndns/standard.log
# adjust port, in my case dyndns is running at port 8080
port = 8080
# remove following two lines to apply default settings
bantime = -1
maxretry = 1</code></pre>
<p>Adjust the jail as desired. In above example, having one valid request with wrong or missing authentication leads to a permanant ban of the host which requested your dyn dns. In my case there is no reason to be less restrictive because any user knows how to authenticate. And in other cases (mostly typos), I unblock them manually. This is maybe not applicable for (more) critical or bigger services. To extend the jail (e.g. to block hosts with bad request as well) you must adjust the filter (and the dns.rb to log host ip as shown next).</p>
<p>Last but not least, using the current version (1.4) of mini DynDNS requires to make little changes to get that jail working. Change at least the following line</p>
<pre><code># dns.rb (v1.4), line 617
log "#{log_prefix}: #{method} #{path_and_querystring} -> not authorized"</code></pre>
<p>to</p>
<pre><code>log "#{connection.peeraddr.last} #{log_prefix}: #{method} #{path_and_querystring} -> not authorized"
</code></pre>
<p>This is neccessary because fail2ban is reading the log files and is looking for all log entries matching the regular expression defined in the filter via failregex. When a match occurs, the given conditions will be checked (bantime, maxretry, findtime etc.) and actions (banaction, port etc.) are applied on matching host IP via iptables (or firewalld).</p>
<p>Don't forget to restart dyndns service to apply code changes with</p>
<pre><code>systemctl restart dyndns</code></pre>
<p>Because fail2ban is reading even older logs, it may occur that you ban yourself. You can undo this by</p>
<pre><code>fail2ban-client set dyndns unbanip <ip to unban></code></pre>
<p>To check how much bans were applied and to prove the jail is working, run</p>
<pre><code>fail2ban-client status dyndns</code></pre>
<p>See you
Sören</p>
Comment by StephanStephanhttp://arkanis.de/weblog/2015-11-27-build-your-own-dyndns#comment-2023-05-10-01-06-26-stephan2023-05-10T01:06:26+02:00
<p>Hi Sören,</p>
<p>Sorry it took me so long to reply. I've finally had some time and peace of mind to clean up all pending stuff of the project.</p>
<p>Using TLS is a pain and I've never tried it in minidyndns with anything other than self-signed certificates. In theory you can use Let's Encrypt certificates as long as the HTTPS server actually runs on the domain name specified in the certificate. But I doubt that it'll work with the certbot or any of the Let's Encrypt tools. minidyndns doesn't server static files so the certbot can't verify that you're the proper host.</p>
<p>Using a reverse proxy for HTTPS might be an easier way in the end. Especially if you already have an Apache or Nginx running on the server. Then this server can do the HTTPS part and just forward requests to minidyndns via plain old simple HTTP. I've just released v1.4.0 which also works behind a reverse proxy. So that might be worth a try.</p>
<p>Happy programming
Stephan</p>
Comment by SörenSörenhttp://arkanis.de/weblog/2015-11-27-build-your-own-dyndns#comment-2022-11-17-18-46-59-s%C3%B6ren2022-11-17T18:46:59+01:00
<p>Stephan, thank you very much for your effort bringing this nice MiniDynDNS on its way. I'm using it with Ruby 3.0.4 and it works well.</p>
<p>The only thing I didn't understand so far is, how to use it with TLS encryption. As far as I understood, I can use a certificate issued by Let's Encrypt but I'm wondering how this will work but I didn't try it so far. I will get started with a certificate for 'ns.mydomain.com' and will referr to this certificate in config.yml. Maybe I can get it running for self-signed certificates as well.</p>
<p>When you have any hints about that, I appreciate your comment.</p>
<p>Nevertheless, thank you very much for this tiny little helper!</p>
Comment by AnonymusAnonymushttp://arkanis.de/weblog/2015-11-27-build-your-own-dyndns#comment-2020-10-24-11-20-31-anonymus2020-10-24T11:20:31+02:00
<p>Hi Reza,</p>
<p>Oh, that made my previous reply sound rather silly, sorry about that. <span class="smiley grin">:D</span></p>
<p>With a static public IP you should have everything you need. But just to make sure I understand the setup: Does this public static IP lead diretly to your webserver or does your router use that IP and there is a port forwarding to the webserver?</p>
<p>The "bind: Cannot assign requested address" error itself happens if you try to start a server on an IP address that isn't assigned to the current system. This error would make sense to me in case your router uses that IP and the webserver is accessable via port forwarding. If so you'll have to tell MiniDynDNS to listen on the local IP address of the Pi:</p>
<pre><code>dns:
port: 53
ip: local-address-of-pi
http:
port: 80
ip: local-address-of-pi
https:
port: 443
ip: local-address-of-pi</code></pre>
<p>And configure some more port forwardings for UDP port 53 (DNS packets), TCP port 80 and 443 (the HTTP and HTTPS interfaces). You might want to change the HTTP and HTTPS ports though to not conflict with your webserver.</p>
<p>If your webserver diretly uses your public static IP I'm kind of baffled about the error. The only thing I can think of is to check what IPs are assigned to that system. Usually you can check this with the command "ip address show" or "ip a" for short. Your public static IP should be in there somewhere. If not there might be a configuration error on the system… or a simple typo somehere. Sorry I don't have any great ideas in that case. <span class="smiley unhappy">:(</span></p>
<p>Good luck
Stephan</p>
Comment by RezaRezahttp://arkanis.de/weblog/2015-11-27-build-your-own-dyndns#comment-2020-10-24-09-36-52-reza2020-10-24T09:36:52+02:00
<p>Oh hi. thanks for your answer.The 'mydomain.com' was a placeholder for not revealing my domain name so do "my public static ip":DI rented a domain and I have my own web server in my house with a static public ip.I have done everything that you said in your website and github, but the error that I wrote in your website before, appears.What did I do wrong and What should I do?</p>
<p>Happy programming to you too ;-)
Reza</p>
Comment by StephanStephanhttp://arkanis.de/weblog/2015-11-27-build-your-own-dyndns#comment-2020-10-22-15-27-02-stephan2020-10-22T15:27:02+02:00
<p>Hi Reza,</p>
<p>you can only run MiniDynDNS on a server that actually has a public static IP address. It'll serve as an address book for the rest of the world to look up your own subdomains. So it has to be directly reachable by the rest of the world. You get that with a virtual server rented from a webhosting company or a server in a data center. When you rent one of those they provide you with a public static IP address for the server and then you can run MiniDynDNS on that server.</p>
<p>"my public static ip" isn't supposed to be a placeholder but you should actually insert the IP address of your server there. Same goes for "mydomain.com", it's just a placeholder for your own domain (you'll also need to rent from a company).</p>
<p>Also IPs like 192.168.x.y or 10.x.y.z (where x, y and z are just some numbers) won't work. Those are private IPs, every private network (household, company, etc.) can use them for their devices. Meaning an IP like 192.168.0.1 will probably point to a different device in every household or company. Making that IP useless in the global internet because it doesn't identify a single target server.</p>
<p>From what you posted it doesn't look like you have the necessary infrastructure for MiniDynDNS. Sorry. <span class="smiley unhappy">:(</span></p>
<p>Happy programming
Stephan</p>
Comment by RezaRezahttp://arkanis.de/weblog/2015-11-27-build-your-own-dyndns#comment-2020-10-06-14-52-06-reza2020-10-06T14:52:06+02:00
<p>Hi there.
I'm trying to setup you miniddns on my pi server (ubuntu) and I have some issues that I can't solve and I hope that you can help me.
when I use ruby dns.rb this error apear:</p>
<p>dns.rb:646:in `bind': Cannot assign requested address - bind(2) for "my public static ip" port 53 (Errno::EADDRNOTAVAIL)</p>
<p>this is my config.yml:</p>
<p>domain: dyn.mydomain.com</p>
<p>dns:
port: 53
ip: my public static ip
http:
port: 80
ip: my public static ip
https:
port: 443
ip: my public static ip</p>
<p>and this is my db,mydomain.com.yml :</p>
<p>---
SERIAL: 2015110200
foo:
pass: oAKrrpozHCDRLyPp97T7umf648aiYQpL
A: 192.168.0.1
AAAA: ff80::1
user1:
pass: UjQFD9Vm3nU6uzn7GPDYeHt9xxRURid6
A: my public ip</p>
<p>user2: UjQFD9Vm3nU6uzn7GPDYeHt9xxRURid6
A: my local ip</p>
<p>when I take nslookup for user1.dyn.mydomain.com it says
** server can't find user1.dyn.mydomain.com: SERVFAIL
what should i do???</p>
<p>thank you
ra3320w@gmail.com</p>
Comment by StephanStephanhttp://arkanis.de/weblog/2015-11-27-build-your-own-dyndns#comment-2020-03-23-07-19-18-stephan2020-03-23T07:19:18+01:00
<p>Hi DaNiel L,</p>
<p>thanks for giving it a try. I'm not sure what the Bind config does but MiniDynDNS doesn't implement any kind of transfer protocol or record replication… just in case that's what you're trying to do.</p>
<p>From what I understand you're running MiniDynDNS on a server with the IP 10.253.254.9 at port 53. The rest isn't quite clear to me so I'll try to write what config should work:</p>
<p>a) The domain dnslocal1.universidad.edu.ec has to point to the server running MiniDynDNS. Meaning in the universidad.edu.ec zone there should be a record like this:</p>
<pre><code>dnslocal1 A 10.253.254.9</code></pre>
<p>That's the record outsiders will use to actually find your MiniDynDNS.</p>
<p>b) The universidad.edu.ec zone needs to delegate the "dyn" subdomain to your MiniDynDNS server. That is done with an NS record in the universidad.edu.ec zone. Together with the above record the universidad.edu.ec zone should contain something like that:</p>
<pre><code>dyn NS dnslocal1.universidad.edu.ec
dnslocal1 A 10.253.254.9</code></pre>
<p>The first record tells outsiders that everything in dyn.universidad.edu.ec is managed by the nameserver dnslocal1.universidad.edu.ec. And through the second record they know that this server has the IP 10.253.254.9. Thanks to that they know where to send the DNS request packets to.</p>
<p>As far as I can tell that should be it. Note that you only have to add the above two records to the universidad.edu.ec zone. You don't need to create the dyn.universidad.edu.ec zone I think.</p>
<p>The records of your MiniDynDNS should be available as foo.dyn.universidad.edu.ec, bar.dyn.universidad.edu.ec and so on.</p>
<p>Give it a try and let me know if that hepled. <span class="smiley smile">:)</span></p>
<p>Happy programming
Stephan</p>
Comment by DaNiel LDaNiel Lhttp://arkanis.de/weblog/2015-11-27-build-your-own-dyndns#comment-2020-03-19-04-11-43-daniel-l2020-03-19T04:11:43+01:00
<p>Hi, Stephan.
I Have a domain "universidad.edu.ec" problem when I try to delegate. dyn.universidad.edu.ec (10.253.254.9) to my miniDyndns
My SOA is for example universidad.edu.ec with NS dnslocal1.universidad.edu.ec
and this is the conf for bind slave zone
zone "dyn.universidad.edu.ec" {
type slave;
masters { 10.253.254.9; };
file "/var/named/internal/dyn.uleam.edu.ec.slave";
};
If I use the miniDynDNS directly i can resolve without problems, but when i try to sync with SOA the slave show this error:
18-Mar-2020 18:46:48.430 xfer-in: error: transfer of 'dyn.universidad.edu.ec/IN/internal' from 10.253.254.9#53: failed to connect: connection refused
MY SOA is slave from another Bind NS and dont have the same problems
in my config.yml I Have this lines</p>
<p>domain: dyn.uleam.edu.ec
soa:
nameserver: dnslocal1.universidad.edu.ec
mail: hostmaster@universidad.edu.ec</p>
<p>Any Solution ?</p>
<p>Sorry my bad English <span class="smiley smile">:)</span>
Best Regards,</p>
Comment by StephanStephanhttp://arkanis.de/weblog/2015-11-27-build-your-own-dyndns#comment-2019-07-11-19-18-35-stephan2019-07-11T19:18:35+02:00
<p>Hi Rick,</p>
<p>Sorry that the reply took a while. I just came back from vacation. The bug is fixed in the new v1.3.1. It's enough to just download and replace dns.rb (<a href="https://github.com/arkanis/minidyndns/blob/master/dns.rb">https://github.com/arkanis/minidyndns/blob/master/dns.rb</a>).</p>
<p>Turned out the certificates were all right. The problem was caused by looking up the IP address of the connection if none was specified in the URL. This worked for HTTP but not for HTTPS. OpenSSL asks the TCP socket to do this job but doesn't pass along any parameters to peeraddr(). That is where the error came from. I found a way around that and it's now covered by a test case. Thanks for the log snippet you posted. It really helped a lot! <span class="smiley smile">:)</span></p>
<p>Happy programming
Stephan</p>
<p>P.S. The theme changes every day depending on the time. Just some quirky habit I caught for my personal website project. <span class="smiley grin">:D</span> You can change it with the style switcher at the top of the page if the afternoon theme gets to exhausting to read (I'm not quite happy with the usability of it…).</p>