Developing a Blockchain-based Domain Name System(DNS) with Ethereum

Antony Prince J
6 min readOct 26, 2020

Domain Name System (DNS) holds a prominent role in the world of internet. Without its existence, utilization of domain names to access our favorite websites would not be possible. We would have to remember the 32 bit or 128 bit IP address for each and every website.

What is DNS?

DNS translates domain names into corresponding ip addresses so the browser can load the internet resources.

In this article, I have tried to build a highly basic implementation of the DNS server using a decentralized system like blockchain.

Picture from https://cdome.comodo.com

What is Blockchain?

In layman terms, Blockchain is just a linked list of blocks with each block connected to other using cryptography. The blocks generally hold data and when the data is modified in a block, the link is broken.

Ethereum is a decentralized highly popular blockchain which offers smart contract functionality. Similar to Java Virtual Machine (JVM), there exists an Ethereum Virtual Machine(EVM) for execution of smart contracts. Smart contracts in ethereum are generally written in Solidity or Vyper.

Note : This tutorial will implement the contract in solidity.

Implementation

In this article, we are going to see how to code a smart contract in solidity which can perform the actions of the DNS.

To develop a smart contract in solidity, Remix ethereum IDE can be used which is available at remix.ethereum.org It is an online browser based IDE.

A DNS server is expected to perform the following actions

  • Store the mapping between domain name and ip address.
  • For a domain name , perform lookup and return the corresponding ip address.
  • Allow for updation of the record mapping between domain and ip address.

Now, let us start coding !

Setting up the layout of the contract file

Go to the Remix IDE and create a new solidity file dns.sol and type the following.

pragma solidity >=0.4.21 <0.7.0;

Every solidity file is required to start by defining the pragma directive. It is used to define the version of compiler that the smart contract supports. It is to avoid any backward compatibility issues that may occur for certain features.

Define the main contract Dns

contract Dns{}

A contract in solidity is analogous to a class, that is, a collection of data and methods. It is mandatory to write code within the contract only. Contracts also supports inheritance.

DNS Records in contract

Deciding what to store in the smart contract is highly crucial as this data is stored in the blockchain. It is generally preferred to not hold data with high memory requirement and keep it simple .

For ease of use , we are going to define a structure— A collection of data variables.

struct Domain{
string domainName;
string A_Record;
string CNAME;
string TXT;
string NS_Record;
string SOA_Record;
bool exists;
}

domainName: It is the website address where users can access the website . Ex: www.google.com, https://medium.com

A_Record: ‘A’ stands for ‘address’ and this is the most fundamental type of DNS record. It indicates the IP address of a given domain.

CNAME: Canonical Name record is a type of DNS record that maps an alias name to a true or canonical domain name. CNAME records are typically used to map a subdomain such as www or mail to the domain hosting that subdomain’s content.

TXT: A TXT record (short for text record) is an informational DNS record used to associate arbitrary text with a host or other name.

NS_Record: NS stands for ‘nameserver,’ and the nameserver record indicates which DNS server is authoritative for that domain

SOA_Record : A Start of Authority record is a type of resource record in the Domain Name System containing administrative information about the zone

exists : Boolean to check if domain mapped to DNS records or not.

Reference : The below picture shows how the DNS is set in GoDaddy

Picture from sendinblue.com

Mapping of records with domain

The functionality of DNS is to return the ip address for a query with website name. To efficiently handle this requirement, a mapping can be used.

A mapping in solidity is a key- value store similar to dictionary in python or simply a hash table.

We will be setting the domain name as key and the struct object with domain records as the value.

mapping (string => Domain) public nameserver;

The string is website name and the Domain is the struct object with the mapping named as nameserver set in public access.

Functions to perform DNS actions

Addition of Domain Records

Let us define a function addDomain()

The function would require to take the DNS records and Domain Name as arguments.

function addDomain
(string memory _domainName ,
string memory _A_Record ,
string memory _CNAME,
string memory _TXT ,
string _NS_Record,
string _SOA_Record)
public returns(bool) {
// Function body}

The function uses require to assert whether the mapping already exists or not.

require(nameserver[_domainName].exists == false,"IP mapping already exists");

Then, we create a new Domain object with the records passed to its constructor.

Domain memory new_domain = Domain(_domainName,_A_Record,_CNAME,_TXT,_NS_Record,_SOA_Record,true);

Then we set the mapping with domainName as key and Domain object as value in the nameserver.

nameserver[_domainName] = new_domain;

The complete function is as below

function addDomain(string memory _domainName , string memory _A_Record , string memory _CNAME, string memory _TXT ,string memory _NS_Record, string memory _SOA_Record) public returns(bool) {        require(nameserver[_domainName].exists == false,"IP mapping already exists");

Domain memory new_domain = Domain(_domainName,_A_Record,_CNAME,_TXT,_NS_Record,_SOA_Record,true);
nameserver[_domainName] = new_domain;

return true;
}

Nameserver Lookup function

Now, let us define another function dnsLookup()

This function will handle the queries to the DNS. The website name is sent as argument and the corresponding DNS records are sent as response.

function dnsLookup(string memory _domainName) public view returns (string memory,string memory,string memory,string memory,string memory, string memory){ require(nameserver[_domainName].exists == true,”DNS not configured yet for the domain”);

return (
nameserver[_domainName].A_Record,
nameserver[_domainName].CNAME,
nameserver[_domainName].TXT,
nameserver[_domainName].NS_Record,
nameserver[_domainName].SOA_Record
);
}

Note: The function is set as public view since it makes no change to the blockchain data, it only retrieves it.

Updating DNS records

Finally, we would require to define functions to modify the DNS records.

Let us consider for A_Record

function modifyARecord(string memory _domainName, string memory _A_Record) public returns (bool){ require(nameserver[_domainName].exists == true,”DNS not configured yet for the domain”);

nameserver[_domainName].A_Record = _A_Record;
return true;

}

We take new A_Record and domainName as input and change it accordingly. Similarly, we can define functions for CNAME,TXT, NS and SOA.

You can find the entire smart contract at

https://github.com/antoprince001/blockDNS

To check if the contract is working properly, we can compile and deploy it to the sandbox blockchain in the browser.

After successful compilation, we can deploy it.

When deployed, we can access all the contract functions in the browser.

Thus, we have created a smart contract that performs the functions of Domain Name system.

In the next part of the tutorial, I will write about how to access the smart contract functions using node.js and web.js

Check out my portfolio at https://antoprince001.github.io

--

--

Antony Prince J

Ever curious developer highly interested in blockchain and data engineering.