Created
April 16, 2011 18:00
-
-
Save fqrouter/923347 to your computer and use it in GitHub Desktop.
dnsproxycn的服务器
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <winsock2.h> | |
#include <Ws2tcpip.h> | |
#include <stdio.h> | |
#include <map> | |
#include <string> | |
using namespace std; | |
#define MAXSOCKET 10 | |
#define MINDELAY 500 | |
#define MAXDELAY 2000 | |
#define IP6HOSTFILE "ip6hosts.txt" | |
std::map <string, string> ip6Table; | |
typedef struct _UDPSOCK_INFO | |
{ | |
SOCKET UDPSocket; | |
SOCKADDR_STORAGE UDPFrom; | |
SOCKADDR_IN UDPTo; | |
char SendBuffer[1024]; | |
int SendBufferLen; | |
int gettimes; | |
DWORD start, end; | |
}UDPSOCK_INFO, *PUDPSOCK_INFO; | |
//DNS header structure | |
struct DNS_HEADER | |
{ | |
unsigned short id; // identification number | |
unsigned char rd :1; // recursion desired | |
unsigned char tc :1; // truncated message | |
unsigned char aa :1; // authoritive answer | |
unsigned char opcode :4; // purpose of message | |
unsigned char qr :1; // query/response flag | |
unsigned char rcode :4; // response code | |
unsigned char cd :1; // checking disabled | |
unsigned char ad :1; // authenticated data | |
unsigned char z :1; // its z! reserved | |
unsigned char ra :1; // recursion available | |
unsigned char q_count_h; // number of question entries | |
unsigned char q_count_l; // number of question entries | |
unsigned char ans_count_h; // number of answer entries | |
unsigned char ans_count_l; // number of answer entries | |
unsigned char auth_count_h; // number of authority entries | |
unsigned char auth_count_l; // number of authority entries | |
unsigned char add_count_h; // number of resource entries | |
unsigned char add_count_l; // number of resource entries | |
}; | |
#pragma pack(push, 1) | |
struct RES_RECORD | |
{ | |
char name[2]; | |
unsigned char type_h; | |
unsigned char type_l; | |
unsigned char _class_h; | |
unsigned char _class_l; | |
unsigned char ttl_hh; | |
unsigned char ttl_h; | |
unsigned char ttl_l; | |
unsigned char ttl_ll; | |
unsigned char data_len_h; | |
unsigned char data_len_l; | |
in6_addr i6addr; | |
}; | |
#pragma pack(pop) | |
void CreateIP6Table (); | |
int CheckIP6 ( char*, in6_addr* ); | |
int main(int argc, char **argv) | |
{ | |
WSADATA wsaData; | |
SOCKET DNSUDP; | |
SOCKADDR_IN UDPAddr_in; | |
struct fd_set fds_read, fds_write; | |
struct timeval timeout; | |
int selectret, i; | |
UDPSOCK_INFO UDPSock[MAXSOCKET]; | |
CreateIP6Table(); | |
// Initialize Winsock version 2.2 | |
if( WSAStartup(MAKEWORD(2,2), &wsaData) != 0) | |
{ | |
printf("Server: WSAStartup failed with error %ld\n", WSAGetLastError()); | |
return -1; | |
} | |
DNSUDP = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); | |
if (DNSUDP == INVALID_SOCKET) | |
{ | |
printf("Server: Error at udp socket(): %ld\n", WSAGetLastError()); | |
WSACleanup(); | |
return -1; | |
} | |
UDPAddr_in.sin_family = AF_INET; | |
UDPAddr_in.sin_port = htons(53); | |
UDPAddr_in.sin_addr.s_addr = htonl(INADDR_ANY); | |
if (bind(DNSUDP, (SOCKADDR *)&UDPAddr_in, sizeof(UDPAddr_in)) == SOCKET_ERROR) | |
{ | |
printf("Server: udp bind() failed! Error: %ld.\n", WSAGetLastError()); | |
closesocket(DNSUDP); | |
WSACleanup(); | |
return -1; | |
} | |
printf("DNS Proxy Starting...\n"); | |
for ( i=0; i<MAXSOCKET; i++) | |
UDPSock[i].UDPSocket = INVALID_SOCKET; | |
timeout.tv_sec = 0; | |
timeout.tv_usec = 100; | |
while (true) | |
{ | |
FD_ZERO(&fds_read); | |
FD_ZERO(&fds_write); | |
FD_SET(DNSUDP, &fds_read); | |
for (i=0; i<MAXSOCKET; i++) | |
{ | |
if (UDPSock[i].UDPSocket != INVALID_SOCKET) | |
FD_SET(UDPSock[i].UDPSocket, &fds_read); | |
} | |
selectret = select(0, &fds_read, &fds_write, 0, &timeout); | |
switch (selectret) | |
{ | |
case 0: | |
// Timed out, do whatever you want to handle this situation | |
//printf("Server: Timeout while waiting !...\n"); | |
break; | |
case SOCKET_ERROR: | |
printf("Server: Some error encountered with code number: %ld\n", WSAGetLastError()); | |
break; | |
default: | |
if (FD_ISSET(DNSUDP, &fds_read)!=0) | |
{ | |
char Buffer[1024]; | |
SOCKADDR_STORAGE from; | |
int fromlen, bytecount, sockNo; | |
fromlen = sizeof(SOCKADDR_STORAGE); | |
bytecount = recvfrom(DNSUDP, Buffer, 1024, 0, (SOCKADDR *)&from, &fromlen); | |
//printf("read %d bytes from client\n", bytecount); | |
if (bytecount > 0) | |
{ | |
sockNo = 10000; | |
for (i=0; i<MAXSOCKET; i++) | |
{ | |
if (UDPSock[i].UDPSocket == INVALID_SOCKET) | |
{ | |
sockNo = i; | |
break; | |
} | |
} | |
if (sockNo != 10000) | |
{ | |
UDPSock[sockNo].UDPFrom = from; | |
UDPSock[sockNo].SendBufferLen = bytecount; | |
int j; | |
for (j=0; j< bytecount; j++) | |
{ | |
UDPSock[sockNo].SendBuffer[j] = Buffer[j]; | |
//printf("%02X ", (unsigned char)Buffer[j]); | |
} | |
//printf("\n"); | |
//for (j=0; j< bytecount; j++) | |
//{ | |
// if (Buffer[j] < 0x20) printf(". "); else printf("%c ", Buffer[j]); | |
//} | |
//printf("\n"); | |
UDPSock[sockNo].UDPSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); | |
if (UDPSock[sockNo].UDPSocket == INVALID_SOCKET) | |
{ | |
printf("Server: Error at udp socket(), error code: %ld.\n", WSAGetLastError()); | |
} | |
else | |
{ | |
//printf("Server: udp socket(%d) is OK!\n", sockNo); | |
//////////////////////////////////////////////////////////////////// | |
in6_addr i6addr; | |
int ret = CheckIP6( Buffer, &i6addr ); | |
if (ret!=0) | |
{ | |
struct DNS_HEADER *dns = NULL; | |
struct RES_RECORD *rr = NULL; | |
dns = (struct DNS_HEADER *)&Buffer; | |
dns->qr = 1; | |
dns->ra = 1; | |
dns->ans_count_h = 0; | |
dns->ans_count_l = 1; | |
rr = (struct RES_RECORD *)&Buffer[bytecount]; | |
rr->name[0]=(char)0xc0; | |
rr->name[1]=(char)0x0c; | |
rr->type_h = 0; | |
rr->type_l = 28; | |
rr->_class_h = 0; | |
rr->_class_l = 1; | |
rr->ttl_hh = 0x3f; | |
rr->ttl_h = 0xff; | |
rr->ttl_l = 0xff; | |
rr->ttl_ll = 0xff; | |
rr->data_len_h = 0; | |
rr->data_len_l = 16; | |
rr->i6addr = i6addr; | |
bytecount += 28; | |
//for (j=0; j< bytecount; j++) | |
//{ | |
// printf("%02X ", (unsigned char)Buffer[j]); | |
//} | |
//printf("\n"); | |
for (j=0; j< bytecount; j++) | |
{ | |
UDPSock[sockNo].SendBuffer[j] = Buffer[j]; | |
} | |
UDPSock[sockNo].SendBufferLen = bytecount; | |
UDPSock[sockNo].start = GetTickCount(); | |
UDPSock[sockNo].end = UDPSock[sockNo].start; | |
UDPSock[sockNo].gettimes = 100; | |
} | |
//////////////////////////////////////////////////////////////////// | |
else | |
{ | |
UDPAddr_in.sin_family = AF_INET; | |
UDPAddr_in.sin_addr.s_addr = (rand()>=16384)?inet_addr( "8.8.8.8" ):inet_addr("8.8.4.4"); | |
//UDPAddr_in.sin_addr.s_addr = inet_addr( "8.8.8.8" ); | |
UDPAddr_in.sin_port = htons( 53 ); | |
UDPSock[sockNo].UDPTo = UDPAddr_in; | |
// Connect to server. | |
if (sendto(UDPSock[sockNo].UDPSocket, UDPSock[sockNo].SendBuffer, UDPSock[sockNo].SendBufferLen, 0, (SOCKADDR *)&UDPAddr_in, sizeof(UDPAddr_in))==-1) | |
{ | |
printf( "Failed to sendto(), error code: %ld.\n", WSAGetLastError()); | |
closesocket(UDPSock[sockNo].UDPSocket); | |
UDPSock[sockNo].UDPSocket=INVALID_SOCKET; | |
} | |
else | |
{ | |
UDPSock[sockNo].start = GetTickCount(); | |
UDPSock[sockNo].end = UDPSock[sockNo].start; | |
UDPSock[sockNo].gettimes = 0; | |
} | |
} | |
} | |
} | |
} | |
} | |
for (i=0; i<MAXSOCKET; i++) | |
{ | |
if ((FD_ISSET(UDPSock[i].UDPSocket, &fds_read)!=0)) | |
{ | |
char Buffer[1024]; | |
int bytecount; | |
int fromlen; | |
fromlen = sizeof(SOCKADDR_STORAGE); | |
bytecount = recvfrom(UDPSock[i].UDPSocket, Buffer, 1024, 0, (SOCKADDR *)&UDPSock[i].UDPTo, &fromlen); | |
UDPSock[i].end = GetTickCount(); | |
UDPSock[i].gettimes ++; | |
//printf("Read from DNS server! byte:%d\n", bytecount); | |
if(bytecount>0) | |
{ | |
UDPSock[i].SendBufferLen = bytecount; | |
int j; | |
for ( j=0; j<bytecount; j++) | |
{ | |
UDPSock[i].SendBuffer[j] = Buffer[j]; | |
//printf("%02X ", (unsigned char)Buffer[j]); | |
} | |
//printf("\n"); | |
//for ( j=0; j<bytecount; j++) | |
// if (Buffer[j]<0x20) printf(". "); else printf("%c ",Buffer[j]); | |
//printf("\n"); | |
} | |
else | |
{ | |
closesocket(UDPSock[i].UDPSocket); | |
UDPSock[i].UDPSocket = INVALID_SOCKET; | |
} | |
} | |
} | |
break; | |
} | |
for (i=0; i<MAXSOCKET; i++) | |
{ | |
DWORD tmnow; | |
DWORD delay; | |
if (UDPSock[i].UDPSocket != INVALID_SOCKET) | |
{ | |
tmnow = GetTickCount(); | |
delay = tmnow - UDPSock[i].start; | |
if (UDPSock[i].gettimes > 0) | |
{ | |
if ( (delay > MINDELAY)||(UDPSock[i].gettimes==100) ) | |
{ | |
int fromlen = sizeof(SOCKADDR_STORAGE); | |
int ret = sendto(DNSUDP, UDPSock[i].SendBuffer, UDPSock[i].SendBufferLen, 0, (SOCKADDR *)&UDPSock[i].UDPFrom, fromlen); | |
//if (UDPSock[i].gettimes > 1) | |
//{ | |
if (UDPSock[i].gettimes == 100) | |
printf("used %dms, !! local force ipv6 !!\t", delay); | |
else | |
printf("used %dms, got %d UDP(s) in %dms\t", delay, UDPSock[i].gettimes, UDPSock[i].end - UDPSock[i].start ); | |
int j; | |
//for ( j=0; j<UDPSock[i].SendBufferLen; j++) | |
//{ | |
// printf("%02X ", (unsigned char)UDPSock[i].SendBuffer[j]); | |
//} | |
//printf("\n"); | |
//for ( j=0; j<UDPSock[i].SendBufferLen; j++) | |
// if (UDPSock[i].SendBuffer[j]<0x20) printf(". "); else printf("%c ",UDPSock[i].SendBuffer[j]); | |
//printf("\n"); | |
j = 13; | |
while (UDPSock[i].SendBuffer[j] != 0 ) | |
{ | |
if (UDPSock[i].SendBuffer[j]<0x20) printf("."); else printf("%c", UDPSock[i].SendBuffer[j]); | |
j++; | |
} | |
printf("\n"); | |
//} | |
closesocket(UDPSock[i].UDPSocket); | |
UDPSock[i].UDPSocket = INVALID_SOCKET; | |
} | |
} | |
else | |
{ | |
if ( delay > MAXDELAY ) | |
{ | |
printf("overtime! used %dms, got %d UDP\t", delay, UDPSock[i].gettimes); | |
int j = 13; | |
while (UDPSock[i].SendBuffer[j] != 0 ) | |
{ | |
if (UDPSock[i].SendBuffer[j]<0x20) printf("."); else printf("%c", UDPSock[i].SendBuffer[j]); | |
j++; | |
} | |
printf("\n"); | |
closesocket(UDPSock[i].UDPSocket); | |
UDPSock[i].UDPSocket = INVALID_SOCKET; | |
} | |
} | |
} | |
} | |
} | |
printf("Server: Finished receiving. Closing the socket...\n"); | |
if (closesocket(DNSUDP) != 0) | |
printf("Server: udp closesocket() failed! Error code: %ld\n", WSAGetLastError()); | |
else | |
printf("Server: udp closesocket() is OK...\n"); | |
printf("Server: Cleaning up...\n"); | |
if(WSACleanup() != 0) | |
printf("Server: WSACleanup() failed! Error code: %ld\n", WSAGetLastError()); | |
else | |
printf("Server: WSACleanup() is OK\n"); | |
return 0; | |
} | |
/////////////////////////////////////////////////////////// | |
void CreateIP6Table () | |
{ | |
FILE *IP6File; | |
char filename[255], line[255], addr[100], hostname[100]; | |
int ret; | |
ret = GetCurrentDirectory(255, filename); | |
strcat_s ( filename, 255, "\\"); | |
strcat_s ( filename, 255, IP6HOSTFILE); | |
//printf("%s\n", filename); | |
ret = fopen_s( &IP6File, filename, "r"); | |
if (ret != 0) | |
{ | |
printf("open ip6 hosts file failure!\n"); | |
return; | |
} | |
//printf("ip6 table creating...\n\n"); | |
while(fgets(line,sizeof(line),IP6File)) | |
{ | |
int index, num, len ; | |
num = 0; index = 0; | |
len = strlen(line); | |
if ( (len>0) && (line[0]!='#') && (isspace(line[0])==0) ) | |
{ | |
//while ( (index<len)&&(isspace(line[index])!= 0) ) index++; | |
while ( (index<len)&&(isspace(line[index])== 0) ) addr[num++] = line[index++]; | |
addr[num]='\0'; | |
while ( (index<len)&&(isspace(line[index])!= 0) ) index++; | |
num = 0; | |
while ( (index<len)&&(isspace(line[index])== 0) ) hostname[num++] = line[index++]; | |
hostname[num]='\0'; | |
//printf("%s\t%s\n", addr, hostname); | |
ip6Table.insert( pair <string, string> (hostname, addr)); | |
} | |
} | |
/* | |
map<string,string>::iterator p; | |
strcpy_s(hostname, 100, "www.google.com"); | |
p = ip6Table.find(hostname); | |
if (p != ip6Table.end()) | |
strcpy_s(addr, 100, (*p).second.c_str()); | |
printf("%s\n", addr); | |
*/ | |
fclose(IP6File); | |
//printf("ip6 table created.\n\n"); | |
} | |
int CheckIP6(char* Buffer, in6_addr* i6addr) | |
{ | |
int ret, i, dot; | |
char hostname[100], addr[100]; | |
i=13; dot=0; | |
while ( Buffer[i] != 0 ) | |
{ | |
if (Buffer[i]<0x20) | |
{ | |
hostname[i-13]='.'; | |
dot++; | |
} | |
else hostname[i-13] = Buffer[i]; | |
i++; | |
} | |
hostname[i-13]='\0'; | |
addr[0]='\0'; | |
map<string,string>::iterator p; | |
p = ip6Table.find(hostname); | |
if (p == ip6Table.end()) | |
{ | |
if (dot>1) | |
{ | |
int j; | |
i=0; j=0; | |
hostname[j]='*'; j++; | |
while ( hostname[i]!='.') i++; | |
while ( hostname[i]!='\0') hostname[j++]=hostname[i++]; | |
hostname[j] = '\0'; | |
p = ip6Table.find(hostname); | |
} | |
else return 0; | |
} | |
if (p != ip6Table.end()) | |
{ | |
strcpy_s(addr, 100, (*p).second.c_str()); | |
//printf("%s %s\n", hostname, addr); | |
sockaddr_in6 saddr; | |
int saddrLen = sizeof(saddr); | |
ret = WSAStringToAddress(addr, AF_INET6, NULL, (LPSOCKADDR)&saddr, &saddrLen); | |
if (ret != 0) | |
{ | |
printf("wsastringtoaddress failure! Error code: %ld\n", WSAGetLastError()); | |
return 0; | |
} | |
else | |
{ | |
*i6addr = saddr.sin6_addr; | |
return 1; | |
} | |
} | |
else | |
{ | |
return 0; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment