├── .github └── workflows │ └── gotest.yml ├── .gitignore ├── .gitmodules ├── .vscode ├── extensions.json └── settings.json ├── LICENSE ├── README.md ├── bind9 ├── Makefile ├── README.md ├── ansible │ ├── Makefile │ ├── ansible.cfg │ ├── hosts.yml │ ├── roles │ │ └── sig0namectl │ │ │ └── tasks │ │ │ ├── install.yml │ │ │ └── main.yml │ └── sig0namectl.yml ├── start.sh └── terraform │ ├── Makefile │ ├── ansible-ssh-keygen.sh │ ├── cloud_init.cfg.tmpl │ ├── main.tf │ └── terraform.tfvars ├── demo ├── .gitignore ├── DNS-SD browser notes.md ├── JsUI.md ├── map │ ├── README.md │ ├── dohjs_helpers.js │ ├── map.html │ └── map.js └── playground │ ├── Makefile │ ├── README.md │ ├── dns.js │ ├── domain_manager.css │ ├── domain_manager.html │ ├── domain_manager.js │ ├── domains.js │ ├── fontawesome │ ├── LICENSE.txt │ ├── css │ │ ├── fontawesome.min.css │ │ ├── regular.min.css │ │ └── solid.min.css │ └── webfonts │ │ ├── fa-regular-400.ttf │ │ ├── fa-regular-400.woff2 │ │ ├── fa-solid-900.ttf │ │ └── fa-solid-900.woff2 │ ├── go.work │ ├── keys.js │ ├── play.css │ ├── play.html │ ├── sd.css │ ├── sd_inspector.html │ ├── sd_inspector.js │ ├── services.js │ ├── sig0.css │ ├── sig0.js │ ├── sig0_wasm.js │ └── wasm_exec.html ├── dnssd-domain ├── dnssd-service ├── docs ├── CNAME ├── DNS-SD Introduction.md ├── index.md ├── sig0namectl Dynamic DNSSEC Server Zone Configuration.md └── sig0namectl Key Management.md ├── dyn_ip ├── dyn_key ├── dyn_loc ├── dyn_txt ├── env ├── env.dnssd-service ├── functions ├── 10-set_vars.sh ├── get_loc.sh ├── get_sig0_keyid.sh ├── get_soa.sh ├── send_nsupdate.sh ├── validateIP.sh └── validateKEY.sh ├── golang ├── .gitignore ├── Makefile ├── cmd │ └── sig0namectl │ │ ├── cli.go │ │ ├── keys.go │ │ ├── query.go │ │ └── update.go ├── env ├── go.mod ├── go.sum ├── notes ├── sig0 │ ├── answers.go │ ├── doh.go │ ├── doh_test.go │ ├── keys.go │ ├── keys_nowasm.go │ ├── keys_test.go │ ├── keys_wasm.go │ ├── query.go │ ├── query_test.go │ ├── request_key.go │ ├── request_key_test.go │ ├── update.go │ └── update_test.go └── wasm │ ├── Makefile │ ├── README.md │ ├── pure.js │ ├── wasm_exec.html │ ├── wasm_exec.js │ └── wrapper_js.go ├── keystore └── .keep ├── presentations ├── 20230815 CCCamp 2023 To Name is to Own.odp ├── 20230815 CCCamp 2023 To Name is to Own.pdf ├── 20230824 Draft Improved Presentation.odp ├── 20230824 Draft Improved Presentation.pdf ├── 20240501 Freifunk Berlin May meeting Presentation.pdf ├── 20240525 P4P Unconference at offline-space.odp └── 20241211 splintercon sig0namectl 16-9 v3.7.pdf ├── process_requests ├── request_key ├── start_loc_loop.sh └── start_process_requests_loop.sh /.github/workflows/gotest.yml: -------------------------------------------------------------------------------- 1 | name: "test" 2 | 3 | on: [push] 4 | 5 | jobs: 6 | gotest: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: Checkout 10 | uses: actions/checkout@v4 11 | - name: Set up Go 12 | uses: actions/setup-go@v5 13 | with: 14 | go-version: 1.22 15 | - name: update apt pkgs 16 | run: sudo apt-get update 17 | - name: install bind9 utilities 18 | run: sudo apt-get install bind9utils 19 | - name: Run tests 20 | run: go test -v ./... 21 | working-directory: ./golang 22 | - name: Check CLI compilation 23 | run: go build 24 | working-directory: ./golang/cmd/sig0namectl 25 | - name: Check WASM compilation 26 | run: GOOS=js GOARCH=wasm go build -o test.wasm 27 | working-directory: ./golang/wasm 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | flake.nix 2 | flake.lock 3 | # exclude everything 4 | keystore/* 5 | # terraform 6 | bind9/terraform/cloud_init.cfg 7 | bind9/terraform/terraform.tfstate* 8 | bind9/terraform/.terraform.lock.hcl 9 | bind9/terraform/.terraform/ 10 | # ansible 11 | bind9/ansible/ansible_ssh_key* 12 | # exceptions to the rule 13 | !keystore/.keep 14 | !zones/.keep 15 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "bind9/ansible/roles/bind9"] 2 | path = bind9/ansible/roles/bind9 3 | url = https://github.com/adam-burns/ansible-role-bind.git 4 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "standard.vscode-standard" 4 | ] 5 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cSpell.words": [ 3 | "dnssec", 4 | "keypair", 5 | "Nameserver", 6 | "rrsig", 7 | "sig0namectl", 8 | "wireformat" 9 | ], 10 | 11 | "javascript.format.enable": false, 12 | "javascript.validate.enable": false, 13 | "standard.enable": true, 14 | "standard.autoFixOnSave": true, 15 | "[javascript]": { 16 | "editor.formatOnSave": true, 17 | }, 18 | 19 | "[css]": { 20 | "editor.formatOnSave": true 21 | } 22 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
7 | to name is to own 8 |
9 | 10 |Request a new domain:
74 | 91 |104 | Import all sig0namectl keys in a folder into this manager. 105 | Select the folder containing the keys on your device. 106 | The keys will be stored in the local cache of this browser. 107 |
108 | 109 |112 | Export all your keys from this manager. 113 | This creates a ZIP file backup of all your keys. When unzipped, the keys can be imported for use in other browsers and devices. 114 |
115 | 116 |133 | Create a discoverable `http` DNS service. 134 | This service is a link to a web page. 135 |
136 | 143 | 164 |
168 | Congratulation! Your service has been successfully published.
169 | Inspect your services with the Service Inspector
170 |
97 | 98 | 99 |
100 | 101 | 102 | -------------------------------------------------------------------------------- /dnssd-domain: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Sends DNS-SD updates for domain browsing setup 4 | #------------------------------------------------------------------------------ 5 | 6 | 7 | # load helpful functions 8 | for i in functions/*.sh 9 | do 10 | . ${i} 11 | [[ -n ${DEBUG_SET_VARS} ]] && echo "Sourced ${PWD}/$i ..." 12 | done 13 | 14 | set_vars $* 15 | 16 | #------------------------------------------------------------------------------ 17 | # test 18 | 19 | NEW_SUBZONE=${NEW_SUBZONE:-""} 20 | 21 | # select zone or subdomain within zone 22 | if [[ -n ${NEW_SUBZONE} ]]; then 23 | DNSSD_DOMAIN="${NEW_SUBZONE}.${ZONE}" 24 | else 25 | DNSSD_DOMAIN="${ZONE}" 26 | fi 27 | 28 | NSUPDATE_AUTH_SIG0_KEY_FQDN=${NSUPDATE_AUTH_SIG0_KEY_FQDN:-${DNSSD_DOMAIN}} 29 | 30 | # define default update add 31 | NSUPDATE_ACTION=${NSUPDATE_ACTION:-"add"} 32 | NSUPDATE_TTL="600" 33 | 34 | for word in lb b db r dr 35 | do 36 | # echo "***** DEBUG: ZONE = '${ZONE}' NEW_SUBZONE='${NEW_SUBZONE}' NEW_FQDN='${NEW_FQDN}'" 37 | case ${NSUPDATE_ACTION} in 38 | add) 39 | NSUPDATE_PRECONDITION_SET="nxrrset" 40 | NSUPDATE_PRECONDITION="prereq ${NSUPDATE_PRECONDITION_SET} ${word}._dns-sd._udp.${DNSSD_DOMAIN}. IN PTR" 41 | NSUPDATE_ITEM_RR="update ${NSUPDATE_ACTION} ${word}._dns-sd._udp.${DNSSD_DOMAIN} ${NSUPDATE_TTL} PTR ${DNSSD_DOMAIN}." 42 | send_nsupdate "${DNSSD_DOMAIN}" "$(echo ${NSUPDATE_PRECONDITION};echo ${NSUPDATE_ITEM_RR})" "${NSUPDATE_AUTH_SIG0_KEY_FQDN}" 43 | ;; 44 | delete) 45 | NSUPDATE_PRECONDITION_SET="yxrrset" 46 | NSUPDATE_PRECONDITION="prereq ${NSUPDATE_PRECONDITION_SET} ${word}._dns-sd._udp.${DNSSD_DOMAIN}. IN PTR" 47 | NSUPDATE_ITEM_RR="update ${NSUPDATE_ACTION} ${word}._dns-sd._udp.${DNSSD_DOMAIN} ${NSUPDATE_TTL} PTR ${DNSSD_DOMAIN}." 48 | send_nsupdate "${DNSSD_DOMAIN}" "$(echo ${NSUPDATE_PRECONDITION};echo ${NSUPDATE_ITEM_RR})" "${NSUPDATE_AUTH_SIG0_KEY_FQDN}" 49 | ;; 50 | *) 51 | # NSUPDATE_ACTION should default to "add" - should never get here 52 | echo "Error: NSUPDATE_ACTION is set to '${NSUPDATE_ACTION}', but must be set to 'add' or 'delete'." 53 | exit 1 54 | ;; 55 | esac 56 | DIG_QUERY_PARAM="@${ZONE_SOA_MASTER} +short" 57 | [[ -n ${DEBUG} ]] && echo "dig @${ZONE_SOA_MASTER} PTR ${word}._dns-sd._udp.${DNSSD_DOMAIN}. '$( dig ${DIG_QUERY_PARAM} PTR ${word}._dns-sd._udp.${DNSSD_DOMAIN}. )'" 58 | done 59 | -------------------------------------------------------------------------------- /dnssd-service: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Sends DNS-DS updates for dns-ds service registration and browsing records 4 | #------------------------------------------------------------------------------ 5 | # 6 | # load helpful functions 7 | for i in functions/*.sh 8 | do 9 | . ${i} 10 | [[ -n ${DEBUG} ]] && echo "Sourced ${PWD}/functions/$i ..." 11 | done 12 | 13 | set_vars $* 14 | 15 | #------------------------------------------------------------------------------ 16 | # test 17 | 18 | NEW_SUBZONE=${NEW_SUBZONE:-""} 19 | 20 | # select zone or subdomain within zone 21 | if [[ -n ${NEW_SUBZONE} ]]; then 22 | DNSSD_DOMAIN="${NEW_SUBZONE}.${ZONE}" 23 | else 24 | DNSSD_DOMAIN="${ZONE}" 25 | fi 26 | 27 | DNSSD_SERVICES=${DNSSD_SERVICES:-""} 28 | if [[ ! -n ${DNSSD_SERVICES} ]]; then 29 | echo "Error: DNSSD SERVICES services \$DNSSD_SERVICES environment variable is not set. No services have been defined to browse in domain ${DNSSD_SERVICES}" 30 | exit 1 31 | fi 32 | 33 | NSUPDATE_AUTH_SIG0_KEY_FQDN=${NSUPDATE_AUTH_SIG0_KEY_FQDN:-${DNSSD_DOMAIN}} 34 | 35 | # define default update add & ttl 36 | NSUPDATE_ACTION=${NSUPDATE_ACTION:-"add"} 37 | NSUPDATE_TTL=${NSUPDATE_TTL:-"60"} 38 | 39 | for service in ${DNSSD_SERVICES} 40 | do 41 | case ${NSUPDATE_ACTION} in 42 | add) 43 | NSUPDATE_PRECONDITION_SET="nxrrset" 44 | NSUPDATE_ITEMS="${NSUPDATE_ITEMS}check-names off\n" 45 | # service type browsing instance pointer 46 | NSUPDATE_ITEMS="${NSUPDATE_ITEMS}update ${NSUPDATE_ACTION} _services._dns-sd._udp.${DNSSD_DOMAIN} ${NSUPDATE_TTL} PTR ${service}.${DNSSD_DOMAIN}.\n" 47 | # service instance of service to browse 48 | NSUPDATE_ITEMS="${NSUPDATE_ITEMS}update ${NSUPDATE_ACTION} ${service}.${DNSSD_DOMAIN} ${NSUPDATE_TTL} PTR ${NEW_SUBZONE}.${service}.${DNSSD_DOMAIN}.\n" 49 | # service SRV record example 50 | NSUPDATE_ITEMS="${NSUPDATE_ITEMS}update ${NSUPDATE_ACTION} ${NEW_SUBZONE}.${service}.${DNSSD_DOMAIN} ${NSUPDATE_TTL} SRV 0 0 80 ${DNSSD_DOMAIN}.\n" 51 | # service TXT record example 52 | NSUPDATE_ITEMS="${NSUPDATE_ITEMS}update ${NSUPDATE_ACTION} ${NEW_SUBZONE}.${service}.${DNSSD_DOMAIN} ${NSUPDATE_TTL} TXT comment=Hello_this_is_a_${service}_service_instance\n" 53 | send_nsupdate "${DNSSD_DOMAIN}" "$(echo ${NSUPDATE_PRECONDITION};echo -e ${NSUPDATE_ITEMS})" "${NSUPDATE_AUTH_SIG0_KEY_FQDN}" 54 | ;; 55 | delete) 56 | NSUPDATE_PRECONDITION_SET="yxrrset" 57 | # service type browsing instance pointer 58 | NSUPDATE_ITEMS="${NSUPDATE_ITEMS}update ${NSUPDATE_ACTION} _services._dns-sd._udp.${DNSSD_DOMAIN} ${NSUPDATE_TTL} PTR ${service}.${DNSSD_DOMAIN}.\n" 59 | # service instance of service to browse 60 | NSUPDATE_ITEMS="${NSUPDATE_ITEMS}update ${NSUPDATE_ACTION} ${service}.${DNSSD_DOMAIN} ${NSUPDATE_TTL} PTR ${NEW_SUBZONE}.${service}.${DNSSD_DOMAIN}.\n" 61 | # service SRV record example 62 | NSUPDATE_ITEMS="${NSUPDATE_ITEMS}update ${NSUPDATE_ACTION} ${NEW_SUBZONE}.${service}.${DNSSD_DOMAIN} ${NSUPDATE_TTL} SRV 0 0 80 ${DNSSD_DOMAIN}.\n" 63 | # service TXT record example 64 | NSUPDATE_ITEMS="${NSUPDATE_ITEMS}update ${NSUPDATE_ACTION} ${NEW_SUBZONE}.${service}.${DNSSD_DOMAIN} ${NSUPDATE_TTL} TXT comment=Hello_this_is_a_${service}_service_instance\n" 65 | send_nsupdate "${DNSSD_DOMAIN}" "$(echo ${NSUPDATE_PRECONDITION};echo -e ${NSUPDATE_ITEMS})" "${NSUPDATE_AUTH_SIG0_KEY_FQDN}" 66 | ;; 67 | *) 68 | # NSUPDATE_ACTION should default to "add" - should never get here 69 | echo "Error: NSUPDATE_ACTION is set to '${NSUPDATE_ACTION}', but must be set to 'add' or 'delete'." 70 | exit 1 71 | ;; 72 | esac 73 | done 74 | 75 | if [[ -n ${DEBUG} ]]; then 76 | echo "---DEBUG" 77 | echo "SCRIPT_NAME = ${SCRIPT_NAME}" 78 | echo "ZONE = ${ZONE}" 79 | echo "DIG_QUERY_PARAM = ${DIG_QUERY_PARAM}" 80 | echo "DNSSD_DOMAIN = ${DNSSD_DOMAIN}" 81 | echo "ZONE_SOA_MASTER = ${ZONE_SOA_MASTER}" 82 | echo "NSUPDATE_SIG0_KEYID = ${NSUPDATE_SIG0_KEYID}" 83 | echo 84 | echo "DEBUG: nsupdate settings" 85 | echo " NSUPDATE_PARAM = ${NSUPDATE_PARAM}" 86 | echo " NSUPDATE_SET_SERVER = ${NSUPDATE_SET_SERVER}" 87 | echo " NSUPDATE_ACTION = ${NSUPDATE_ACTION}" 88 | echo " NSUPDATE_PRECONDITION_SET = ${NSUPDATE_PRECONDITION_SET} (not implemented for ${SCRIPT_NAME})" 89 | echo 90 | echo "DEBUG: nsupdate commands to send" 91 | echo 92 | echo "NSUPDATE_SET_SERVER = ${NSUPDATE_SET_SERVER}" 93 | echo "-- NSUPDATE_ITEMS" 94 | echo -e "${NSUPDATE_ITEMS}" 95 | echo "--" 96 | fi 97 | 98 | if [[ -n ${DEBUG} ]]; then 99 | echo 100 | echo "Browsable services via dig ${DIG_QUERY_PARAM} +short _services._dns-sd._udp.${DNSSD_DOMAIN} PTR" 101 | dig ${DIG_QUERY_PARAM} +short _services._dns-sd._udp.${DNSSD_DOMAIN} PTR 102 | echo 103 | echo "Browsable services type instances via dig" 104 | for SERVICE in ${DNSSD_SERVICES} 105 | do 106 | echo "* ${SERVICE}: dig ${DIG_QUERY_PARAM} +short ${SERVICE}.${DNSSD_DOMAIN} PTR" 107 | dig ${DIG_QUERY_PARAM} +short ${SERVICE}.${DNSSD_DOMAIN} PTR 108 | done 109 | echo 110 | AVAHI_BROWSE=${AVAHI_BROWSE:-"avahi-browse"} 111 | echo "Browsable services via ${AVAHI_BROWSE} ${AVAHI_BROWSE_PARAM} -d ${DNSSD_DOMAIN}" 112 | ${AVAHI_BROWSE} ${AVAHI_BROWSE_PARAM} -d ${DNSSD_DOMAIN} 113 | fi 114 | -------------------------------------------------------------------------------- /docs/CNAME: -------------------------------------------------------------------------------- 1 | sig0namectl.networkcommons.org 2 | -------------------------------------------------------------------------------- /docs/DNS-SD Introduction.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Service Discovery Browsing and Registration Domains 4 | 5 | To enable clients to discover and browse services registered under a domain, the following PTR resource records are required. 6 | 7 | ``` 8 | $ORIGIN example.com 9 | ; 10 | ; Add PTR records to indicate browsing and registering domains 11 | b._dns-sd._udp IN PTR @ ; "b" = browse domain 12 | db._dns-sd._udp IN PTR @ ; "db" = default browse domain 13 | lb._dns-sd._udp IN PTR @ ; "lb" = legacy browse domain 14 | r._dns-sd._udp IN PTR @ ; "r" = registration domain 15 | dr._dns-sd._udp IN PTR @ ; "dr" = default registration domain 16 | ``` 17 | 18 | ## Browsing Service Types 19 | 20 | In order to browse the service types offered within a domain, PTR records are required. Service types are listed as PTR records in `_services._dns-sd._udp` traditionally of the form `_[service]._[protocol]`. 21 | 22 | 23 | ``` 24 | $ORIGIN example.com 25 | ; 26 | ; For each browse/register domain, add PTR records to indicate the available service types that can be browsed/registered. 27 | 28 | _services._dns-sd._udp IN PTR _http._tcp 29 | _services._dns-sd._udp IN PTR _ftp._tcp 30 | ... 31 | ``` 32 | 33 | ## Service Instance Lists 34 | 35 | For each service type, there multiple service instances can be registered, for instance: 36 | 37 | ``` 38 | $ORIGIN example.com 39 | ; 40 | ; For each service type, add PTR records to indicate a list of service instances of that service type. 41 | 42 | _http._tcp IN PTR zembla._http._tcp ; zembla's web server 43 | _http._tcp IN PTR math._http._tcp ; mathias' web server 44 | _http._tcp IN PTR \032*\032SlashDot,\032News\032for\032Nerds._http._tcp ; external web server 45 | _http._tcp IN PTR freifunk.net 46 | ... 47 | _ftp._tcp IN PTR zembla._ftp._tcp 48 | ... 49 | ``` 50 | 51 | ## Service Resolution & Connection Details 52 | 53 | Finally to allow clients to resolve and connect to each service instance SRV and TXT records are used to indicate host and port number (SRV) as well as other properties (TXT) required for machine connection configuration and human readable service entries: 54 | 55 | ``` 56 | zembla._http._tcp IN SRV 0 0 80 zembla.zenr.io. 57 | \032*\032SlashDot,\032News\032for\032Nerds._http._tcp IN SRV 0 0 80 slashdot.com. 58 | ... 59 | ``` 60 | Note SRV targets should resolve to at least one IPv4 or IPv6 address. 61 | 62 | ## Custom Service Types 63 | 64 | For custom service types other DNS RR may be added, but are not defined within current standards (such as LOC for GPS position points, etc). 65 | 66 | ## Compatibility with existing DNS-SD stacks 67 | 68 | For the avahi DNS-SD stack to successfully resolve a service, 69 | - at least one SRV record and one TXT record must be present for each service instance 70 | - service types must be defined as at least a pair of underscored labels (single underscored labels do not work) 71 | - the closest to root label must be either \_udp or \_tcp 72 | - the SRV target must resolve to a IPv4 or IPv6 address, if not, service resolution fails 73 | 74 | ## Further Resources 75 | 76 | - [RFC 6763](https://www.rfc-editor.org/rfc/rfc6763) 77 | - [Service Discovery for IP Applications](https://datatracker.ietf.org/meeting/106/materials/slides-106-edu-sessf-service-discovery-for-ip-applications-00.pdf), Dr Stuart Cheshire, IETF 106, Singapore, Sunday 17th November 2019 78 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | ../README.md -------------------------------------------------------------------------------- /docs/sig0namectl Dynamic DNSSEC Server Zone Configuration.md: -------------------------------------------------------------------------------- 1 | # sig0namectl 2 | 3 | ## DNSSEC Zone configuration for primary DNS servers 4 | 5 | ### DNSSEC 6 | 7 | DNSSEC must be enabled in all parent zones. 8 | 9 | In a primary authorative BIND9 DNS server zone configuration, this can be enabled, for example, the following enables DNSSEC in the **`zenr.io`** zone : 10 | 11 | type master; 12 | file "dynamic/zenr.io/named.zenr.io"; 13 | key-directory "dynamic/zenr.io"; 14 | auto-dnssec maintain; 15 | 16 | 17 | ### Dynamic zone update policy configuration 18 | 19 | Each dynamic DNSSEC update zone to be managed by sig0namectl must have at least one (or more) KEY resource records that are granted update permissions for within that dynamic zone. 20 | 21 | 22 | In a primary authorative BIND9 DNS server zone configuration, this can be enabled. for example, the following allows updates for **`zenr.io`** zone using: 23 | 24 | Firstly, an initial zone management keypair with the label **`vortex.zenr.io`** is generated by invoking 25 | 26 | ./register_key vortex.zenr.io 27 | 28 | (or using dnssec-keygen directly) and the contents of the public key file is copied into a corresponding KEY RR into the `zenr.io` zonefile. 29 | 30 | Secondly, a dynamic DNSSEC update policy is applied to the `zenr.io` zone configuration 31 | 32 | update-policy { 33 | grant "vortex.zenr.io" name zenr.io. ANY; 34 | grant "vortex.zenr.io" subdomain zenr.io. ANY; 35 | grant * selfsub . ANY; 36 | }; 37 | 38 | A BIND DNS server authenticates signed update requests only for SIG(0) KEY RRs in zones for which it is authoritative. 39 | 40 | 41 | ### Dynamic Subzone for named key registration requests 42 | 43 | A subzone with dynamic DNS is configured to allow clients to submit named key requests below the zone. The default subzone registration policy is to allow all registration requests for any new label with **no existing resource records of any type**. This default registration policy is also known as "First Come, First Served". 44 | 45 | sig0namectl uses the environment variable `SIGNAL_SUBZONE` to define the subzone where name requests are managed. It can be set though configuration files or overriden on command line invocation. 46 | 47 | Default value in **`env`** configuation file: 48 | 49 | `SIGNAL_SUBZONE="_signal"` 50 | 51 | Zone keys allow for a scripted policy to be applied to name requests placed in this 'holding zone'. If the policy is successful, the zone key is used with `nsupdate` to update the parent zone of **`${SIGNAL_SUBZONE}`** with the requested named KEY resource record (the FQDN without the `${SIGNAL_SUBZONE}` label). 52 | 53 | -------------------------------------------------------------------------------- /docs/sig0namectl Key Management.md: -------------------------------------------------------------------------------- 1 | # sig0namectl 2 | 3 | ## Keypair Generation 4 | 5 | From man page of `dnssec-keygen`: 6 | 7 | > When `dnssec-keygen` completes successfully, it prints a string of the form `Knnnn.+aaa+iiiii` to the standard output. This is an identification string for the key it has generated. 8 | > * nnnn is the key name. 9 | > * aaa is the numeric representation of the algorithm. 10 | > * *iiiii is the key identifier (or footprint). 11 | > 12 | > `dnssec-keygen` creates two files, with names based on the printed string. `Knnnn.+aaa+iiiii.key` contains the public key, and `Knnnn.+aaa+iiiii.private` contains the private key. 13 | > 14 | > The `.key` file contains a DNS KEY record that can be inserted into a zone file (directly or with a $INCLUDE statement). 15 | > 16 | > The `.private` file contains algorithm-specific fields. For obvious security reasons, this file does not have general read permission. 17 | > 18 | 19 | ## Key Identifier clarification 20 | 21 | Key identifiers (key ids or footprints) for KEY & DNSKEY RR files referred to in the `dnssec-keygen` man page correspond to what is referred to as key 'tags' in DNSSEC terminology (RFC4034 see [3.3](https://www.rfc-editor.org/rfc/rfc4034#section-3.3)). For example, the filename id component of a zone's ZSK DNSKEY corresponds to the RRSIG key tag field in the zone it signs. So in theory, the C reference code example in [RFC4034 Appendix B](https://www.rfc-editor.org/rfc/rfc4034#appendix-B) should generate key identifiers. 22 | 23 | Note that `dig` also calculates this ID from the KEY RR itself. 24 | 25 | For example: 26 | ``` 27 | $ ls Kvortex* && dig +short +dnssec +rrcomments vortex.zenr.io KEY 28 | Kvortex.zenr.io.+015+56161.key Kvortex.zenr.io.+015+56161.private 29 | 512 3 15 2MK3KZkUgYQVumU9bhy1KzIZ2FhFQZ8yLP2nFMJRCEQ= ; alg = ED25519 ; key id = 56161 30 | ``` 31 | 32 | 33 | ## sig0 Key Usage 34 | 35 | ### nsupdate 36 | From the man page of `nsupdate`: 37 | 38 | `nsupdate` is used to submit Dynamic DNS Update requests, as defined in RFC 2136, to a name server. This allows resource records to be added or removed from a zone without manually editing the zone file. A single update request can contain requests to add or remove more than one resource record. 39 | 40 | Zones that are under dynamic control via nsupdate or a DHCP server should not be edited by hand. Manual edits could conflict with dynamic updates and cause data to be lost. 41 | 42 | The resource records that are dynamically added or removed with nsupdate must be in the same zone. Requests are sent to the zone's primary server, which is identified by the MNAME field of the zone's SOA record. 43 | 44 | Transaction signatures can be used to authenticate the Dynamic DNS updates. These use the TSIG resource record type described in RFC 2845, the SIG(0) record described in RFC 2535 and RFC 2931, or GSS-TSIG as described in RFC 3645. 45 | 46 | ... 47 | 48 | SIG(0) uses public key cryptography. To use a SIG(0) key, the public key must be stored in a KEY record in a zone served by the name server. 49 | 50 | ... 51 | 52 | **-k keyfile** 53 | 54 | This option indicates the file containing the TSIG authentication key. Keyfiles may be in two formats: 55 | * a single file containing a named.conf-format key statement, which may be generated automatically by ddns-confgen; or a pair of files whose names are of the format `K{name}.+157.+{random}.key` and `K{name}.+157.+{random}.private`, which can be generated by dnssec-keygen. The **-k** option can also be used to specify a SIG(0) key used to authenticate Dynamic DNS update requests. In this case, the key specified is not an HMAC-MD5 key. 56 | 57 | ## Local Keystore 58 | 59 | sig0namectl uses the environment variable `NSUPDATE_SIG0_KEYPATH` to be the directory it uses to manage all keypairs generated. It can be set though the configuration files or overriden by command line library option **-k**. 60 | 61 | Default value in **`env`** configuation file: 62 | 63 | `NSUPDATE_SIG0_KEYPATH="${PWD}/keystore"` 64 | 65 | Key generation through `request_key` writes newly generated key files in the directory path of `${NSUPDATE_SIG0_KEYPATH}`. 66 | 67 | Workflow scripts use this environment variable to prepend a default path to keypairs to invoke `nsupdate` with a **-k ${NSUPDATE_SIG0_KEYPATH}/keyfile** argument. 68 | 69 | ## Key Management 70 | 71 | sig0namectl uses the environment variable `SIGNAL_SUBZONE` to define the subzone where name requests are managed. 72 | 73 | Default value in **`env`** configuation file: 74 | 75 | `SIGNAL_SUBZONE="_signal"` 76 | -------------------------------------------------------------------------------- /dyn_ip: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Sends DNS-SD updates for domain browsing setup 4 | #------------------------------------------------------------------------------ 5 | 6 | 7 | # load helpful functions 8 | for i in functions/*.sh 9 | do 10 | . ${i} 11 | [[ -n ${DEBUG_SET_VARS} ]] && echo "Sourced ${PWD}/$i ..." 12 | done 13 | 14 | set_vars $* 15 | 16 | #------------------------------------------------------------------------------ 17 | 18 | # define default update add 19 | NSUPDATE_ACTION=${NSUPDATE_ACTION:-"add"} 20 | NSUPDATE_TTL="60" 21 | 22 | NSUPDATE_AUTH_SIG0_KEY_FQDN=${NSUPDATE_AUTH_SIG0_KEY_FQDN:-${NEW_FQDN}} 23 | [[ -n ${DEBUG} ]] && echo "DEBUG: NSUPDATE_AUTH_SIG0_KEY_FQDN='${NSUPDATE_AUTH_SIG0_KEY_FQDN}'" 24 | 25 | # split NEW_FQDN into DNS ZONE & SUBLABEL 26 | ZONE=$(get_soa "${NEW_FQDN}") 27 | [[ ! -n ${ZONE} ]] && echo "Could not find SOA in FQDN '${NEW_FQDN}'" && exit 1 28 | NEW_SUBZONE=${NEW_FQDN%*${ZONE}} 29 | [[ -n ${NEW_SUBZONE} ]] && NEW_SUBZONE=${NEW_SUBZONE::-1} # if not null, remove trailing dot 30 | 31 | # recursively search keystore for most particular subdomain keypair under ZONE 32 | subdomain="${NSUPDATE_AUTH_SIG0_KEY_FQDN:-NEW_FQDN}" 33 | while [[ ! -n "${NSUPDATE_AUTH_SIG0_KEYID}" ]] && [[ "${subdomain}" == *"${ZONE}" ]] 34 | do 35 | # [[ -n ${DEBUG} ]] && echo "DEBUG: get_sig0_keyid NSUPDATE_AUTH_SIG0_KEYID '${subdomain}' '${NSUPDATE_SIG0_KEYPATH}'" 36 | get_sig0_keyid NSUPDATE_AUTH_SIG0_KEYID "${subdomain}" "${NSUPDATE_SIG0_KEYPATH}" 37 | [[ ! -n "${NSUPDATE_AUTH_SIG0_KEYID}" ]] && subdomain="${subdomain#*.}" 38 | done 39 | 40 | # loop over command line parameter (post getops()) for IPv[4,6] assignments 41 | for ip in ${CMDLINE_EXTRA_PARAMS}; do 42 | if validateIPv4 "${ip}";then 43 | NSUPDATE_RRTYPE="A" 44 | # [[ -n ${DEBUG} ]] && echo "$ip is parsed as an IPv4 Address. Set A Record" 45 | NSUPDATE_ITEM_RR="${NSUPDATE_ITEM_RR}update ${NSUPDATE_ACTION} ${NEW_FQDN} ${NSUPDATE_TTL} ${NSUPDATE_RRTYPE} ${ip}\n" 46 | else 47 | validateIPv6 "${ip}" 48 | isIPv6="$?" 49 | if [[ $isIPv6 -eq 0 ]];then 50 | NSUPDATE_RRTYPE="AAAA" 51 | # [[ -n ${DEBUG} ]] && echo "$ip is parsed as an IPv6 Address. Set ${NSUPDATE_RRTYPE} Record" 52 | NSUPDATE_ITEM_RR="${NSUPDATE_ITEM_RR}update ${NSUPDATE_ACTION} ${NEW_FQDN} ${NSUPDATE_TTL} ${NSUPDATE_RRTYPE} ${ip}\n" 53 | else 54 | echo "Warning: Skipping Invalid IP Address ($ip)" 55 | fi 56 | fi 57 | done 58 | 59 | # form nsupdate RR update statements 60 | case ${NSUPDATE_ACTION} in 61 | add) 62 | # NSUPDATE_PRECONDITION_SET="nxrrset" 63 | # NSUPDATE_PRECONDITION="prereq ${NSUPDATE_PRECONDITION_SET} ${word}._dns-sd._udp.${DNSSD_DOMAIN}. IN PTR" 64 | # NSUPDATE_ITEM_RR="update ${NSUPDATE_ACTION} ${word}._dns-sd._udp.${DNSSD_DOMAIN} ${NSUPDATE_TTL} PTR ${DNSSD_DOMAIN}." 65 | send_nsupdate "${NEW_FQDN}" "$(echo ${NSUPDATE_PRECONDITION};echo -e ${NSUPDATE_ITEM_RR})" "${subdomain}" 66 | ;; 67 | delete) 68 | # NSUPDATE_PRECONDITION_SET="yxrrset" 69 | # NSUPDATE_PRECONDITION="prereq ${NSUPDATE_PRECONDITION_SET} ${word}._dns-sd._udp.${DNSSD_DOMAIN}. IN PTR" 70 | # NSUPDATE_ITEM_RR="update ${NSUPDATE_ACTION} ${word}._dns-sd._udp.${DNSSD_DOMAIN} ${NSUPDATE_TTL} PTR ${DNSSD_DOMAIN}." 71 | send_nsupdate "${NEW_FQDN}" "$(echo ${NSUPDATE_PRECONDITION};echo -e ${NSUPDATE_ITEM_RR})" "${subdomain}" 72 | ;; 73 | *) 74 | # NSUPDATE_ACTION should default to "add" - should never get here 75 | echo "Error: NSUPDATE_ACTION is set to '${NSUPDATE_ACTION}', but must be set to 'add' or 'delete'." 76 | exit 1 77 | ;; 78 | esac 79 | 80 | 81 | DIG_QUERY_PARAM="@${ZONE_SOA_MASTER} +noall +answer +dnssec" 82 | echo "$( dig ${DIG_QUERY_PARAM} ${NEW_FQDN} A )" 83 | echo "$( dig ${DIG_QUERY_PARAM} ${NEW_FQDN} AAAA )" 84 | -------------------------------------------------------------------------------- /dyn_key: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Manages KEY entries under a writable domain 4 | # usage 5 | # ./dyn_key fqdn pkey pkey .... 6 | # where 7 | # - fqdn is the fully qualified domain name to place the public keys 8 | # - pkey is the fqdn of the key(s) to add 9 | # 10 | # by default all key RRs of pkey are added or deleted from fqdn 11 | # if no pkey is specified, all exisiting KEY RRs at fqdn are listed 12 | #------------------------------------------------------------------------------ 13 | 14 | 15 | # load helpful functions 16 | for i in functions/*.sh 17 | do 18 | . ${i} 19 | [[ -n ${DEBUG_SET_VARS} ]] && echo "Sourced ${PWD}/$i ..." 20 | done 21 | 22 | set_vars $* 23 | 24 | #------------------------------------------------------------------------------ 25 | 26 | # define default update add 27 | NSUPDATE_ACTION=${NSUPDATE_ACTION:-"add"} 28 | NSUPDATE_TTL="60" 29 | 30 | # For a given ${NEW_FQDN}, recursively search keystore for closest (most particular) keypair 31 | subdomain="${NEW_FQDN}" 32 | while [[ ! -n "${NSUPDATE_AUTH_SIG0_KEYID}" ]] && [[ "${subdomain}" == *"."* ]] 33 | do 34 | [[ -n ${DEBUG} ]] && echo "DEBUG: get_sig0_keyid NSUPDATE_AUTH_SIG0_KEYID '${subdomain}' '${NSUPDATE_SIG0_KEYPATH}'" 35 | get_sig0_keyid NSUPDATE_AUTH_SIG0_KEYID "${subdomain}" "${NSUPDATE_SIG0_KEYPATH}" 36 | [[ ! -n "${NSUPDATE_AUTH_SIG0_KEYID}" ]] && subdomain="${subdomain#*.}" || NSUPDATE_AUTH_SIG0_KEY_FQDN="${subdomain}" 37 | done 38 | 39 | if [[ -n ${DEBUG} ]]; then 40 | echo 41 | echo "NEW_FQDN='${NEW_FQDN}'" 42 | echo "subdomain='${subdomain}'" 43 | echo "NSUPDATE_AUTH_SIG0_KEYID='${NSUPDATE_AUTH_SIG0_KEYID}'" 44 | echo "NSUPDATE_AUTH_SIG0_KEY_FQDN='${NSUPDATE_AUTH_SIG0_KEY_FQDN}'" 45 | echo "ZONE='${ZONE}'" 46 | echo "---" 47 | #echo "cat ${NSUPDATE_SIG0_KEYPATH}/${NSUPDATE_AUTH_SIG0_KEYID}.key | cut -f4- -d' '" 48 | echo "keystore public key for ${NSUPDATE_AUTH_SIG0_KEY_FQDN}: $(cat ${NSUPDATE_SIG0_KEYPATH}/${NSUPDATE_AUTH_SIG0_KEYID}.key)" 49 | #echo "dig +short ${NSUPDATE_AUTH_SIG0_KEY_FQDN} KEY" 50 | echo "DNS named public key for ${NSUPDATE_AUTH_SIG0_KEY_FQDN}: $(dig +noall +nottlid +answer ${NSUPDATE_AUTH_SIG0_KEY_FQDN} KEY)" 51 | echo "---" 52 | echo "Processing named KEY parameters" 53 | fi 54 | 55 | # loop over command line parameter (post getops()) for IPv[4,6] assignments 56 | 57 | NSUPDATE_ITEM_RR="" 58 | for keyname in ${CMDLINE_EXTRA_PARAMS}; do 59 | if validateKEY "${keyname}";then 60 | NSUPDATE_RRTYPE="KEY" 61 | [[ -n ${DEBUG} ]] && echo "KEY '${keyname}' resolves, marked to ${NSUPDATE_ACTION}" 62 | NSUPDATE_ITEM_RR="${NSUPDATE_ITEM_RR}update ${NSUPDATE_ACTION} ${NEW_FQDN} ${NSUPDATE_TTL} ${NSUPDATE_RRTYPE} $(dig +short ${keyname} ${NSUPDATE_RRTYPE})\n" 63 | else 64 | echo "Warning: Skipping no KEY resolved with FQDN '${keyname}'" 65 | fi 66 | done 67 | 68 | if [[ -n ${DEBUG} ]]; then 69 | echo "---" 70 | echo NSUPDATE_ITEM_RR 71 | echo -e ${NSUPDATE_ITEM_RR} 72 | fi 73 | # form nsupdate RR update statements 74 | case ${NSUPDATE_ACTION} in 75 | add) 76 | # NSUPDATE_PRECONDITION_SET="nxrrset" 77 | # NSUPDATE_PRECONDITION="prereq ${NSUPDATE_PRECONDITION_SET} ${word}._dns-sd._udp.${DNSSD_DOMAIN}. IN PTR" 78 | # NSUPDATE_ITEM_RR="update ${NSUPDATE_ACTION} ${word}._dns-sd._udp.${DNSSD_DOMAIN} ${NSUPDATE_TTL} PTR ${DNSSD_DOMAIN}." 79 | send_nsupdate "${NEW_FQDN}" "$(echo ${NSUPDATE_PRECONDITION};echo -e ${NSUPDATE_ITEM_RR})" "${subdomain}" 80 | ;; 81 | delete) 82 | # NSUPDATE_PRECONDITION_SET="yxrrset" 83 | # NSUPDATE_PRECONDITION="prereq ${NSUPDATE_PRECONDITION_SET} ${word}._dns-sd._udp.${DNSSD_DOMAIN}. IN PTR" 84 | # NSUPDATE_ITEM_RR="update ${NSUPDATE_ACTION} ${word}._dns-sd._udp.${DNSSD_DOMAIN} ${NSUPDATE_TTL} PTR ${DNSSD_DOMAIN}." 85 | send_nsupdate "${NEW_FQDN}" "$(echo ${NSUPDATE_PRECONDITION};echo -e ${NSUPDATE_ITEM_RR})" "${subdomain}" 86 | ;; 87 | *) 88 | # NSUPDATE_ACTION should default to "add" - should never get here 89 | echo "Error: NSUPDATE_ACTION is set to '${NSUPDATE_ACTION}', but must be set to 'add' or 'delete'." 90 | exit 1 91 | ;; 92 | esac 93 | 94 | 95 | DIG_QUERY_PARAM="@${ZONE_SOA_MASTER} +noall +answer +dnssec" 96 | echo "$( dig ${DIG_QUERY_PARAM} ${NEW_FQDN} KEY )" 97 | -------------------------------------------------------------------------------- /dyn_loc: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Sends LOC updates of GPS co-ordinates 4 | # (currently only for Android with Termux using termux-location tool) 5 | # * added gpsd for *nix/*bsd in functions/get_loc.sh 6 | #------------------------------------------------------------------------------ 7 | 8 | 9 | # load helpful functions 10 | for i in functions/*.sh 11 | do 12 | . ${i} 13 | [[ -n ${DEBUG_SET_VARS} ]] && echo "Sourced ${PWD}/$i ..." 14 | done 15 | 16 | set_vars $* 17 | 18 | #------------------------------------------------------------------------------ 19 | 20 | # define default update add 21 | NSUPDATE_ACTION=${NSUPDATE_ACTION:-"add"} 22 | NSUPDATE_TTL=${NSUPDATE_TTL:-"30"} 23 | 24 | NSUPDATE_AUTH_SIG0_KEY_FQDN=${NSUPDATE_AUTH_SIG0_KEY_FQDN:-${NEW_FQDN}} 25 | [[ -n ${DEBUG} ]] && echo "DEBUG: NSUPDATE_AUTH_SIG0_KEY_FQDN='${NSUPDATE_AUTH_SIG0_KEY_FQDN}'" 26 | 27 | # split NEW_FQDN into DNS ZONE & SUBLABEL 28 | ZONE=$(get_soa "${NEW_FQDN}") 29 | [[ ! -n ${ZONE} ]] && echo "Could not find SOA in FQDN '${NEW_FQDN}'" && exit 1 30 | NEW_SUBZONE=${NEW_FQDN%*${ZONE}} 31 | [[ -n ${NEW_SUBZONE} ]] && NEW_SUBZONE=${NEW_SUBZONE::-1} # if not null, remove trailing dot 32 | 33 | # recursively search keystore for most particular subdomain keypair under ZONE 34 | subdomain="${NSUPDATE_AUTH_SIG0_KEY_FQDN:-NEW_FQDN}" 35 | while [[ ! -n "${NSUPDATE_AUTH_SIG0_KEYID}" ]] && [[ "${subdomain}" == *"${ZONE}" ]] 36 | do 37 | # [[ -n ${DEBUG} ]] && echo "DEBUG: get_sig0_keyid NSUPDATE_AUTH_SIG0_KEYID '${subdomain}' '${NSUPDATE_SIG0_KEYPATH}'" 38 | get_sig0_keyid NSUPDATE_AUTH_SIG0_KEYID "${subdomain}" "${NSUPDATE_SIG0_KEYPATH}" 39 | [[ ! -n "${NSUPDATE_AUTH_SIG0_KEYID}" ]] && subdomain="${subdomain#*.}" 40 | done 41 | 42 | NSUPDATE_RRTYPE="LOC" 43 | 44 | # form nsupdate RR update statements 45 | case ${NSUPDATE_ACTION} in 46 | add) 47 | LOC_RR_DATA=$(get_loc "${CMDLINE_EXTRA_PARAMS}") 48 | NSUPDATE_ITEM_RR="${NSUPDATE_RRTYPE} ${LOC_RR_DATA}" 49 | # 50 | NSUPDATE_ITEM_RR="update delete ${NEW_FQDN} ${NSUPDATE_RRTYPE}\n" 51 | # 52 | #NSUPDATE_PRECONDITION_SET="nxrrset ${NEW_FQDN} ${NSUPDATE_RRTYPE}" 53 | #NSUPDATE_PRECONDITION="prereq ${NSUPDATE_PRECONDITION_SET}" 54 | NSUPDATE_ITEM_RR="${NSUPDATE_ITEM_RR}update ${NSUPDATE_ACTION} ${NEW_FQDN} ${NSUPDATE_TTL} ${NSUPDATE_RRTYPE} ${LOC_RR_DATA}\n" 55 | echo "send_nsupdate ${NEW_FQDN} $(echo ${NSUPDATE_PRECONDITION};echo -e ${NSUPDATE_ITEM_RR})" 56 | send_nsupdate "${NEW_FQDN}" "$(echo ${NSUPDATE_PRECONDITION};echo -e ${NSUPDATE_ITEM_RR})" "${subdomain}" 57 | ;; 58 | delete) 59 | LOC_RR_DATA="" 60 | NSUPDATE_ITEM_RR="${NSUPDATE_RRTYPE} ${LOC_RR_DATA}" 61 | # 62 | NSUPDATE_PRECONDITION_SET="yxrrset ${NEW_FQDN} ${NSUPDATE_RRTYPE}" 63 | NSUPDATE_PRECONDITION="prereq ${NSUPDATE_PRECONDITION_SET}" 64 | NSUPDATE_ITEM_RR="update ${NSUPDATE_ACTION} ${NEW_FQDN} ${NSUPDATE_RRTYPE}" 65 | echo "send_nsupdate ${NEW_FQDN} $(echo ${NSUPDATE_PRECONDITION};echo -e ${NSUPDATE_ITEM_RR})" 66 | send_nsupdate "${NEW_FQDN}" "$(echo ${NSUPDATE_PRECONDITION};echo -e ${NSUPDATE_ITEM_RR})" "${subdomain}" 67 | ;; 68 | *) 69 | # NSUPDATE_ACTION should default to "add" - should never get here 70 | echo "Error: NSUPDATE_ACTION is set to '${NSUPDATE_ACTION}', but must be set to 'add' or 'delete'." 71 | exit 1 72 | ;; 73 | esac 74 | 75 | 76 | DIG_QUERY_PARAM="@${ZONE_SOA_MASTER} +noall +answer +dnssec" 77 | echo "$( dig ${DIG_QUERY_PARAM} ${NEW_FQDN} LOC )" 78 | -------------------------------------------------------------------------------- /dyn_txt: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # dyn_txt15 | 16 | 17 | 18 |
19 | 20 | 21 |30 | 31 | 32 |
33 | 34 |36 | 37 | 38 |
39 | 40 | 41 |43 | 44 | 45 |
46 | 47 | 48 |50 | 51 |