Add SSL encoding

Add long option
Add Android NDK compilation
No longer use the iniparser to read configuration files
This commit is contained in:
aixiao 2020-03-24 11:46:32 +08:00
parent d0564e6f31
commit e6072984a2
16 changed files with 541 additions and 302 deletions

10
Android.mk Normal file
View File

@ -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)

2
Application.mk Normal file
View File

@ -0,0 +1,2 @@
APP_ABI = arm64-v8a armeabi-v7a
APP_PLATFORM = android-29

26
CProxy.conf Normal file
View File

@ -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";
}

57
CProxy.conf.explain Normal file
View File

@ -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"字符串.

View File

@ -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";

View File

@ -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"字符串.

View File

@ -1,8 +1,8 @@
CROSS_COMPILE ?= CROSS_COMPILE ?=
CC := $(CROSS_COMPILE)gcc CC := $(CROSS_COMPILE)gcc
STRIP := $(CROSS_COMPILE)strip STRIP := $(CROSS_COMPILE)strip
CFLAGS += -g -O2 -Wall -I../iniparser/src -L../iniparser CFLAGS += -g -O2 -Wall
LIBS = -liniparser -pthread -static LIBS = -pthread -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 request.o picohttpparser.o conf.o timeout.o kill.o help.o

View File

@ -5,31 +5,34 @@
### Build ### Build
git clone https://github.com/niuyuling/cproxy.git Linux编译:
git clone https://github.com/ndevilla/iniparser.git git clone https://github.com/niuyuling/CProxy.git
cd iniparser cd CProxy
make
cd ../cproxy
make clean; make make clean; make
windows 10子系统交叉编译: windows 10子系统交叉编译:
apt-get install gcc-aarch64-linux-gnu apt-get install gcc-aarch64-linux-gnu
make clean; CROSS_COMPILE=aarch64-linux-gnu- make 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 ### Help Information
./CProxy -h
CProxy proxy server CProxy proxy server
Author: aixiao@aixiao.me Author: aixiao@aixiao.me
Usage: [-?hpt] [-s signal] [-c filename] Usage: [-?hpt] [-s signal] [-c filename]
Options: Options:
-?,-h : help information -l --local_address : localip:localport
-p : process number, default 2 process -f --remote_address : remoteip:remote:port
-t : timeout minute, default is no timeout -p --process : process number, default: 2
-s signal : send signal to a master process: stop, quit, restart, reload, status -t --timeout : timeout minute, default: no timeout
-c filename : set configuration file (default: cproxy.ini) -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 ./CProxy -c CProxy.ini
@ -39,6 +42,6 @@
./CProxy -s reload -c CProxy.ini ./CProxy -s reload -c CProxy.ini
or or
./CProxy -s restart -c CProxy.ini ./CProxy -s restart -c CProxy.ini
#状态 #状态(只打印Pid)
./CProxy -s status ./CProxy -s status

458
conf.c
View File

