The modified code supports C proxy.

This commit is contained in:
aixiao 2022-04-04 20:00:36 +08:00
parent 3383ecbbf7
commit 1141fca0e4
13 changed files with 92 additions and 70 deletions

0
.gitignore vendored Normal file → Executable file
View File

0
LICENSE Normal file → Executable file
View File

18
Makefile Normal file → Executable file
View File

@ -1,21 +1,19 @@
CROSS_COMPILE ?=
CC := $(CROSS_COMPILE)gcc
STRIP := $(CROSS_COMPILE)strip
CFLAGS := -O2 -g -Wall -pthread
OBJ := SpecialProxy
CC := gcc
CFLAGS := -O2 -Wall -pthread
STRIP := strip
#如果是安卓编译
ifeq ($(ANDROID_DATA),/data)
CFLAGS := -O2 -pie -Wall
SHELL = /system/bin/sh
endif
all : main.o http.o dns.o timeout.o
$(CC) $(CFLAGS) $(DEFS) -o $(OBJ) $^
$(STRIP) $(OBJ)
-chmod 777 $(OBJ) 2>&-
: $(STRIP) $(OBJ)
-chmod 755 $(OBJ) 2>&-
.c.o :
$(CC) $(CFLAGS) $(DEFS) -c $<
clean :
rm -f *.o
rm $(OBJ)

0
README.md Normal file → Executable file
View File

0
SpecialProxy.sh Normal file → Executable file
View File

0
dns.c Normal file → Executable file
View File

0
dns.h Normal file → Executable file
View File

138
http.c Normal file → Executable file
View File

