From 3a4c630c86c21123432055aa7d7eebffac05c263 Mon Sep 17 00:00:00 2001 From: mmmdbybyd <915445800@qq.com> Date: Sat, 26 Jan 2019 11:53:32 +0800 Subject: [PATCH] Add files via upload --- Makefile | 3 ++- README.md | 15 ++++++----- dns.c | 49 ++++++++++++++---------------------- http.c | 74 +++++++++++++++++++++++++++---------------------------- http.h | 11 ++++----- main.c | 60 ++++++++++++++++++++++---------------------- timeout.c | 14 +++++++---- timeout.h | 6 +---- 8 files changed, 112 insertions(+), 120 deletions(-) diff --git a/Makefile b/Makefile index e7b48a1..d179f90 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,7 @@ OBJ := SpecialProxy CC := gcc CFLAGS := -O2 -Wall -pthread +STRIP := strip #如果是安卓编译 ifeq ($(ANDROID_DATA),/data) CFLAGS := -O2 -pie -Wall @@ -10,7 +11,7 @@ endif all : main.o http.o dns.o timeout.o $(CC) $(CFLAGS) $(DEFS) -o $(OBJ) $^ - strip $(OBJ) + $(STRIP) $(OBJ) -chmod 777 $(OBJ) 2>&- .c.o : diff --git a/README.md b/README.md index 58fbddf..7cccbd8 100644 --- a/README.md +++ b/README.md @@ -21,13 +21,16 @@ SpecialProxy 服务器的返回数据也编码 ##### 启动参数: - -l [监听ip:]监听端口 默认监听IP为 "0.0.0.0" - -p 代理头域 默认为 "Host" - -L 本地代理头域 默认为 "Local" - -d DNS查询IP[:端口] 默认为 "114.114.114.114" - -s SSL代理字符串 默认为 "CONNECT" + -l [监听ip:]监听端口 默认监听IP为 "0.0.0.0" + -p 代理头域 默认为 "Host" + -L 本地代理头域 默认为 "Local" + -d DNS查询IP[:端口] 默认为 "114.114.114.114" + -s SSL代理字符串 默认为 "CONNECT" + -e host和数据的编码代码(128-255) 默认为0不编码 + -t 连接超时时间, 单位: 分 默认不超时 + -i 忽略host前字符个数 默认为0 -u 设置uid - -a 对所有HTTP请求重新拼接 + -a 对所有HTTP请求重新拼接 -h 显示帮助 -w 工作进程数 diff --git a/dns.c b/dns.c index 930f080..27df58e 100644 --- a/dns.c +++ b/dns.c @@ -1,34 +1,33 @@ #include "dns.h" #include "http.h" -struct dns dns_list[MAX_CONNECTION / 2]; //一个客户端 + 一个服务端 占用一个dns结构体 +struct dns dns_list[MAX_CONNECTION >> 1]; //一个客户端 + 一个服务端 占用一个dns结构体 int dnsFd; void read_dns_rsp() { - char rsp_data[512], *p, ip[16]; - unsigned char *_p; + static char rsp_data[512], *ip, *p; struct dns *dns; conn_t *client; - int16_t len, dns_flag; + int16_t len, dns_id; while ((len = read(dnsFd, rsp_data, 512)) > 11) { - memcpy(&dns_flag, rsp_data, 2); - dns = dns_list + dns_flag; - client = cts + (dns_flag << 1); + memcpy(&dns_id, rsp_data, 2); + dns = dns_list + dns_id; + client = cts + (dns_id << 1); //判断是否是正常DNS回应,是否已关闭连接 - if (dns_flag > MAX_CONNECTION >> 1 || client->fd < 0) + if (dns_id > MAX_CONNECTION >> 1 || client->fd < 0) continue; if (dns->request_len + 12 > len || (unsigned char)rsp_data[3] != 128) //char只有7位可用,则正数最高为127 { close_connection(client); continue; } - + /* get domain ip */ p = rsp_data + dns->request_len + 11; - ip[0] = 0; + ip = NULL; while (p - rsp_data + 4 <= len) { //type @@ -37,19 +36,10 @@ void read_dns_rsp() p += *p + 12; continue; } - _p = (unsigned char *)p + 1; - sprintf(ip, "%d.%d.%d.%d", _p[0], _p[1], _p[2], _p[3]); + ip = p + 1; break; } - if (ip[0]) - { - if (connectionToServer(ip, client + 1) != 0) - { - close_connection(client); - continue; - } - } - else + if (ip == NULL || connectionToServer(*(in_addr_t *)ip, client + 1) != 0) { close_connection(client); continue; @@ -61,16 +51,15 @@ void read_dns_rsp() static int8_t send_dns_req(struct dns *dns) { int write_len; - - write_len = write(dnsFd, dns->request + dns->sent_len, dns->request_len - dns->sent_len); + + write_len = write(dnsFd, dns->request, dns->request_len); if (write_len == dns->request_len - dns->sent_len) { dns->sent_len = dns->request_len; return 0; } - else if (write_len >= 0) + else if (write_len > 0) { - dns->sent_len += write_len; return 1; } else @@ -82,7 +71,7 @@ static int8_t send_dns_req(struct dns *dns) void dns_query() { int16_t i, ret; - + for (i = 0; i < MAX_CONNECTION >> 1; i++) { if (dns_list[i].request_len != dns_list[i].sent_len) @@ -110,8 +99,7 @@ int8_t build_dns_req(struct dns *dns, char *domain) domain_size = strlen(domain); p = dns->request + 12; - memcpy(p+1, domain, domain_size); - *(p+1+domain_size) = 0; + memcpy(p+1, domain, domain_size + 1); while ((_p = strchr(p+1, '.')) != NULL) { *p = _p - p - 1; @@ -127,15 +115,14 @@ int8_t build_dns_req(struct dns *dns, char *domain) switch (send_dns_req(dns)) { case 0: - ev.data.fd = dnsFd; return 0; - + case 1: ev.data.fd = dnsFd; ev.events = EPOLLIN|EPOLLOUT|EPOLLET; epoll_ctl(efd, EPOLL_CTL_MOD, dnsFd, &ev); return 1; - + default: return -1; } diff --git a/http.c b/http.c index 77d7289..97493da 100644 --- a/http.c +++ b/http.c @@ -2,31 +2,33 @@ #include "dns.h" #include "timeout.h" -#define SSL_RSP "HTTP/1.1 200 Connection established\r\n\r\n" +#define SSL_RSP "HTTP/1.1 200 Connection established\r\nVia: SpecialProxy_CuteBi\r\n\r\n" #define HTTP_TYPE 0 #define OTHER_TYPE 1 conn_t cts[MAX_CONNECTION]; char *local_header, *proxy_header, *ssl_proxy; -int lisFd, proxy_header_len, local_header_len; +int lisFd, proxy_header_len, local_header_len, ignore_host_before_count; uint8_t strict_spilce, sslEncodeCode; /* 对数据进行编码 */ static void dataEncode(char *data, int data_len) { - if (sslEncodeCode == 0) - return; - while (data_len-- > 0) - data[data_len] ^= sslEncodeCode; + if (sslEncodeCode) + while (data_len-- > 0) + data[data_len] ^= sslEncodeCode; } -int8_t connectionToServer(char *ip, conn_t *server) +int8_t connectionToServer(in_addr_t ip, conn_t *server) { + struct sockaddr_in addr; + server->fd = socket(AF_INET, SOCK_STREAM, 0); if (server->fd < 0) return 1; fcntl(server->fd, F_SETFL, O_NONBLOCK); - addr.sin_addr.s_addr = inet_addr(ip); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = ip; addr.sin_port = htons(server->destPort); if (connect(server->fd, (struct sockaddr *)&addr, sizeof(addr)) != 0 && errno != EINPROGRESS) return 1; @@ -114,21 +116,22 @@ static char *read_data(conn_t *in, char *data, int *data_len) *data_len += read_len; } while (read_len == BUFFER_SIZE); *(data + *data_len) = '\0'; - + return data; } static char *get_host(char *data) { char *hostEnd, *host; + int i; host = strstr(data, local_header); if (host != NULL) { char *local_host; - + host += local_header_len; - while (*host == ' ') + while (*host == ' ' || *host == '\t') host++; for (hostEnd = host; *hostEnd < 58 && *hostEnd > 48; hostEnd++); //判断该头域是否正确使用 @@ -146,29 +149,25 @@ static char *get_host(char *data) if (host == NULL) return NULL; host += proxy_header_len; - while (*host == ' ') + while (*host == ' ' || *host == '\t') host++; + for (i = 0; i < ignore_host_before_count; i++) + if (host[i] == '\0') //防止越界 + break; + host += i; hostEnd = strchr(host, '\r'); - if (hostEnd) - return strndup(host, hostEnd - host); - else - return strdup(host); + return hostEnd ? strndup(host, hostEnd - host) : strdup(host); } /* 删除请求头中的头域 */ static void del_hdr(char *header, int *header_len) { - char *key_end, *line_begin, *line_end; - int key_len; + char *line_begin, *line_end; for (line_begin = strchr(header, '\n'); line_begin++ && *line_begin != '\r'; line_begin = line_end) { - key_end = strchr(line_begin, ':'); - if (key_end == NULL) - return; - key_len = key_end - line_begin; - line_end = strchr(key_end, '\n'); - if (strncasecmp(line_begin, "host", key_len) == 0 || strncmp(line_begin, local_header + 1, key_len) == 0 || strncmp(line_begin, proxy_header + 1, key_len) == 0) + line_end = strchr(line_begin, '\n'); + if (strncasecmp(line_begin, "host:", 5) == 0 || strncasecmp(line_begin, local_header + 1, local_header_len - 1) == 0 || strncasecmp(line_begin, proxy_header + 1, proxy_header_len - 1) == 0) { if (line_end++) { @@ -273,14 +272,14 @@ static int8_t parse_host(conn_t *server, char *host) for (p = host; (*p > 47 && *p < 58) || *p == '.'; p++); if (*p == '\0') { - if (connectionToServer(host, server) != 0) + if (connectionToServer(inet_addr(host), server) != 0) return 1; } else if (build_dns_req(dns_list + ((server - cts) >> 1), host) == -1) return 1; if (port) *port = ':'; - + return 0; } @@ -291,7 +290,7 @@ static int8_t copy_data(conn_t *ct) if (ct->ready_data) { char *new_data; - + new_data = (char *)realloc(ct->ready_data, ct->ready_data_len + ct->incomplete_data_len); if (new_data == NULL) return 1; @@ -358,7 +357,7 @@ void tcp_out(conn_t *to) from = to - 1; else from = to + 1; - from->last_event_time = to->last_event_time = time(NULL); + from->timer = to->timer = 0; write_len = write(to->fd, from->ready_data + from->sent_len, from->ready_data_len - from->sent_len); if (write_len == from->ready_data_len - from->sent_len) { @@ -400,19 +399,19 @@ void tcp_in(conn_t *in) { conn_t *server; char *host, *headerEnd; - + if (in->fd < 0) return; //如果in - cts是奇数,那么是服务端触发事件 if ((in - cts) & 1) { - in->last_event_time = (in-1)->last_event_time = time(NULL); + in->timer = (in-1)->timer = 0; if (in->ready_data_len <= 0) serverToClient(in); return; } - - in->last_event_time = (in+1)->last_event_time = time(NULL); + + in->timer = (in+1)->timer = 0; in->incomplete_data = read_data(in, in->incomplete_data, &in->incomplete_data_len); if (in->incomplete_data == NULL) { @@ -501,15 +500,17 @@ void tcp_in(conn_t *in) void accept_client() { struct epoll_event epollEvent; + struct sockaddr_in addr; conn_t *client; - + socklen_t addr_len = sizeof(addr); + /* 偶数为客户端,奇数为服务端 */ for (client = cts; client - cts < MAX_CONNECTION; client += 2) if (client->fd < 0) break; if (client - cts >= MAX_CONNECTION) return; - client->last_event_time = (client+1)->last_event_time = time(NULL); + client->timer = (client+1)->timer = 0; client->fd = accept(lisFd, (struct sockaddr *)&addr, &addr_len); if (client->fd < 0) return; @@ -521,6 +522,7 @@ void accept_client() void create_listen(char *ip, int port) { + struct sockaddr_in addr; int optval = 1; if ((lisFd = socket(AF_INET, SOCK_STREAM, 0)) < 0) @@ -528,6 +530,7 @@ void create_listen(char *ip, int port) perror("socket"); exit(1); } + addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = inet_addr(ip); if (setsockopt(lisFd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0) @@ -546,6 +549,3 @@ void create_listen(char *ip, int port) exit(1); } } - - - diff --git a/http.h b/http.h index 60b04e7..0aea2e9 100644 --- a/http.h +++ b/http.h @@ -5,8 +5,7 @@ typedef struct tcp_connection { char *ready_data, *incomplete_data; - int fd, ready_data_len, incomplete_data_len, sent_len; - time_t last_event_time; + int fd, ready_data_len, incomplete_data_len, sent_len, timer; uint16_t destPort; unsigned reread_data :1; unsigned request_type :1; @@ -17,13 +16,13 @@ typedef struct tcp_connection { extern void create_listen(char *ip, int port); extern void accept_client(); extern void close_connection(conn_t *conn); -extern int8_t connectionToServer(char *ip, conn_t *server); -extern void tcp_in(conn_t *ct); -extern void tcp_out(conn_t *ct); +extern int8_t connectionToServer(in_addr_t ip, conn_t *server); +extern void tcp_in(conn_t *in); +extern void tcp_out(conn_t *to); extern conn_t cts[MAX_CONNECTION]; extern char *local_header, *proxy_header, *ssl_proxy; -extern int lisFd, local_header_len, proxy_header_len; +extern int lisFd, local_header_len, proxy_header_len, ignore_host_before_count; extern uint8_t strict_spilce, sslEncodeCode; #endif \ No newline at end of file diff --git a/main.c b/main.c index 21f2935..33194dc 100644 --- a/main.c +++ b/main.c @@ -4,12 +4,10 @@ #include "dns.h" #include -#define VERSION "0.3" +#define VERSION "0.4" #define DEFAULT_DNS_IP "114.114.114.114" struct epoll_event evs[MAX_CONNECTION + 1], ev; -struct sockaddr_in addr; -socklen_t addr_len; int efd; static void usage() @@ -20,9 +18,10 @@ static void usage() " -L local proxy header \033[35G default is 'Local'\n" " -d dns query address \033[35G default is " DEFAULT_DNS_IP "\n" " -s ssl proxy string \033[35G default is 'CONNECT'\n" - " -t timeout \033[35G default is 35s\n" - " -u uid \033[35G running uid\n" - " -e ssl data encode code \033[35G default is 0\n" + " -t timeout minute \033[35G default is no timeout\n" + " -u uid \033[35G running uid\n" + " -e ssl data encode code(128-255) \033[35G default is 0\n" + " -i ignore host before string count \033[35G default is 0\n" " -a \033[35G all http requests repeat spilce\n" " -h display this infomaction\n" " -w worker process\n"); @@ -40,7 +39,8 @@ static void server_loop() ev.events = EPOLLIN; ev.data.fd = lisFd; epoll_ctl(efd, EPOLL_CTL_ADD, lisFd, &ev); - pthread_create(&thId, NULL, &close_timeout_connectionLoop, NULL); + if (timeout_minute) + pthread_create(&thId, NULL, &close_timeout_connectionLoop, NULL); while (1) { n = epoll_wait(efd, evs, MAX_CONNECTION + 1, -1); @@ -73,18 +73,16 @@ static void initializate(int argc, char **argv) struct sockaddr_in dnsAddr; char *p; int opt, i, workers; - - /* 初始化部分变量值 */ - addr_len = sizeof(addr); + + /* 初始化部分变量值 */ lisFd = -1; workers = 1; - dnsAddr.sin_family = addr.sin_family = AF_INET; + dnsAddr.sin_family = AF_INET; //默认dns地址 dnsAddr.sin_addr.s_addr = inet_addr(DEFAULT_DNS_IP); dnsAddr.sin_port = htons(53); dns_connect(&dnsAddr); //主进程中的fd - timeout_seconds = DEFAULT_TIMEOUT; - strict_spilce = sslEncodeCode = 0; + ignore_host_before_count = timeout_minute = strict_spilce = sslEncodeCode = 0; local_header = NULL; ssl_proxy = (char *)"CONNECT"; local_header = (char *)"\nLocal:"; @@ -92,7 +90,7 @@ static void initializate(int argc, char **argv) proxy_header_len = strlen(proxy_header); local_header_len = strlen(local_header); /* 处理命令行参数 */ - while ((opt = getopt(argc, argv, "d:l:p:s:e:w:t:u:L:ah")) != -1) + while ((opt = getopt(argc, argv, "d:l:p:s:e:i:w:t:u:L:ah")) != -1) { switch (opt) { @@ -106,7 +104,7 @@ static void initializate(int argc, char **argv) dnsAddr.sin_addr.s_addr = inet_addr(optarg); connect(dnsFd, (struct sockaddr *)&dnsAddr, sizeof(dnsAddr)); break; - + case 'l': p = strchr(optarg, ':'); if (p) @@ -119,7 +117,7 @@ static void initializate(int argc, char **argv) create_listen((char *)"0.0.0.0", atoi(optarg)); } break; - + case 'p': //假如选项值为 "Proxy", proxy_header设置为 "\nProxy:" proxy_header_len = strlen(optarg) + 2; @@ -133,7 +131,7 @@ static void initializate(int argc, char **argv) } sprintf(proxy_header, "\n%s:", optarg); break; - + case 'L': local_header_len = strlen(optarg) + 2; if (optarg[local_header_len] == ':') @@ -146,27 +144,31 @@ static void initializate(int argc, char **argv) } sprintf(local_header, "\n%s:", optarg); break; - + case 's': ssl_proxy = optarg; break; - + case 'e': sslEncodeCode = atoi(optarg); break; - + + case 'i': + ignore_host_before_count = atoi(optarg); + break; + case 'a': strict_spilce = 1; break; - + case 't': - timeout_seconds = (time_t)atoi(optarg); + timeout_minute = (time_t)atoi(optarg); break; - + case 'w': workers = atoi(optarg); break; - + case 'u': if (setgid(atoi(optarg)) != 0) { @@ -179,13 +181,13 @@ static void initializate(int argc, char **argv) exit(1); } break; - + default: usage(); break; } } - /* 初始化剩下的变量值 */ + /* 初始化的变量值 */ if (lisFd < 0) { fputs("no listen address\n", stderr); @@ -204,9 +206,9 @@ static void initializate(int argc, char **argv) exit(1); } } - //设置dns请求头首部 + //设置dns请求头首部 memset(dns_list, 0, sizeof(dns_list)); - for (i = MAX_CONNECTION / 2; i--; ) + for (i = MAX_CONNECTION >> 1; i--; ) { memcpy(dns_list[i].request, &i, sizeof(uint16_t)); dns_list[i].request[2] = 1; @@ -242,6 +244,6 @@ int main(int argc, char **argv) return 1; } server_loop(); - + return 0; } diff --git a/timeout.c b/timeout.c index 8b88877..4497e3d 100644 --- a/timeout.c +++ b/timeout.c @@ -1,8 +1,7 @@ #include "main.h" #include "http.h" -#include "time.h" -int timeout_seconds; +int timeout_minute; void *close_timeout_connectionLoop(void *nullPtr) { @@ -10,9 +9,14 @@ void *close_timeout_connectionLoop(void *nullPtr) while (1) { - sleep(1); + sleep(60); for (i = 0; i < MAX_CONNECTION; i += 2) - if (cts[i].fd > -1&& (int)(time(NULL) - cts[i].last_event_time) >= timeout_seconds) - close_connection(cts + i); + if (cts[i].fd > -1) + { + if (cts[i].timer >= timeout_minute) + close_connection(cts + i); + else + cts[i].timer = 0; + } } } \ No newline at end of file diff --git a/timeout.h b/timeout.h index 71de091..527eab0 100644 --- a/timeout.h +++ b/timeout.h @@ -1,11 +1,7 @@ #ifndef TIME_H #define TIME_H -#define DEFAULT_TIMEOUT 60 - -#include - -extern int timeout_seconds; +extern int timeout_minute; void *close_timeout_connectionLoop(void *nullPtr);