What is Whois ?
Whois is a protocol to fetch the registered users of a internet resource such as a domain name or an IP block, it is documented in RFC 3912.
Whois information can be used to know some basic information about a domian name like the person or the organization it is registered to, registration & expiry date etc.,
One of the popular use case for the whois information is to check the availability of a domain name, you can read more about this in my other post.
The protocol
The whois protocol is a pretty straight forward TCP based query response protocol, each TLD or top level domain(example .com, .net, .org, etc., ) will have a whois server that will listen on the port number 43 for the queries, Once a request is received the server will check its internal database for the domain name details and return the information in the response, the availability of a domain name in a particular TLD can be identified from the whois information returned, the structure of the whois might differ from server to server.
The protocol can be explained simply as follows
Connect to the service host TCP: service port 43 decimal Send a single "command", ending with a new line character(ASCII CR and then ASCII LF) Receive information in response to the command line. The server closes its connections as soon as the output is finished.
Implementation In C#
To get the Whois information of any domain, we need 3 parameters
- Domain name
- Record type, which is “domain”
- The whois server address for the TLD of the given domain name
A collection of Whois server list is maintained by nirsoft.net which we can use to determine the correct Whois server for a given domain name based on its TLD
Once we get this, all we have to do is connect to the server on port 43 using TCP and send the query as combination of the text “domain” and your domain name, seperated by a single space character ” “, your query should always end with a new line character.
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Net.Sockets; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace DomainTools | |
{ | |
/// <summary> | |
/// A class to lookup whois information. | |
/// </summary> | |
public class Whois | |
{ | |
private const int Whois_Server_Default_PortNumber = 43; | |
private const string Domain_Record_Type = "domain"; | |
private const string DotCom_Whois_Server = "whois.verisign-grs.com"; | |
/// <summary> | |
/// Retrieves whois information | |
/// </summary> | |
/// <param name="domainName">The registrar or domain or name server whose whois information to be retrieved</param> | |
/// <param name="recordType">The type of record i.e a domain, nameserver or a registrar</param> | |
/// <returns></returns> | |
public static string Lookup(string domainName) | |
{ | |
using (TcpClient whoisClient = new TcpClient()) | |
{ | |
whoisClient.Connect(DotCom_Whois_Server, Whois_Server_Default_PortNumber); | |
string domainQuery = Domain_Record_Type + " " + domainName + "\r\n"; | |
byte[] domainQueryBytes = Encoding.ASCII.GetBytes(domainQuery.ToCharArray()); | |
Stream whoisStream = whoisClient.GetStream(); | |
whoisStream.Write(domainQueryBytes, 0, domainQueryBytes.Length); | |
StreamReader whoisStreamReader = new StreamReader(whoisClient.GetStream(), Encoding.ASCII); | |
string streamOutputContent = ""; | |
List<string> whoisData = new List<string>(); | |
while (null != (streamOutputContent = whoisStreamReader.ReadLine())) | |
{ | |
whoisData.Add(streamOutputContent); | |
} | |
whoisClient.Close(); | |
return String.Join(Environment.NewLine, whoisData); | |
} | |
} | |
} | |
} |
You can get the whois information by just calling the Whois.Lookup method with your domain name as parameter as shown in the code below.
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
namespace DomainTools | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
Console.WriteLine("Enter a domain name to get the whois information."); | |
var domainName = Console.ReadLine(); | |
try | |
{ | |
var whoisText = Whois.Lookup(domainName); | |
Console.WriteLine(whoisText); | |
} | |
catch (Exception ex) | |
{ | |
Console.WriteLine(ex.ToString()); | |
} | |
Console.WriteLine("Press any key to exit.."); | |
Console.Read(); | |
} | |
} | |
} |
Note
Please note that this is implementation works only “.com” TLD domains, you have to change the server name to make it work for other TLD’s, you can find the implementation which works with different TLD’s in the github project I linked below
Usefull links
- Browse the source code on github
- Download the full source code along with a demo
This post is originally published on coderbuddy.wordpress.com.
[…] the original here: A simple C# class to get whois information « Coder buddy By admin | category: domain name lookup | tags: code, domain-name, from-the-list, issue, […]
LikeLike
[…] posted here: A simple C# class to get whois information « Coder buddy By admin | category: domain lookup | tags: address, conversion, dial-up, domain lookup, […]
LikeLike
cool code man – fair play – its well useful!
LikeLike
[…] A simple C# class to get whois information (coderbuddy.wordpress.com) .dk whois, dk hostmaster whois, Domain name registry, Domain privacy, dot dk whois, ICANN, WHOIS […]
LikeLike
it doesnt work for many websites,
thanks anyway
LikeLike
It only works for .com TLD, if you want to make it work for other TLD’s change the whois_server_address value, you can find a list of whois servers for popular TLD’s here http://www.domaininformation.de/whoisserver_list.html
LikeLike
Here is the extended class I hacked in a prettier version. My comment above should probably be deleted, but I couldn’t find a delete button.
I extended this class because I work for a service provider, and I wrote an app that looks up whois information for our customer domains. I did some RegEx matching in the code to match different formats of whois records, the RegEx’s could be improved. Also, I created exceptions which I called “idn1-idn4″ or something like that, which just means “international domain name” each idn exception could use multiple TLD’s if they return whois information in the same format.
Here is the code.
class Whois
{
private static object locker = new object();
public enum RecordType { whois, domain, nameserver, registrar, expiration };
static string[] idns1 = new string[] { “.ca” }; //handle idn’s that have different whois formats
static string[] idns2 = new string[] { “.uk” };
static string[] idns3 = new string[] { “.ae” };
static string[] idns4 = new string[] { “.ch” };
static string[] idns5 = new string[] { “.eu” };
static string[] idns6 = new string[] { “.info” };
public static string getwhois(string domain) //gets the whois record string (replaces \n with \r\n) from the designated whois server for the domain’s TLD, see getwhoisserver()
{
TcpClient tcp = new TcpClient();
tcp.Connect(getwhoisserver(gettopleveldomain(domain)), 43);
string strDomain = (domain + “\r\n”);
byte[] arrdomain = Encoding.ASCII.GetBytes(strDomain);
Stream s = tcp.GetStream();
s.Write(arrdomain, 0, strDomain.Length);
StreamReader sr = new StreamReader(tcp.GetStream(), Encoding.ASCII);
string whois = sr.ReadToEnd().Replace(“\n”, “\r\n”);
tcp.Close();
return whois;
}
public static void refreshwhois(string domain, string whoispath) //created this function for caching whois files on the server
{
string filename = whoispath + domain + “.whois.txt”;
//if (!File.Exists(filename)) File.Create(filename);
//check the fileinfo for creation date, if more than a week old delete it and refresh it
FileInfo fi = new FileInfo(filename);
if (File.Exists(filename) && fi.CreationTime row.Contains(“Name Servers:”)) + 1; }
else if (idns2.Contains(gettopleveldomain(domainname))) {
index = Array.FindIndex(whoislines, row => row.Contains(“Name servers:”)) + 1;
return whoislines[index].Replace(“\r”, “”).Trim();
}
else { index = Array.FindIndex(whoislines, row => row.Contains(“Name Server: “)); }
return whoislines[index].Split(‘:’)[1].Replace(“\r”,””).Trim();
case RecordType.registrar:
if (idns1.Contains(gettopleveldomain(domainname))) { index = Array.FindIndex(whoislines, row => row.Contains(“Registrar:”)) + 1; }
else if (idns2.Contains(gettopleveldomain(domainname))) { index = Array.FindIndex(whoislines, row => row.Contains(“Registrar”)) + 2; }
else { index = Array.FindIndex(whoislines, row => row.Contains(“Registrar:”)); }
return whoislines[index].Split(‘:’)[1].Trim();
case RecordType.expiration:
if (idns1.Contains(gettopleveldomain(domainname)) || idns2.Contains(gettopleveldomain(domainname))) { index = Array.FindIndex(whoislines, row => row.Contains(“Expiry date:”)); }
else { index = Array.FindIndex(whoislines, row => row.Contains(“Expiration Date:”)); }
return formatexpiration(whoislines[index].Replace(“\r”,””));
}
return null;
} //gets parameters from live whois queries, expensive since you’ll hit the server 3-4 times per domain iteration
public static string getwhoisinfo(string domainname, RecordType recordType, string whoisfilename) //gets parameters from whois text file
{
string whois = null;
using (StreamReader sr = new StreamReader(whoisfilename))
{
whois = sr.ReadToEnd();
sr.Dispose();
}
string[] whoislines = Regex.Split(whois, “\r\n”);
var index = 0;
switch (recordType)
{
case RecordType.whois:
return whois;
case RecordType.nameserver:
if (idns1.Contains(gettopleveldomain(domainname)))
{
index = Array.FindIndex(whoislines, row => row.Contains(“Name Servers:”)) + 1;
}
else if (idns2.Contains(gettopleveldomain(domainname))) {
index = Array.FindIndex(whoislines, row => row.Contains(“Name servers:”)) + 1;
return whoislines[index].Replace(“\r”, “”).Trim().ToLower();
}
else if (idns4.Contains(gettopleveldomain(domainname)))
{
index = Array.FindIndex(whoislines, row => row.Contains(“Name servers:”)) + 1;
return whoislines[index].Replace(“\r”, “”).Trim().ToLower();
}
else if (idns5.Contains(gettopleveldomain(domainname)))
{
index = Array.FindIndex(whoislines, row => row.Contains(“Name servers:”)) + 1;
return whoislines[index].Replace(“\r”, “”).Trim().ToLower();
}
else
{
index = Array.FindIndex(whoislines, row => row.Contains(“Name Server:”));
}
return whoislines[index].Split(‘:’)[1].Replace(“\r”, “”).Trim().ToLower();
case RecordType.registrar:
if (idns1.Contains(gettopleveldomain(domainname)) || idns5.Contains(gettopleveldomain(domainname))) { index = Array.FindIndex(whoislines, row => row.Contains(“Registrar:”)) + 1; }
else if (idns2.Contains(gettopleveldomain(domainname))) { index = Array.FindIndex(whoislines, row => row.Contains(“Registrar”)) + 2; }
else if (idns3.Contains(gettopleveldomain(domainname))) { index = Array.FindIndex(whoislines, row => row.Contains(“Registrar Name:”)); }
else if (idns4.Contains(gettopleveldomain(domainname))) return null;
else { index = Array.FindIndex(whoislines, row => row.Contains(“Registrar:”)); }
return whoislines[index].Split(‘:’)[1].Replace(“\r”,””).Trim();
case RecordType.expiration:
if (idns1.Contains(gettopleveldomain(domainname)) || idns2.Contains(gettopleveldomain(domainname))) {
index = Array.FindIndex(whoislines, row => row.Contains(“Expiry date:”));
return formatexpiration(whoislines[index].Replace(“\r”, “”));
}
else if (idns3.Contains(gettopleveldomain(domainname)) || idns4.Contains(gettopleveldomain(domainname)) || idns5.Contains(gettopleveldomain(domainname)))
{
return null;
}
else if (idns6.Contains(gettopleveldomain(domainname)))
{
index = Array.FindIndex(whoislines, row => row.Contains(“Expiration Date:”));
return formatexpiration(whoislines[index]);
}
else
{
index = Array.FindIndex(whoislines, row => row.Contains(“Expiration Date:”));
return formatexpiration(whoislines[index]);
}
}
return null;
}
public static string formatexpiration(string strexp)
{
string year = null;
string month = null;
string day = null;
if (strexp.Contains(“Domain Expiration Date:”)) strexp = strexp.Replace(“Domain Expiration Date:”, “”);
if (strexp.Contains(“Expiration Date:”)) strexp = strexp.Replace(“Expiration Date:”, “”);
if (strexp.Contains(“Expiry date:”)) strexp = strexp.Replace(“Expiry date:”, “”);
strexp = strexp.Trim();
if (strexp.Contains(“/”) && Regex.IsMatch(strexp.Split(‘/’)[0], @”^[0-9]+$”) && Regex.IsMatch(strexp.Split(‘/’)[1], @”^[0-9]+$”) && Regex.IsMatch(strexp.Split(‘/’)[2], @”^[0-9]+$”))
{
//format = “yyyy/mm/dd”;
month = DateTime.ParseExact(strexp.Split(‘/’)[1], “MM”, CultureInfo.CurrentCulture).Month.ToString();
day = DateTime.ParseExact(strexp.Split(‘/’)[2], “dd”, CultureInfo.CurrentCulture).Day.ToString();
year = DateTime.ParseExact(strexp.Split(‘/’)[0], “yyyy”, CultureInfo.CurrentCulture).Year.ToString();
}
if (Regex.IsMatch(strexp.Split(‘ ‘)[0], @”^[a-zA-Z]+$”) && Regex.IsMatch(strexp.Split(‘ ‘)[1], @”^[a-zA-Z]+$”) && Regex.IsMatch(strexp.Split(‘ ‘)[2], @”^[0-9]+$”))
{
//format Mon Jan 26 23:59:59 GMT 2015
month = DateTime.ParseExact(strexp.Split(‘ ‘)[1], “MMM”, CultureInfo.CurrentCulture).Month.ToString();
day = DateTime.ParseExact(strexp.Split(‘ ‘)[2], “dd”, CultureInfo.CurrentCulture).Day.ToString();
year = DateTime.ParseExact(strexp.Split(‘ ‘)[5], “yyyy”, CultureInfo.CurrentCulture).Year.ToString();
}
if (Regex.IsMatch(strexp, @”^\d{2}-[a-zA-Z]{3}-\d{4}\s\d{2}:\d{2}:\d{2}\s[a-zA-Z]{3}$”)) //format 21-Feb-2016 00:00:00 UTC
{
strexp = strexp.Split(‘ ‘)[0];
month = DateTime.ParseExact(strexp.Split(‘-‘)[1], “MMM”, CultureInfo.CurrentCulture).Month.ToString();
day = DateTime.ParseExact(strexp.Split(‘-‘)[0], “dd”, CultureInfo.CurrentCulture).Day.ToString();
year = DateTime.ParseExact(strexp.Split(‘-‘)[2], “yyyy”, CultureInfo.CurrentCulture).Year.ToString();
}
if (Regex.IsMatch(strexp.Split(‘ ‘)[0], @”^\d{2}-[a-zA-Z]{3}-\d{4}”)) //format 21-Feb-2016
{
month = DateTime.ParseExact(strexp.Split(‘-‘)[1], “MMM”, CultureInfo.CurrentCulture).Month.ToString();
day = DateTime.ParseExact(strexp.Split(‘-‘)[0], “dd”, CultureInfo.CurrentCulture).Day.ToString();
year = DateTime.ParseExact(strexp.Split(‘-‘)[2], “yyyy”, CultureInfo.CurrentCulture).Year.ToString();
}
return month + “/” + day + “/” + year;
}//formats the expiration dates for different types of whois records
public static string gettopleveldomain(string domainname)
{
string tld = domainname.Substring(domainname.LastIndexOf(“.”), (domainname.Length – domainname.LastIndexOf(“.”)));
return tld;
}//returns the tld of any given domain name string (anything after and including the last “.”)
public static string getwhoisserver(string topleveldomain)
{
string whoisserver = null;
switch (topleveldomain)
{
case “.com”:
whoisserver = “whois.crsnic.net”;
break;
case “.net”:
whoisserver = “whois.crsnic.net”;
break;
case “.org”:
whoisserver = “whois.pir.org”;
Thread.Sleep(15000);
break;
case “.edu”:
whoisserver = “whois.crsnic.net”;
break;
case “.co”:
whoisserver = “whois.nic.co”;
break;
case “.biz”:
whoisserver = “whois.neulevel.biz”;
break;
case “.info”:
whoisserver = “whois.afilias.info”;
break;
case “.us”:
whoisserver = “whois.nic.us”;
break;
case “.uk”:
whoisserver = “whois.nic.uk”;
break;
case “.ca”:
whoisserver = “whois.cira.ca”;
break;
case “.de”:
whoisserver = “whois.nic.de”;
break;
case “.ws”:
whoisserver = “whois.nic.ws”;
break;
case “.au”:
whoisserver = “whois.aunic.net”;
break;
case “.nu”:
whoisserver = “whois.nic.nu”;
break;
case “.eu”:
whoisserver = “whois.eu”;
break;
case “.ae”:
whoisserver = “whois.aeda.net.ae”;
break;
case “.gov”:
whoisserver = “whois.nic.gov”;
break;
case “.ch”:
whoisserver = “whois.nic.ch”;
break;
}
return whoisserver;
}//gets the whois server name for a domain’s tld
}
LikeLike
Ok I give up, u gota tab in the code yourself.
LikeLike
I’m not sure, what you are saying here
LikeLiked by 1 person