// mydnsrelay.cpp : 定义控制台应用程序的入口点。
//
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <windows.h>
#include <time.h>
#include <string>
#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
#pragma comment(lib, "Ws2_32.lib")
#define DEF_DNS_ADDRESS "202.106.0.20" //外部DNS服务器地址
#define LOCAL_ADDRESS "127.0.0.1" //本地DNS服务器地址
#define DNS_PORT 53 //进行DNS服务的53端口
#define BUF_SIZE 512
#define LENGTH 1024
#define AMOUNT 300
#define NOTFOUND -1
//DNS报文首部
typedef struct DNSHeader
{
unsigned short ID;
unsigned short Flags;
unsigned short QuestNum;
unsigned short AnswerNum;
unsigned short AuthorNum;
unsigned short AdditionNum;
} DNSHDR, *pDNSHDR;
//DNS域名解析表结构
typedef struct translate
{
string IP; //IP地址
string domain; //域名
} Translate;
//ID转换表结构
typedef struct IDChange
{
unsigned short oldID; //原有ID
BOOL done; //标记是否完成解析
SOCKADDR_IN client; //请求者套接字地址
} IDTransform;
Translate DNS_table[AMOUNT]; //DNS域名解析表
IDTransform IDTransTable[AMOUNT]; //ID转换表
int IDcount = 0; //转换表中的条目个数
char url[LENGTH]; //域名
SYSTEMTIME sys; //系统时间
int Day, Hour, Minute, Second, Milliseconds;//保存系统时间的变量
//函数:获取域名解析表
int GetTable(char *tablePath)
{
int i=0, j, pos=0;
string table[AMOUNT];
ifstream infile(tablePath, ios::in); //以读入方式打开文本文件
if(! infile) {
cerr << "Open" << tablePath << "error!" <<endl;
exit(1);
}
//每次从文件中读入一行,直至读到文件结束符为止
while (getline(infile, table[i]) && i < AMOUNT)
i++;
if (i == AMOUNT)
cout << "The DNS table memory is full. " << endl;
for (j = 0; j < i-1; j++)
{
pos = table[j].find(' ');
if (pos > table[j].size())
cout << "The record is not in a correct format. " << endl;
else
{
DNS_table[j].IP = table[j].substr(0, pos);
DNS_table[j].domain = table[j].substr(pos+1);
}
}
infile.close(); //关闭文件
cout << "Load records succeed. " << endl;
return i-1; //返回域名解析表中条目个数
}
//函数:获取DNS请求中的域名
void GetUrl(char *recvbuf, int recvnum)//字符串、字符串长度
{
char urlname[LENGTH];
int i = 0, j, k = 0;
memset(url, 0, LENGTH);
memcpy(urlname, &(recvbuf[sizeof(DNSHDR)]), recvnum-16); //获取请求报文中的域名表示
int len = strlen(urlname);
//域名转换
while (i < len)
{
if (urlname[i] > 0 && urlname[i] <= 63)
for (j = urlname[i], i++; j > 0; j--, i++, k++)
url[k] = urlname[i];
if (urlname[i] != 0)
{
url[k] = '.';
k++;
}
}
url[k] = '\0';
}
//函数:判断是否在表中找到DNS请求中的域名,找到返回下标
int IsFind(char* url, int num)
{
int find = NOTFOUND;
char* domain;
for (int i = 0; i < num; i++)
{
domain = (char *)DNS_table[i].domain.c_str();
if (strcmp(domain, url) == 0)
{ //找到
find = i;
break;
}
}
return find;
}
//函数:将请求ID转换为新的ID,并将信息写入ID转换表中
unsigned short RegisterNewID (unsigned short oID, SOCKADDR_IN temp, BOOL ifdone)
{
if(IDcount == AMOUNT)
IDcount = 0;
//srand(time(NULL));
IDTransTable[IDcount].oldID = oID;
IDTransTable[IDcount].client = temp;
IDTransTable[IDcount].done = ifdone;
IDcount++;
return (unsigned short)(IDcount-1); //以表中下标作为新的ID
}
//函数:打印 时间 newID 功能 域名 IP
void DisplayInfo(unsigned short newID, int find)
{
//打印时间
GetLocalTime( &sys );
if(sys.wMilliseconds >= Milliseconds)
{
cout << setiosflags(ios::right) << setw(7) << setfill(' ') << (((sys.wDay - Day) * 24 + sys.wHour - Hour) * 60 + sys.wMinute - Minute) * 60 + sys.wSecond - Second;//设置宽度为7,right对齐方式
cout << '.' << setiosflags(ios::right) << setw(3) << setfill('0') << sys.wMilliseconds - Milliseconds;
}
else {
cout << setiosflags(ios::right) << setw(7) << setfill(' ') << (((sys.wDay - Day) * 24 + sys.wHour - Hour) * 60 + sys.wMinute - Minute) * 60 + sys.wSecond - Second - 1;//设置宽度为7,right对齐方式
cout << '.' << setiosflags(ios::right) << setw(3) << setfill('0') << 1000 + sys.wMilliseconds - Milliseconds;
}
cout << " ";
//打印转换后新的ID
cout.setf(ios::left);
cout << setiosflags(ios::left) << setw(4) << setfill(' ') << newID;
cout << " ";
//在表中没有找到DNS请求中的域名
if (find == NOTFOUND)
{
//中继功能
cout.setf(ios::left);
cout << setiosflags(ios::left) << setw(6) << setfill(' ') << "中继";
cout << " ";
//打印域名
cout.setf(ios::left);
cout << setiosflags(ios::left) << setw(20) << setfill(' ') << url;
cout << " ";
cout.setf(ios::left);
cout << setiosflags(ios::left) << setw(20) << setfill(' ') << endl;
}
//在表中找到DNS请求中的域名
else {
if(DNS_table[find].IP == "0.0.0.0") //不良网站拦截
{
//屏蔽功能
cout.setf(ios::left);
cout << setiosflags(ios::left) << setw(6) << setfill(' ') << "屏蔽";
cout << " ";
//打印域名(加*)
cout.setf(ios::left);
cout << "*" << setiosflags(ios::left) << setw(19) << setfill(' ') << url;
cout << " ";
cout.setf(ios::left);
cout << setiosflags(ios::left) << setw(20) << setfill(' ') << endl;
}
//检索结果为普通IP地址,则向客户返回这个地址
else {
//服务器功能
cout.setf(ios::left);
cout << setiosflags(ios::left) << setw(6) << setfill(' ') << "服务器";
cout << " ";
//打印域名
cout.setf(ios::left);
cout << "*" << setiosflags(ios::left) << setw(19) << setfill(' ') << url;
cout << " ";
//打印IP
cout.setf(ios::left);
cout << setiosflags(ios::left) << setw(20) << setfill(' ') << DNS_table[find].IP << endl;
}
}
}
int main(int argc, char** argv)
{
WSADATA wsaData;
SOCKET socketServer, socketLocal; //本地DNS和外部DNS两个套接字
SOCKADDR_IN serverName, clientName, localName; //本地DNS、外部DNS和请求端三个网络套接字地址
char sendbuf[BUF_SIZE];
char recvbuf[BUF_SIZE];
char tablePath[100];
char outerDns[16];
int iLen_cli, iSend, iRecv;
int num;
fd_set fdset;//套接字集合
struct timeval t1;
if (argc == 1)
{
strcpy(outerDns, DEF_DNS_ADDRESS);
strcpy(tablePath, "D:\\document\\大学课程\\DNS\\dnsrelay.txt");
}
else if (argc == 2)
{
strcpy(outerDns, argv[1]);
strcpy(tablePath, "D:\\document\\大学课程\\DNS\\dnsrelay.txt");
}
else if (argc == 3)
{
strcpy(outerDns, argv[1]);
strcpy(tablePath, argv[2]);
}
num = GetTable(tablePath); //获取域名解析表
//保存系统的时间
GetLocalTime(&sys);
Day = sys.wDay;
Hour = sys.wHour;
Minute = sys.wMinute;
Second = sys.wSecond;
Milliseconds = sys.wMilliseconds;
for (int i=0; i < AMOUNT; i++)
{ //初始化ID转换表
IDTransTable[i].oldID = 0;
IDTransTable[i].done = FALSE;
memset(&(IDTransTable[i].client), 0, sizeof(SOCKADDR_IN));
}
WSAStartup(MAKEWORD(2,2), &wsaData); //初始化ws2_32.dll动态链接库
//创建本地DNS和外部DNS套接字
socketServer = socket(AF_INET, SOCK_DGRAM, 0);
socketLocal = socket(AF_INET, SOCK_DGRAM, 0);
//设置本地DNS和外部DNS两个套接字
localName.sin_family = AF_INET;
localName.sin_port = htons(DNS_PORT);
localName.sin_addr.s_addr = inet_addr(LOCAL_ADDRESS);//(LOCAL_ADDRESS);INADDR_ANY
serverName.sin_family = AF_INET;
serverName.sin_port = htons(DNS_PORT);
serverName.sin_addr.s_addr = inet_addr(outerDns);
const char on = 1;
if(setsockopt(socketLocal,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)))
cout << "setsockopt failed";
//绑定本地DNS服务器地址
if (bind(socketLocal, (SOCKADDR*)&localName, sizeof(localName)))
{
cout << "Binding Port 53 failed." << endl;
exit(1);
}
else
cout << "Binding Port 53 succeed." << endl;
//本地DNS服务器的具体操作
while (1)
{
DNS.rar_DNS中继服务器_DNS服务器编程_dns 服务器_dns服务器_pudn dns server
版权申诉
82 浏览量
2022-09-19
19:55:28
上传
评论
收藏 6.55MB RAR 举报
邓凌佳
- 粉丝: 65
- 资源: 1万+
最新资源
- 批量将py编译为pyd文件.atbx
- Python项目-学生管理系统
- verilog HDL硬件语法设计包括算术运算三人表决器Verilog的阻塞和非阻塞赋值源码例程quartus13.1工程合集
- 【文章话题分类论文】OpenAlex Topic Classification Whitepaper
- linux学习常用命令
- 功率拓扑快速参考指南-ti,TI官方出品
- 开关电源拓朴图表,各种电路拓扑表格
- 登录和注册 前端:vue3+iview plus +axios 后台:spring boot +mybatis
- 软件测试入门简介:从基础到实践的全面介绍
- 2024CDA Level Ⅰ 认证考试大纲
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