Add files via upload

This commit is contained in:
mmmdbybyd 2018-11-28 12:14:35 +08:00 committed by GitHub
parent 9f1299e721
commit f5cb1c8e02
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 81 additions and 47 deletions

View File

@ -1,6 +1,12 @@
OBJ := SpecialProxy OBJ := SpecialProxy
CC := gcc 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 all : main.o http.o dns.o
$(CC) $(CFLAGS) $(DEFS) -o $(OBJ) $^ $(CC) $(CFLAGS) $(DEFS) -o $(OBJ) $^

View File

@ -1,6 +1,6 @@
SpecialProxy SpecialProxy
====== ======
用epoll多路复用io写的一个HTTP代理自带DNS解析 用epoll多路复用io写的一个HTTP代理轻快,自带DNS解析
##### SpecialProxy有如下特性 ##### SpecialProxy有如下特性
1. 普通HTTP代理通过请求头首行的host或者Host头域字段获得目标主机 1. 普通HTTP代理通过请求头首行的host或者Host头域字段获得目标主机
@ -16,8 +16,9 @@ SpecialProxy
4. -L参数设置重定向到本地端口的头域比如-L Local 4. -L参数设置重定向到本地端口的头域比如-L Local
然后请求头中含有Local: 443代理会将请求发送到127.0.0.1:443 然后请求头中含有Local: 443代理会将请求发送到127.0.0.1:443
##### 搭建: 5. -e设置数据编码的代码
curl -k -O https://raw.githubusercontent.com/mmmdbybyd/SpecialProxy/master/SpecialProxy.sh && bash SpecialProxy.sh 对客户端uri Host Referer以及请求附带的数据编码
服务器的返回数据也编码
##### 启动参数: ##### 启动参数:
-l [监听ip:]监听端口 默认监听IP为 "0.0.0.0" -l [监听ip:]监听端口 默认监听IP为 "0.0.0.0"
@ -25,13 +26,14 @@ SpecialProxy
-L 本地代理头域 默认为 "Local" -L 本地代理头域 默认为 "Local"
-d DNS查询IP[:端口] 默认为 "114.114.114.114" -d DNS查询IP[:端口] 默认为 "114.114.114.114"
-s SSL代理字符串 默认为 "CONNECT" -s SSL代理字符串 默认为 "CONNECT"
-u 设置运行uid -u 设置uid
-e 设置代理CProxy的数据编码代码(1-127)
-a 对所有HTTP请求重新拼接 -a 对所有HTTP请求重新拼接
-h 显示帮助 -h 显示帮助
-w 工作进程数 -w 工作进程数
##### BUG ##### BUG
好像有些连接不关闭,需要定时重启代理 待发现
##### 编译: ##### 编译:
~~~~~ ~~~~~
@ -39,4 +41,4 @@ Linux/Android:
make make
Android-ndk: Android-ndk:
ndk-build ndk-build
~~~~~ ~~~~~

92
http.c
View File

