SpecialProxy/main.c

248 lines
7.2 KiB
C
Raw Normal View History

2017-07-12 12:29:56 +08:00
#include "main.h"
#include "http.h"
2018-12-07 09:29:41 +08:00
#include "timeout.h"
2017-07-12 12:29:56 +08:00
#include "dns.h"
#include <pthread.h>
2018-12-21 19:13:07 +08:00
#define VERSION "0.3"
2017-07-12 12:29:56 +08:00
#define DEFAULT_DNS_IP "114.114.114.114"
2018-10-14 11:58:56 +08:00
struct epoll_event evs[MAX_CONNECTION + 1], ev;
2017-07-12 12:29:56 +08:00
struct sockaddr_in addr;
socklen_t addr_len;
int efd;
static void usage()
{
puts("SpecialProxy(" VERSION "):\n"
" -l [listenip:]listenport \033[35G default ip is 0.0.0.0\n"
" -p proxy header \033[35G default is 'Host'\n"
" -L local proxy header \033[35G default is 'Local'\n"
" -d dns query address \033[35G default is " DEFAULT_DNS_IP "\n"
" -s ssl proxy string \033[35G default is 'CONNECT'\n"
2018-12-07 09:29:41 +08:00
" -t timeout \033[35G default is 35s\n"
" -u uid \033[35G running uid\n"
2018-12-21 19:13:07 +08:00
" -e ssl data encode code \033[35G default is 0\n"
2017-07-12 12:29:56 +08:00
" -a \033[35G all http requests repeat spilce\n"
" -h display this infomaction\n"
" -w worker process\n");
exit(0);
}
static void server_loop()
{
2018-12-21 19:13:07 +08:00
pthread_t thId;
2017-07-12 12:29:56 +08:00
int n;
2018-12-21 19:13:07 +08:00
ev.events = EPOLLIN|EPOLLET;
2017-07-12 12:29:56 +08:00
ev.data.fd = dnsFd;
epoll_ctl(efd, EPOLL_CTL_ADD, dnsFd, &ev);
2018-12-21 19:13:07 +08:00
ev.events = EPOLLIN;
ev.data.fd = lisFd;
epoll_ctl(efd, EPOLL_CTL_ADD, lisFd, &ev);
pthread_create(&thId, NULL, &close_timeout_connectionLoop, NULL);
2017-07-12 12:29:56 +08:00
while (1)
{
2018-10-14 11:58:56 +08:00
n = epoll_wait(efd, evs, MAX_CONNECTION + 1, -1);
2017-07-12 12:29:56 +08:00
while (n-- > 0)
2017-07-12 12:52:46 +08:00
{
2018-12-21 19:13:07 +08:00
if (evs[n].data.fd == lisFd)
{
accept_client();
}
else if (evs[n].data.fd == dnsFd)
2017-07-12 12:29:56 +08:00
{
if (evs[n].events & EPOLLIN)
read_dns_rsp();
if (evs[n].events & EPOLLOUT)
dns_query();
}
else
{
if (evs[n].events & EPOLLIN)
tcp_in((conn_t *)evs[n].data.ptr);
if (evs[n].events & EPOLLOUT)
tcp_out((conn_t *)evs[n].data.ptr);
}
}
}
}
static void initializate(int argc, char **argv)
{
2017-07-12 12:52:46 +08:00
struct sockaddr_in dnsAddr;
2017-07-12 12:29:56 +08:00
char *p;
2018-10-27 22:30:57 +08:00
int opt, i, workers;
2017-07-12 12:29:56 +08:00
2018-10-27 22:30:57 +08:00
/* 初始化部分变量值 */
2017-07-12 12:29:56 +08:00
addr_len = sizeof(addr);
lisFd = -1;
2018-10-27 22:30:57 +08:00
workers = 1;
2017-07-12 12:29:56 +08:00
dnsAddr.sin_family = addr.sin_family = AF_INET;
2017-07-12 12:52:46 +08:00
//默认dns地址
2017-07-12 12:29:56 +08:00
dnsAddr.sin_addr.s_addr = inet_addr(DEFAULT_DNS_IP);
dnsAddr.sin_port = htons(53);
2017-07-12 12:52:46 +08:00
dns_connect(&dnsAddr); //主进程中的fd
2018-12-21 19:13:07 +08:00
timeout_seconds = DEFAULT_TIMEOUT;
strict_spilce = sslEncodeCode = 0;
2017-07-12 12:29:56 +08:00
local_header = NULL;
ssl_proxy = (char *)"CONNECT";
local_header = (char *)"\nLocal:";
proxy_header = (char *)"\nHost:";
proxy_header_len = strlen(proxy_header);
2017-07-12 12:52:46 +08:00
local_header_len = strlen(local_header);
2018-10-27 22:30:57 +08:00
/* 处理命令行参数 */
2018-12-21 19:13:07 +08:00
while ((opt = getopt(argc, argv, "d:l:p:s:e:w:t:u:L:ah")) != -1)
2017-07-12 12:29:56 +08:00
{
switch (opt)
2017-07-12 12:52:46 +08:00
{
2017-07-12 12:29:56 +08:00
case 'd':
p = strchr(optarg, ':');
if (p)
{
*p = '\0';
dnsAddr.sin_port = htons(atoi(p+1));
}
dnsAddr.sin_addr.s_addr = inet_addr(optarg);
2017-07-12 12:52:46 +08:00
connect(dnsFd, (struct sockaddr *)&dnsAddr, sizeof(dnsAddr));
2017-07-12 12:29:56 +08:00
break;
case 'l':
p = strchr(optarg, ':');
if (p)
{
*p = '\0';
create_listen(optarg, atoi(p+1));
}
else
{
create_listen((char *)"0.0.0.0", atoi(optarg));
}
break;
case 'p':
2017-07-12 12:52:46 +08:00
//假如选项值为 "Proxy", proxy_header设置为 "\nProxy:"
2017-07-12 12:29:56 +08:00
proxy_header_len = strlen(optarg) + 2;
if (optarg[proxy_header_len] == ':')
optarg[proxy_header_len--] = '\0';
proxy_header = (char *)malloc(proxy_header_len + 1);
if (proxy_header == NULL)
{
fputs("out of memory.\n", stderr);
exit(1);
}
sprintf(proxy_header, "\n%s:", optarg);
break;
case 'L':
local_header_len = strlen(optarg) + 2;
if (optarg[local_header_len] == ':')
optarg[local_header_len--] = '\0';
local_header = (char *)malloc(local_header_len + 1);
if (local_header == NULL)
{
fputs("out of memory.\n", stderr);
exit(1);
}
sprintf(local_header, "\n%s:", optarg);
break;
case 's':
ssl_proxy = optarg;
break;
2018-12-21 19:13:07 +08:00
case 'e':
sslEncodeCode = atoi(optarg);
break;
2017-07-12 12:29:56 +08:00
case 'a':
strict_spilce = 1;
break;
2018-12-07 09:29:41 +08:00
case 't':
2018-12-21 19:13:07 +08:00
timeout_seconds = (time_t)atoi(optarg);
2018-12-07 09:29:41 +08:00
break;
2017-07-12 12:29:56 +08:00
case 'w':
workers = atoi(optarg);
break;
2018-10-27 22:30:57 +08:00
case 'u':
2018-11-13 07:58:23 +08:00
if (setgid(atoi(optarg)) != 0)
2018-10-27 22:30:57 +08:00
{
perror("setgid");
exit(1);
}
2018-11-13 07:58:23 +08:00
if (setuid(atoi(optarg)) != 0)
2018-10-27 22:30:57 +08:00
{
perror("setuid");
exit(1);
}
break;
2017-07-12 12:29:56 +08:00
default:
usage();
break;
}
}
2018-10-27 22:30:57 +08:00
/* 初始化剩下的变量值 */
2017-07-12 12:29:56 +08:00
if (lisFd < 0)
{
fputs("no listen address\n", stderr);
exit(1);
}
memset(cts, 0, sizeof(cts));
for (i = MAX_CONNECTION; i--; )
cts[i].fd = -1;
2017-07-12 12:52:46 +08:00
//为服务端的结构体分配内存
2017-07-12 12:29:56 +08:00
for (i = 1; i < MAX_CONNECTION; i += 2)
{
cts[i].ready_data = (char *)malloc(BUFFER_SIZE);
if (cts[i].ready_data == NULL)
{
fputs("out of memory.", stderr);
exit(1);
}
}
2018-10-27 22:30:57 +08:00
//设置dns请求头首部
2017-07-12 12:29:56 +08:00
memset(dns_list, 0, sizeof(dns_list));
for (i = MAX_CONNECTION / 2; i--; )
{
memcpy(dns_list[i].request, &i, sizeof(uint16_t));
dns_list[i].request[2] = 1;
dns_list[i].request[3] = 0;
dns_list[i].request[4] = 0;
dns_list[i].request[5] = 1;
dns_list[i].request[6] = 0;
dns_list[i].request[7] = 0;
dns_list[i].request[8] = 0;
dns_list[i].request[9] = 0;
dns_list[i].request[10] = 0;
dns_list[i].request[11] = 0;
}
2018-10-27 22:30:57 +08:00
signal(SIGPIPE, SIG_IGN); //忽略PIPE信号
//子进程中的dnsFd必须重新申请不然epoll监听可能读取到其他进程得到的数据
2017-07-12 12:52:46 +08:00
while (workers-- > 1 && fork() == 0)
dns_connect(&dnsAddr);
2018-10-14 11:58:56 +08:00
efd = epoll_create(MAX_CONNECTION + 1);
if (efd < 0)
{
perror("epoll_create");
exit(1);
}
2017-07-12 12:29:56 +08:00
}
int main(int argc, char **argv)
{
initializate(argc, argv);
2018-12-07 09:29:41 +08:00
if (daemon(1, 1))
2017-07-12 12:29:56 +08:00
{
perror("daemon");
return 1;
}
server_loop();
return 0;
}