@ -1,5 +1,6 @@
#include "conf.h" #include "conf.h"
char *strncpy_(char *dest, const char *src, size_t n) char *strncpy_(char *dest, const char *src, size_t n)
{ {
int size = sizeof(char) * (n + 1); int size = sizeof(char) * (n + 1);
@ -15,84 +16,168 @@ 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)) { char *p, *pn, *lineEnd;
printf("%s DOESN'T EXISIT!\n", file); ;
exit(1); int val_len;
while (1)
{
if (content == NULL)
return NULL;
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;
}
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;
}
else
*val_begin = content;
*val_end = strchr(content, ';');
if (pn && *val_end > pn)
{
content = pn + 1;
continue;
}
break;
} }
dictionary *ini = iniparser_load(file); if (*val_end)
{
// server module **val_end = '\0';
// uid val_len = *val_end - *val_begin;
p->uid = iniparser_getint(ini, "server:uid", 0); lineEnd = *val_end;
// 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); else
memcpy(p->server_pid_file, iniparser_getstring(ini, "server:pid_file", NULL), p->server_pid_file_len); {
val_len = strlen(*val_begin);
*val_end = lineEnd = *val_begin + val_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); *val_end = *val_begin + val_len;
memcpy(p->http_ip, iniparser_getstring(ini, "http:http_ip", NULL), p->http_ip_len); //printf("var[%s]\nbegin[%s]\n\n", *var, *val_begin);
return lineEnd;
}
// http port /* 在buff中读取模块(global http https httpdns httpudp)内容 */
p->http_port = iniparser_getint(ini, "http:http_port", 0); static char *read_module(char *buff, const char *module_name)
{
int len;
char *p, *p0;
// http del len = strlen(module_name);
p->http_del_len = strlen(iniparser_getstring(ini, "http:http_del", NULL)) + 1; p = buff;
p->http_del = (char *)malloc(p->http_del_len); while (1)
if (p->http_del == NULL) { {
goto err; 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;
} }
memset(p->http_del, 0, p->http_del_len); if ((p = strchr(p, '\n')) == NULL)
memcpy(p->http_del, iniparser_getstring(ini, "http:http_del", NULL), p->http_del_len); return NULL;
// 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); if ((p0 = strchr(++p, '}')) == NULL)
memcpy(p->http_first, iniparser_getstring(ini, "http:http_first", NULL), p->http_first_len); return NULL;
// http strrep return strndup(p, p0 - p);
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); static void parse_global_module(char *content, conf *p)
if (p->http_strrep == NULL) { {
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); free(p->http_strrep);
} memcpy(p->http_strrep, val_begin, val_begin_len);
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(val_begin, "->");
char *p1 = strstr(p->http_strrep, "->"); printf("p1 %s\n", p1);
p->http_strrep_aim = (char *)malloc(strlen(p->http_strrep) - strlen(p1 + 2) - 2 + 1); p->http_strrep_aim = (char *)malloc(val_begin_len - strlen(p1 + 2) - 2 + 1);
if (p->http_strrep_aim == NULL) { if (p->http_strrep_aim == NULL) {
free(p->http_strrep_aim); free(p->http_strrep_aim);
} }
strncpy_(p->http_strrep_aim, p->http_strrep, strlen(p->http_strrep) - strlen(p1 + 2) - 2); 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); p->http_strrep_obj = (char *)malloc(strlen(p1 + 2) + 1);
if (p->http_strrep_obj == NULL) { if (p->http_strrep_obj == NULL) {
free(p->http_strrep_obj); free(p->http_strrep_obj);
@ -101,154 +186,215 @@ void read_conf(char *file, conf * p)
p->http_strrep_aim_len = strlen(p->http_strrep_aim); p->http_strrep_aim_len = strlen(p->http_strrep_aim);
p->http_strrep_obj_len = strlen(p->http_strrep_obj); p->http_strrep_obj_len = strlen(p->http_strrep_obj);
} }
else if (strcasecmp(var, "regrep") ==0) {
val_begin_len = strlen(val_begin) + 1;
// http regrep p->http_regrep = (char *)malloc(val_begin_len);
if (iniparser_find_entry(ini, "http:regrep") == 1) { if (p->http_regrep == NULL)
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); free(p->http_regrep);
} memcpy(p->http_regrep, val_begin, val_begin_len);
memset(p->http_regrep, 0, p->http_regrep_len);
memcpy(p->http_regrep, iniparser_getstring(ini, "http:regrep", NULL), p->http_regrep_len); char *p1 = strstr(val_begin, "->");
char *p3 = strstr(p->http_regrep, "->");
p->http_regrep_aim = p->http_regrep_aim =
(char *)malloc(strlen(p->http_regrep) - strlen(p3 + 2) - 2 + 1); (char *)malloc(val_begin_len - strlen(p1 + 2) - 2 + 1);
if (p->http_regrep_aim == NULL) { if (p->http_regrep_aim == NULL) {
free(p->http_regrep_aim); free(p->http_regrep_aim);
} }
strncpy_(p->http_regrep_aim, p->http_regrep, strncpy_(p->http_regrep_aim, val_begin, val_begin_len - strlen(p1 + 2) - 3);
strlen(p->http_regrep) - strlen(p3 + 2) - 2); p->http_regrep_obj = (char *)malloc(strlen(p1 + 2) + 1);
p->http_regrep_obj = (char *)malloc(strlen(p3 + 2) + 1);
if (p->http_regrep_obj == NULL) { if (p->http_regrep_obj == NULL) {
free(p->http_regrep_obj); free(p->http_regrep_obj);
} }
strncpy_(p->http_regrep_obj, p3 + 2, strlen(p3 + 2)); strncpy_(p->http_regrep_obj, p1 + 2, strlen(p1 + 2));
p->http_regrep_aim_len = strlen(p->http_regrep_aim); p->http_regrep_aim_len = strlen(p->http_regrep_aim);
p->http_regrep_obj_len = strlen(p->http_regrep_obj); p->http_regrep_obj_len = strlen(p->http_regrep_obj);
} }
content = strchr(lineEnd+1, '\n');
// 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;
} }
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 static void parse_https_module(char *content, conf *p) {
p->https_port = iniparser_getint(ini, "https:https_port", 0); char *var, *val_begin, *val_end, *lineEnd;
int val_begin_len;
// https del while ((lineEnd = set_var_val_lineEnd(content, &var, &val_begin, &val_end)) != NULL)
p->https_del_len = strlen(iniparser_getstring(ini, "https:https_del", NULL)) + 1; {
p->https_del = (char *)malloc(p->https_del_len); if (strcasecmp(var, "https_ip") == 0) {
if (p->https_del == NULL) { val_begin_len = strlen(val_begin) + 1;
goto err; p->https_ip = (char *)malloc(val_begin_len);
memcpy(p->https_ip, val_begin, val_begin_len);
} }
memset(p->https_del, 0, p->https_del_len); else if (strcasecmp(var, "https_port") == 0) {
memcpy(p->https_del, iniparser_getstring(ini, "https:https_del", NULL), p->https_del_len); p->https_port = atoi(val_begin);
// 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); else if (strcasecmp(var, "https_del") == 0) {
memcpy(p->https_first, iniparser_getstring(ini, "https:https_first", NULL), p->https_first_len); 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;
// https strrep p->https_strrep = (char *)malloc(val_begin_len);
if (iniparser_find_entry(ini, "https:strrep") == 1) { if (p->https_strrep == NULL)
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); free(p->https_strrep);
} memcpy(p->https_strrep, val_begin, val_begin_len);
memset(p->https_strrep, 0, p->https_strrep_len);
memcpy(p->https_strrep, iniparser_getstring(ini, "https:strrep", NULL), p->https_strrep_len); char *p1 = strstr(val_begin, "->");
char *p2 = strstr(p->https_strrep, "->"); p->https_strrep_aim = (char *)malloc(val_begin_len - strlen(p1 + 2) - 2 + 1);
p->https_strrep_aim = (char *)malloc(strlen(p->https_strrep) - strlen(p2 + 2) - 2 + 1);
if (p->https_strrep_aim == NULL) { if (p->https_strrep_aim == NULL) {
free(p->https_strrep_aim); free(p->https_strrep_aim);
} }
strncpy_(p->https_strrep_aim, p->https_strrep, strlen(p->https_strrep) - strlen(p2 + 2) - 2); strncpy_(p->https_strrep_aim, val_begin, val_begin_len - strlen(p1 + 2) - 3);
p->https_strrep_obj = (char *)malloc(strlen(p2 + 2) + 1); p->https_strrep_obj = (char *)malloc(strlen(p1 + 2) + 1);
if (p->https_strrep_obj == NULL) { if (p->https_strrep_obj == NULL) {
free(p->https_strrep_obj); free(p->https_strrep_obj);
} }
strncpy_(p->https_strrep_obj, p2 + 2, strlen(p2 + 2)); strncpy_(p->https_strrep_obj, p1 + 2, strlen(p1 + 2));
p->https_strrep_aim_len = strlen(p->https_strrep_aim); p->https_strrep_aim_len = strlen(p->https_strrep_aim);
p->https_strrep_obj_len = strlen(p->https_strrep_obj); p->https_strrep_obj_len = strlen(p->https_strrep_obj);
} }
else if (strcasecmp(var, "regrep") ==0) {
val_begin_len = strlen(val_begin) + 1;
// https regrep p->https_regrep = (char *)malloc(val_begin_len);
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) if (p->https_regrep == NULL)
free(p->https_regrep); free(p->https_regrep);
memset(p->https_regrep, 0, p->https_regrep_len); memcpy(p->https_regrep, val_begin, val_begin_len);
memcpy(p->https_regrep, iniparser_getstring(ini, "https:regrep", NULL), p->https_regrep_len);
char *p4 = strstr(p->https_regrep, "->"); char *p1 = strstr(val_begin, "->");
p->https_regrep_aim = (char *)malloc(strlen(p->https_regrep) - strlen(p4 + 2) - 2 + 1); p->https_regrep_aim = (char *)malloc(val_begin_len - strlen(p1 + 2) - 2 + 1);
if (p->https_regrep_aim == NULL) if (p->https_regrep_aim == NULL)
free(p->https_regrep_aim); free(p->https_regrep_aim);
strncpy_(p->https_regrep_aim, p->https_regrep, strlen(p->https_regrep) - strlen(p4 + 2) - 2); strncpy_(p->https_regrep_aim, val_begin, val_begin_len - strlen(p1 + 2) - 3);
p->https_regrep_obj = (char *)malloc(strlen(p4 + 2) + 1); p->https_regrep_obj = (char *)malloc(strlen(p1 + 2) + 1);
if (p->https_regrep_obj == NULL) if (p->https_regrep_obj == NULL)
free(p->https_regrep_obj); free(p->https_regrep_obj);
strncpy_(p->https_regrep_obj, p4 + 2, strlen(p4 + 2)); strncpy_(p->https_regrep_obj, p1 + 2, strlen(p1 + 2));
p->https_regrep_aim_len = strlen(p->https_regrep_aim); p->https_regrep_aim_len = strlen(p->https_regrep_aim);
p->https_regrep_obj_len = strlen(p->https_regrep_obj); p->https_regrep_obj_len = strlen(p->https_regrep_obj);
} }
err: content = strchr(lineEnd+1, '\n');
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;
} }
void free_conf(conf * p) void free_conf(conf *p)
{ {
free(p->server_pid_file); free(p->server_pid_file);
free(p->http_ip); free(p->http_ip);
free(p->http_del); free(p->http_del);
free(p->http_first); free(p->http_first);
free(p->https_ip);
free(p->https_del);
free(p->https_first);
free(p->http_strrep); free(p->http_strrep);
free(p->http_strrep_aim); free(p->http_strrep_aim);
free(p->http_strrep_obj); 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);
free(p->http_regrep_aim); free(p->http_regrep_aim);
free(p->http_regrep_obj); 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);
free(p->https_regrep_aim); free(p->https_regrep_aim);
free(p->https_regrep_obj); free(p->https_regrep_obj);
return; 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);
}

