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>
|
|
|
|
|
|
2019-03-10 05:23:50 +08:00
|
|
|
|
#define VERSION "0.5"
|
2017-07-12 12:29:56 +08:00
|
|
|
|
|
2018-10-14 11:58:56 +08:00
|
|
|
|
struct epoll_event evs[MAX_CONNECTION + 1], ev;
|
2017-07-12 12:29:56 +08:00
|
|
|
|
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"
|
2019-01-26 11:53:32 +08:00
|
|
|
|
" -t timeout minute \033[35G default is no timeout\n"
|
|
|
|
|
" -u uid \033[35G running uid\n"
|
|
|
|
|
" -e ssl data encode code(128-255) \033[35G default is 0\n"
|
|
|
|
|
" -i ignore host before string count \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);
|
2019-01-26 11:53:32 +08:00
|
|
|
|
if (timeout_minute)
|
|
|
|
|
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;
|
2019-01-26 11:53:32 +08:00
|
|
|
|
|
|
|
|
|
/* 初始化部分变量值 */
|
2017-07-12 12:29:56 +08:00
|
|
|
|
lisFd = -1;
|
2018-10-27 22:30:57 +08:00
|
|
|
|
workers = 1;
|
2019-01-26 11:53:32 +08:00
|
|
|
|
dnsAddr.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);
|
2019-03-10 05:23:50 +08:00
|
|
|
|
dns_connect(&dnsAddr);
|
2019-01-26 11:53:32 +08:00
|
|
|
|
ignore_host_before_count = timeout_minute = 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
|
|
|
|
/* 处理命令行参数 */
|
2019-01-26 11:53:32 +08:00
|
|
|
|
while ((opt = getopt(argc, argv, "d:l:p:s:e:i: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);
|
2019-03-10 05:23:50 +08:00
|
|
|
|
close(dnsFd);
|
2019-03-10 15:09:55 +08:00
|
|
|
|
dns_connect(&dnsAddr);
|
2017-07-12 12:29:56 +08:00
|
|
|
|
break;
|
2019-01-26 11:53:32 +08:00
|
|
|
|
|
2017-07-12 12:29:56 +08:00
|
|
|
|
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;
|
2019-01-26 11:53:32 +08:00
|
|
|
|
|
2017-07-12 12:29:56 +08:00
|
|
|
|
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;
|
2019-01-26 11:53:32 +08:00
|
|
|
|
|
2017-07-12 12:29:56 +08:00
|
|
|
|
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;
|
2019-01-26 11:53:32 +08:00
|
|
|
|
|
2017-07-12 12:29:56 +08:00
|
|
|
|
case 's':
|
|
|
|
|
ssl_proxy = optarg;
|
|
|
|
|
break;
|
2019-01-26 11:53:32 +08:00
|
|
|
|
|
2018-12-21 19:13:07 +08:00
|
|
|
|
case 'e':
|
|
|
|
|
sslEncodeCode = atoi(optarg);
|
|
|
|
|
break;
|
2019-01-26 11:53:32 +08:00
|
|
|
|
|
|
|
|
|
case 'i':
|
|
|
|
|
ignore_host_before_count = atoi(optarg);
|
|
|
|
|
break;
|
|
|
|
|
|
2017-07-12 12:29:56 +08:00
|
|
|
|
case 'a':
|
|
|
|
|
strict_spilce = 1;
|
|
|
|
|
break;
|
2019-01-26 11:53:32 +08:00
|
|
|
|
|
2018-12-07 09:29:41 +08:00
|
|
|
|
case 't':
|
2019-01-26 11:53:32 +08:00
|
|
|
|
timeout_minute = (time_t)atoi(optarg);
|
2018-12-07 09:29:41 +08:00
|
|
|
|
break;
|
2019-01-26 11:53:32 +08:00
|
|
|
|
|
2017-07-12 12:29:56 +08:00
|
|
|
|
case 'w':
|
|
|
|
|
workers = atoi(optarg);
|
|
|
|
|
break;
|
2019-01-26 11:53:32 +08:00
|
|
|
|
|
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;
|
2019-01-26 11:53:32 +08:00
|
|
|
|
|
2017-07-12 12:29:56 +08:00
|
|
|
|
default:
|
|
|
|
|
usage();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-01-26 11:53:32 +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);
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-01-26 11:53:32 +08:00
|
|
|
|
//设置dns请求头首部
|
2017-07-12 12:29:56 +08:00
|
|
|
|
memset(dns_list, 0, sizeof(dns_list));
|
2019-01-26 11:53:32 +08:00
|
|
|
|
for (i = MAX_CONNECTION >> 1; i--; )
|
2017-07-12 12:29:56 +08:00
|
|
|
|
{
|
|
|
|
|
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();
|
2019-01-26 11:53:32 +08:00
|
|
|
|
|
2017-07-12 12:29:56 +08:00
|
|
|
|
return 0;
|
|
|
|
|
}
|