#include "main.h" #include "http.h" #include "dns.h" #include #define VERSION "0.1" #define DEFAULT_DNS_IP "114.114.114.114" struct epoll_event evs[MAX_CONNECTION + 2], ev; 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" " -a \033[35G all http requests repeat spilce\n" " -h display this infomaction\n" " -w worker process\n"); exit(0); } static void server_loop() { pthread_t thread_id; int n; //单独进程accept多进程并发环境下不会惊群 pthread_create(&thread_id, NULL, accept_loop, NULL); ev.events = EPOLLIN; ev.data.fd = dnsFd; epoll_ctl(efd, EPOLL_CTL_ADD, dnsFd, &ev); while (1) { n = epoll_wait(efd, evs, MAX_CONNECTION + 2, -1); while (n-- > 0) { if (evs[n].data.fd == dnsFd) { 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) { struct sockaddr_in dnsAddr; char *p; int opt, i, workers = 1; addr_len = sizeof(addr); lisFd = -1; efd = epoll_create(MAX_CONNECTION + 2); if (efd < 0) { perror("epoll_create"); exit(1); } dnsAddr.sin_family = addr.sin_family = AF_INET; //默认dns地址 dnsAddr.sin_addr.s_addr = inet_addr(DEFAULT_DNS_IP); dnsAddr.sin_port = htons(53); dns_connect(&dnsAddr); //主进程中的fd strict_spilce = 0; local_header = NULL; ssl_proxy = (char *)"CONNECT"; local_header = (char *)"\nLocal:"; proxy_header = (char *)"\nHost:"; proxy_header_len = strlen(proxy_header); local_header_len = strlen(local_header); /* 读取命令行参数 */ while ((opt = getopt(argc, argv, "d:l:p:s:w:L:ah")) != -1) { switch (opt) { case 'd': p = strchr(optarg, ':'); if (p) { *p = '\0'; dnsAddr.sin_port = htons(atoi(p+1)); } else { dnsAddr.sin_port = htons(53); } dnsAddr.sin_addr.s_addr = inet_addr(optarg); connect(dnsFd, (struct sockaddr *)&dnsAddr, sizeof(dnsAddr)); 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': //假如选项值为 "Proxy", proxy_header设置为 "\nProxy:" 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; case 'a': strict_spilce = 1; break; case 'w': workers = atoi(optarg); break; default: usage(); break; } } 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; //为服务端的结构体分配内存 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); } } 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; } signal(SIGPIPE, SIG_IGN); while (workers-- > 1 && fork() == 0) //子进程中的dnsFd必须重新申请,不然epoll监听可能读取到其他进程得到的数据 dns_connect(&dnsAddr); } int main(int argc, char **argv) { initializate(argc, argv); //if (daemon(1, 1)) if (daemon(1, 0)) { perror("daemon"); return 1; } server_loop(); return 0; }