From 843e5c80b552a08c527ab3bb21258f3c212a560d Mon Sep 17 00:00:00 2001 From: aixiao Date: Thu, 5 Nov 2020 21:56:08 +0800 Subject: [PATCH] Fix create_connection6() to support ipv6 --- CProxy.conf | 11 +++--- CProxy.conf.explain | 20 +++++++++- conf.c | 2 + conf.h | 1 + http_proxy.c | 2 +- http_proxy.h | 2 +- http_request.c | 9 +++-- main.c | 93 +++++++++++++++++++++++++++++++++++++++++++-- 8 files changed, 125 insertions(+), 15 deletions(-) diff --git a/CProxy.conf b/CProxy.conf index 8604a6b..1c1de7f 100644 --- a/CProxy.conf +++ b/CProxy.conf @@ -4,12 +4,13 @@ global { timeout=60; encode=128; tcp_listen=0124; - dns_listen=0125; + tcp6_listen=0124; + dns_listen=0126; } http { - http_ip=47.240.75.93; - http_port=124; + http_ip="2001:19f0:7001:3bcb:5400:3ff:fe03:860e"; + http_port=127; http_del="Host"; http_first="[M] http://[host][U] [V]\r\nHost: [host]\r\n"; //strrep="Windows NT 10.0->Linux"; @@ -17,8 +18,8 @@ http { } https { - https_ip=47.240.75.93; - https_port=124; + https_ip="2001:19f0:7001:3bcb:5400:3ff:fe03:860e"; + https_port=127; https_del="Host,host,x-online-host"; https_first="[M] [U] [V]\r\nHost: [host]\r\n"; //strrep="Windows NT 10.0->Linux"; diff --git a/CProxy.conf.explain b/CProxy.conf.explain index c7c0d70..dca5252 100644 --- a/CProxy.conf.explain +++ b/CProxy.conf.explain @@ -4,6 +4,7 @@ global { timeout=60; sslencoding=128; tcp_listen=0124; + tcp6_listen=0124; dns_listen=0125; } @@ -31,8 +32,18 @@ httpdns { } -http、https 模块关键字: [M], [method], [uri], [U], [V], [version], [H], [host], [port], \r, \n, \v, \f, \b, \t, \a. 如果原本请求头含有关键字也会被替换. +global模块 +uid=3004; //进程UID +process=2; //进程数量(已经弃用) +timeout=60; //超时时间(秒) +sslencoding=128; //编码(非零生效) +tcp_listen=0124; //TCP监听端口 +tcp6_listen=0124; //TCP6监听端口 (TCP和TCP6可以使用同一个端口, IPV4的数据走内部IPV6程序结构, IPV6数据走内部IPV6程序结构.) +dns_listen=0125; //UDP监听端口 + +http、https模块 +http、https 模块关键字: [M], [method], [uri], [U], [V], [version], [H], [host], [port], \r, \n, \v, \f, \b, \t, \a. 如果原本请求头含有关键字也会被替换. [M]、[method] 原请求方法 [U] 原请求url [uri] 原请求uri(http 模块) @@ -41,12 +52,17 @@ http、https 模块关键字: [M], [method], [uri], [U], [V], [version], [H], [h [port] 原请求端口 [H] 原请求[host]:[port] +http_ip=cproxy.aixiao.me; //指定HTTP服务器 +http_port=124; //端口 +http_del="x-online-host,X-Online-Host,host,Host"; //删除HTTP头字段,逗号分开 +http_first="[M] [U] [V]\r\nHost: [H]\r\n"; //自定义HTTP头 关键字strrep替换字符串指令. strrep = "Mi MIX 2->Linux"; 以"->"为分界符,"Mi MIX 2"字符串替换为"Linux"字符串. - 关键字regrep正则匹配替换字符串. regrep = "Host*.+?->Host: iread.wo.cn:443"; 以"->"为分界符,匹配到的内容"Host*.+?"替换为"Host: iread.wo.cn:443"字符串. +httpdns模块 httpdns 模块关键字: [M], [D], [V], \r, \n, \v, \f, \b, \t, \a. 默认 [M] 为 GET 默认 [V] 为 HTTP/1.0 +addr=119.29.29.29:53; //httpdns服务器IP diff --git a/conf.c b/conf.c index 215d686..abef83a 100644 --- a/conf.c +++ b/conf.c @@ -118,6 +118,8 @@ static void parse_global_module(char *content, conf * p) p->sslencoding = atoi(val_begin); } else if (strcasecmp(var, "tcp_listen") == 0) { p->tcp_listen = atoi(val_begin); + } else if (strcasecmp(var, "tcp6_listen") == 0) { + p->tcp6_listen = atoi(val_begin); } else if (strcasecmp(var, "dns_listen") == 0) { p->dns_listen = atoi(val_begin); } diff --git a/conf.h b/conf.h index 74bef63..e3c3bae 100644 --- a/conf.h +++ b/conf.h @@ -16,6 +16,7 @@ typedef struct CONF { int sslencoding; //int server_port; int tcp_listen; + int tcp6_listen; int dns_listen; // http module diff --git a/http_proxy.c b/http_proxy.c index c859550..85e28da 100644 --- a/http_proxy.c +++ b/http_proxy.c @@ -3,7 +3,7 @@ int sslEncodeCode; int remote_port; -char remote_host[128]; +char remote_host[270]; /* 对数据进行编码 */ void dataEncode(char *data, int data_len) diff --git a/http_proxy.h b/http_proxy.h index 2a28450..922e161 100644 --- a/http_proxy.h +++ b/http_proxy.h @@ -8,7 +8,7 @@ #define OTHER_TYPE 1 extern int remote_port; -extern char remote_host[128]; +extern char remote_host[270]; extern int sslEncodeCode; typedef struct conn_t { diff --git a/http_request.c b/http_request.c index c348669..878d672 100644 --- a/http_request.c +++ b/http_request.c @@ -319,6 +319,7 @@ char *request_head(conn * in, conf * configure) char https_del_copy[configure->https_del_len * 2]; char *result = NULL; + memset(remote_host, 0, 270); if (configure->https_port > 0) remote_port = configure->https_port; if (configure->https_ip != NULL) @@ -360,23 +361,25 @@ char *request_head(conn * in, conf * configure) incomplete_head = replace(incomplete_head, &incomplete_head_len, "[host]", 6, http_request->host, http_request->host_len); incomplete_head = replace(incomplete_head, &incomplete_head_len, "[port]", 6, http_request->port, http_request->port_len); incomplete_head = replace(incomplete_head, &incomplete_head_len, "[H]", 3, http_request->H, http_request->H_len); - //printf("%s", incomplete_head); // 打印HTTP HEADER + printf("%s", incomplete_head); // 打印HTTP HEADER memset(in->header_buffer, 0, strlen(in->header_buffer)); strcpy(in->header_buffer, incomplete_head); in->header_buffer_len = strlen(in->header_buffer); free(incomplete_head); - } else if (strncmp(in->header_buffer, "GET", 3) == 0 || strncmp(in->header_buffer, "POST", 4) == 0) { + } else { char *incomplete_head; int incomplete_head_len; char http_del_copy[configure->http_del_len]; char *result = NULL; + memset(remote_host, 0, 270); if (configure->http_port > 0) remote_port = configure->http_port; if (configure->http_ip != NULL) - memmove(remote_host, configure->http_ip, strlen(configure->http_ip)); + strcpy(remote_host, 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/main.c b/main.c index ab5daee..aa342b0 100644 --- a/main.c +++ b/main.c @@ -49,6 +49,64 @@ int create_connection(char *remote_host, int remote_port) return sock; } +int check_ipversion(char * address) +{ +/* Check for valid IPv4 or Iv6 string. Returns AF_INET for IPv4, AF_INET6 for IPv6 */ + + struct in6_addr bindaddr; + + if (inet_pton(AF_INET, address, &bindaddr) == 1) { + return AF_INET; + } else { + if (inet_pton(AF_INET6, address, &bindaddr) == 1) { + return AF_INET6; + } + } + return 0; +} + +int create_connection6(char *remote_host, int remote_port) { + struct addrinfo hints, *res=NULL; + int sock; + int validfamily=0; + char portstr[12]; + + memset(&hints, 0x00, sizeof(hints)); + + 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,请跳过解析 */ + } + + /* 检查指定的主机是否有效。 如果remote_host是主机名,请尝试解析地址 */ + if (getaddrinfo(remote_host, portstr , &hints, &res) != 0) { + errno = EFAULT; + return -1; + } + + if ((sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0) { + return -1; + } + + if (connect(sock, res->ai_addr, res->ai_addrlen) < 0) { + return -1; + } + + if (res != NULL) + freeaddrinfo(res); + + fcntl(sock, F_SETFL, O_NONBLOCK); + return sock; +} + +/* int create_connection6(char *remote_host, int remote_port) { char port[270]; @@ -62,6 +120,8 @@ int create_connection6(char *remote_host, int remote_port) sprintf(port, "%d", remote_port); // 转为字符串 if ((getaddrinfo(remote_host, port, &hints, &result)) != 0) return -1; + + //printf("%d\n", result->ai_addrlen); switch (result->ai_family) { case AF_INET:{ sock = socket(result->ai_family, result->ai_socktype, result->ai_protocol); @@ -76,7 +136,6 @@ int create_connection6(char *remote_host, int remote_port) sock = socket(result->ai_family, result->ai_socktype, result->ai_protocol); if (connect(sock, result->ai_addr, result->ai_addrlen) < 0) { perror("AF_INET6 connect"); - close(sock); return -1; } break; @@ -89,6 +148,7 @@ int create_connection6(char *remote_host, int remote_port) fcntl(sock, F_SETFL, O_NONBLOCK); return sock; } +*/ int create_server_socket(int port) { @@ -229,6 +289,33 @@ void *http_proxy_loop(void *p) return NULL; } +void *start_server(conf * configure) +{ + int n; + pthread_t thread_id; + if (timeout_minute) + pthread_create(&thread_id, NULL, &tcp_timeout_check, NULL); + + while (1) { + n = epoll_wait(epollfd, events, MAX_CONNECTION, -1); + while (n-- > 0) { + if (events[n].data.fd == server_sock) { + accept_client(); + } else if (events[n].data.fd == server_sock6) { + accept_client6(); + } else { + if (events[n].events & EPOLLIN) { + tcp_in((conn *) events[n].data.ptr, configure); + } + if (events[n].events & EPOLLOUT) { + tcp_out((conn *) events[n].data.ptr); + } + } + } + } + close(epollfd); +} + int process_signal(int signal, char *process_name) { char bufer[PATH_SIZE]; @@ -418,7 +505,7 @@ void _main(int argc, char *argv[]) } server_sock = create_server_socket(configure->tcp_listen); // IPV4 - server_sock6 = create_server_socket6(configure->tcp_listen);// IPV6 + server_sock6 = create_server_socket6(configure->tcp6_listen);// IPV6 epollfd = epoll_create(MAX_CONNECTION); if (epollfd == -1) { perror("epoll_create"); @@ -460,7 +547,7 @@ void _main(int argc, char *argv[]) pthread_join(thread_id, NULL); pthread_exit(NULL); -/* 线程分离未使用 +/* 线程分离 pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);