A Rust-based DNS management service using gRPC, Diesel (Postgres), and Tonic.
- Rust (https://rustup.rs/)
- PostgreSQL (https://www.postgresql.org/)
- Diesel CLI (for migrations)
- Protobuf Compiler (
protoc) - Postman (for gRPC testing)
Just clone this repo
Create a .env file in the project root with the following variables (adjust as needed):
DATABASE_URL=postgres://user:password@localhost/dns_db
DNS_ADDRESS=127.0.0.1:50051
BIND9_PATH=/usr/sbin/named
BIND9_CONFIGFILE=/etc/bind/named.conf
DEFAULT_TTL=3600
HOSTMASTER_EMAIL=hostmaster.example.com // signifies hostmaster@example.com
DNS_HOSTNAME=ns1.example.comcargo install diesel_cli --no-default-features --features postgresDependencies are already specified in Cargo.toml. To fetch them:
cargo fetchInitialize the database and run migrations:
diesel setup
diesel migration run
# (Optional) To redo the last migration:
diesel migration redoThis will also generate the Rust code from your .proto files:
cargo buildcargo runThe gRPC server will start at the address specified in your .env (DNS_ADDRESS).
- Open Postman.
- Switch to the "gRPC" tab.
- Import your
.protofiles from theproto/directory. - Set the server address (e.g.,
127.0.0.1:50051). - Call the available gRPC methods.
This service exposes two main gRPC services for DNS management:
Manages DNS domains.
Creates a new domain with an associated IP address.
Request: CreateDomainDto
message CreateDomainDto {
string domain = 1; // Domain name (e.g., "example.com")
string ip_address = 2; // IP address to associate with the domain
}Response: RpcDomain
message RpcDomain {
string id = 1; // Unique domain ID
string domain = 2; // Domain name
int64 default_ttl = 3; // Default TTL value
}Example:
{
"domain": "example.com",
"ip_address": "192.168.1.1"
}Deletes an existing domain by ID.
Request: DeleteDomainRequest
message DeleteDomainRequest {
int32 domain_id = 1; // ID of the domain to delete
}Response: DeleteDomainResponse
message DeleteDomainResponse {
bool success = 1; // Whether deletion was successful
string message = 2; // Status message
repeated string errors = 3; // Any errors encountered
}Manages DNS records for domains.
Creates a new DNS record for a domain.
Request: CreateDomainRecordDto
message CreateDomainRecordDto {
int64 ttl = 1; // Time to live in seconds
string class = 2; // DNS class (typically "IN" for Internet)
string host = 3; // Hostname/subdomain (e.g., "www", "@", "mail")
string record_type = 4; // Record type (A, AAAA, CNAME, MX, TXT, NS, PTR, SRV)
int64 mx_preference = 5; // MX priority (only for MX records)
string value = 6; // Record value (IP, hostname, text, etc.)
int32 domain_id = 7; // ID of the parent domain
}Response: RpcDomainRecord
message RpcDomainRecord {
int32 id = 1; // Unique record ID
string host = 2; // Hostname
int64 ttl = 3; // Time to live
string type = 4; // Record type
int64 priority = 5; // Priority (for MX records)
string value = 6; // Record value
}Example (A Record):
{
"ttl": 3600,
"class": "IN",
"host": "www",
"record_type": "A",
"value": "192.168.1.1",
"domain_id": 1
}Example (MX Record):
{
"ttl": 3600,
"class": "IN",
"host": "@",
"record_type": "MX",
"mx_preference": 10,
"value": "mail.example.com",
"domain_id": 1
}Updates an existing DNS record.
Request: UpdateDomainRecordDto
message UpdateDomainRecordDto {
int32 id = 1; // ID of the record to update
string host = 2; // New hostname
int64 ttl = 3; // New TTL
string value = 4; // New value
string type = 5; // New record type
}Response: RpcDomainRecord (same as CreateDomainRecord response)
Deletes a DNS record by ID.
Request: DeleteDomainRecordDto
message DeleteDomainRecordDto {
int32 id = 1; // ID of the record to delete
}Response: RpcDomainRecord (returns the deleted record details)
Retrieves a specific DNS record by ID.
Request: GetRecordByIdDto
message GetRecordByIdDto {
int32 id = 1; // ID of the record to retrieve
}Response: RpcDomainRecord (same as CreateDomainRecord response)
enum DomainRecordType {
A = 0; // IPv4 address
NS = 1; // Name server
CNAME = 2; // Canonical name
PTR = 3; // Pointer record
MX = 4; // Mail exchange
TXT = 5; // Text record
AAAA = 6; // IPv6 address
SRV = 7; // Service record
}- gRPC Reflection: Enabled for service discovery
- Logging Middleware: Request/response logging via tracing
- Database: PostgreSQL with Diesel ORM
- Transport: Tonic (gRPC for Rust)
- Make sure PostgreSQL is running and accessible.
- If you change
.protofiles, re-runcargo buildto regenerate Rust code. - For troubleshooting, check
.envvalues and database connectivity. - The server listens on the address specified in
DNS_ADDRESSenvironment variable.
MIT