@ -1,14 +1,21 @@
#include "http.h" #include "http.h"
#include "dns.h" #include "dns.h"
#define SSL_RSP "HTTP/1.1 200 Connection established\r\n\r\n"
#define HTTP_TYPE 0 #define HTTP_TYPE 0
#define OTHER_TYPE 1 #define OTHER_TYPE 1
conn_t cts[MAX_CONNECTION]; 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; char *local_header, *proxy_header, *ssl_proxy;
int lisFd, proxy_header_len, local_header_len; 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) int8_t connectionToServer(char *ip, conn_t *server)
{ {
@ -139,10 +146,19 @@ static char *get_host(char *data)
while (*host == ' ') while (*host == ' ')
host++; host++;
hostEnd = strchr(host, '\r'); hostEnd = strchr(host, '\r');
if (hostEnd) if (hostEnd)
{
if (encodeCode)
dataEncode(host, hostEnd - host);
return strndup(host, hostEnd - host); return strndup(host, hostEnd - host);
}
else else
{
if (encodeCode)
dataEncode(host, strlen(host));
return strdup(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) 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'); lf = strchr(header, '\n');
if (url == NULL || lf == NULL || lf - 10 <= header) if (url == NULL || lf == NULL || lf - 10 <= header)
return client_data; return client_data;
if (url < lf && *(++url) != '/') if (url < lf && *(++url) != '/')
{ {
uri = strchr(url + 7, '/'); uri = strchr(url + 7, '/');
@ -208,6 +243,12 @@ static char *build_request(char *client_data, int *data_len, char *host)
*data_len -= p - url; *data_len -= p - url;
lf -= 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"的长度 *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); free(client_data);
if (proxy_host != host) if (proxy_host != host)
free(proxy_host); free(proxy_host);
if (encodeCode)
encodeReferer(new_data);
if (strict_spilce == 0) if (strict_spilce == 0)
return new_data; return new_data;
client_data = new_data; client_data = new_data;
@ -300,25 +343,6 @@ static int8_t copy_data(conn_t *ct)
return 0; 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) static void serverToClient(conn_t *server)
{ {
conn_t *client; conn_t *client;
@ -328,6 +352,8 @@ static void serverToClient(conn_t *server)
client = server - 1; client = server - 1;
while ((server->ready_data_len = read(server->fd, server->ready_data, BUFFER_SIZE)) > 0) 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); write_len = write(client->fd, server->ready_data, server->ready_data_len);
if (write_len == -1) if (write_len == -1)
{ {
@ -345,18 +371,11 @@ static void serverToClient(conn_t *server)
epoll_ctl(efd, EPOLL_CTL_MOD, client->fd, &ev); epoll_ctl(efd, EPOLL_CTL_MOD, client->fd, &ev);
return; 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) if (server->ready_data_len < BUFFER_SIZE)
break; 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); close_connection(server);
else else
server->ready_data_len = server->sent_len = 0; 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); server->request_type = in->request_type = request_type(in->incomplete_data);
if (in->request_type == OTHER_TYPE) if (in->request_type == OTHER_TYPE)
{ {
if (encodeCode)
dataEncode(in->incomplete_data, in->incomplete_data_len);
//如果是第一次读取数据并且不是HTTP请求的关闭连接。复制数据失败的也关闭连接 //如果是第一次读取数据并且不是HTTP请求的关闭连接。复制数据失败的也关闭连接
if (in->reread_data == 0 || copy_data(in) != 0) if (in->reread_data == 0 || copy_data(in) != 0)
{ {
@ -443,18 +464,19 @@ void tcp_in(conn_t *in)
} }
goto handle_data_complete; goto handle_data_complete;
} }
headerEnd = strstr(in->incomplete_data, "\n\r"); headerEnd = strstr(in->incomplete_data, "\n\r\n");
//请求头不完整,等待下次读取 //请求头不完整,等待下次读取
if (headerEnd == NULL) if (headerEnd == NULL)
return; return;
headerEnd += 3;
if (encodeCode)
dataEncode(headerEnd, in->incomplete_data_len - (headerEnd - in->incomplete_data));
host = get_host(in->incomplete_data); host = get_host(in->incomplete_data);
if (host == NULL) if (host == NULL)
{ {
close_connection(in); close_connection(in);
return; return;
} }
/* 判断是否长连接 */
server->keep_alive = in->keep_alive = is_keepAlive(in->incomplete_data);
/* 第一次读取数据 */ /* 第一次读取数据 */
if (in->reread_data == 0) if (in->reread_data == 0)
{ {
@ -467,16 +489,14 @@ void tcp_in(conn_t *in)
} }
if (strstr(in->incomplete_data, ssl_proxy)) if (strstr(in->incomplete_data, ssl_proxy))
{ {
server->keep_alive = in->keep_alive = 1;
server->is_ssl = in->is_ssl = 1; server->is_ssl = in->is_ssl = 1;
/* 这时候即使fd是非阻塞也只需要判断返回值是否小于0 */ /* 这时候即使fd是非阻塞也只需要判断返回值是否小于0 */
if (write(in->fd, SSL_RSP, 39) < 0) if (write(in->fd, ssl_rsp, sizeof(ssl_rsp) - 1) < 0)
{ {
free(host); free(host);
close_connection(in); close_connection(in);
return; return;
} }
headerEnd += 3;
if (headerEnd - in->incomplete_data < in->incomplete_data_len) if (headerEnd - in->incomplete_data < in->incomplete_data_len)
{ {
in->incomplete_data_len -= headerEnd - in->incomplete_data; in->incomplete_data_len -= headerEnd - in->incomplete_data;
@ -527,6 +547,8 @@ void *accept_loop(void *ptr)
struct epoll_event epollEvent; struct epoll_event epollEvent;
conn_t *client; conn_t *client;
if (encodeCode)
dataEncode(ssl_rsp, sizeof(ssl_rsp) - 1);
epollEvent.events = EPOLLIN|EPOLLET; epollEvent.events = EPOLLIN|EPOLLET;
while (1) while (1)
{ {

3
http.h
View File

@ -9,7 +9,6 @@ typedef struct tcp_connection {
uint16_t destPort; uint16_t destPort;
unsigned reread_data :1; unsigned reread_data :1;
unsigned request_type :1; unsigned request_type :1;
unsigned keep_alive :1;
unsigned is_ssl :1; unsigned is_ssl :1;
} conn_t; } conn_t;
@ -23,6 +22,6 @@ extern void tcp_out(conn_t *ct);
extern conn_t cts[MAX_CONNECTION]; extern conn_t cts[MAX_CONNECTION];
extern char *local_header, *proxy_header, *ssl_proxy; 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;
extern uint8_t strict_spilce; extern uint8_t strict_spilce, isEncode, encodeCode;
#endif #endif

9
main.c
View File

@ -20,6 +20,7 @@ static void usage()
" -d dns query address \033[35G default is " DEFAULT_DNS_IP "\n" " -d dns query address \033[35G default is " DEFAULT_DNS_IP "\n"
" -s ssl proxy string \033[35G default is 'CONNECT'\n" " -s ssl proxy string \033[35G default is 'CONNECT'\n"
" -u uid \033[35G running uid\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" " -a \033[35G all http requests repeat spilce\n"
" -h display this infomaction\n" " -h display this infomaction\n"
" -w worker process\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_addr.s_addr = inet_addr(DEFAULT_DNS_IP);
dnsAddr.sin_port = htons(53); dnsAddr.sin_port = htons(53);
dns_connect(&dnsAddr); //主进程中的fd dns_connect(&dnsAddr); //主进程中的fd
strict_spilce = 0; strict_spilce = encodeCode = 0;
local_header = NULL; local_header = NULL;
ssl_proxy = (char *)"CONNECT"; ssl_proxy = (char *)"CONNECT";
local_header = (char *)"\nLocal:"; local_header = (char *)"\nLocal:";
@ -87,7 +88,7 @@ static void initializate(int argc, char **argv)
proxy_header_len = strlen(proxy_header); proxy_header_len = strlen(proxy_header);
local_header_len = strlen(local_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) switch (opt)
{ {
@ -115,6 +116,10 @@ static void initializate(int argc, char **argv)
} }
break; break;
case 'e':
encodeCode = (int8_t)atoi(optarg);
break;
case 'p': case 'p':
//假如选项值为 "Proxy", proxy_header设置为 "\nProxy:" //假如选项值为 "Proxy", proxy_header设置为 "\nProxy:"
proxy_header_len = strlen(optarg) + 2; proxy_header_len = strlen(optarg) + 2;

2
main.h
View File

@ -16,7 +16,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <signal.h> #include <signal.h>
#define BUFFER_SIZE 10240 #define BUFFER_SIZE 4096
#define MAX_CONNECTION 1020 #define MAX_CONNECTION 1020
extern struct epoll_event evs[MAX_CONNECTION + 1], ev; extern struct epoll_event evs[MAX_CONNECTION + 1], ev;