Use multithreading instead
This commit is contained in:
parent
ac28689fac
commit
a1c87d2bee
6
Makefile
6
Makefile
@ -1,11 +1,11 @@
|
|||||||
CROSS_COMPILE ?=
|
CROSS_COMPILE ?=
|
||||||
CC := $(CROSS_COMPILE)gcc
|
CC := $(CROSS_COMPILE)gcc
|
||||||
STRIP := $(CROSS_COMPILE)strip
|
STRIP := $(CROSS_COMPILE)strip
|
||||||
CFLAGS += -g -O2 -Wall
|
CFLAGS += -g -O2 -Wall -pthread
|
||||||
LIBS = -pthread -static
|
LIBS = -static
|
||||||
OBJ := CProxy
|
OBJ := CProxy
|
||||||
|
|
||||||
all: proxy.o http.o request.o picohttpparser.o conf.o timeout.o kill.o help.o
|
all: proxy.o http.o httpdns.o request.o picohttpparser.o conf.o timeout.o kill.o help.o
|
||||||
$(CC) $(CFLAGS) -o $(OBJ) $^ $(LIBS)
|
$(CC) $(CFLAGS) -o $(OBJ) $^ $(LIBS)
|
||||||
.c.o:
|
.c.o:
|
||||||
$(CC) $(CFLAGS) -c $< $(LIBS)
|
$(CC) $(CFLAGS) -c $< $(LIBS)
|
||||||
|
2
conf.h
2
conf.h
@ -50,4 +50,6 @@ char *strncpy_(char *dest, const char *src, size_t n);
|
|||||||
void read_conf(char *file, conf * p);
|
void read_conf(char *file, conf * p);
|
||||||
void free_conf(conf * p);
|
void free_conf(conf * p);
|
||||||
|
|
||||||
|
void printfconf(conf * configure);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
2
http.c
2
http.c
@ -4,7 +4,7 @@
|
|||||||
int sslEncodeCode;
|
int sslEncodeCode;
|
||||||
|
|
||||||
/* 对数据进行编码 */
|
/* 对数据进行编码 */
|
||||||
static void dataEncode(char *data, int data_len)
|
void dataEncode(char *data, int data_len)
|
||||||
{
|
{
|
||||||
if (sslEncodeCode)
|
if (sslEncodeCode)
|
||||||
while (data_len-- > 0)
|
while (data_len-- > 0)
|
||||||
|
2
http.h
2
http.h
@ -10,6 +10,7 @@
|
|||||||
int remote_port;
|
int remote_port;
|
||||||
char remote_host[128];
|
char remote_host[128];
|
||||||
|
|
||||||
|
|
||||||
extern int sslEncodeCode;
|
extern int sslEncodeCode;
|
||||||
|
|
||||||
typedef struct conn_t {
|
typedef struct conn_t {
|
||||||
@ -25,5 +26,6 @@ extern void clienttoserver(conn * in);
|
|||||||
extern void close_connection(conn * conn);
|
extern void close_connection(conn * conn);
|
||||||
|
|
||||||
extern char *request_head(conn * in, conf * configure);
|
extern char *request_head(conn * in, conf * configure);
|
||||||
|
void dataEncode(char *data, int data_len);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
450
httpdns.c
Normal file
450
httpdns.c
Normal file
@ -0,0 +1,450 @@
|
|||||||
|
#include "httpdns.h"
|
||||||
|
|
||||||
|
int encodeCode=0;
|
||||||
|
/* hosts变量 */
|
||||||
|
char *hosts_path = NULL;
|
||||||
|
FILE *hostsfp = NULL;
|
||||||
|
struct dns_hosts *hosts, *last_hosts = NULL;
|
||||||
|
|
||||||
|
/* encode domain and ipAddress */
|
||||||
|
static void dataEncode(unsigned char *data, int data_len)
|
||||||
|
{
|
||||||
|
while (data_len-- > 0)
|
||||||
|
data[data_len] ^= encodeCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
int read_hosts_file(char *path)
|
||||||
|
{
|
||||||
|
char *ip_begin, *ip_end, *host_begin, *host_end, *buff, *next_line;
|
||||||
|
int file_size, i;
|
||||||
|
|
||||||
|
hosts = last_hosts = NULL;
|
||||||
|
if ((hostsfp = fopen(path, "r")) == NULL) {
|
||||||
|
fputs("error hosts file path", stderr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
//读取文件内容
|
||||||
|
fseek(hostsfp, 0, SEEK_END);
|
||||||
|
file_size = ftell(hostsfp);
|
||||||
|
//文件没有内容则不用读取
|
||||||
|
if (file_size == 0)
|
||||||
|
return 0;
|
||||||
|
if ((buff = (char *)alloca(file_size + 1)) == NULL) {
|
||||||
|
fclose(hostsfp);
|
||||||
|
fputs("out of memory", stderr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
rewind(hostsfp);
|
||||||
|
fread(buff, file_size, 1, hostsfp);
|
||||||
|
*(buff + file_size) = '\0';
|
||||||
|
fclose(hostsfp);
|
||||||
|
|
||||||
|
struct dns_hosts *h = NULL;
|
||||||
|
for (ip_begin = buff; ip_begin; ip_begin = next_line) {
|
||||||
|
next_line = strchr(ip_begin, '\n');
|
||||||
|
if (next_line != NULL)
|
||||||
|
*next_line++ = '\0';
|
||||||
|
while (*ip_begin == '\t' || *ip_begin == ' ' || *ip_begin == '\r')
|
||||||
|
if (*ip_begin++ == '\0')
|
||||||
|
continue;
|
||||||
|
for (i = 0, ip_end = ip_begin; *ip_end != ' ' && *ip_end != '\t' && *ip_end != '\r' && *ip_end != '\0'; ip_end++) {
|
||||||
|
if (*ip_end == '.')
|
||||||
|
i++;
|
||||||
|
else if (*ip_end == '\0')
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (i != 3)
|
||||||
|
continue;
|
||||||
|
for (host_begin = ip_end; *host_begin == '\t' || *host_begin == ' ' || *host_begin == '\r';) {
|
||||||
|
if (*host_begin++ == '\0')
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (host_end = host_begin; *host_end != ' ' && *host_end != '\t' && *host_end != '\r' && *host_end != '\n' && *host_end != '\0'; host_end++) ;
|
||||||
|
if (h) {
|
||||||
|
h->next = (struct dns_hosts *)malloc(sizeof(struct dns_hosts));
|
||||||
|
if (h->next == NULL)
|
||||||
|
return 1;
|
||||||
|
h = h->next;
|
||||||
|
} else {
|
||||||
|
hosts = h = (struct dns_hosts *)malloc(sizeof(struct dns_hosts));
|
||||||
|
if (hosts == NULL) {
|
||||||
|
fputs("out of memory", stderr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
h->next = NULL;
|
||||||
|
h->ip = strndup(ip_begin, ip_end - ip_begin);
|
||||||
|
if (*(host_end - 1) == '.')
|
||||||
|
host_end--;
|
||||||
|
h->host = strndup(host_begin, host_end - host_begin);
|
||||||
|
if (h->ip == NULL || h->host == NULL) {
|
||||||
|
fputs("out of memory", stderr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
last_hosts = h;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *hosts_lookup(char *host)
|
||||||
|
{
|
||||||
|
struct dns_hosts *h;
|
||||||
|
|
||||||
|
h = hosts;
|
||||||
|
while (h) {
|
||||||
|
if (strcmp(h->host, host) == 0)
|
||||||
|
return h->ip;
|
||||||
|
h = h->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void close_client(dns_t * dns)
|
||||||
|
{
|
||||||
|
close(dns->fd);
|
||||||
|
if (dns->http_rsp_len != sizeof(ERROR_MSG) - 1) //ERROR_MSG not free()
|
||||||
|
free(dns->http_rsp);
|
||||||
|
dns->http_rsp = NULL;
|
||||||
|
dns->sent_len = dns->dns_req_len = 0;
|
||||||
|
dns->fd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void build_http_rsp(dns_t * dns, char *ips)
|
||||||
|
{
|
||||||
|
int ips_len = strlen(ips);
|
||||||
|
|
||||||
|
if (encodeCode)
|
||||||
|
dataEncode((unsigned char *)ips, ips_len);
|
||||||
|
dns->http_rsp_len = sizeof(SUCCESS_HEADER) - 1 + ips_len;
|
||||||
|
dns->http_rsp = (char *)malloc(dns->http_rsp_len + 1);
|
||||||
|
if (dns->http_rsp == NULL)
|
||||||
|
return;
|
||||||
|
strcpy(dns->http_rsp, SUCCESS_HEADER);
|
||||||
|
memcpy(dns->http_rsp + sizeof(SUCCESS_HEADER) - 1, ips, ips_len);
|
||||||
|
dns->sent_len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void response_client(dns_t * out)
|
||||||
|
{
|
||||||
|
int write_len = write(out->fd, out->http_rsp + out->sent_len, out->http_rsp_len - out->sent_len);
|
||||||
|
if (write_len == out->http_rsp_len - out->sent_len || write_len == -1)
|
||||||
|
close_client(out);
|
||||||
|
else
|
||||||
|
out->sent_len += write_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void build_dns_req(dns_t * dns, char *domain, int domain_size)
|
||||||
|
{
|
||||||
|
char *p, *_p;
|
||||||
|
|
||||||
|
p = dns->dns_req + 12;
|
||||||
|
memcpy(p + 1, domain, domain_size + 1); //copy '\0'
|
||||||
|
while ((_p = strchr(p + 1, '.')) != NULL) {
|
||||||
|
*p = _p - p - 1;
|
||||||
|
p = _p;
|
||||||
|
}
|
||||||
|
*p = strlen(p + 1);
|
||||||
|
p = dns->dns_req + 14 + domain_size;
|
||||||
|
*p++ = 0;
|
||||||
|
*p++ = 1;
|
||||||
|
*p++ = 0;
|
||||||
|
*p++ = 1;
|
||||||
|
dns->dns_req_len = p - dns->dns_req;
|
||||||
|
}
|
||||||
|
|
||||||
|
int send_dns_req(char *dns_req, int req_len)
|
||||||
|
{
|
||||||
|
int write_len;
|
||||||
|
|
||||||
|
write_len = write(dstFd, dns_req, req_len);
|
||||||
|
if (write_len == req_len)
|
||||||
|
return 0;
|
||||||
|
return write_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void query_dns()
|
||||||
|
{
|
||||||
|
dns_t *dns;
|
||||||
|
int i, ret;
|
||||||
|
|
||||||
|
for (i = MAX_FD - 2, dns = &dns_list[MAX_FD - 3]; i--; dns--) {
|
||||||
|
if (dns->http_rsp == NULL && dns->dns_req_len != dns->sent_len) {
|
||||||
|
ret = send_dns_req(dns->dns_req + dns->sent_len, dns->dns_req_len - dns->sent_len);
|
||||||
|
if (ret == 0) {
|
||||||
|
dns->sent_len = dns->dns_req_len;
|
||||||
|
} else if (ret > -1) {
|
||||||
|
dns->sent_len += ret;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
close_client(dns);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ev.events = EPOLLIN | EPOLLET;
|
||||||
|
ev.data.fd = dstFd;
|
||||||
|
epoll_ctl(eFd, EPOLL_CTL_MOD, dstFd, &ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
void recv_dns_rsp()
|
||||||
|
{
|
||||||
|
static char rsp_data[BUFF_SIZE + 1], *p, *ips, *ips_save;
|
||||||
|
unsigned char *_p;
|
||||||
|
dns_t *dns;
|
||||||
|
int len, ips_len;
|
||||||
|
int16_t flag;
|
||||||
|
|
||||||
|
len = read(dstFd, rsp_data, BUFF_SIZE);
|
||||||
|
if (len < 2)
|
||||||
|
return;
|
||||||
|
memcpy(&flag, rsp_data, sizeof(int16_t));
|
||||||
|
if (flag > MAX_FD - 3)
|
||||||
|
return;
|
||||||
|
dns = dns_list + flag;
|
||||||
|
dns->sent_len = 0;
|
||||||
|
dns->http_rsp = ERROR_MSG;
|
||||||
|
dns->http_rsp_len = sizeof(ERROR_MSG) - 1;
|
||||||
|
if (dns->dns_req_len + 12 > len || (unsigned char)rsp_data[3] != 128 /*(signed char) max is 127 */ )
|
||||||
|
goto modEvToOut;
|
||||||
|
rsp_data[len] = '\0';
|
||||||
|
/* get ips */
|
||||||
|
p = rsp_data + dns->dns_req_len + 11;
|
||||||
|
ips_len = 0;
|
||||||
|
ips = NULL;
|
||||||
|
while (p - rsp_data + 4 <= len) {
|
||||||
|
//type
|
||||||
|
if (*(p - 8) != 1) {
|
||||||
|
p += *p + 12;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ips_save = ips;
|
||||||
|
ips = (char *)realloc(ips, ips_len + 16);
|
||||||
|
if (ips == NULL) {
|
||||||
|
ips = ips_save;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_p = (unsigned char *)p + 1;
|
||||||
|
ips_len += sprintf(ips + ips_len, "%d.%d.%d.%d", _p[0], _p[1], _p[2], _p[3]);
|
||||||
|
p += 16; //next address
|
||||||
|
ips[ips_len++] = ';';
|
||||||
|
}
|
||||||
|
if (ips) {
|
||||||
|
ips[ips_len - 1] = '\0';
|
||||||
|
//printf("ips %s\n", ips);
|
||||||
|
build_http_rsp(dns, ips);
|
||||||
|
free(ips);
|
||||||
|
if (dns->http_rsp) {
|
||||||
|
response_client(dns);
|
||||||
|
if (dns->http_rsp == NULL) {
|
||||||
|
dns->http_rsp = ERROR_MSG;
|
||||||
|
dns->http_rsp_len = sizeof(ERROR_MSG) - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
modEvToOut:
|
||||||
|
ev.data.ptr = dns;
|
||||||
|
ev.events = EPOLLOUT | EPOLLET;
|
||||||
|
epoll_ctl(eFd, EPOLL_CTL_MOD, dns->fd, &ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
void read_client(dns_t * in)
|
||||||
|
{
|
||||||
|
static char httpReq[BUFF_SIZE + 1];
|
||||||
|
int domain_size, httpReq_len;
|
||||||
|
char *domain_begin, *domain_end, *domain = NULL, *ips;
|
||||||
|
|
||||||
|
httpReq_len = read(in->fd, httpReq, BUFF_SIZE);
|
||||||
|
//必须大于5,否则不处理
|
||||||
|
if (httpReq_len < 6) {
|
||||||
|
close_client(in);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
httpReq[httpReq_len] = '\0';
|
||||||
|
in->http_rsp = ERROR_MSG;
|
||||||
|
in->http_rsp_len = sizeof(ERROR_MSG) - 1;
|
||||||
|
if ((domain_begin = strstr(httpReq, "?dn=")))
|
||||||
|
domain_begin += 4;
|
||||||
|
else if ((domain_begin = strstr(httpReq, "?host=")))
|
||||||
|
domain_begin += 6;
|
||||||
|
else
|
||||||
|
goto response_client;
|
||||||
|
|
||||||
|
domain_end = strchr(domain_begin, ' ');
|
||||||
|
if (domain_end == NULL)
|
||||||
|
goto response_client;
|
||||||
|
if (*(domain_end - 1) == '.')
|
||||||
|
domain_size = domain_end - domain_begin - 1;
|
||||||
|
else
|
||||||
|
domain_size = domain_end - domain_begin;
|
||||||
|
domain = strndup(domain_begin, domain_size);
|
||||||
|
if (encodeCode)
|
||||||
|
dataEncode((unsigned char *)domain, domain_size);
|
||||||
|
if (domain == NULL || domain_size <= 0)
|
||||||
|
goto response_client;
|
||||||
|
if (hostsfp && (ips = hosts_lookup(domain)) != NULL) {
|
||||||
|
free(domain);
|
||||||
|
build_http_rsp(in, ips);
|
||||||
|
if (in->http_rsp == NULL) {
|
||||||
|
in->http_rsp = ERROR_MSG;
|
||||||
|
in->http_rsp_len = sizeof(ERROR_MSG) - 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
build_dns_req(in, domain, domain_size);
|
||||||
|
free(domain);
|
||||||
|
int ret = send_dns_req(in->dns_req, in->dns_req_len);
|
||||||
|
switch (ret) {
|
||||||
|
case 0:
|
||||||
|
in->sent_len = in->dns_req_len;
|
||||||
|
ev.events = EPOLLIN;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case -1:
|
||||||
|
close_client(in);
|
||||||
|
return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
in->sent_len += ret;
|
||||||
|
ev.events = EPOLLIN | EPOLLOUT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ev.data.fd = dstFd;
|
||||||
|
epoll_ctl(eFd, EPOLL_CTL_MOD, dstFd, &ev);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
response_client:
|
||||||
|
response_client(in);
|
||||||
|
if (in->http_rsp) {
|
||||||
|
ev.data.ptr = in;
|
||||||
|
ev.events = EPOLLOUT | EPOLLET;
|
||||||
|
epoll_ctl(eFd, EPOLL_CTL_MOD, in->fd, &ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void httpdns_accept_client()
|
||||||
|
{
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
dns_t *client;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = MAX_FD - 2; i--;) {
|
||||||
|
if (dns_list[i].fd < 0) {
|
||||||
|
client = &dns_list[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//printf("i = %d\n" , i);
|
||||||
|
if (i < 0)
|
||||||
|
return;
|
||||||
|
client->fd = accept(listenFd, (struct sockaddr *)&addr, &addr_len);
|
||||||
|
if (client->fd < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fcntl(client->fd, F_SETFL, O_NONBLOCK);
|
||||||
|
ev.data.ptr = client;
|
||||||
|
ev.events = EPOLLIN | EPOLLET;
|
||||||
|
if (epoll_ctl(eFd, EPOLL_CTL_ADD, client->fd, &ev) != 0) {
|
||||||
|
close(client->fd);
|
||||||
|
client->fd = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int httpdns_initialize()
|
||||||
|
{
|
||||||
|
struct sockaddr_in listenAddr, dnsAddr;
|
||||||
|
int optval = 0;
|
||||||
|
|
||||||
|
//ignore PIPE signal
|
||||||
|
signal(SIGPIPE, SIG_IGN);
|
||||||
|
dnsAddr.sin_family = listenAddr.sin_family = AF_INET; // IPv4
|
||||||
|
dnsAddr.sin_addr.s_addr = inet_addr(DEFAULT_UPPER_IP); // 本地监听
|
||||||
|
dnsAddr.sin_port = htons(53);
|
||||||
|
|
||||||
|
listenAddr.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
listenAddr.sin_port = htons(53);
|
||||||
|
|
||||||
|
listenFd = socket(AF_INET, SOCK_STREAM, 0); // 本地监听,TCP协议
|
||||||
|
dstFd = socket(AF_INET, SOCK_DGRAM, 0); // DNS监听,UDP协议
|
||||||
|
if (dstFd < 0 || listenFd < 0) {
|
||||||
|
perror("socket");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
fcntl(dstFd, F_SETFL, O_NONBLOCK); // dstFd 非阻塞
|
||||||
|
fcntl(listenFd, F_SETFL, O_NONBLOCK); // listenFd 非阻塞
|
||||||
|
|
||||||
|
optval = 1;
|
||||||
|
if (setsockopt(listenFd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) != 0) {
|
||||||
|
perror("setsockopt");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (bind(listenFd, (struct sockaddr *)&listenAddr, sizeof(listenAddr)) != 0) {
|
||||||
|
perror("bind");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (listen(listenFd, 20) != 0) {
|
||||||
|
perror("listen");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
eFd = epoll_create(MAX_FD - 1);
|
||||||
|
if (eFd < 0) {
|
||||||
|
perror("epoll_create");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
connect(dstFd, (struct sockaddr *)&dnsAddr, sizeof(dnsAddr));
|
||||||
|
ev.data.fd = listenFd;
|
||||||
|
ev.events = EPOLLIN;
|
||||||
|
epoll_ctl(eFd, EPOLL_CTL_ADD, listenFd, &ev);
|
||||||
|
ev.data.fd = dstFd;
|
||||||
|
ev.events = EPOLLIN;
|
||||||
|
epoll_ctl(eFd, EPOLL_CTL_ADD, dstFd, &ev);
|
||||||
|
memset(dns_list, 0, sizeof(dns_list));
|
||||||
|
//初始化DNS请求结构
|
||||||
|
int16_t i;
|
||||||
|
for (i = MAX_FD - 2; i--;) {
|
||||||
|
dns_list[i].fd = -1;
|
||||||
|
memcpy(dns_list[i].dns_req, &i, sizeof(i));
|
||||||
|
dns_list[i].dns_req[2] = 1;
|
||||||
|
dns_list[i].dns_req[3] = 0;
|
||||||
|
dns_list[i].dns_req[4] = 0;
|
||||||
|
dns_list[i].dns_req[5] = 1;
|
||||||
|
dns_list[i].dns_req[6] = 0;
|
||||||
|
dns_list[i].dns_req[7] = 0;
|
||||||
|
dns_list[i].dns_req[8] = 0;
|
||||||
|
dns_list[i].dns_req[9] = 0;
|
||||||
|
dns_list[i].dns_req[10] = 0;
|
||||||
|
dns_list[i].dns_req[11] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *httpdns_start_server(void *p)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
n = epoll_wait(eFd, evs, MAX_FD - 1, -1);
|
||||||
|
//printf("n = %d\n", n);
|
||||||
|
while (n-- > 0) {
|
||||||
|
if (evs[n].data.fd == listenFd) {
|
||||||
|
httpdns_accept_client();
|
||||||
|
} else if (evs[n].data.fd == dstFd) {
|
||||||
|
if (evs[n].events & EPOLLIN) {
|
||||||
|
recv_dns_rsp();
|
||||||
|
} else if (evs[n].events & EPOLLOUT) {
|
||||||
|
query_dns();
|
||||||
|
}
|
||||||
|
} else if (evs[n].events & EPOLLIN) {
|
||||||
|
read_client(evs[n].data.ptr);
|
||||||
|
} else if (evs[n].events & EPOLLOUT) {
|
||||||
|
response_client(evs[n].data.ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
55
httpdns.h
Normal file
55
httpdns.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#ifndef _HTTPDNS_
|
||||||
|
#define _HTTPDNS_
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/epoll.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#define DEFAULT_UPPER_IP "114.114.114.114"
|
||||||
|
#define MAX_FD 1024
|
||||||
|
#define DNS_REQUEST_SIZE 512
|
||||||
|
#define BUFF_SIZE 1024
|
||||||
|
|
||||||
|
typedef struct dns_request {
|
||||||
|
char dns_req[DNS_REQUEST_SIZE + 1];
|
||||||
|
char *http_rsp;
|
||||||
|
unsigned int http_rsp_len, sent_len, dns_req_len;
|
||||||
|
int fd;
|
||||||
|
} dns_t;
|
||||||
|
|
||||||
|
struct dns_hosts {
|
||||||
|
char *host;
|
||||||
|
char *ip;
|
||||||
|
struct dns_hosts *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define VERSION "0.3"
|
||||||
|
#define ERROR_MSG "HTTP/1.0 404 Not Found\r\nConnection: close\r\nVia: Mmmdbybyd(HTTP-DNS Server "VERSION")\r\nContent-type: charset=utf-8\r\n\r\n<html><head><title>HTTP DNS Server</title></head><body>查询域名失败<br/><br/>By: 萌萌萌得不要不要哒<br/>E-mail: 915445800@qq.com</body></html>"
|
||||||
|
#define SUCCESS_HEADER "HTTP/1.0 200 OK\r\nConnection: close\r\nVia: Mmmdbybyd(HTTP-DNS Server "VERSION")\r\n\r\n"
|
||||||
|
|
||||||
|
dns_t dns_list[MAX_FD - 2]; //监听客户端FD DNS服务端fd
|
||||||
|
struct epoll_event evs[MAX_FD - 1], ev;
|
||||||
|
|
||||||
|
int listenFd, dstFd, eFd;
|
||||||
|
socklen_t addr_len;
|
||||||
|
void recv_dns_rsp();
|
||||||
|
void query_dns();
|
||||||
|
void read_client(dns_t * in);
|
||||||
|
void response_client(dns_t * out);
|
||||||
|
void httpdns_accept_client();
|
||||||
|
int httpdns_initialize();
|
||||||
|
void *httpdns_start_server();
|
||||||
|
|
||||||
|
#endif
|
103
proxy.c
103
proxy.c
@ -5,6 +5,7 @@
|
|||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
#include "kill.h"
|
#include "kill.h"
|
||||||
#include "help.h"
|
#include "help.h"
|
||||||
|
#include "httpdns.h"
|
||||||
|
|
||||||
#define SERVER_STOP 1
|
#define SERVER_STOP 1
|
||||||
#define SERVER_RELOAD 2
|
#define SERVER_RELOAD 2
|
||||||
@ -95,12 +96,36 @@ void accept_client()
|
|||||||
epoll_ctl(epollfd, EPOLL_CTL_ADD, client->fd, &epollEvent);
|
epoll_ctl(epollfd, EPOLL_CTL_ADD, client->fd, &epollEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void start_server(conf * configure)
|
void *http_proxy_loop(void *p)
|
||||||
|
{
|
||||||
|
conf *configure = (conf *) p;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
n = epoll_wait(epollfd, events, MAX_CONNECTION, -1);
|
||||||
|
while (n-- > 0) {
|
||||||
|
if (events[n].data.fd == server_sock) {
|
||||||
|
accept_client();
|
||||||
|
} else {
|
||||||
|
if (events[n].events & EPOLLIN) {
|
||||||
|
tcp_in((conn *) events[n].data.ptr, configure);
|
||||||
|
}
|
||||||
|
if (events[n].events & EPOLLOUT) {
|
||||||
|
tcp_out((conn *) events[n].data.ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(epollfd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *start_server(conf * configure)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
pthread_t thId;
|
pthread_t thread_id;
|
||||||
if (timeout_minute)
|
if (timeout_minute)
|
||||||
pthread_create(&thId, NULL, &close_timeout_connectionLoop, NULL);
|
pthread_create(&thread_id, NULL, &close_timeout_connectionLoop, NULL);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
n = epoll_wait(epollfd, events, MAX_CONNECTION, -1);
|
n = epoll_wait(epollfd, events, MAX_CONNECTION, -1);
|
||||||
@ -152,18 +177,28 @@ int process_signal(int signal, char *process_name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
closedir(dir);
|
||||||
|
|
||||||
|
if (signal == SERVER_STATUS) { // 状态
|
||||||
n -= 2; // 去除最后一个搜索时的本身进程
|
n -= 2; // 去除最后一个搜索时的本身进程
|
||||||
for (; n >= 0; n--) {
|
for (; n >= 0; n--) {
|
||||||
if (signal == SERVER_STATUS)
|
|
||||||
printf("\t%d\n", num[n]);
|
printf("\t%d\n", num[n]);
|
||||||
}
|
}
|
||||||
if (signal == SERVER_STOP || signal == SERVER_RELOAD) {
|
}
|
||||||
//kill(num[n], SIGTERM);
|
if (signal == SERVER_STOP) { // 关闭
|
||||||
struct passwd *pwent = NULL;
|
struct passwd *pwent = NULL;
|
||||||
pwent = getpwnam("root");
|
pwent = getpwnam("root");
|
||||||
return kill_all(15, 1, &process_name, pwent);
|
return kill_all(15, 1, &process_name, pwent);
|
||||||
}
|
}
|
||||||
closedir(dir);
|
if (signal == SERVER_RELOAD) { // 重启
|
||||||
|
n -= 2;
|
||||||
|
for (; n >= 0; n--) {
|
||||||
|
//printf("\t%d\n", num[n]);
|
||||||
|
//printf("kill 返回 %d\n", kill(num[n], SIGTERM));
|
||||||
|
kill(num[n], SIGTERM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,9 +216,19 @@ int get_executable_path(char *processdir, char *processname, int len)
|
|||||||
return (int)(filename - processdir);
|
return (int)(filename - processdir);
|
||||||
}
|
}
|
||||||
|
|
||||||
int _main(int argc, char *argv[])
|
void server_ini()
|
||||||
{
|
{
|
||||||
int opt, i, process;
|
signal(SIGPIPE, SIG_IGN); // 忽略PIPE信号
|
||||||
|
if (daemon(1, 1)) {
|
||||||
|
perror("daemon");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//while (process-- > 1 && fork() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int opt, i;
|
||||||
char path[PATH_SIZE] = { 0 };
|
char path[PATH_SIZE] = { 0 };
|
||||||
char executable_filename[PATH_SIZE] = { 0 };
|
char executable_filename[PATH_SIZE] = { 0 };
|
||||||
(void)get_executable_path(path, executable_filename, sizeof(path));
|
(void)get_executable_path(path, executable_filename, sizeof(path));
|
||||||
@ -258,8 +303,9 @@ int _main(int argc, char *argv[])
|
|||||||
free_conf(configure);
|
free_conf(configure);
|
||||||
exit(process_signal(SERVER_STOP, executable_filename));
|
exit(process_signal(SERVER_STOP, executable_filename));
|
||||||
}
|
}
|
||||||
if (strcasecmp(optarg, "restart") == 0 || strcasecmp(optarg, "reload") == 0)
|
if (strcasecmp(optarg, "restart") == 0 || strcasecmp(optarg, "reload") == 0) {
|
||||||
process_signal(SERVER_RELOAD, executable_filename);
|
process_signal(SERVER_RELOAD, executable_filename);
|
||||||
|
}
|
||||||
if (strcasecmp(optarg, "status") == 0)
|
if (strcasecmp(optarg, "status") == 0)
|
||||||
exit(process_signal(SERVER_STATUS, executable_filename));
|
exit(process_signal(SERVER_STATUS, executable_filename));
|
||||||
break;
|
break;
|
||||||
@ -273,9 +319,7 @@ int _main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
server_sock = create_server_socket(configure->local_port);
|
httpdns_initialize(); // 初始化http_dns
|
||||||
signal(SIGPIPE, SIG_IGN); // 忽略PIPE信号
|
|
||||||
|
|
||||||
memset(cts, 0, sizeof(cts));
|
memset(cts, 0, sizeof(cts));
|
||||||
for (i = MAX_CONNECTION; i--;)
|
for (i = MAX_CONNECTION; i--;)
|
||||||
cts[i].fd = -1;
|
cts[i].fd = -1;
|
||||||
@ -287,13 +331,7 @@ int _main(int argc, char *argv[])
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
server_sock = create_server_socket(configure->local_port);
|
||||||
if (daemon(1, 1)) {
|
|
||||||
perror("daemon");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (process-- > 0 && fork() == 0)
|
|
||||||
epollfd = epoll_create(MAX_CONNECTION);
|
epollfd = epoll_create(MAX_CONNECTION);
|
||||||
if (epollfd == -1) {
|
if (epollfd == -1) {
|
||||||
perror("epoll_create");
|
perror("epoll_create");
|
||||||
@ -305,15 +343,32 @@ int _main(int argc, char *argv[])
|
|||||||
if (-1 == epoll_ctl(epollfd, EPOLL_CTL_ADD, server_sock, &event)) {
|
if (-1 == epoll_ctl(epollfd, EPOLL_CTL_ADD, server_sock, &event)) {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setegid(configure->uid) == -1 || seteuid(configure->uid) == -1) // 设置uid
|
if (setegid(configure->uid) == -1 || seteuid(configure->uid) == -1) // 设置uid
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
||||||
start_server(configure);
|
server_ini(); // 初始化http_proxy
|
||||||
return 0;
|
pthread_t thread_id;
|
||||||
|
sigset_t signal_mask;
|
||||||
|
sigemptyset(&signal_mask);
|
||||||
|
sigaddset(&signal_mask, SIGPIPE); // 忽略PIPE信号
|
||||||
|
if (pthread_sigmask(SIG_BLOCK, &signal_mask, NULL) != 0) {
|
||||||
|
printf("block sigpipe error\n");
|
||||||
|
}
|
||||||
|
pthread_detach(thread_id);
|
||||||
|
if (timeout_minute)
|
||||||
|
pthread_create(&thread_id, NULL, &close_timeout_connectionLoop, NULL);
|
||||||
|
if (pthread_create(&thread_id, NULL, &http_proxy_loop, (void *)configure) != 0)
|
||||||
|
perror("pthread_create");
|
||||||
|
|
||||||
|
if (pthread_create(&thread_id, NULL, &httpdns_start_server, NULL) != 0)
|
||||||
|
perror("pthread_create");
|
||||||
|
|
||||||
|
pthread_join(thread_id, NULL);
|
||||||
|
pthread_exit(NULL);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
return _main(argc, argv);
|
_main(argc, argv);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user