From e6072984a25af2d70a18842a272262bdf73e0183 Mon Sep 17 00:00:00 2001 From: aixiao Date: Tue, 24 Mar 2020 11:46:32 +0800 Subject: [PATCH] Add SSL encoding Add long option Add Android NDK compilation No longer use the iniparser to read configuration files --- Android.mk | 10 + Application.mk | 2 + CProxy.conf | 26 ++ CProxy.conf.explain | 57 +++++ CProxy.ini | 20 -- CProxy.ini.explain | 34 --- Makefile | 4 +- README.md | 29 ++- conf.c | 562 ++++++++++++++++++++++++++++---------------- conf.h | 13 +- help.c | 13 +- http.c | 14 +- http.h | 2 + proxy.c | 32 ++- proxy.h | 3 + request.c | 22 +- 16 files changed, 541 insertions(+), 302 deletions(-) create mode 100644 Android.mk create mode 100644 Application.mk create mode 100644 CProxy.conf create mode 100644 CProxy.conf.explain delete mode 100644 CProxy.ini delete mode 100644 CProxy.ini.explain diff --git a/Android.mk b/Android.mk new file mode 100644 index 0000000..f363b42 --- /dev/null +++ b/Android.mk @@ -0,0 +1,10 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) +LOCAL_CFLAGS = -O2 -pie -Wall +LOCAL_LDFLAGS = -O2 -pie -Wall +LOCAL_ARM_MODE = arm +LOCAL_MODULE = CProxy +LOCAL_MODULE_FILENAME = CProxy +c_src_files = $(wildcard $(LOCAL_PATH)/*.c) +LOCAL_SRC_FILES = $(c_src_files:$(LOCAL_PATH)/%=%) +include $(BUILD_EXECUTABLE) diff --git a/Application.mk b/Application.mk new file mode 100644 index 0000000..75d4de5 --- /dev/null +++ b/Application.mk @@ -0,0 +1,2 @@ +APP_ABI = arm64-v8a armeabi-v7a +APP_PLATFORM = android-29 \ No newline at end of file diff --git a/CProxy.conf b/CProxy.conf new file mode 100644 index 0000000..7723f11 --- /dev/null +++ b/CProxy.conf @@ -0,0 +1,26 @@ +global { + uid=3004; + process=2; + timer=60; + sslencoding=0; + local_port=9606; +} + +http { + http_ip=192.168.1.102; + http_port=1080; + http_del="x-online-host,X-Online-Host,host,Host"; + http_first="[M] [U] [V]\r\nHost: [host]\r\n"; + //strrep="Windows NT 10.0->Linux"; + //regrep="Host*.+?->Host: hu60.cn:443"; +} + +https { + https_ip=192.168.1.102; + https_port=1080; + https_del="Host,host,x-online-host"; + https_first="[M] [H] [V]\r\nHost: [host]\r\n"; + strrep="Windows NT 10.0->Linux"; + //regrep="Host*.+?->Host: hu60.cn:443"; +} + diff --git a/CProxy.conf.explain b/CProxy.conf.explain new file mode 100644 index 0000000..164f785 --- /dev/null +++ b/CProxy.conf.explain @@ -0,0 +1,57 @@ +global { + // 设置进程UID + uid=3004; + + // 进程数 + process=2; + + // 超时 + timer=60; + + // ssl编码,1-128 + sslencoding=0; + + // 本地端口 + local_port=9606; +} + +http { + // 代理IP + http_ip=192.168.1.102; + // 代理端口 + http_port=1080; + http_del="x-online-host,X-Online-Host,host,Host"; + http_first="[M] [U] [V]\r\nHost: [host]\r\n"; + //strrep="Windows NT 10.0->Linux"; + //regrep="Host*.+?->Host: hu60.cn:443"; +} + +https { + // 代理IP + https_ip=192.168.1.102; + // 代理端口 + https_port=1080; + // 删除Host行 + https_del="Host,host,x-online-host"; + // https头第一行 + https_first="[M] [H] [V]\r\nHost: [host]\r\n"; + //strrep="Windows NT 10.0->Linux"; + //regrep="Host*.+?->Host: hu60.cn:443"; +} + +http、https 模块关键字: [M], [method], [uri], [U], [V], [version], [H], [host], [port], \r, \n, \v, \f, \b, \t, \a. 如果原本请求头含有关键字也会被替换. + +[M]、[method] 原请求方法 +[U] 原请求url +[uri] 原请求uri(http 模块) +[V]、[version] 原请求协议版本 +[host] 原请求host +[port] 原请求端口 +[H] 原请求[host]:[port] + +关键字strrep替换字符串指令. +strrep = "Mi MIX 2->Linux"; 以"->"为分界符,"Mi MIX 2"字符串替换为"Linux"字符串. + +关键字regrep正则匹配替换字符串. +regrep = "Host*.+?->Host: iread.wo.cn:443"; 以"->"为分界符,匹配到的内容"Host*.+?"替换为"Host: iread.wo.cn:443"字符串. + diff --git a/CProxy.ini b/CProxy.ini deleted file mode 100644 index fa8b160..0000000 --- a/CProxy.ini +++ /dev/null @@ -1,20 +0,0 @@ -[server] -uid=3004; -process=3; -timer=60; -local_port=9606; -pid_file=CProxy.pid; - -[http] -http_ip=192.168.1.102; -http_port=1080; -http_del="x-online-host,X-Online-Host,host,Host"; -http_first="[M] [U] [V]\r\nHost: [host]\r\n"; - -[https] -https_ip=192.168.1.102; -https_port=1080; -https_del="Host,host"; -https_first="[M] [H] [V]\r\nHost: [host]\r\n"; -;strrep = "Windows NT 10.0; Win64; x64->Linux"; -;regrep = "Host*.+?->Host: hu60.cn:443"; diff --git a/CProxy.ini.explain b/CProxy.ini.explain deleted file mode 100644 index 05a902c..0000000 --- a/CProxy.ini.explain +++ /dev/null @@ -1,34 +0,0 @@ -模块: [server], [http], [https] -[http]、[https]模块关键字: [M], [U], [V], [H], [host], [port], \r, \n, \v, \f, \b, \t, \a. 如果原本请求头含有关键字也会被替换. - -[server]模块 -uid 设置进程UID -process 进程数 -timer 超时 -local_port 端口 -pid_file PID文件 - -[http]模块 -[M] 原请求方法 -[U] 原请求url -[V] 原请求协议版本 -[H] 原[host]:[port] -[host] 原请求host -[port] 原请求端口 -关键字strrep替换字符串指令. -strrep = "Mi MIX 2->Linux"; 以"->"为分界符,"Mi MIX 2"字符串替换为"Linux"字符串. -关键字regrep正则匹配替换字符串. -regrep = "Host*.+?->Host: iread.wo.cn:443"; 以"->"为分界符,匹配到的内容"Host*.+?"替换为"Host: iread.wo.cn:443"字符串. - -[https]模块 -[M] 原请求方法 -[U] 原请求url -[V] 原请求协议版本 -[H] 原[host]:[port] -[host] 原请求host -[port] 原请求端口 -关键字strrep替换字符串指令. -strrep = "Mi MIX 2->Linux"; 以"->"为分界符,"Mi MIX 2"字符串替换为"Linux"字符串. -关键字regrep正则匹配替换字符串. -regrep = "Host*.+?->Host: iread.wo.cn:443"; 以"->"为分界符,匹配到的内容"Host*.+?"替换为"Host: iread.wo.cn:443"字符串. - diff --git a/Makefile b/Makefile index c20dd6f..7e16832 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ CROSS_COMPILE ?= CC := $(CROSS_COMPILE)gcc STRIP := $(CROSS_COMPILE)strip -CFLAGS += -g -O2 -Wall -I../iniparser/src -L../iniparser -LIBS = -liniparser -pthread -static +CFLAGS += -g -O2 -Wall +LIBS = -pthread -static OBJ := CProxy all: proxy.o http.o request.o picohttpparser.o conf.o timeout.o kill.o help.o diff --git a/README.md b/README.md index c86db51..f6c75b6 100644 --- a/README.md +++ b/README.md @@ -5,31 +5,34 @@ ### Build - git clone https://github.com/niuyuling/cproxy.git - git clone https://github.com/ndevilla/iniparser.git - cd iniparser - make - cd ../cproxy + Linux编译: + git clone https://github.com/niuyuling/CProxy.git + cd CProxy make clean; make windows 10子系统交叉编译: apt-get install gcc-aarch64-linux-gnu make clean; CROSS_COMPILE=aarch64-linux-gnu- make + + Android 编译: + ndk-build NDK_PROJECT_PATH=. NDK_APPLICATION_MK=Application.mk APP_BUILD_SCRIPT=Android.mk ### Help Information - ./CProxy -h CProxy proxy server Author: aixiao@aixiao.me Usage: [-?hpt] [-s signal] [-c filename] Options: - -?,-h : help information - -p : process number, default 2 process - -t : timeout minute, default is no timeout - -s signal : send signal to a master process: stop, quit, restart, reload, status - -c filename : set configuration file (default: cproxy.ini) + -l --local_address : localip:localport + -f --remote_address : remoteip:remote:port + -p --process : process number, default: 2 + -t --timeout : timeout minute, default: no timeout + -e --coding : ssl coding, default: [0-128] + -s --signal : send signal to a master process: stop, quit, restart, reload, status + -c --config : set configuration file, default: CProxy.ini + -? -h --? --help : help information - Jan 13 2020 19:56:06 Compile、link. + Mar 22 2020 09:29:11 Compile、link. #启动 ./CProxy -c CProxy.ini @@ -39,6 +42,6 @@ ./CProxy -s reload -c CProxy.ini or ./CProxy -s restart -c CProxy.ini - #状态 + #状态(只打印Pid) ./CProxy -s status \ No newline at end of file diff --git a/conf.c b/conf.c index 953f622..56d911f 100644 --- a/conf.c +++ b/conf.c @@ -1,5 +1,6 @@ #include "conf.h" + char *strncpy_(char *dest, const char *src, size_t n) { int size = sizeof(char) * (n + 1); @@ -15,240 +16,385 @@ char *strncpy_(char *dest, const char *src, size_t n) } } -void read_conf(char *file, conf * p) +/* 在content中,设置变量(var)的首地址,值(val)的位置首地址和末地址,返回下一行指针 */ +static char *set_var_val_lineEnd(char *content, char **var, char **val_begin, char **val_end) { - if (access(file, F_OK)) { - printf("%s DOESN'T EXISIT!\n", file); - exit(1); - } + char *p, *pn, *lineEnd; + ; + int val_len; - dictionary *ini = iniparser_load(file); + while (1) + { + if (content == NULL) + return NULL; - // server module - // uid - p->uid = iniparser_getint(ini, "server:uid", 0); - - // process - p->process = iniparser_getint(ini, "server:process", 0); - - // timer - p->timer = iniparser_getint(ini, "server:timer", 0); - - //local_port - p->server_port = iniparser_getint(ini, "server:local_port", 0); - //pid_file - p->server_pid_file_len = strlen(iniparser_getstring(ini, "server:pid_file", NULL)) + 1; - p->server_pid_file = (char *)malloc(p->server_pid_file_len); - if (p->server_pid_file == NULL) { - goto err; - } - memset(p->server_pid_file, 0, p->server_pid_file_len); - memcpy(p->server_pid_file, iniparser_getstring(ini, "server:pid_file", NULL), p->server_pid_file_len); - - - - // http module - // http ip - p->http_ip_len = strlen(iniparser_getstring(ini, "http:http_ip", NULL)) + 1; - p->http_ip = (char *)malloc(p->http_ip_len); - if (p->http_ip == NULL) { - goto err; - } - memset(p->http_ip, 0, p->http_ip_len); - memcpy(p->http_ip, iniparser_getstring(ini, "http:http_ip", NULL), p->http_ip_len); - - // http port - p->http_port = iniparser_getint(ini, "http:http_port", 0); - - // http del - p->http_del_len = strlen(iniparser_getstring(ini, "http:http_del", NULL)) + 1; - p->http_del = (char *)malloc(p->http_del_len); - if (p->http_del == NULL) { - goto err; - } - memset(p->http_del, 0, p->http_del_len); - memcpy(p->http_del, iniparser_getstring(ini, "http:http_del", NULL), p->http_del_len); - - // http first - p->http_first_len = strlen(iniparser_getstring(ini, "http:http_first", NULL)) + 1; - p->http_first = (char *)malloc(p->http_first_len); - if (p->http_first == NULL) { - goto err; - } - memset(p->http_first, 0, p->http_first_len); - memcpy(p->http_first, iniparser_getstring(ini, "http:http_first", NULL), p->http_first_len); - - // http strrep - if (iniparser_find_entry(ini, "http:strrep") == 1) { - p->http_strrep_len = strlen(iniparser_getstring(ini, "http:strrep", NULL)) + 1; - p->http_strrep = (char *)malloc(p->http_strrep_len); - if (p->http_strrep == NULL) { - free(p->http_strrep); + for (;*content == ' ' || *content == '\t' || *content == '\r' || *content == '\n'; content++); + if (*content == '\0') + return NULL; + *var = content; + pn = strchr(content, '\n'); + p = strchr(content, '='); + if (p == NULL) + { + if (pn) + { + content = pn + 1; + continue; + } + else + return NULL; } - memset(p->http_strrep, 0, p->http_strrep_len); - memcpy(p->http_strrep, iniparser_getstring(ini, "http:strrep", NULL), p->http_strrep_len); - char *p1 = strstr(p->http_strrep, "->"); - p->http_strrep_aim = (char *)malloc(strlen(p->http_strrep) - strlen(p1 + 2) - 2 + 1); - if (p->http_strrep_aim == NULL) { - free(p->http_strrep_aim); + content = p; + //将变量以\0结束 + for (p--; *p == ' ' || *p == '\t'; p--); + *(p+1) = '\0'; + //值的首地址 + for (content++; *content == ' ' || *content == '\t'; content++); + if (*content == '\0') + return NULL; + //双引号引起来的值支持换行 + if (*content == '"') + { + *val_begin = content + 1; + *val_end = strstr(*val_begin, "\";"); + if (*val_end != NULL) + break; } - strncpy_(p->http_strrep_aim, p->http_strrep, strlen(p->http_strrep) - strlen(p1 + 2) - 2); - p->http_strrep_obj = (char *)malloc(strlen(p1 + 2) + 1); - if (p->http_strrep_obj == NULL) { - free(p->http_strrep_obj); + else + *val_begin = content; + *val_end = strchr(content, ';'); + if (pn && *val_end > pn) + { + content = pn + 1; + continue; } - strncpy_(p->http_strrep_obj, p1 + 2, strlen(p1 + 2)); - p->http_strrep_aim_len = strlen(p->http_strrep_aim); - p->http_strrep_obj_len = strlen(p->http_strrep_obj); - } - - // http regrep - if (iniparser_find_entry(ini, "http:regrep") == 1) { - p->http_regrep_len = strlen(iniparser_getstring(ini, "http:regrep", NULL)) + 1; - p->http_regrep = (char *)malloc(p->http_regrep_len); - if (p->http_regrep == NULL) { - free(p->http_regrep); - } - memset(p->http_regrep, 0, p->http_regrep_len); - memcpy(p->http_regrep, iniparser_getstring(ini, "http:regrep", NULL), p->http_regrep_len); - char *p3 = strstr(p->http_regrep, "->"); - p->http_regrep_aim = - (char *)malloc(strlen(p->http_regrep) - strlen(p3 + 2) - 2 + 1); - if (p->http_regrep_aim == NULL) { - free(p->http_regrep_aim); - } - strncpy_(p->http_regrep_aim, p->http_regrep, - strlen(p->http_regrep) - strlen(p3 + 2) - 2); - p->http_regrep_obj = (char *)malloc(strlen(p3 + 2) + 1); - if (p->http_regrep_obj == NULL) { - free(p->http_regrep_obj); - } - strncpy_(p->http_regrep_obj, p3 + 2, strlen(p3 + 2)); - p->http_regrep_aim_len = strlen(p->http_regrep_aim); - p->http_regrep_obj_len = strlen(p->http_regrep_obj); + break; } - - - // https module - // https ip - p->https_ip_len = strlen(iniparser_getstring(ini, "https:https_ip", NULL)) + 1; - p->https_ip = (char *)malloc(p->https_ip_len); - if (p->https_ip == NULL) { - goto err; + if (*val_end) + { + **val_end = '\0'; + val_len = *val_end - *val_begin; + lineEnd = *val_end; } - memset(p->https_ip, 0, p->https_ip_len); - memcpy(p->https_ip, iniparser_getstring(ini, "https:https_ip", NULL), p->https_ip_len); - - //https port - p->https_port = iniparser_getint(ini, "https:https_port", 0); - - // https del - p->https_del_len = strlen(iniparser_getstring(ini, "https:https_del", NULL)) + 1; - p->https_del = (char *)malloc(p->https_del_len); - if (p->https_del == NULL) { - goto err; + else + { + val_len = strlen(*val_begin); + *val_end = lineEnd = *val_begin + val_len; } - memset(p->https_del, 0, p->https_del_len); - memcpy(p->https_del, iniparser_getstring(ini, "https:https_del", NULL), p->https_del_len); - - // https first - p->https_first_len = strlen(iniparser_getstring(ini, "https:https_first", NULL)) + 1; - p->https_first = (char *)malloc(p->https_first_len); - if (p->https_first == NULL) { - goto err; - } - memset(p->https_first, 0, p->https_first_len); - memcpy(p->https_first, iniparser_getstring(ini, "https:https_first", NULL), p->https_first_len); - - // https strrep - if (iniparser_find_entry(ini, "https:strrep") == 1) { - p->https_strrep_len = strlen(iniparser_getstring(ini, "https:strrep", NULL)) + 1; - p->https_strrep = (char *)malloc(p->https_strrep_len); - if (p->https_strrep == NULL) { - free(p->https_strrep); - } - memset(p->https_strrep, 0, p->https_strrep_len); - memcpy(p->https_strrep, iniparser_getstring(ini, "https:strrep", NULL), p->https_strrep_len); - char *p2 = strstr(p->https_strrep, "->"); - p->https_strrep_aim = (char *)malloc(strlen(p->https_strrep) - strlen(p2 + 2) - 2 + 1); - if (p->https_strrep_aim == NULL) { - free(p->https_strrep_aim); - } - strncpy_(p->https_strrep_aim, p->https_strrep, strlen(p->https_strrep) - strlen(p2 + 2) - 2); - p->https_strrep_obj = (char *)malloc(strlen(p2 + 2) + 1); - if (p->https_strrep_obj == NULL) { - free(p->https_strrep_obj); - } - strncpy_(p->https_strrep_obj, p2 + 2, strlen(p2 + 2)); - p->https_strrep_aim_len = strlen(p->https_strrep_aim); - p->https_strrep_obj_len = strlen(p->https_strrep_obj); - } - - // https regrep - if (iniparser_find_entry(ini, "https:regrep") == 1) { - p->https_regrep_len = strlen(iniparser_getstring(ini, "https:regrep", NULL)) + 1; - p->https_regrep = (char *)malloc(p->https_regrep_len); - if (p->https_regrep == NULL) - free(p->https_regrep); - memset(p->https_regrep, 0, p->https_regrep_len); - memcpy(p->https_regrep, iniparser_getstring(ini, "https:regrep", NULL), p->https_regrep_len); - char *p4 = strstr(p->https_regrep, "->"); - p->https_regrep_aim = (char *)malloc(strlen(p->https_regrep) - strlen(p4 + 2) - 2 + 1); - if (p->https_regrep_aim == NULL) - free(p->https_regrep_aim); - strncpy_(p->https_regrep_aim, p->https_regrep, strlen(p->https_regrep) - strlen(p4 + 2) - 2); - p->https_regrep_obj = (char *)malloc(strlen(p4 + 2) + 1); - if (p->https_regrep_obj == NULL) - free(p->https_regrep_obj); - strncpy_(p->https_regrep_obj, p4 + 2, strlen(p4 + 2)); - p->https_regrep_aim_len = strlen(p->https_regrep_aim); - p->https_regrep_obj_len = strlen(p->https_regrep_obj); - } - -err: - if (p->server_pid_file == NULL) - free(p->server_pid_file); - if (p->http_ip == NULL) - free(p->http_ip); - if (p->http_del == NULL) - free(p->http_del); - if (p->http_first == NULL) - free(p->http_first); - if (p->https_ip == NULL) - free(p->https_ip); - if (p->https_del == NULL) - free(p->https_del); - if (p->https_first == NULL) - free(p->https_first); - - iniparser_freedict(ini); - return; + *val_end = *val_begin + val_len; + //printf("var[%s]\nbegin[%s]\n\n", *var, *val_begin); + return lineEnd; } -void free_conf(conf * p) +/* 在buff中读取模块(global http https httpdns httpudp)内容 */ +static char *read_module(char *buff, const char *module_name) +{ + int len; + char *p, *p0; + + len = strlen(module_name); + p = buff; + while (1) + { + while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') + p++; + if (strncasecmp(p, module_name, len) == 0) + { + p += len; + while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') + p++; + if (*p == '{') + break; + } + if ((p = strchr(p, '\n')) == NULL) + return NULL; + } + if ((p0 = strchr(++p, '}')) == NULL) + return NULL; + + return strndup(p, p0 - p); +} + +static void parse_global_module(char *content, conf *p) +{ + char *var, *val_begin, *val_end, *lineEnd; + + while ((lineEnd = set_var_val_lineEnd(content, &var, &val_begin, &val_end)) != NULL) + { + if (strcasecmp(var, "uid") == 0) { + p->uid = atoi(val_begin); + } else if (strcasecmp(var, "process") == 0) { + p->process = atoi(val_begin); + } else if (strcasecmp(var, "timer") == 0) { + p->timer = atoi(val_begin); + } else if (strcasecmp(var, "sslencoding") == 0) { + p->sslencoding = atoi(val_begin); + } else if (strcasecmp(var, "local_port") == 0) { + p->local_port = atoi(val_begin); + } + + content = strchr(lineEnd+1, '\n'); + } +} + +static void parse_http_module(char *content, conf *p) { + char *var, *val_begin, *val_end, *lineEnd; + int val_begin_len; + + while ((lineEnd = set_var_val_lineEnd(content, &var, &val_begin, &val_end)) != NULL) + { + if (strcasecmp(var, "http_ip") == 0) { + val_begin_len = strlen(val_begin) + 1; + p->http_ip = (char *)malloc(val_begin_len); + memset(p->http_ip, 0, val_begin_len); + memcpy(p->http_ip, val_begin, val_begin_len); + } + else if (strcasecmp(var, "http_port") == 0) { + p->http_port = atoi(val_begin); + } + else if (strcasecmp(var, "http_del") == 0) { + val_begin_len = strlen(val_begin) + 1; + p->http_del = (char *)malloc(val_begin_len); + memcpy(p->http_del, val_begin, val_begin_len); + } + else if (strcasecmp(var, "http_first") == 0) { + val_begin_len = strlen(val_begin) + 1; + p->http_first = (char *)malloc(val_begin_len); + memcpy(p->http_first, val_begin, val_begin_len); + } + else if (strcasecmp(var, "strrep") ==0) { + val_begin_len = strlen(val_begin) + 1; + + p->http_strrep = (char *)malloc(val_begin_len); + if (p->http_strrep == NULL) + free(p->http_strrep); + memcpy(p->http_strrep, val_begin, val_begin_len); + + char *p1 = strstr(val_begin, "->"); + printf("p1 %s\n", p1); + p->http_strrep_aim = (char *)malloc(val_begin_len - strlen(p1 + 2) - 2 + 1); + if (p->http_strrep_aim == NULL) { + free(p->http_strrep_aim); + } + strncpy_(p->http_strrep_aim, val_begin, val_begin_len - strlen(p1 + 2) - 3); // 实际 val_begin_len 多1 + p->http_strrep_obj = (char *)malloc(strlen(p1 + 2) + 1); + if (p->http_strrep_obj == NULL) { + free(p->http_strrep_obj); + } + strncpy_(p->http_strrep_obj, p1 + 2, strlen(p1 + 2)); + p->http_strrep_aim_len = strlen(p->http_strrep_aim); + p->http_strrep_obj_len = strlen(p->http_strrep_obj); + } + else if (strcasecmp(var, "regrep") ==0) { + val_begin_len = strlen(val_begin) + 1; + + p->http_regrep = (char *)malloc(val_begin_len); + if (p->http_regrep == NULL) + free(p->http_regrep); + memcpy(p->http_regrep, val_begin, val_begin_len); + + char *p1 = strstr(val_begin, "->"); + p->http_regrep_aim = + (char *)malloc(val_begin_len - strlen(p1 + 2) - 2 + 1); + if (p->http_regrep_aim == NULL) { + free(p->http_regrep_aim); + } + strncpy_(p->http_regrep_aim, val_begin, val_begin_len - strlen(p1 + 2) - 3); + p->http_regrep_obj = (char *)malloc(strlen(p1 + 2) + 1); + if (p->http_regrep_obj == NULL) { + free(p->http_regrep_obj); + } + strncpy_(p->http_regrep_obj, p1 + 2, strlen(p1 + 2)); + p->http_regrep_aim_len = strlen(p->http_regrep_aim); + p->http_regrep_obj_len = strlen(p->http_regrep_obj); + } + + content = strchr(lineEnd+1, '\n'); + } +} + +static void parse_https_module(char *content, conf *p) { + char *var, *val_begin, *val_end, *lineEnd; + int val_begin_len; + + while ((lineEnd = set_var_val_lineEnd(content, &var, &val_begin, &val_end)) != NULL) + { + if (strcasecmp(var, "https_ip") == 0) { + val_begin_len = strlen(val_begin) + 1; + p->https_ip = (char *)malloc(val_begin_len); + memcpy(p->https_ip, val_begin, val_begin_len); + } + else if (strcasecmp(var, "https_port") == 0) { + p->https_port = atoi(val_begin); + } + else if (strcasecmp(var, "https_del") == 0) { + val_begin_len = strlen(val_begin) + 1; + p->https_del = (char *)malloc(val_begin_len); + memcpy(p->https_del, val_begin, val_begin_len); + } + else if (strcasecmp(var, "https_first") == 0) { + val_begin_len = strlen(val_begin) + 1; + p->https_first = (char *)malloc(val_begin_len); + memcpy(p->https_first, val_begin, val_begin_len); + } + else if (strcasecmp(var, "strrep") ==0) { + val_begin_len = strlen(val_begin) + 1; + + p->https_strrep = (char *)malloc(val_begin_len); + if (p->https_strrep == NULL) + free(p->https_strrep); + memcpy(p->https_strrep, val_begin, val_begin_len); + + char *p1 = strstr(val_begin, "->"); + p->https_strrep_aim = (char *)malloc(val_begin_len - strlen(p1 + 2) - 2 + 1); + if (p->https_strrep_aim == NULL) { + free(p->https_strrep_aim); + } + strncpy_(p->https_strrep_aim, val_begin, val_begin_len - strlen(p1 + 2) - 3); + p->https_strrep_obj = (char *)malloc(strlen(p1 + 2) + 1); + if (p->https_strrep_obj == NULL) { + free(p->https_strrep_obj); + } + strncpy_(p->https_strrep_obj, p1 + 2, strlen(p1 + 2)); + p->https_strrep_aim_len = strlen(p->https_strrep_aim); + p->https_strrep_obj_len = strlen(p->https_strrep_obj); + } + else if (strcasecmp(var, "regrep") ==0) { + val_begin_len = strlen(val_begin) + 1; + + p->https_regrep = (char *)malloc(val_begin_len); + if (p->https_regrep == NULL) + free(p->https_regrep); + memcpy(p->https_regrep, val_begin, val_begin_len); + + char *p1 = strstr(val_begin, "->"); + p->https_regrep_aim = (char *)malloc(val_begin_len - strlen(p1 + 2) - 2 + 1); + if (p->https_regrep_aim == NULL) + free(p->https_regrep_aim); + strncpy_(p->https_regrep_aim, val_begin, val_begin_len - strlen(p1 + 2) - 3); + p->https_regrep_obj = (char *)malloc(strlen(p1 + 2) + 1); + if (p->https_regrep_obj == NULL) + free(p->https_regrep_obj); + strncpy_(p->https_regrep_obj, p1 + 2, strlen(p1 + 2)); + p->https_regrep_aim_len = strlen(p->https_regrep_aim); + p->https_regrep_obj_len = strlen(p->https_regrep_obj); + } + + content = strchr(lineEnd+1, '\n'); + } +} + +void free_conf(conf *p) { free(p->server_pid_file); free(p->http_ip); free(p->http_del); free(p->http_first); - free(p->https_ip); - free(p->https_del); - free(p->https_first); - free(p->http_strrep); free(p->http_strrep_aim); free(p->http_strrep_obj); - free(p->https_strrep); - free(p->https_strrep_aim); - free(p->https_strrep_obj); - free(p->http_regrep); free(p->http_regrep_aim); free(p->http_regrep_obj); + + free(p->https_ip); + free(p->https_del); + free(p->https_first); + free(p->https_strrep); + free(p->https_strrep_aim); + free(p->https_strrep_obj); free(p->https_regrep); free(p->https_regrep_aim); free(p->https_regrep_obj); return; } + +void read_conf(char *filename, conf *configure) +{ + char *buff, *global_content, *http_content, *https_content; + FILE *file; + long file_size; + + file = fopen(filename, "r"); + if (file == NULL) { + perror("cannot open config file."); + exit(-1); + } + fseek(file, 0, SEEK_END); + file_size = ftell(file); + buff = (char *)alloca(file_size + 1); + if (buff == NULL) + perror("out of memory."); + rewind(file); + fread(buff, file_size, 1, file); + fclose(file); + buff[file_size] = '\0'; + + if ((global_content = read_module(buff, "global")) == NULL) + perror("read global module error"); + parse_global_module(global_content, configure); + free(global_content); + + if ((http_content = read_module(buff, "http")) == NULL) + perror("read http module error"); + parse_http_module(http_content, configure); + free(http_content); + + if ((https_content = read_module(buff, "https")) == NULL) + perror("read https module error"); + parse_https_module(https_content, configure); + free(https_content); + +} + +void printfconf(conf *configure) { + printf("%d\n", configure->uid); + printf("%d\n", configure->process); + printf("%d\n", configure->timer); + printf("%d\n", configure->sslencoding); + printf("%d\n", configure->local_port); + printf("\n"); + if (configure->http_ip) + printf("%s\n", configure->http_ip); + printf("%d\n", configure->http_port); + if (configure->http_del) + printf("%s\n", configure->http_del); + if (configure->http_first) + printf("%s\n", configure->http_first); + if (configure->http_strrep) + printf("%s\n", configure->http_strrep); + if (configure->http_strrep_aim) + printf("%s\n", configure->http_strrep_aim); + if (configure->http_strrep_obj) + printf("%s\n", configure->http_strrep_obj); + if (configure->http_regrep) + printf("%s\n", configure->http_regrep); + if (configure->http_regrep_aim) + printf("%s\n", configure->http_regrep_aim); + if (configure->http_regrep_obj) + printf("%s\n", configure->http_regrep_obj); + + printf("\n"); + if (configure->https_ip) + printf("%s\n", configure->https_ip); + printf("%d\n", configure->https_port); + if (configure->https_del) + printf("%s\n", configure->https_del); + if (configure->https_first) + printf("%s\n", configure->https_first); + if (configure->https_strrep) + printf("%s\n", configure->https_strrep); + if (configure->https_strrep_aim) + printf("%s\n", configure->https_strrep_aim); + if (configure->https_strrep_obj) + printf("%s\n", configure->https_strrep_obj); + if (configure->https_regrep) + printf("%s\n", configure->https_regrep); + if (configure->https_regrep_aim) + printf("%s\n", configure->https_regrep_aim); + if (configure->https_regrep_obj) + printf("%s\n", configure->https_regrep_obj); +} + diff --git a/conf.h b/conf.h index c6982ce..d314611 100644 --- a/conf.h +++ b/conf.h @@ -1,7 +1,10 @@ #ifndef CONF_H #define CONF_H -#include "iniparser.h" +#include +#include +#include +#include #include // 配置文件结构 @@ -10,7 +13,9 @@ typedef struct CONF { int uid; int process; int timer; - int server_port; + int sslencoding; + //int server_port; + int local_port; char *server_pid_file; int server_pid_file_len; // length @@ -42,7 +47,7 @@ typedef struct CONF { } conf; char *strncpy_(char *dest, const char *src, size_t n); -void read_conf(char *file, conf * p); -void free_conf(conf * p); +void read_conf(char *file, conf *p); +void free_conf(conf *p); #endif diff --git a/help.c b/help.c index 8c87fee..11e1fba 100644 --- a/help.c +++ b/help.c @@ -14,11 +14,14 @@ char help_information(void) static const char *s_help[] = { "", "Options:", - " -?,-h : help information", - " -p : process number, default 2 process", - " -t : timeout minute, default is no timeout", - " -s signal : send signal to a master process: stop, quit, restart, reload, status", - " -c filename : set configuration file, default CProxy.ini", + " -l --local_address : localip:localport", + " -f --remote_address : remoteip:remote:port", + " -p --process : process number, default: 2", + " -t --timeout : timeout minute, default: no timeout", + " -e --coding : ssl coding, default: [0-128]", + " -s --signal : send signal to a master process: stop, quit, restart, reload, status", + " -c --config : set configuration file, default: CProxy.ini", + " -? -h --? --help : help information", "", 0 }; diff --git a/http.c b/http.c index 0e64352..6e604cb 100644 --- a/http.c +++ b/http.c @@ -1,6 +1,16 @@ #include "http.h" #include "proxy.h" +int sslEncodeCode; + +/* 对数据进行编码 */ +static void dataEncode(char *data, int data_len) +{ + if (sslEncodeCode) + while (data_len-- > 0) + data[data_len] ^= sslEncodeCode; +} + static char *read_data(conn *in, char *data, int *data_len) { char *new_data; @@ -56,6 +66,7 @@ static void serverToClient(conn *server) client = server - 1; while ((server->header_buffer_len = read(server->fd, server->header_buffer, BUFFER_SIZE)) > 0) { + dataEncode(server->header_buffer, server->header_buffer_len); write_len = write(client->fd, server->header_buffer, server->header_buffer_len); if (write_len <= 0) { if (write_len == 0 || errno != EAGAIN) @@ -86,7 +97,7 @@ void clienttoserver(conn *in) int write_len; conn *remote; remote = in + 1; - + write_len = write(remote->fd, in->header_buffer, in->header_buffer_len); if (write_len == in->header_buffer_len) { in->header_buffer_len = 0; @@ -144,6 +155,7 @@ void tcp_in(conn *in, conf *configure) epoll_ctl(epollfd, EPOLL_CTL_ADD, remote->fd, &epollEvent); } } + dataEncode(in->header_buffer, in->header_buffer_len); clienttoserver(in); return; } diff --git a/http.h b/http.h index f52bc6f..0b72a60 100644 --- a/http.h +++ b/http.h @@ -10,6 +10,8 @@ int remote_port; char remote_host[128]; +extern int sslEncodeCode; + typedef struct conn_t { int fd; char *header_buffer; diff --git a/proxy.c b/proxy.c index 763217b..65f2df5 100644 --- a/proxy.c +++ b/proxy.c @@ -182,11 +182,12 @@ int get_executable_path(char *processdir, char *processname, int len) int _main(int argc, char *argv[]) { + sslEncodeCode = 0; int opt, i, process; char path[PATH_SIZE] = { 0 }; char executable_filename[PATH_SIZE] = { 0 }; (void)get_executable_path(path, executable_filename, sizeof(path)); - char *inifile = "/CProxy.ini"; + char *inifile = "/CProxy.conf"; inifile = strcat(path, inifile); conf *configure = (struct CONF *)malloc(sizeof(struct CONF)); read_conf(inifile, configure); @@ -198,9 +199,24 @@ int _main(int argc, char *argv[]) if (configure->process > 0) process = configure->process; - char optstrs[] = ":l:f:t:p:c:s:h?"; + //char optstring[] = ":l:f:t:p:c:e:s:h?"; + int longindex = 0; + char optstring[] = ":l:f:t:p:c:e:s:h?"; + static struct option longopts[] = { + { "local_address", required_argument, 0, 'l' }, + { "remote_address", required_argument, 0, 'f' }, + { "timeout", required_argument, 0, 't' }, + { "process", required_argument, 0, 'p' }, + { "config", required_argument, 0, 'c' }, + { "coding", required_argument, 0, 'e' }, + { "signal", required_argument, 0, 's' }, + { "help", no_argument, 0, 'h' }, + { "?", no_argument, 0, '?' }, + { 0, 0, 0, 0 } + }; char *p = NULL; - while (-1 != (opt = getopt(argc, argv, optstrs))) { + //while (-1 != (opt = getopt(argc, argv, optstring))) { + while (-1 != (opt = getopt_long(argc, argv, optstring, longopts, &longindex))) { switch (opt) { case 'l': p = strchr(optarg, ':'); @@ -231,6 +247,9 @@ int _main(int argc, char *argv[]) inifile = optarg; read_conf(inifile, configure); break; + case 'e': + sslEncodeCode = atoi(optarg); + break; case 's': if (strcasecmp(optarg, "stop") == 0 || strcasecmp(optarg, "quit") == 0) { free_conf(configure); @@ -250,8 +269,11 @@ int _main(int argc, char *argv[]) ; } } - - server_sock = create_server_socket(configure->server_port); + + if (configure->sslencoding > 0) + sslEncodeCode = configure->sslencoding; + + server_sock = create_server_socket(configure->local_port); signal(SIGPIPE, SIG_IGN); //忽略PIPE信号 memset(cts, 0, sizeof(cts)); diff --git a/proxy.h b/proxy.h index 0594a81..fbf5680 100644 --- a/proxy.h +++ b/proxy.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -16,6 +17,8 @@ #include #include #include +#include +#include #define MAX_CONNECTION 1020 #define BUFFER_SIZE 10240 diff --git a/request.c b/request.c index 508f448..45606fd 100644 --- a/request.c +++ b/request.c @@ -156,11 +156,10 @@ char *delete_head(char *head, const char *character, int string) return strcpy(head, tmp); } -int extract_host(char *header, char *host, char *port, char *H) +int extract_host(char *header, char *host, char *port) { bzero(host, strlen(host)); bzero(port, strlen(port)); - bzero(H, strlen(H)); char *_p = strstr(header, "CONNECT"); // 在 CONNECT 方法中解析 隧道主机名称及端口号 if (_p) { char *_p1 = strchr(_p, ' '); @@ -178,9 +177,6 @@ int extract_host(char *header, char *host, char *port, char *H) strncpy(host, _p1 + 1, (int)(_p3 - _p1) - 1); strcpy(port, "80"); } - strcpy(H, host); - strcat(H, ":"); - strcat(H, port); return 0; } @@ -210,9 +206,6 @@ int extract_host(char *header, char *host, char *port, char *H) host[h_len] = '\0'; strcpy(port, "80"); } - strcpy(H, host); - strcat(H, ":"); - strcat(H, port); return 0; } @@ -256,9 +249,10 @@ char *request_head(conn *in, conf *configure) char host[path_len]; char port[path_len]; char H[path_len*2]; - extract_host(in->header_buffer, host, port, H); + extract_host(in->header_buffer, host, port); - + +//printfconf(configure); if (strncmp(M, "CONNECT", 7) == 0) { char https_del_copy[configure->https_del_len]; @@ -296,6 +290,10 @@ char *request_head(conn *in, conf *configure) incomplete_head = replace(incomplete_head, &incomplete_head_len, "[version]", 9, V, V_len); incomplete_head = replace(incomplete_head, &incomplete_head_len, "[host]", 6, host, (int)strlen(host)); incomplete_head = replace(incomplete_head, &incomplete_head_len, "[port]", 6, port, (int)strlen(port)); + memset(H, 0, strlen(H)); + memcpy(H, host, path_len); + strcat(H, ":"); + strcat(H, port); incomplete_head = replace(incomplete_head, &incomplete_head_len, "[H]", 3, H, (int)strlen(H)); if (configure->https_strrep) { incomplete_head = replace(incomplete_head, &incomplete_head_len, configure->https_strrep_aim, configure->https_strrep_aim_len, configure->https_strrep_obj, configure->https_strrep_obj_len); @@ -355,6 +353,10 @@ char *request_head(conn *in, conf *configure) incomplete_head = replace(incomplete_head, &incomplete_head_len, "[version]", 9, V, V_len); incomplete_head = replace(incomplete_head, &incomplete_head_len, "[host]", 6, host, (int)strlen(host)); incomplete_head = replace(incomplete_head, &incomplete_head_len, "[port]", 6, port, (int)strlen(port)); + memset(H, 0, strlen(H)); + memcpy(H, host, path_len); + strcat(H, ":"); + strcat(H, port); incomplete_head = replace(incomplete_head, &incomplete_head_len, "[H]", 3, H, (int)strlen(H)); if (configure->http_strrep) { incomplete_head = replace(incomplete_head, &incomplete_head_len, configure->http_strrep_aim, configure->http_strrep_aim_len, configure->http_strrep_obj, configure->http_strrep_obj_len);