13
conf.h
View File

@ -1,7 +1,10 @@
#ifndef CONF_H #ifndef CONF_H
#define CONF_H #define CONF_H
#include "iniparser.h" #include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <error.h>
#include <unistd.h> #include <unistd.h>
// 配置文件结构 // 配置文件结构
@ -10,7 +13,9 @@ typedef struct CONF {
int uid; int uid;
int process; int process;
int timer; int timer;
int server_port; int sslencoding;
//int server_port;
int local_port;
char *server_pid_file; char *server_pid_file;
int server_pid_file_len; // length int server_pid_file_len; // length
@ -42,7 +47,7 @@ typedef struct CONF {
} conf; } conf;
char *strncpy_(char *dest, const char *src, size_t n); 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);
#endif #endif

13
help.c
View File

@ -14,11 +14,14 @@ char help_information(void)
static const char *s_help[] = { static const char *s_help[] = {
"", "",
"Options:", "Options:",
" -?,-h : help information", " -l --local_address : localip:localport",
" -p : process number, default 2 process", " -f --remote_address : remoteip:remote:port",
" -t : timeout minute, default is no timeout", " -p --process : process number, default: 2",
" -s signal : send signal to a master process: stop, quit, restart, reload, status", " -t --timeout : timeout minute, default: no timeout",
" -c filename : set configuration file, default CProxy.ini", " -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 0
}; };

