diff --git a/Cargo.toml b/Cargo.toml index c132bf9..4ab7b01 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,10 @@ dotenv = "0.15.0" name = "client" path = "src/client.rs" +[[bin]] +name = "zone" +path = "src/utils.rs" + [[bin]] name = "main" path = "src/main.rs" \ No newline at end of file diff --git a/bash/create_subdomain.sh b/bash/create_subdomain.sh new file mode 100755 index 0000000..376a8ec --- /dev/null +++ b/bash/create_subdomain.sh @@ -0,0 +1,12 @@ +# For each subdomain, +# - generate a new ddns key (tsig-keygen -a hmac-md5 {{subdomain}}.dyn.commoninternet.net) and append it to /etc/bind/dyn.commoninternet.net.keys +# - add a zone section to /etc/bind/named.conf.local, associating the key with the subdomain +# - add a minimal zone file to /var/lib/bind/subdomain.dyn.commoninternet.net +# - reload bind and return the secret key to the client + +SUBDOMAIN=$1 +BASE_DOMAIN=dyn.commoninternet.net +FULL_DOMAIN="${SUBDOMAIN}.${BASE_DOMAIN}" +echo "[generating zone for ${FULL_DOMAIN}]" + +tsig-keygen -a hmac-md5 {{subdomain}}.dyn.commoninternet.net \ No newline at end of file diff --git a/bind_config/bind-subdomain.md b/bind_config/bind-subdomain.md new file mode 100644 index 0000000..aef4d7c --- /dev/null +++ b/bind_config/bind-subdomain.md @@ -0,0 +1,53 @@ + + + +Add the following to /etc/bind/named.conf.local: +``` +key "ddns-key.dyn.commoninternet.net" { + algorithm hmac-sha256; + secret "yoursecrethere"; +}; + +zone "dyn.commoninternet.net" { +type master; +file "/var/lib/bind/dyn.commoninternet.net"; + update-policy { + grant ddns-key.dyn.commoninternet.net subdomain dyn.commoninternet.net; + }; +}; +``` + +For each subdomain, +- generate a new ddns key (tsig-keygen -a hmac-md5 {{subdomain}}.dyn.commoninternet.net) and append it to /etc/bind/dyn.commoninternet.net.keys +- add a zone section to named.conf.local, associating the key with the subdomain [B] +- add a zone file to /var/lib/bind/subdomain.dyn.commoninternet.net [C] +- reload bind and return the secret key to the client + +Add the following to /var/lib/bind/{{subdomain}}.dyn.commoninternet.net: [C] +``` +$ORIGIN . +$TTL 30 ; 30 seconds +{{subdomain}}.dyn.commoninternet.net IN SOA ns.commoninternet.net. root.commoninternet.net. ( + 2016062801 ; serial + 3600 ; refresh (1 hour) + 600 ; retry (10 minutes) + 2600 ; expire (43 minutes 20 seconds) + 30 ; minimum (30 seconds) + ) + NS ns.commoninternet.net. +``` + +Append the following to /etc/bind/named.conf.local: [B] +``` +zone "{{subdomain}}.dyn.commoninternet.net" { +type master; +file "/var/lib/bind/{{subdomain}}.dyn.commoninternet.net"; + update-policy { + grant {{subdomain}}.dyn.commoninternet.net self {{subdomain}}.dyn.commoninternet.net; + }; +}; +``` + + +Questions: +- an easy way to delete a subdomain? diff --git a/bind_config/setting-up-bind.md b/bind_config/setting-up-bind.md index 1713d99..4cd8393 100644 --- a/bind_config/setting-up-bind.md +++ b/bind_config/setting-up-bind.md @@ -1,5 +1,6 @@ + Add the following to /etc/bind/named.conf.local: ``` key "ddns-key.dyn.commoninternet.net" { @@ -16,7 +17,6 @@ file "/var/lib/bind/dyn.commoninternet.net"; }; ``` - Add the following to /var/lib/bind/dyn.commoninternet.net: ``` $ORIGIN . diff --git a/generate_zone.sh b/generate_zone.sh new file mode 100755 index 0000000..01fbd3c --- /dev/null +++ b/generate_zone.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +cargo run --bin zone -- -vvv \ No newline at end of file diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 0000000..afed411 --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,93 @@ +/* For each subdomain, +- generate a new ddns key (tsig-keygen -a hmac-md5 {{subdomain}}.dyn.commoninternet.net) and append it to /etc/bind/dyn.commoninternet.net.keys +- add a zone section to /etc/bind/named.conf.local, associating the key with the subdomain +- add a minimal zone file to /var/lib/bind/subdomain.dyn.commoninternet.net +- reload bind and return the secret key to the client +*/ +use std::process::Command; +use std::io::Error; +use std::io::Write; +use std::string::FromUtf8Error; +use std::{fs::OpenOptions}; +use std::fs::File; + +const BASE_DOMAIN : &str = "dyn.commoninternet.net"; + + +#[derive(Debug)] +pub enum PeachDynError { + GenerateTsigIoError(std::io::Error), + GenerateTsigParseError(std::string::FromUtf8Error), +} + +impl From for PeachDynError { + fn from(err: std::io::Error) -> PeachDynError { + PeachDynError::GenerateTsigIoError(err) + } +} + +impl From for PeachDynError { + fn from(err: std::string::FromUtf8Error) -> PeachDynError { + PeachDynError::GenerateTsigParseError(err) + } +} + + +/// helper function to generate a TSIG key file +pub fn generate_tsig_key(full_domain: &str) -> Result { + let output = Command::new("/usr/sbin/tsig-keygen") + .arg("-a") + .arg("hmac-md5") + .arg(full_domain) + .output()?; + let key_file_text = String::from_utf8(output.stdout)?; + Ok(key_file_text) +} + + + +fn generate_zone(subdomain: &str) { + + let full_domain=format!("{}.{}", subdomain, BASE_DOMAIN); + println!("[generating zone for {}]", subdomain); + + // generate key_file_text + let key_file_text = generate_tsig_key(&full_domain).unwrap(); + println!("key_file_text: {}", key_file_text); + + // write key_file_text to file + let key_file_path = "/etc/bind/dyn.commoninternet.net.keys"; + let mut file = OpenOptions::new() + .append(true) + .open(key_file_path).unwrap(); + if let Err(e) = writeln!(file, "{}", key_file_text) { + eprintln!("Couldn't write to file: {}", e); + } + + // append to named.local.conf + let bind_conf_path = "/etc/bind/named.local.conf"; + let mut file = OpenOptions::new() + .append(true) + .open(bind_conf_path).unwrap(); + let zone_section_text = format!("\ + zone \"{full_domain}\" {{ + type master; + file \"/var/lib/bind/{full_domain}\"; + update-policy {{ + grant {full_domain} self {full_domain}; + }}; + }}; + ", full_domain=full_domain); + if let Err(e) = writeln!(file, "{}", zone_section_text) { + eprintln!("Couldn't write to file: {}", e); + } + + + +} + + + +fn main() { + generate_zone("blue"); +}