Simple DNS Server
By default, DNS is connection-less and runs on port 53/UDP. An optional DNS service on port 53/TCP can be used for connection-oriented requests. A basic DNS server receives requests and provides replies. Listing below shows a very simple DNS server that receives DNS requests and always provides the same reply: a single IP address and TXT comment. The full source code is available on the CD-ROM as dnsd.c.
Queries to this simple DNS daemon from host, nslookup, and dig return the same reply. Each request receives the IP address and TXT information specified when starting the server. More complex DNS servers, such as BIND and NSD, relay requests to other DNS servers, use internal databases for storing hostnames, and cache responses from relayed requests.
Simple DNS Daemon
int main (int argc, char *argv[]) { int UDPsocket; /* server socket */ DNS_RR Request,Reply; int RequestLen,ReplyLen; struct sockaddr_in Server; struct sockaddr Client; int ClientLen; int Len; int Ipaddr; if (argc != 4) { printf("Simple DNS server that always returns "); printf("the same reply.\n"); printf("Usage: %s ipaddress hostname text\n",argv[0]); printf(" ipaddress: IP address to reply (1.2.3.4)\n"); printf(" hostname: hostname to reply (cow.farm.lan)\n"); printf(" text: text comment to reply "); printf("(\"Text in quotes\")\n"); exit(-1); } UDPsocket = socket(AF_INET,SOCK_DGRAM,0); if (UDPsocket < 0) { fprintf(stderr,"ERROR: Unable to open socket.\n"); exit(-1); } Server.sin_family = AF_INET; Server.sin_addr.s_addr = INADDR_ANY; /* DNS normally runs on port 53/UDP */ Server.sin_port = htons(53); if (bind(UDPsocket,(struct sockaddr *)(&Server),sizeof(Server))) { fprintf(stderr,"ERROR: Failed to bind to port 53/UDP.\n"); exit(-1); } /* Now listen for requests and reply */ while(1) { ClientLen=sizeof(Client); RequestLen = recvfrom(UDPsocket,&Request,sizeof(Request),0, &Client,&ClientLen); if (RequestLen >= 12) /* 12 bytes is minimum */ { /* Process packet request */ memset(&Reply,0,sizeof(Reply)); Reply.ID = Request.ID; /* set authoritative reply */ Reply.Flags = FLAG_REPLY | FLAG_AA; Reply.Rcode = RCODE_SERVER_ERROR; /* assume error */ ReplyLen = 12; /* check if it is a request we can handle */ if ((Request.Flags & FLAG_REPLY) == 0) { Reply.Rcode = RCODE_NO_ERROR; Reply.Acount = htons(2); /* 2 replies: hostname and TXT */ Len=0; /* Reply #1: hostname and IP address */ /* store hostname */ Reply.Data[Len++]=strlen(argv[2]); memcpy(Reply.Data+Len,argv[2],strlen(argv[2])); Len+=strlen(argv[2]); Reply.Data[Len++] = 0; /* end of string */ /* set upper byte of TYPE */ Reply.Data[Len++] = (TYPE_A/256)&0xff; /* set lower byte of TYPE */ Reply.Data[Len++] = (TYPE_A)&0xff; /* set CLASS */ Reply.Data[Len++] = (CLASS_IN/256)&0xff; Reply.Data[Len++] = (CLASS_IN)&0xff; /* set TTL */ Reply.Data[Len++] = 0; /* TTL = 4 bytes */ Reply.Data[Len++] = 0; /* TTL */ Reply.Data[Len++] = 0; /* TTL */ /* lowest part of TTL = 10 seconds */ Reply.Data[Len++] = 10; /* set data length: octets */ Reply.Data[Len++] = 0; Reply.Data[Len++] = 4; Ipaddr = ntohl(inet_addr(argv[1])); Reply.Data[Len++] = (Ipaddr >> 24) & 0xff; Reply.Data[Len++] = (Ipaddr >> 16) & 0xff; Reply.Data[Len++] = (Ipaddr >> 8) & 0xff; Reply.Data[Len++] = (Ipaddr) & 0xff; /* Reply #2: hostname and TXT string */ Reply.Data[Len++]=0xc0; /* make this a pointer */ Reply.Data[Len++]=0x0c; /* point to name (start of data) */ /* set TYPE */ Reply.Data[Len++] = (TYPE_TXT/256)&0xff; Reply.Data[Len++] = (TYPE_TXT)&0xff; /* set CLASS */ Reply.Data[Len++] = (CLASS_IN/256)&0xff; Reply.Data[Len++] = (CLASS_IN)&0xff; /* set TTL to 10 seconds */ Reply.Data[Len++] = 0; /* TTL = 4 bytes */ Reply.Data[Len++] = 0; /* TTL */ Reply.Data[Len++] = 0; /* TTL */ Reply.Data[Len++] = 10; /* lowest part of TTL */ Reply.Data[Len++] = 0; /* upper part of data length */ Reply.Data[Len++] = strlen(argv[3])+1; /* data length */ Reply.Data[Len++] = strlen(argv[3]); /* string length */ memcpy(Reply.Data+Len,argv[3],strlen(argv[3])); Len += strlen(argv[3]); ReplyLen += Len; /* total size of packet */ } /* if request */ sendto(UDPsocket,&Reply,ReplyLen,0,&Client,ClientLen); /* if at least 12 bytes */ } /* while(1) */ /* Should never get here! */ return(0); } /* main() */
In this tutorial:
- Domain Name System (DNS)
- DNS Common Uses
- Hostname-to-Address Mapping
- Common Lookup Tools
- Naming Confusion Attack Vectors
- Dotted Names
- Name Formatting
- Exploited Anonymity
- Mail Servers
- Sender Policy Framework Overloading
- Domain Keys Overloading
- DNS Protocol
- Packet Information
- Simple DNS Server
- Distributed Architecture
- Top Level Domain Servers
- Generic Top Level Domain (gTLD)
- Secondary Level Domain (SLD)
- Primary and Secondary Servers
- Caching Servers
- DNS Management
- DNS Direct Risks
- DNS Performance versus Security
- DNS Cache Poisoning
- Corrupt DNS Packets
- DNS Domain Hijacking
- DNS Server Hijacking
- Dynamic DNS
- Similar Hostnames
- Domain Renewals
- Hostnames
- Zone Transfers
- Host Listing
- DNS Fields
- Mitgation Option
- Technical Threat Mitigation
- Social Threat Mitigation
- Defining Trusted Replies