From f5cb1c8e02a2777e59b704cbcb6bddd90eb6f00d Mon Sep 17 00:00:00 2001 From: mmmdbybyd <915445800@qq.com> Date: Wed, 28 Nov 2018 12:14:35 +0800 Subject: [PATCH] Add files via upload --- Makefile | 8 ++++- README.md | 14 +++++---- http.c | 92 ++++++++++++++++++++++++++++++++++--------------------- http.h | 3 +- main.c | 9 ++++-- main.h | 2 +- 6 files changed, 81 insertions(+), 47 deletions(-) diff --git a/Makefile b/Makefile index 3427111..393d282 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,12 @@ OBJ := SpecialProxy CC := gcc -CFLAGS := -O3 -Wall -pthread +CFLAGS := -O2 -Wall -pthread +#如果是安卓编译 +ifeq ($(ANDROID_DATA),/data) + CFLAGS := -O2 -pie -Wall + SHELL = /system/bin/sh +endif + all : main.o http.o dns.o $(CC) $(CFLAGS) $(DEFS) -o $(OBJ) $^ diff --git a/README.md b/README.md index 36b1c04..0f884b4 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ SpecialProxy ====== -用epoll多路复用io写的一个HTTP代理,自带DNS解析 +用epoll多路复用io写的一个HTTP代理,轻快,自带DNS解析 ##### SpecialProxy有如下特性: 1. 普通HTTP代理通过请求头首行的host或者Host头域字段获得目标主机, @@ -16,8 +16,9 @@ SpecialProxy 4. -L参数设置重定向到本地端口的头域,比如-L Local, 然后请求头中含有Local: 443,代理会将请求发送到127.0.0.1:443 -##### 搭建: - curl -k -O https://raw.githubusercontent.com/mmmdbybyd/SpecialProxy/master/SpecialProxy.sh && bash SpecialProxy.sh + 5. -e设置数据编码的代码, + 对客户端uri Host Referer以及请求附带的数据编码, + 服务器的返回数据也编码 ##### 启动参数: -l [监听ip:]监听端口 默认监听IP为 "0.0.0.0" @@ -25,13 +26,14 @@ SpecialProxy -L 本地代理头域 默认为 "Local" -d DNS查询IP[:端口] 默认为 "114.114.114.114" -s SSL代理字符串 默认为 "CONNECT" - -u 设置运行uid + -u 设置uid + -e 设置代理CProxy的数据编码代码(1-127) -a 对所有HTTP请求重新拼接 -h 显示帮助 -w 工作进程数 ##### BUG: - 好像有些连接不关闭,需要定时重启代理 + 待发现 ##### 编译: ~~~~~ @@ -39,4 +41,4 @@ Linux/Android: make Android-ndk: ndk-build -~~~~~ +~~~~~ \ No newline at end of file diff --git a/http.c b/http.c index a229a16..9d8dfeb 100644 --- a/http.c +++ b/http.c @@ -1,14 +1,21 @@ #include "http.h" #include "dns.h" -#define SSL_RSP "HTTP/1.1 200 Connection established\r\n\r\n" #define HTTP_TYPE 0 #define OTHER_TYPE 1 conn_t cts[MAX_CONNECTION]; +static char ssl_rsp[] = "HTTP/1.1 200 Connection established\r\n\r\n"; char *local_header, *proxy_header, *ssl_proxy; int lisFd, proxy_header_len, local_header_len; -uint8_t strict_spilce; +uint8_t strict_spilce, encodeCode; + +/* 对数据进行编码 */ +static void dataEncode(char *data, int data_len) +{ + while (data_len-- > 0) + data[data_len] ^= encodeCode; +} int8_t connectionToServer(char *ip, conn_t *server) { @@ -139,10 +146,19 @@ static char *get_host(char *data) while (*host == ' ') host++; hostEnd = strchr(host, '\r'); + if (hostEnd) + { + if (encodeCode) + dataEncode(host, hostEnd - host); return strndup(host, hostEnd - host); + } else + { + if (encodeCode) + dataEncode(host, strlen(host)); return strdup(host); + } } /* 删除请求头中的头域 */ @@ -176,6 +192,24 @@ static void del_hdr(char *header, int *header_len) } } +/* 对请求头中的Referer头域进行编码 */ +static void encodeReferer(char *request) +{ + char *referer_key, *referer_value, *line, *pr; + + for (line = strchr(request, '\n'); (referer_key = strstr(line, "\nReferer:")) != NULL || (referer_key = strstr(line, "\nreferer:")) != NULL; line = pr + 1) + { + referer_value = referer_key + sizeof("\nReferer:") - 1; + while (*referer_value == ' ') + referer_value++; + pr = strchr(referer_value, '\r'); + if (pr) + dataEncode(referer_value, pr - referer_value); + else + dataEncode(referer_value, strlen(referer_value)); + } +} + /* 构建新请求头 */ static char *build_request(char *client_data, int *data_len, char *host) { @@ -191,6 +225,7 @@ static char *build_request(char *client_data, int *data_len, char *host) lf = strchr(header, '\n'); if (url == NULL || lf == NULL || lf - 10 <= header) return client_data; + if (url < lf && *(++url) != '/') { uri = strchr(url + 7, '/'); @@ -208,6 +243,12 @@ static char *build_request(char *client_data, int *data_len, char *host) *data_len -= p - url; lf -= p - url; } + if (encodeCode) + dataEncode(url + 1, lf - 10 - (url + 1)); + } + else if (url < lf && encodeCode) + { + dataEncode(url + 1, lf - 10 - (url + 1)); } *data_len += strlen(proxy_host) + 8; //8为 "Host: " + "\r\n"的长度 @@ -232,6 +273,8 @@ static char *build_request(char *client_data, int *data_len, char *host) free(client_data); if (proxy_host != host) free(proxy_host); + if (encodeCode) + encodeReferer(new_data); if (strict_spilce == 0) return new_data; client_data = new_data; @@ -300,25 +343,6 @@ static int8_t copy_data(conn_t *ct) return 0; } -/* 判断请求是否为长连接 */ -static int is_keepAlive(char *header) -{ - char *ConnectionValue; - - ConnectionValue = strstr(header, "\nConnection: "); - if (ConnectionValue) - { - ConnectionValue += 13; - if (*ConnectionValue == 'C' || *ConnectionValue == 'c') - return 0; - else - return 1; - } - if (strstr(header, "HTTP/1.1")) - return 1; - return 0; -} - static void serverToClient(conn_t *server) { conn_t *client; @@ -328,6 +352,8 @@ static void serverToClient(conn_t *server) client = server - 1; while ((server->ready_data_len = read(server->fd, server->ready_data, BUFFER_SIZE)) > 0) { + if (encodeCode) //对服务端的数据编码 + dataEncode(server->ready_data, server->ready_data_len); write_len = write(client->fd, server->ready_data, server->ready_data_len); if (write_len == -1) { @@ -345,18 +371,11 @@ static void serverToClient(conn_t *server) epoll_ctl(efd, EPOLL_CTL_MOD, client->fd, &ev); return; } - /* 判断服务端是否close */ - if (client->request_type == HTTP_TYPE && client->is_ssl == 0) - { - server->ready_data[server->ready_data_len] = '\0'; - if (strncmp(server->ready_data, "HTTP/1.", 7) == 0) - client->keep_alive = server->keep_alive = is_keepAlive(server->ready_data); - } if (server->ready_data_len < BUFFER_SIZE) break; } //判断是否关闭连接 - if (server->ready_data_len == 0 || (errno != EAGAIN && errno != 0) || client->keep_alive == 0) + if (server->ready_data_len == 0 || (errno != EAGAIN && errno != 0)) close_connection(server); else server->ready_data_len = server->sent_len = 0; @@ -435,6 +454,8 @@ void tcp_in(conn_t *in) server->request_type = in->request_type = request_type(in->incomplete_data); if (in->request_type == OTHER_TYPE) { + if (encodeCode) + dataEncode(in->incomplete_data, in->incomplete_data_len); //如果是第一次读取数据,并且不是HTTP请求的,关闭连接。复制数据失败的也关闭连接 if (in->reread_data == 0 || copy_data(in) != 0) { @@ -443,18 +464,19 @@ void tcp_in(conn_t *in) } goto handle_data_complete; } - headerEnd = strstr(in->incomplete_data, "\n\r"); + headerEnd = strstr(in->incomplete_data, "\n\r\n"); //请求头不完整,等待下次读取 if (headerEnd == NULL) return; + headerEnd += 3; + if (encodeCode) + dataEncode(headerEnd, in->incomplete_data_len - (headerEnd - in->incomplete_data)); host = get_host(in->incomplete_data); if (host == NULL) { close_connection(in); return; } - /* 判断是否长连接 */ - server->keep_alive = in->keep_alive = is_keepAlive(in->incomplete_data); /* 第一次读取数据 */ if (in->reread_data == 0) { @@ -467,16 +489,14 @@ void tcp_in(conn_t *in) } if (strstr(in->incomplete_data, ssl_proxy)) { - server->keep_alive = in->keep_alive = 1; server->is_ssl = in->is_ssl = 1; /* 这时候即使fd是非阻塞也只需要判断返回值是否小于0 */ - if (write(in->fd, SSL_RSP, 39) < 0) + if (write(in->fd, ssl_rsp, sizeof(ssl_rsp) - 1) < 0) { free(host); close_connection(in); return; } - headerEnd += 3; if (headerEnd - in->incomplete_data < in->incomplete_data_len) { in->incomplete_data_len -= headerEnd - in->incomplete_data; @@ -527,6 +547,8 @@ void *accept_loop(void *ptr) struct epoll_event epollEvent; conn_t *client; + if (encodeCode) + dataEncode(ssl_rsp, sizeof(ssl_rsp) - 1); epollEvent.events = EPOLLIN|EPOLLET; while (1) { diff --git a/http.h b/http.h index eed58f6..0704dda 100644 --- a/http.h +++ b/http.h @@ -9,7 +9,6 @@ typedef struct tcp_connection { uint16_t destPort; unsigned reread_data :1; unsigned request_type :1; - unsigned keep_alive :1; unsigned is_ssl :1; } conn_t; @@ -23,6 +22,6 @@ extern void tcp_out(conn_t *ct); extern conn_t cts[MAX_CONNECTION]; extern char *local_header, *proxy_header, *ssl_proxy; extern int lisFd, local_header_len, proxy_header_len; -extern uint8_t strict_spilce; +extern uint8_t strict_spilce, isEncode, encodeCode; #endif \ No newline at end of file diff --git a/main.c b/main.c index 4f3ced0..0b24614 100644 --- a/main.c +++ b/main.c @@ -20,6 +20,7 @@ static void usage() " -d dns query address \033[35G default is " DEFAULT_DNS_IP "\n" " -s ssl proxy string \033[35G default is 'CONNECT'\n" " -u uid \033[35G running uid\n" + " -e \033[35G set encode data code(1-127)\n" " -a \033[35G all http requests repeat spilce\n" " -h display this infomaction\n" " -w worker process\n"); @@ -79,7 +80,7 @@ static void initializate(int argc, char **argv) dnsAddr.sin_addr.s_addr = inet_addr(DEFAULT_DNS_IP); dnsAddr.sin_port = htons(53); dns_connect(&dnsAddr); //主进程中的fd - strict_spilce = 0; + strict_spilce = encodeCode = 0; local_header = NULL; ssl_proxy = (char *)"CONNECT"; local_header = (char *)"\nLocal:"; @@ -87,7 +88,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:w:u:L:ah")) != -1) + while ((opt = getopt(argc, argv, "d:l:e:p:s:w:u:L:ah")) != -1) { switch (opt) { @@ -115,6 +116,10 @@ static void initializate(int argc, char **argv) } break; + case 'e': + encodeCode = (int8_t)atoi(optarg); + break; + case 'p': //假如选项值为 "Proxy", proxy_header设置为 "\nProxy:" proxy_header_len = strlen(optarg) + 2; diff --git a/main.h b/main.h index 0b52b39..5eaff0d 100644 --- a/main.h +++ b/main.h @@ -16,7 +16,7 @@ #include #include -#define BUFFER_SIZE 10240 +#define BUFFER_SIZE 4096 #define MAX_CONNECTION 1020 extern struct epoll_event evs[MAX_CONNECTION + 1], ev;