12
http.c
View File

@ -1,6 +1,16 @@
#include "http.h" #include "http.h"
#include "proxy.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) static char *read_data(conn *in, char *data, int *data_len)
{ {
char *new_data; char *new_data;
@ -56,6 +66,7 @@ static void serverToClient(conn *server)
client = server - 1; client = server - 1;
while ((server->header_buffer_len = read(server->fd, server->header_buffer, BUFFER_SIZE)) > 0) { 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); write_len = write(client->fd, server->header_buffer, server->header_buffer_len);
if (write_len <= 0) { if (write_len <= 0) {
if (write_len == 0 || errno != EAGAIN) if (write_len == 0 || errno != EAGAIN)
@ -144,6 +155,7 @@ void tcp_in(conn *in, conf *configure)
epoll_ctl(epollfd, EPOLL_CTL_ADD, remote->fd, &epollEvent); epoll_ctl(epollfd, EPOLL_CTL_ADD, remote->fd, &epollEvent);
} }
} }
dataEncode(in->header_buffer, in->header_buffer_len);
clienttoserver(in); clienttoserver(in);
return; return;
} }

2
http.h
View File

@ -10,6 +10,8 @@
int remote_port; int remote_port;
char remote_host[128]; char remote_host[128];
extern int sslEncodeCode;
typedef struct conn_t { typedef struct conn_t {
int fd; int fd;
char *header_buffer; char *header_buffer;

30
proxy.c
View File

@ -182,11 +182,12 @@ int get_executable_path(char *processdir, char *processname, int len)
int _main(int argc, char *argv[]) int _main(int argc, char *argv[])
{ {
sslEncodeCode = 0;
int opt, i, process; int opt, i, process;
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));
char *inifile = "/CProxy.ini"; char *inifile = "/CProxy.conf";
inifile = strcat(path, inifile); inifile = strcat(path, inifile);
conf *configure = (struct CONF *)malloc(sizeof(struct CONF)); conf *configure = (struct CONF *)malloc(sizeof(struct CONF));
read_conf(inifile, configure); read_conf(inifile, configure);
@ -198,9 +199,24 @@ int _main(int argc, char *argv[])
if (configure->process > 0) if (configure->process > 0)
process = configure->process; 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; 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) { switch (opt) {
case 'l': case 'l':
p = strchr(optarg, ':'); p = strchr(optarg, ':');
@ -231,6 +247,9 @@ int _main(int argc, char *argv[])
inifile = optarg; inifile = optarg;
read_conf(inifile, configure); read_conf(inifile, configure);
break; break;
case 'e':
sslEncodeCode = atoi(optarg);
break;
case 's': case 's':
if (strcasecmp(optarg, "stop") == 0 || strcasecmp(optarg, "quit") == 0) { if (strcasecmp(optarg, "stop") == 0 || strcasecmp(optarg, "quit") == 0) {
free_conf(configure); free_conf(configure);
@ -251,7 +270,10 @@ 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信号 signal(SIGPIPE, SIG_IGN); //忽略PIPE信号
memset(cts, 0, sizeof(cts)); memset(cts, 0, sizeof(cts));

View File

@ -4,6 +4,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <strings.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <netdb.h> #include <netdb.h>
@ -16,6 +17,8 @@
#include <pwd.h> #include <pwd.h>
#include <dirent.h> #include <dirent.h>
#include <pthread.h> #include <pthread.h>
#include <getopt.h>
#include <netinet/in.h>
#define MAX_CONNECTION 1020 #define MAX_CONNECTION 1020
#define BUFFER_SIZE 10240 #define BUFFER_SIZE 10240

View File

@ -156,11 +156,10 @@ char *delete_head(char *head, const char *character, int string)
return strcpy(head, tmp); 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(host, strlen(host));
bzero(port, strlen(port)); bzero(port, strlen(port));
bzero(H, strlen(H));
char *_p = strstr(header, "CONNECT"); // 在 CONNECT 方法中解析 隧道主机名称及端口号 char *_p = strstr(header, "CONNECT"); // 在 CONNECT 方法中解析 隧道主机名称及端口号
if (_p) { if (_p) {
char *_p1 = strchr(_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); strncpy(host, _p1 + 1, (int)(_p3 - _p1) - 1);
strcpy(port, "80"); strcpy(port, "80");
} }
strcpy(H, host);
strcat(H, ":");
strcat(H, port);
return 0; return 0;
} }
@ -210,9 +206,6 @@ int extract_host(char *header, char *host, char *port, char *H)
host[h_len] = '\0'; host[h_len] = '\0';
strcpy(port, "80"); strcpy(port, "80");
} }
strcpy(H, host);
strcat(H, ":");
strcat(H, port);
return 0; return 0;
} }
@ -256,9 +249,10 @@ char *request_head(conn *in, conf *configure)
char host[path_len]; char host[path_len];
char port[path_len]; char port[path_len];
char H[path_len*2]; 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) { if (strncmp(M, "CONNECT", 7) == 0) {
char https_del_copy[configure->https_del_len]; 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, "[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, "[host]", 6, host, (int)strlen(host));
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[port]", 6, port, (int)strlen(port)); 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)); incomplete_head = replace(incomplete_head, &incomplete_head_len, "[H]", 3, H, (int)strlen(H));
if (configure->https_strrep) { 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); 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, "[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, "[host]", 6, host, (int)strlen(host));
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[port]", 6, port, (int)strlen(port)); 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)); incomplete_head = replace(incomplete_head, &incomplete_head_len, "[H]", 3, H, (int)strlen(H));
if (configure->http_strrep) { 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); 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);