mario-campos / dyndnsd Goto Github PK
View Code? Open in Web Editor NEWDynamic DNS Daemon for OpenBSD
Home Page: https://mario-campos.github.io/software/dyndnsd
License: BSD 3-Clause "New" or "Revised" License
Dynamic DNS Daemon for OpenBSD
Home Page: https://mario-campos.github.io/software/dyndnsd
License: BSD 3-Clause "New" or "Revised" License
This feature would make more sense if dyndnsd
were not typically run as a daemon. In other words, if it were run by a normal user account, then it might make more sense to utilize $SHELL
. But, as the primary way to run this will be as a daemon, the daemon likely won't have an exotic $SHELL
.
Plus, it simplifies the code and removes a branch.
Some DNS providers don't utilize the fully-qualified domain name, like most that use the dyndns2 protocol. Namecheap, for example, require the hostname, and the domain name, as two separate query parameters.
For this reason, I think the variables should be as such:
$fqdn
: the fully-qualified domain name (e.g. www.example.com)
$hostname
: the name of the host in the FQDN (e.g. www)
$domain
: the name of the domain in the FQDN (e.g. example.com)
$tld
: the top-level domain (e.g. com)
Here's an example configuration sample:
interface em0 {
domain www.example.com
http-get https://dynamicdns.park-your-domain.com/update?host=$hostname&domain=$domain&password=[ddns_password]&ip=$ip_address
}
Unfortunately, the dyndns2 protocol does not use the HTTP status codes for error handling. It seems that most implementations use some sort of error keyword in the body of the response. It seems that the best, most-generic way to handle errors will be to parse the first line of text, whether that be in HTML or not.
Example:
iface0=em0
domain0=github.io
command_to_run="curl https://www.google.com"
interface $iface0 {
domain ${domain0}
run $command_to_run
}
Because these macros would follow the same syntax as environment-variable interpolation in the run
string, it's best not to allow them to mingle, otherwise things could get messy (code-wise) and confusing (reading-wise). So, macros will be an alternative to the STRING
/STRINGS
tokens. Macros will not be evaluated inside STRING
/STRINGS
tokens:
command-to-run=echo $DYNDNSD_IFACE
interface em0 {
domain example.com
run $command_to_run
}
dyndnsd
should be able to log (via syslog(3)
) a successful request. The format may be something like this:
em0 1.2.3.4 https://foo:[email protected]/some/path?myip=1.2.3.4&hostname=foo.example.com 200
em0 5.6.7.8 https://foo:[email protected]/some/path?myip=5.6.7.8&hostname=foo.example.com 500
em0 5.6.7.8 https://foo:[email protected]/some/path?myip=5.6.7.8&hostname=foo.example.com 200
The URL in the log file should be HTTP-encoded.
I have reservations about including the credentials in the log, but removing them would require more parsing code. What to do...
Use a testing suite, using testing tools such as NetBSD's Automated Testing Framework (ATF), cmocka, and cwrap.
The problem with testing network applications has been how to test/mock system calls, that don't really do any business logic. That's where cwrap comes in. It will wrap system calls to be able to mock it and test it. Now it should be possible to obtain a thorough test suite.
Unix daemons typically support the convention of reloading their configuration file by receiving a SIGHUP
signal.
Rather than use one of the signal system calls, I'd like to take this as an opportunity to learn and implement kqueue(2)
. It won't be as portable—won't work on Linux—but it should be cleaner, more readable, and more reliable than using the self-pipe trick.
This is a good 'insanity test', to verify that the configuration settings are correct when running. Furthermore, it helps for troubleshooting if the program's log statements are ever copied/pasted. Obviously, nothing sensitive, such as usernames and passwords, should be logged.
Currently, dyndnsd
is polling the system every 60 seconds for its interfaces. This poll shouldn't be taxing, but it is largely unnecessary and inefficient, given that DHCP interfaces tend to hold onto their leased IP addresses for very long times.
Instead of this, I'd like to implement the route(4) socket, which can "listen" for interface-related "events" and act on them in a event-driven manner. This—having the kernel tell you when an interface has changed its IP address—would be much more efficient than asking the kernel every minute.
dyndnsd
might need two calls to pledge(2). The first one is called immediately upon execution, to initially sandbox dyndnsd
. Once dyndnsd
completes its initialization and calls fork(2), then it may call pledge(2) again, to tighten the sandbox even more.
However, two calls won't be necessary if the second call to pledge(2) does not tighten the sandbox (i.e. reduce the number of promises).
Hello,
I would like to discuss about the feasibility of adopting the famous "three processes" model which is used for lots of OpenBSD services.
I'm not a developper, but if I understand correctly, the benefit of this model is having three specialized processes that you can very easily restrict with pledge/unveil, while with a single thread that does everything, you have to do some compromises for it to work correctly.
Here is a skeleton example of an OpenBSD daemon for reference.
Instead of custom make file
User input should not cause the program to segfault or crash in any unexpected way.
I was trying to build this on 6.7, but there is an error:
gate# uname -a
OpenBSD gate.lan 6.7 GENERIC.MP#edfc13b amd64
gate# pwd
/tmp/dyndnsd
gate# doas -u nobody make CONF_PATH=/etc/dyndnsd.conf USER=nobody GROUP=nobody
cc -O2 -pipe -std=c99 -MD -MP -DDYNDNSD_CONF_PATH=\"/etc/dyndnsd.conf\" -DDYNDNSD_USER=\"nobody\" -DDYNDNSD_GROUP=\"nobody\" -c cst.c
cst.c:8:10: fatal error: 'y.tab.h' file not found
#include "y.tab.h"
^~~~~~~~~
1 error generated.
*** Error 1 in /tmp/dyndnsd (<sys.mk>:87 'cst.o')
The most recent OpenBSD vulnerablity report mentions that certain applications were abused by the fact that they did not verify the owner of configuration files:
If the S/Key or YubiKey authentication type is enabled (they are both
installed by default but disabled), then a local attacker can exploit
the privileges of the group "auth" to obtain the full privileges of the
user "root" (because login_skey and login_yubikey do not verify that the
files in /etc/skey and /var/db/yubikey belong to the correct user, and
these directories are both writable by the group "auth").
dyndnsd
should print a warning (probably early enough to be included in -n
) if dynsnd.conf is not owned by dyndnsd
's UID.dyndnsd
should print a warning (probably early enough to be included in -n
) if dynsnd.conf is readable by "other."dyndnsd
should print a warning (probably early enough to be included in -n
) if dynsnd.conf is executable.Implement a Recursive Descent Parser rather than use Yacc/Lex. It may be more work, but it will allow more fine-grain control over the code, and the ability to eliminate warnings/bugs where one might not otherwise be able to.
Use libevent instead of hardcoding kqueue(2) calls.
Like in System Administration, hard memory-allocation limits (defaults) should be set for this, in such a way that they're configurable in the build process. I'm thinking having Meson define a limits.h
file, or a defaults.h
file. Basically, any memory allocation currently using a magic number should instead using a #define
in this file.
These system calls allow you to pass in an environment, meaning you no longer have to explicitly set environment variables prior to calling exec
.
And use CUnit.
I'd like to be able to organize my source files into a src
folder, as well as the test.c
file into a test
folder. However, this breaks the default Lex rule in make
. It would also be nice to have a build
directory. Either way, this means more custom rules to the makefile
.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.