diff --git a/conf.c b/conf.c index abef83a..6a23b84 100644 --- a/conf.c +++ b/conf.c @@ -347,7 +347,7 @@ void free_conf(conf * p) free(p->https_regrep_aim); if (p->https_regrep_obj) free(p->https_regrep_obj); - + if (p->addr) free(p->addr); if (p->http_req) @@ -392,7 +392,7 @@ void read_conf(char *filename, conf * configure) perror("read https module error"); parse_https_module(https_content, configure); free(https_content); - + if ((httpdns_content = read_module(buff, "httpdns")) == NULL) perror("read httpdns module error"); parse_httpdns_module(httpdns_content, configure); diff --git a/conf.h b/conf.h index e3c3bae..ca825f9 100644 --- a/conf.h +++ b/conf.h @@ -44,8 +44,7 @@ typedef struct CONF { char *https_regrep_aim, *https_regrep_obj; int https_regrep_aim_len, https_regrep_obj_len; - - + // http dns_listen char *addr; char *http_req; @@ -57,5 +56,4 @@ char *strncpy_(char *dest, const char *src, size_t n); void read_conf(char *file, conf * p); void free_conf(conf * p); - #endif diff --git a/http_proxy.c b/http_proxy.c index 25e2e53..7b21940 100644 --- a/http_proxy.c +++ b/http_proxy.c @@ -41,54 +41,45 @@ static char *read_data(conn_t * in, char *data, int *data_len) return data; } - -void close_connection(conn_t *conn) +void close_connection(conn_t * conn) { epoll_ctl(epollfd, EPOLL_CTL_DEL, conn->fd, NULL); close(conn->fd); - if ((conn - cts) & 1) - { + if ((conn - cts) & 1) { char *server_data; server_data = conn->ready_data; memset(conn, 0, sizeof(conn_t)); conn->ready_data = server_data; - conn-- ->fd = -1; - } - else - { + conn--->fd = -1; + } else { free(conn->ready_data); free(conn->incomplete_data); memset(conn, 0, sizeof(conn_t)); - conn++ ->fd = -1; + conn++->fd = -1; } if (conn->fd >= 0) close_connection(conn); } - -static void serverToClient(conn_t *server) +static void serverToClient(conn_t * server) { conn_t *client; int write_len; 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) { dataEncode(server->ready_data, server->ready_data_len); write_len = write(client->fd, server->ready_data, server->ready_data_len); - if (write_len <= 0) - { + if (write_len <= 0) { if (write_len == 0 || errno != EAGAIN) close_connection(server); else server->sent_len = 0; return; - } - else if (write_len < server->ready_data_len) - { + } else if (write_len < server->ready_data_len) { server->sent_len = write_len; - ev.events = EPOLLIN|EPOLLOUT|EPOLLET; + ev.events = EPOLLIN | EPOLLOUT | EPOLLET; ev.data.ptr = client; epoll_ctl(epollfd, EPOLL_CTL_MOD, client->fd, &ev); return; @@ -124,31 +115,18 @@ void clientToserver(conn_t * in) // 判断请求类型 static int8_t request_type(char *data) { - if (strncmp(data, "GET", 3) == 0 || - strncmp(data, "POST", 4) == 0 || - strncmp(data, "CONNECT", 7) == 0 || - strncmp(data, "HEAD", 4) == 0 || - strncmp(data, "PUT", 3) == 0 || - strncmp(data, "OPTIONS", 7) == 0 || - strncmp(data, "MOVE", 4) == 0 || - strncmp(data, "COPY", 4) == 0 || - strncmp(data, "TRACE", 5) == 0 || - strncmp(data, "DELETE", 6) == 0 || - strncmp(data, "LINK", 4) == 0 || - strncmp(data, "UNLINK", 6) == 0 || - strncmp(data, "PATCH", 5) == 0 || - strncmp(data, "WRAPPED", 7) == 0) + if (strncmp(data, "GET", 3) == 0 || strncmp(data, "POST", 4) == 0 || strncmp(data, "CONNECT", 7) == 0 || strncmp(data, "HEAD", 4) == 0 || strncmp(data, "PUT", 3) == 0 || strncmp(data, "OPTIONS", 7) == 0 || strncmp(data, "MOVE", 4) == 0 || strncmp(data, "COPY", 4) == 0 || strncmp(data, "TRACE", 5) == 0 || strncmp(data, "DELETE", 6) == 0 || strncmp(data, "LINK", 4) == 0 || strncmp(data, "UNLINK", 6) == 0 || strncmp(data, "PATCH", 5) == 0 || strncmp(data, "WRAPPED", 7) == 0) return HTTP_TYPE; return OTHER_TYPE; } // Check for valid IPv4 or Iv6 string. Returns AF_INET for IPv4, AF_INET6 for IPv6 -int check_ipversion(char * address) +int check_ipversion(char *address) { struct in6_addr bindaddr; if (inet_pton(AF_INET, address, &bindaddr) == 1) { - return AF_INET; + return AF_INET; } else { if (inet_pton(AF_INET6, address, &bindaddr) == 1) { return AF_INET6; @@ -157,28 +135,28 @@ int check_ipversion(char * address) return 0; } -int create_connection6(char *remote_host, int remote_port) { - struct addrinfo hints, *res=NULL; +int create_connection6(char *remote_host, int remote_port) +{ + struct addrinfo hints, *res = NULL; int sock; - int validfamily=0; + int validfamily = 0; char portstr[270]; memset(&hints, 0x00, sizeof(hints)); - hints.ai_flags = AI_NUMERICSERV; // numeric service number, not resolve - hints.ai_family = AF_UNSPEC; + hints.ai_flags = AI_NUMERICSERV; // numeric service number, not resolve + hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; sprintf(portstr, "%d", remote_port); // check for numeric IP to specify IPv6 or IPv4 socket if ((validfamily = check_ipversion(remote_host)) != 0) { - hints.ai_family = validfamily; - hints.ai_flags |= AI_NUMERICHOST; // remote_host是有效的数字ip,跳过解析 + hints.ai_family = validfamily; + hints.ai_flags |= AI_NUMERICHOST; // remote_host是有效的数字ip,跳过解析 } - // 检查指定的主机是否有效。 如果remote_host是主机名,尝试解析地址 - if (getaddrinfo(remote_host, portstr , &hints, &res) != 0) { + if (getaddrinfo(remote_host, portstr, &hints, &res) != 0) { errno = EFAULT; perror("getaddrinfo"); return -1; @@ -188,24 +166,23 @@ int create_connection6(char *remote_host, int remote_port) { perror("socket"); return -1; } - + if (connect(sock, res->ai_addr, res->ai_addrlen) < 0) { perror("connect"); return -1; } if (res != NULL) - freeaddrinfo(res); + freeaddrinfo(res); return sock; } /* 读取到的数据全部就绪,将incomplete_data复制到ready_data */ -static int8_t copy_data(conn_t *ct) +static int8_t copy_data(conn_t * ct) { dataEncode(ct->incomplete_data, ct->incomplete_data_len); - if (ct->ready_data) - { + if (ct->ready_data) { char *new_data; new_data = (char *)realloc(ct->ready_data, ct->ready_data_len + ct->incomplete_data_len); @@ -215,9 +192,7 @@ static int8_t copy_data(conn_t *ct) memcpy(new_data + ct->ready_data_len, ct->incomplete_data, ct->incomplete_data_len); ct->ready_data_len += ct->incomplete_data_len; free(ct->incomplete_data); - } - else - { + } else { ct->ready_data = ct->incomplete_data; ct->ready_data_len = ct->incomplete_data_len; } @@ -235,20 +210,18 @@ void tcp_in(conn_t * in, conf * configure) if (in->fd < 0) return; //如果in - cts是奇数,那么是服务端触发事件 - if ((in - cts) & 1) - { - in->timer = (in-1)->timer = 0; + if ((in - cts) & 1) { + in->timer = (in - 1)->timer = 0; if (in->ready_data_len <= 0) serverToClient(in); return; } - in->timer = (in+1)->timer = 0; + in->timer = (in + 1)->timer = 0; in->incomplete_data = read_data(in, in->incomplete_data, &in->incomplete_data_len); //printf("%s", in->incomplete_data); - if (in->incomplete_data == NULL) - { + if (in->incomplete_data == NULL) { close_connection(in); return; } @@ -266,19 +239,17 @@ void tcp_in(conn_t * in, conf * configure) epoll_ctl(epollfd, EPOLL_CTL_ADD, server->fd, &ev); } - - if (in->incomplete_data == NULL || copy_data(in) != 0) - { + + if (in->incomplete_data == NULL || copy_data(in) != 0) { close_connection(in); return; } - // 这个判断是防止 多次读取客户端数据,但是没有和服务端建立连接,导致报错 if (server->fd >= 0) tcp_out(server); } -void tcp_out(conn_t *to) +void tcp_out(conn_t * to) { conn_t *from; int write_len; @@ -291,38 +262,29 @@ void tcp_out(conn_t *to) 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 (write_len == from->ready_data_len - from->sent_len) { //服务端的数据可能没全部写入到客户端 - if ((from - cts) & 1) - { + if ((from - cts) & 1) { serverToClient(from); - if (from->fd >= 0 && from->ready_data_len == 0) - { - ev.events = EPOLLIN|EPOLLET; + if (from->fd >= 0 && from->ready_data_len == 0) { + ev.events = EPOLLIN | EPOLLET; ev.data.ptr = to; epoll_ctl(epollfd, EPOLL_CTL_MOD, to->fd, &ev); } - } - else - { - ev.events = EPOLLIN|EPOLLET; + } else { + ev.events = EPOLLIN | EPOLLET; ev.data.ptr = to; epoll_ctl(epollfd, EPOLL_CTL_MOD, to->fd, &ev); free(from->ready_data); from->ready_data = NULL; from->ready_data_len = 0; } - } - else if (write_len > 0) - { + } else if (write_len > 0) { from->sent_len += write_len; - ev.events = EPOLLIN|EPOLLOUT|EPOLLET; + ev.events = EPOLLIN | EPOLLOUT | EPOLLET; ev.data.ptr = to; epoll_ctl(epollfd, EPOLL_CTL_MOD, to->fd, &ev); - } - else if (errno != EAGAIN) - { + } else if (errno != EAGAIN) { close_connection(to); } } diff --git a/http_proxy.h b/http_proxy.h index 85b63dc..9096d6d 100644 --- a/http_proxy.h +++ b/http_proxy.h @@ -16,12 +16,9 @@ typedef struct tcp_connection { char *ready_data, *incomplete_data; int fd, ready_data_len, incomplete_data_len, sent_len, timer; uint16_t destPort; - unsigned reread_data :1, - request_type :1, - keep_alive :1; + unsigned reread_data:1, request_type:1, keep_alive:1; } conn_t; - extern conn_t cts[MAX_CONNECTION]; extern void tcp_in(conn_t * in, conf * configure); extern void tcp_out(conn_t * out); diff --git a/http_request.c b/http_request.c index 2e86d5c..655e3fd 100644 --- a/http_request.c +++ b/http_request.c @@ -160,6 +160,17 @@ int extract_host(char *header, char *host, char *port) { char *_p = strstr(header, "CONNECT"); // 在 CONNECT 方法中解析 隧道主机名称及端口号 if (_p) { + + if (strchr(header, '[') || strchr(header, ']')) { // IPv6 + char *_p1 = strchr(header, '['); + char *_p2 = strchr(_p1 + 1, ']'); + + strncpy(host, _p1 + 1, (int)(_p2 - _p1) - 1); + remote_port = 443; + + return 0; + } + char *_p1 = strchr(_p, ' '); char *_p2 = strchr(_p1 + 1, ':'); char *_p3 = strchr(_p1 + 1, ' '); @@ -379,7 +390,7 @@ char *request_head(conn_t * in, conf * configure) remote_port = configure->http_port; if (configure->http_ip != NULL) strcpy(remote_host, configure->http_ip); - //memmove(remote_host, configure->http_ip, strlen(configure->http_ip)); + //memmove(remote_host, configure->http_ip, strlen(configure->http_ip)); incomplete_head = (char *)malloc(sizeof(char) * (BUFFER_SIZE)); if (incomplete_head == NULL) { free(incomplete_head); diff --git a/httpdns.c b/httpdns.c index 654e48f..6c6aab1 100644 --- a/httpdns.c +++ b/httpdns.c @@ -14,7 +14,7 @@ struct dns_cache *cache, *cache_temp; socklen_t addr_len = sizeof(dst_addr); unsigned int cache_using, cacheLimit; dns_t dns_list[DNS_MAX_CONNECTION]; -struct epoll_event evs[DNS_MAX_CONNECTION+1], event; +struct epoll_event evs[DNS_MAX_CONNECTION + 1], event; int read_cache_file() { @@ -341,7 +341,7 @@ error: in->query_type = 0; } -void new_client(conf *configure) +void new_client(conf * configure) { dns_t *dns; int i, len; @@ -415,7 +415,7 @@ void new_client(conf *configure) dns->http_request = replace(dns->http_request, &http_request_len, "\\n", 2, "\n", 1); dns->http_request_len = strlen(dns->http_request); //printf("%s\n", dns->http_request); - + event.events = EPOLLOUT | EPOLLERR | EPOLLET; event.data.ptr = dns; epoll_ctl(dns_efd, EPOLL_CTL_ADD, dns->fd, &event); @@ -460,7 +460,7 @@ void *httpdns_loop(void *p) } } } - + return NULL; } @@ -484,21 +484,21 @@ int udp_listen(char *ip, int port) return fd; } -int httpdns_initialize(conf * configure) { +int httpdns_initialize(conf * configure) +{ char *p; p = strchr(configure->addr, ':'); host_value = configure->addr; *p = '\0'; //printf("udp: %s %d %d\n", configure->addr, configure->dns_listen, atoi(p+1)); - + dnsListenFd = udp_listen("0.0.0.0", configure->dns_listen); dst_addr.sin_addr.s_addr = inet_addr(configure->addr); dst_addr.sin_family = AF_INET; - dst_addr.sin_port = htons(atoi(p+1)); + dst_addr.sin_port = htons(atoi(p + 1)); signal(SIGPIPE, SIG_IGN); signal(SIGTERM, write_dns_cache); host_value_len = strlen(host_value); return 0; } - diff --git a/httpdns.h b/httpdns.h index c190b21..eed1b2e 100644 --- a/httpdns.h +++ b/httpdns.h @@ -19,21 +19,20 @@ #include "conf.h" -#define DNS_MAX_CONNECTION 256 //此值的大小关系到respod_clients函数的效率 +#define DNS_MAX_CONNECTION 256 //此值的大小关系到respod_clients函数的效率 #define DATA_SIZE 512 #define HTTP_RSP_SIZE 1024 - typedef struct dns_connection { char dns_req[DATA_SIZE]; struct sockaddr_in src_addr; - char *reply; //回应内容 + char *reply; //回应内容 char *http_request, *host; unsigned int http_request_len, dns_rsp_len; int fd; char query_type; - unsigned host_len :7; //域名最大长度64位 - unsigned wait_response_client :1; //已构建好DNS回应,等待可写事件 + unsigned host_len:7; //域名最大长度64位 + unsigned wait_response_client:1; //已构建好DNS回应,等待可写事件 } dns_t; struct dns_cache { @@ -44,11 +43,9 @@ struct dns_cache { }; extern dns_t dns_list[DNS_MAX_CONNECTION]; -extern struct epoll_event evs[DNS_MAX_CONNECTION+1], event; - +extern struct epoll_event evs[DNS_MAX_CONNECTION + 1], event; void *httpdns_loop(void *p); int httpdns_initialize(conf * configure); - #endif diff --git a/main.c b/main.c index a0981ce..a374e4c 100644 --- a/main.c +++ b/main.c @@ -166,7 +166,6 @@ void *http_proxy_loop(void *p) conf *configure = (conf *) p; int n; - ev.events = EPOLLIN; ev.data.fd = server_sock; if (-1 == epoll_ctl(epollfd, EPOLL_CTL_ADD, server_sock, &ev)) { @@ -178,7 +177,7 @@ void *http_proxy_loop(void *p) if (-1 == epoll_ctl(epollfd, EPOLL_CTL_ADD, server_sock6, &ev)) { exit(1); } - + while (1) { n = epoll_wait(epollfd, events, MAX_CONNECTION, -1); while (n-- > 0) { @@ -186,8 +185,7 @@ void *http_proxy_loop(void *p) //printf("accept_client6()!!!\n"); accept_client6(); ; - } - else if (events[n].data.fd == server_sock) { + } else if (events[n].data.fd == server_sock) { //printf("accept_client()!!!\n"); accept_client(); } else { @@ -305,7 +303,6 @@ void server_ini() perror("daemon"); return; } - //while (process-- > 1 && fork() == 0); } @@ -409,7 +406,7 @@ void _main(int argc, char *argv[]) perror("setrlimit"); } - server_ini(); // 守护进程 + server_ini(); // 守护进程 httpdns_initialize(configure); // 初始化httpdns memset(cts, 0, sizeof(cts)); for (i = MAX_CONNECTION; i--;) @@ -422,16 +419,15 @@ void _main(int argc, char *argv[]) exit(1); } } - - server_sock = create_server_socket(configure->tcp_listen); // IPV4 - server_sock6 = create_server_socket6(configure->tcp6_listen);// IPV6 + + server_sock = create_server_socket(configure->tcp_listen); // IPV4 + server_sock6 = create_server_socket6(configure->tcp6_listen); // IPV6 epollfd = epoll_create(MAX_CONNECTION); if (epollfd == -1) { perror("epoll_create"); exit(1); } - if (setegid(configure->uid) == -1 || seteuid(configure->uid) == -1) // 设置uid exit(1); diff --git a/timeout.c b/timeout.c index 3b4f610..acf4e3b 100644 --- a/timeout.c +++ b/timeout.c @@ -14,8 +14,7 @@ void *tcp_timeout_check(void *nullPtr) if (cts[i].fd > -1) { if (cts[i].timer >= timeout_minute) { close_connection(cts + i); - } - else + } else cts[i].timer++; } }