@ -2,6 +2,7 @@
#include "dns.h"
#include "timeout.h"
#define SSL_RSP 270
#define SSL_RSP_CONNECT "HTTP/1.1 200 Connection established\r\nServer: SpecialProxy_CuteBi\r\nConnection: keep-alive\r\n\r\n"
#define SSL_RSP_HTTP "HTTP/1.1 200 OK\r\nContent-length: 99999999\r\nServer: SpecialProxy_CuteBi\r\nContent-Type: text/plain; charset=utf-8\r\nConnection: keep-alive\r\n\r\n"
#define SSL_RSP_WEBSOCKET "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: SpecialProxy_CuteBi\r\n\r\n"
@ -67,6 +68,7 @@ void close_connection(conn_t *conn)
}
if (conn->fd >= 0)
close_connection(conn);
}
@ -105,6 +107,7 @@ static char *read_data(conn_t *in, char *data, int *data_len)
}
data = new_data;
read_len = read(in->fd, data + *data_len, BUFFER_SIZE);
dataEncode(data, read_len);
/* 判断是否关闭连接 */
if (read_len <= 0)
{
@ -288,7 +291,7 @@ static int8_t parse_host(conn_t *server, char *host)
/* 读取到的数据全部就绪将incomplete_data复制到ready_data */
static int8_t copy_data(conn_t *ct)
{
dataEncode(ct->incomplete_data, ct->incomplete_data_len);
//dataEncode(ct->incomplete_data, ct->incomplete_data_len);
if (ct->ready_data)
{
char *new_data;
@ -348,55 +351,6 @@ static void serverToClient(conn_t *server)
server->ready_data_len = server->sent_len = 0;
}
void tcp_out(conn_t *to)
{
conn_t *from;
int write_len;
if (to->fd == -1)
return;
else if ((to - cts) & 1)
from = to - 1;
else
from = to + 1;
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)
{
//服务端的数据可能没全部写入到客户端
if ((from - cts) & 1)
{
serverToClient(from);
if (from->fd >= 0 && from->ready_data_len == 0)
{
ev.events = EPOLLIN|EPOLLET;
ev.data.ptr = to;
epoll_ctl(efd, EPOLL_CTL_MOD, to->fd, &ev);
}
}
else
{
ev.events = EPOLLIN|EPOLLET;
ev.data.ptr = to;
epoll_ctl(efd, EPOLL_CTL_MOD, to->fd, &ev);
free(from->ready_data);
from->ready_data = NULL;
from->ready_data_len = 0;
}
}
else if (write_len > 0)
{
from->sent_len += write_len;
ev.events = EPOLLIN|EPOLLOUT|EPOLLET;
ev.data.ptr = to;
epoll_ctl(efd, EPOLL_CTL_MOD, to->fd, &ev);
}
else if (errno != EAGAIN)
{
close_connection(to);
}
}
/* ssl代理回应 */
static int respond_sslStatus(conn_t *in)
{
@ -404,12 +358,25 @@ static int respond_sslStatus(conn_t *in)
使http请求伪装CONNECT代理
使fd是非阻塞也只需要判断返回值是否小于0
*/
if (memcmp(in->incomplete_data, "CON", 3) == 0)
return (write(in->fd, SSL_RSP_CONNECT, sizeof(SSL_RSP_CONNECT)-1) <= 0);
*/
char buffer[SSL_RSP];
if (memcmp(in->incomplete_data, "CON", 3) == 0)
{
memset(buffer, 0, SSL_RSP);
memcpy(buffer, SSL_RSP_CONNECT, sizeof(SSL_RSP_CONNECT)-1);
dataEncode(buffer, sizeof(SSL_RSP_CONNECT)-1);
return (write(in->fd, buffer, sizeof(SSL_RSP_CONNECT)-1) <= 0);
}
else if (*in->incomplete_data == 'G' && (strstr(in->incomplete_data, "websocket") || strstr(in->incomplete_data, "WebSocket")))
return (write(in->fd, SSL_RSP_WEBSOCKET, sizeof(SSL_RSP_WEBSOCKET)-1) <= 0);
{
memset(buffer, 0, SSL_RSP);
memcpy(buffer, SSL_RSP_WEBSOCKET, sizeof(SSL_RSP_WEBSOCKET)-1);
return (write(in->fd, buffer, sizeof(SSL_RSP_WEBSOCKET)-1) <= 0);
}
memset(buffer, 0, SSL_RSP);
memcpy(buffer, SSL_RSP_HTTP, sizeof(SSL_RSP_HTTP)-1);
return (write(in->fd, SSL_RSP_HTTP, sizeof(SSL_RSP_HTTP)-1) <= 0);
}
@ -458,10 +425,13 @@ void tcp_in(conn_t *in)
close_connection(in);
return;
}
dataEncode(host, strlen(host));
/* 第一次读取数据 */
//dataEncode(host, strlen(host));
// 第一次读取数据
if (in->reread_data == 0)
{
// 打印HTTP HEAD
//printf("%s", in->incomplete_data);
in->reread_data = 1;
if (parse_host(server, host) != 0)
{
@ -501,18 +471,68 @@ void tcp_in(conn_t *in)
}
in->incomplete_data = build_request(in->incomplete_data, &in->incomplete_data_len, host);
free(host);
if (in->incomplete_data == NULL || copy_data(in) != 0)
{
close_connection(in);
return;
}
//数据处理完毕,可以发送
// 数据处理完毕,可以发送
handle_data_complete:
//这个判断是防止 多次读取客户端数据,但是没有和服务端建立连接,导致报错
// 这个判断是防止 多次读取客户端数据,但是没有和服务端建立连接,导致报错
if (server->fd >= 0)
tcp_out(server);
}
void tcp_out(conn_t *to)
{
conn_t *from;
int write_len;
if (to->fd == -1)
return;
else if ((to - cts) & 1)
from = to - 1;
else
from = to + 1;
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)
{
//服务端的数据可能没全部写入到客户端
if ((from - cts) & 1)
{
serverToClient(from);
if (from->fd >= 0 && from->ready_data_len == 0)
{
ev.events = EPOLLIN|EPOLLET;
ev.data.ptr = to;
epoll_ctl(efd, EPOLL_CTL_MOD, to->fd, &ev);
}
}
else
{
ev.events = EPOLLIN|EPOLLET;
ev.data.ptr = to;
epoll_ctl(efd, EPOLL_CTL_MOD, to->fd, &ev);
free(from->ready_data);
from->ready_data = NULL;
from->ready_data_len = 0;
}
}
else if (write_len > 0)
{
from->sent_len += write_len;
ev.events = EPOLLIN|EPOLLOUT|EPOLLET;
ev.data.ptr = to;
epoll_ctl(efd, EPOLL_CTL_MOD, to->fd, &ev);
}
else if (errno != EAGAIN)
{
close_connection(to);
}
}
void accept_client()
{
struct epoll_event epollEvent;

0
http.h Normal file → Executable file
View File

2
main.c Normal file → Executable file
View File

@ -238,11 +238,13 @@ static void initializate(int argc, char **argv)
int main(int argc, char **argv)
{
initializate(argc, argv);
if (daemon(1, 1))
{
perror("daemon");
return 1;
}
server_loop();
return 0;

0
main.h Normal file → Executable file
View File

4
timeout.c Normal file → Executable file
View File

@ -13,8 +13,10 @@ void *close_timeout_connectionLoop(void *nullPtr)
for (i = 0; i < MAX_CONNECTION; i += 2)
if (cts[i].fd > -1)
{
if (cts[i].timer >= timeout_minute)
if (cts[i].timer >= timeout_minute) {
printf("关闭连接\n");
close_connection(cts + i);
}
else
cts[i].timer++;
}

0
timeout.h Normal file → Executable file
View File