mirror of
https://github.com/ZeusWPI/ZNS.git
synced 2024-11-21 21:41:10 +01:00
add README and fix some todos
This commit is contained in:
parent
271ee5e395
commit
c1ab0cc953
4 changed files with 94 additions and 7 deletions
83
README.md
Normal file
83
README.md
Normal file
|
@ -0,0 +1,83 @@
|
|||
# Zeus (Domain) Name Server
|
||||
|
||||
Is implementation of an authoritative DNS server.
|
||||
|
||||
It gives all users who have a [Zauth](https://zauth.zeus.gent) account an own domain: `username.users.zeus.gent`.
|
||||
|
||||
## General Information
|
||||
|
||||
Creating/Updating your DNS records is only possible using dynamic DNS updating (DDNS, rfc2136).
|
||||
It's an extension of DNS that lets you update your DNS records using the DNS protocol.
|
||||
|
||||
ZNS authenticates these update requests using SIG(0) (rfc2931).
|
||||
This is another extension of DNS that defines a signature record. It is appended to the query and contains the signature of the original query and
|
||||
some other information like expiration time to prevent replay attacks.
|
||||
|
||||
The signature is created with the private key of the signer and validated on the server with the corresponding public key.
|
||||
ZNS has 2 methods of validating the signature:
|
||||
- Using your SSH Keys in [Zauth](https://zauth.zeus.gent)
|
||||
- Using a [DNSKEY record](https://datatracker.ietf.org/doc/html/rfc4034#section-2)
|
||||
|
||||
|
||||
## User Guide
|
||||
|
||||
How to add an `A` record to `<your zauth username>.users.zeus.gent`.
|
||||
|
||||
### Step 1
|
||||
|
||||
Create an SSH key pair (or use an existing one). Currently, only ED25519 and RSA SSH key types are supported.
|
||||
Add the public key to your Zauth account.
|
||||
|
||||
### Step 2
|
||||
|
||||
The (most) painless way for sending DNS update queries is using the `nsupdate` program.
|
||||
With `nsupdate -k keys`, you can pass it your keys. But `nsupdate` expects your keys to have a certain format, so it won't accept the OPENSSH private key format.
|
||||
That's why there is a CLI (`zns-cli`) available that converts the OPENSSH private key format and creates `.key` and `.private` files corresponding with your public and private keys.
|
||||
And with some more info like the update ZONE (`username.users.zeus.gent`), the signing algorithm (ED25519 or RSA), ...
|
||||
|
||||
Execute:
|
||||
|
||||
```sh
|
||||
zns-cli --key <path to private ssh key> --username <zauth username>
|
||||
```
|
||||
|
||||
Now you can run `nsupdate -k Kdns.private`.
|
||||
|
||||
```
|
||||
> zone username.users.zeus.gent
|
||||
> update add username.users.zeus.gent 300 A <ip address>
|
||||
> send
|
||||
```
|
||||
|
||||
This will add an A record to `username.users.zeus.gent`.
|
||||
The message will be signed with the private key, and the server will try to validate by trying to find a valid public SSH key from your Zauth account. Matching the `username` given in the zone.
|
||||
The default expiration time with `nsupdate` is 5 minutes.
|
||||
|
||||
That's it... not that hard, is it?
|
||||
|
||||
### Step 3 (Optional)
|
||||
|
||||
It is also possible to put your public key in a DNSKEY record instead of Zauth. In the previous step, `zns-cli` also generated a `.key` file.
|
||||
This contains a DNSKEY resource record you can add to your zone using `nsupdate`. Now the signature can be validated directly using this record.
|
||||
|
||||
It's also possible to directly generate a DNSKEY record key pair using `dnssec-keygen`.
|
||||
|
||||
## Server Setup Guide
|
||||
|
||||
There are three crates available at the root of the repo.
|
||||
|
||||
`zns` is a library which is both used by `zns-cli` and `zns-daemon`.
|
||||
`zns-daemon` is the server that handles DNS queries.
|
||||
|
||||
The following environment variables should be set (or stored in a `.env` file):
|
||||
```
|
||||
DATABASE_URL=postgres://zns@localhost/zns
|
||||
ZAUTH_URL="https://zauth.zeus.gent"
|
||||
ZONE="users.zeus.gent"
|
||||
```
|
||||
|
||||
Optional: `ZNS_ADDRESS` and `ZNS_PORT`.
|
||||
|
||||
After setting `DATABASE_URL`, create the database and run the migrations with `diesel migration run`.
|
||||
|
||||
It's quite possible that something is not conform to an RFC, creating an issue is appreciated.
|
|
@ -1,5 +1,5 @@
|
|||
use base64::prelude::*;
|
||||
use num_bigint::{BigInt, BigUint};
|
||||
use num_bigint::BigUint;
|
||||
use num_traits::FromPrimitive;
|
||||
use std::error::Error;
|
||||
use std::fs::{self, File};
|
||||
|
@ -76,7 +76,7 @@ fn read_bytes(reader: &mut Reader) -> Result<Vec<u8>, ZNSError> {
|
|||
|
||||
impl KeyTransformer for Ed25519KeyPair {
|
||||
fn from_openssh(reader: &mut Reader) -> Result<Self, ZNSError> {
|
||||
// public key parts
|
||||
// public key parts//TODO: change to SIG
|
||||
let length = reader.read_u32()?;
|
||||
reader.read(length as usize)?;
|
||||
|
||||
|
@ -259,6 +259,7 @@ impl KeyTransformer for OpenSSHKey {
|
|||
|
||||
const OPENSSH_START: &str = "-----BEGIN OPENSSH PRIVATE KEY-----";
|
||||
const OPENSSH_END: &str = "-----END OPENSSH PRIVATE KEY-----";
|
||||
const FILENAME: &str = "Kdns";
|
||||
|
||||
fn ssh_to_dnskey(file_content: &str, username: &str) -> Result<(), Box<dyn Error>> {
|
||||
if !file_content.starts_with(OPENSSH_START) || !file_content.ends_with(OPENSSH_END) {
|
||||
|
@ -277,8 +278,8 @@ fn ssh_to_dnskey(file_content: &str, username: &str) -> Result<(), Box<dyn Error
|
|||
let mut reader = Reader::new(&bin);
|
||||
let key = OpenSSHKey::from_openssh(&mut reader)?;
|
||||
|
||||
let mut file_private = File::create("Kdns.private")?;
|
||||
let mut file_public = File::create("Kdns.key")?;
|
||||
let mut file_private = File::create(format!("{}.private", FILENAME))?;
|
||||
let mut file_public = File::create(format!("{}.key", FILENAME))?;
|
||||
|
||||
let (private, public) = key.to_dnskey(username);
|
||||
file_private.write(private.as_bytes())?;
|
||||
|
@ -292,7 +293,10 @@ fn main() {
|
|||
|
||||
match fs::read_to_string(args.key) {
|
||||
Ok(contents) => match ssh_to_dnskey(contents.trim(), &args.username) {
|
||||
Ok(()) => println!("Success"),
|
||||
Ok(()) => println!(
|
||||
"Successfully written {}.private and {}.key",
|
||||
FILENAME, FILENAME
|
||||
),
|
||||
Err(error) => eprintln!("{}", error),
|
||||
},
|
||||
Err(error) => eprintln!("{}", error),
|
||||
|
|
|
@ -51,7 +51,7 @@ impl ResponseHandler for UpdateHandler {
|
|||
|
||||
//TODO: this code is ugly
|
||||
let last = message.additional.last();
|
||||
if last.is_some() && last.unwrap()._type == Type::Type(RRType::KEY) {
|
||||
if last.is_some() && last.unwrap()._type == Type::Type(RRType::SIG) {
|
||||
let sig = Sig::new(last.unwrap(), raw)?;
|
||||
|
||||
if !authenticate::authenticate(&sig, &zone.qname, connection)
|
||||
|
|
|
@ -11,7 +11,7 @@ pub enum Type {
|
|||
pub enum RRType {
|
||||
A = 1,
|
||||
SOA = 6,
|
||||
KEY = 24, //TODO: change to SIG
|
||||
SIG = 24,
|
||||
DNSKEY = 48,
|
||||
OPT = 41,
|
||||
ANY = 255,
|
||||
|
|
Loading…
Reference in a new issue