An abstract-encoding compliant module for encoding and decoding DNS packets with support for all major DNS record types and transport protocols
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
DNS packet structure handling for questions, answers, authorities, and additional sections with proper flag management and metadata.
Complete DNS packet object with all sections and metadata.
// Complete DNS packet structure
interface DNSPacket {
type: 'query' | 'response'; // Packet type
id?: number; // Transaction ID (0-65535)
flags?: number; // DNS flags bitfield
questions?: Question[]; // Question section
answers?: Answer[]; // Answer section
authorities?: Answer[]; // Authority section
additionals?: Answer[]; // Additional section
}
// Question structure
interface Question {
type: string; // DNS record type ('A', 'AAAA', 'MX', etc.)
class?: string; // DNS class (default: 'IN')
name: string; // Domain name to query
}
// Answer/Authority/Additional structure
interface Answer {
type: string; // DNS record type
class?: string; // DNS class (default: 'IN')
name: string; // Domain name
ttl?: number; // Time to live in seconds
// Record-specific data properties
}Bitfield constants for DNS packet flags exported from the main module.
const dnsPacket = require('dns-packet');
// DNS flag constants
const AUTHORITATIVE_ANSWER = dnsPacket.AUTHORITATIVE_ANSWER; // 1 << 10 (0x0400)
const TRUNCATED_RESPONSE = dnsPacket.TRUNCATED_RESPONSE; // 1 << 9 (0x0200)
const RECURSION_DESIRED = dnsPacket.RECURSION_DESIRED; // 1 << 8 (0x0100)
const RECURSION_AVAILABLE = dnsPacket.RECURSION_AVAILABLE; // 1 << 7 (0x0080)
const AUTHENTIC_DATA = dnsPacket.AUTHENTIC_DATA; // 1 << 5 (0x0020)
const CHECKING_DISABLED = dnsPacket.CHECKING_DISABLED; // 1 << 4 (0x0010)
const DNSSEC_OK = dnsPacket.DNSSEC_OK; // 1 << 15 (0x8000)Additional Flag Details from Decoded Headers:
When decoding DNS headers, additional flag properties are available:
// Extended flag properties in decoded headers
interface DecodedHeader {
id: number;
type: 'query' | 'response';
flags: number; // Raw flags value
flag_qr: boolean; // Query/Response flag
opcode: string; // Operation code name
flag_aa: boolean; // Authoritative Answer
flag_tc: boolean; // Truncated Response
flag_rd: boolean; // Recursion Desired
flag_ra: boolean; // Recursion Available
flag_z: boolean; // Zero flag (reserved)
flag_ad: boolean; // Authentic Data
flag_cd: boolean; // Checking Disabled
rcode: string; // Response code name
questions: Array; // Question section array
answers: Array; // Answer section array
authorities: Array; // Authority section array
additionals: Array; // Additional section array
}Usage Examples:
const dnsPacket = require('dns-packet');
// Single flag
const queryPacket = {
type: 'query',
flags: dnsPacket.RECURSION_DESIRED,
questions: [{ type: 'A', name: 'example.com' }]
};
// Multiple flags using bitwise OR
const flags = dnsPacket.RECURSION_DESIRED | dnsPacket.DNSSEC_OK;
const secureQuery = {
type: 'query',
flags: flags,
questions: [{ type: 'A', name: 'example.com' }]
};
// Check for flags using bitwise AND
const hasRecursion = packet.flags & dnsPacket.RECURSION_DESIRED;
const isAuthoritative = packet.flags & dnsPacket.AUTHORITATIVE_ANSWER;Handling for DNS question section.
const { question } = require('dns-packet');
// Question encoding/decoding
question.encode(q, buf, offset);
question.decode(buf, offset);
question.encodingLength(q);
// Question structure
interface Question {
type: string; // Record type ('A', 'AAAA', 'MX', etc.)
class?: string; // DNS class (defaults to 'IN')
name: string; // Domain name to query
}Example:
const q = {
type: 'A',
class: 'IN', // Optional, defaults to 'IN'
name: 'example.com'
};
const encodedQuestion = question.encode(q);Handling for DNS answer, authority, and additional sections.
const { answer } = require('dns-packet');
// Answer encoding/decoding (also used for authorities and additionals)
answer.encode(a, buf, offset);
answer.decode(buf, offset);
answer.encodingLength(a);
// Answer structure (same for authorities and additionals)
interface Answer {
type: string; // Record type
class?: string; // DNS class (defaults to 'IN')
name: string; // Domain name
ttl?: number; // Time to live in seconds
// Additional properties based on record type
}Examples:
// A record answer
const aRecord = {
type: 'A',
name: 'example.com',
ttl: 300,
data: '192.168.1.1'
};
// MX record answer
const mxRecord = {
type: 'MX',
name: 'example.com',
ttl: 3600,
preference: 10,
exchange: 'mail.example.com'
};
// TXT record answer
const txtRecord = {
type: 'TXT',
name: 'example.com',
ttl: 300,
data: ['v=spf1 include:_spf.google.com ~all']
};Domain name encoding and decoding with compression support.
const { name } = require('dns-packet');
// Name encoding/decoding
name.encode(str, buf, offset, options);
name.decode(buf, offset, options);
name.encodingLength(str, options);
// Options for name encoding/decoding
interface NameOptions {
mail?: boolean; // Handle mail address format (@ as .)
}Usage Examples:
// Standard domain name
const domain = 'example.com';
const encoded = name.encode(domain);
const decoded = name.decode(encoded, 0);
// Mail address format (for SOA RNAME field)
const mailAddr = 'admin@example.com';
const encodedMail = name.encode('admin.example.com', buf, offset, { mail: true });Common packet validation patterns and error handling.
Query Packet:
const queryPacket = {
type: 'query',
id: Math.floor(Math.random() * 65536),
flags: dnsPacket.RECURSION_DESIRED,
questions: [{
type: 'A',
name: 'example.com'
}]
};Response Packet:
const responsePacket = {
type: 'response',
id: 1234, // Must match query ID
flags: dnsPacket.RECURSION_AVAILABLE | dnsPacket.AUTHORITATIVE_ANSWER,
questions: [/* original questions */],
answers: [{
type: 'A',
name: 'example.com',
ttl: 300,
data: '192.168.1.1'
}]
};Common error conditions and validation:
try {
const packet = dnsPacket.decode(buffer);
// Validate packet structure
if (!packet.questions || packet.questions.length === 0) {
throw new Error('No questions in packet');
}
// Check for truncation
if (packet.flags & dnsPacket.TRUNCATED_RESPONSE) {
console.warn('Response was truncated, consider using TCP');
}
} catch (error) {
if (error.message.includes('buffer overflow')) {
console.error('Malformed DNS packet');
} else if (error.message.includes('name too long')) {
console.error('Domain name exceeds maximum length');
} else {
console.error('DNS parsing error:', error.message);
}
}All packet structure functions track bytes consumed/produced:
const encoded = question.encode(q);
console.log('Question bytes:', question.encode.bytes);
const decoded = answer.decode(buf, offset);
console.log('Answer bytes consumed:', answer.decode.bytes);Install with Tessl CLI
npx tessl i tessl/npm-dns-packet