一个快速灵活的IPv4和IPv6非递归DNS服务器(C/C++代码实现)

在网络世界中,DNS(域名系统)在将人类友好的域名转换为计算机可以理解的IP地址方面发挥着关键作用。然而,设置和管理DNS服务器可能相当复杂,特别是当你需要一个既快速又灵活的解决方案时。这就是quick DNS的用武之地,它是一个轻量级且高效的DNS服务器,能够处理IPv4和IPv6查询,甚至可以在没有将地址绑定到接口的情况下工作。

概述

quick dns旨在提供一个非递归DNS服务器解决方案。它被设计为简单易设置和操作,即使在没有静态IP地址的环境中也能工作。服务器基于本地区域数据库响应DNS查询。

核心特性

  • 支持IPv4和IPv6:能够处理IPv4和IPv6查询,使其成为现代网络的多功能选择。
  • 非递归操作:它作为非递归服务器运行,意味着它不会将查询转发到其他DNS服务器,而是基于本地区域数据库响应。
  • 可定制性:允许通过命令行参数进行定制,使管理员能够根据特定需求调整其行为。
  • 效率:它旨在提供快速的DNS解析。

一个快速灵活的IPv4和IPv6非递归DNS服务器(C/C++代码实现)

int dns::build_error(const string &s)
{
   
   
	err = "qdns::";
	err += s;
	if (errno) {
   
   
		err += ": ";
		err += strerror(errno);
	}
	return -1;
}


int dns::init(const map<string, string> &args)
{
   
   
	if (args.count("laddr"))
		io = new (nothrow) socket_provider();
	else if (args.count("mon") > 0)
		io = new (nothrow) usipp_provider();

	if (!io)
		return build_error("init: OOM");

	if (io->init(args) < 0)
		return build_error(string("init:") + io->why());

	auto it = args.find("nxdomain");
	if (it != args.end())
		nxdomain = (strtoul(it->second.c_str(), NULL, 10) != 0);
	if (args.count("resend") > 0)
		resend = 1;

	return 0;
}


int dns::loop()
{
   
   
	if (!io)
		return build_error("loop: no IO provider initialized");

	string log = "";
	int r = 0;

	for (;;) {
   
   
		client.pkt = "";
		client.reply = "";

		if (io->recv(client.pkt) < 0) {
   
   
			cerr<<io->why()<<endl;
			continue;
		}
		src = io->sender();
		r = parse_packet(client.pkt, client.reply, log);

		if (r == 0) {
   
   
			// 返回0的回复等于重新发送的pkt
			if (io->resend(client.reply) < 0) {
   
   
				cerr<<src<<": "<<io->why()<<endl;
				continue;
			}
		} else if (r > 0) {
   
   
			if (io->reply(client.reply) < 0) {
   
   
				cerr<<src<<": "<<io->why()<<endl;
				continue;
			}
		} // in < 0 case, just log output

		cout<<src<<": "<<log<<endl;
	}

	return 0;
}


int dns::parse_packet(const string &query, string &response, string &log)
{
   
   
	using net_headers::dnshdr;
	using net_headers::dns_type;

	log = "invalid query";
	response = "";

	if (query.size() <= sizeof(dnshdr))
		return -1;

	const char *ptr = query.c_str(), *end_ptr = ptr + query.size();

	dnshdr hdr;
	memcpy(&hdr, query.c_str(), sizeof(dnshdr));
	ptr += sizeof(dnshdr);

	// dst端口53没有查询?
	if (hdr.qr != 0 || hdr.opcode != 0)
		return -1;

	if (hdr.q_count != htons(1))
		return -1;

	// skip QNAME
	auto qptr = ptr;
	while (*ptr != 0 && ptr < end_ptr)
		++ptr;
	++ptr;


	if (ptr + 2*sizeof(uint16_t) > end_ptr)
		return -1;

	uint16_t qtype = 0;
	memcpy(&qtype, ptr, sizeof(qtype));

	string qname = string(qptr, ptr - qptr);
	string question = string(qptr, ptr + 2*sizeof(uint16_t) - qptr);
	string fqdn = "";

	if (qname2host(qname, fqdn) <= 0)
		return -1;

	switch (ntohs(qtype)) {
   
   
	case dns_type::A:
		log = "A? ";
		break;
	case dns_type::AAAA:
		log = "AAAA? ";
		break;
	case dns_type::MX:
		log = "MX? ";
		break;
	case dns_type::CNAME:
		log = "CNAME? ";
		break;
	case dns_type::NS:
		log = "NS? ";
		break;
	case dns_type::PTR:
		log = "PTR? ";
		break;
	case dns_type::SRV:
		log = "SRV? ";
		break;
	case dns_type::TXT:
		log = "TXT? ";
		break;
	default:
		char s[32];
		snprintf(s, sizeof(s), "%d? ", ntohs(qtype));
		log = s;
	}

	log += fqdn;
	log += " -> ";

	bool found_domain = 1;
	auto it1 = exact_matches.find(make_pair(qname, qtype)), lit = it1;

	if (lit == exact_matches.end()) {
   
   
		string::size_type pos = string::npos, minpos = string::npos;

		// 尝试找到最大的子字符串匹配
		for (auto it2 = wild_matches.begin(); it2 != wild_matches.end(); ++it2) {
   
   
			if ((pos = qname.find(it2->first.first
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值