Add to get the HTTPS IPv6 host.

This commit is contained in:
aixiao 2020-12-15 10:43:06 +08:00
parent 3c0d42da76
commit e082b111f7
9 changed files with 79 additions and 119 deletions

2
conf.h
View File

@ -45,7 +45,6 @@ typedef struct CONF {
char *https_regrep_aim, *https_regrep_obj; char *https_regrep_aim, *https_regrep_obj;
int https_regrep_aim_len, https_regrep_obj_len; int https_regrep_aim_len, https_regrep_obj_len;
// http dns_listen // http dns_listen
char *addr; char *addr;
char *http_req; 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 read_conf(char *file, conf * p);
void free_conf(conf * p); void free_conf(conf * p);
#endif #endif

View File

@ -41,54 +41,45 @@ static char *read_data(conn_t * in, char *data, int *data_len)
return data; return data;
} }
void close_connection(conn_t * conn)
void close_connection(conn_t *conn)
{ {
epoll_ctl(epollfd, EPOLL_CTL_DEL, conn->fd, NULL); epoll_ctl(epollfd, EPOLL_CTL_DEL, conn->fd, NULL);
close(conn->fd); close(conn->fd);
if ((conn - cts) & 1) if ((conn - cts) & 1) {
{
char *server_data; char *server_data;
server_data = conn->ready_data; server_data = conn->ready_data;
memset(conn, 0, sizeof(conn_t)); memset(conn, 0, sizeof(conn_t));
conn->ready_data = server_data; conn->ready_data = server_data;
conn-- ->fd = -1; conn--->fd = -1;
} } else {
else
{
free(conn->ready_data); free(conn->ready_data);
free(conn->incomplete_data); free(conn->incomplete_data);
memset(conn, 0, sizeof(conn_t)); memset(conn, 0, sizeof(conn_t));
conn++ ->fd = -1; conn++->fd = -1;
} }
if (conn->fd >= 0) if (conn->fd >= 0)
close_connection(conn); close_connection(conn);
} }
static void serverToClient(conn_t * server)
static void serverToClient(conn_t *server)
{ {
conn_t *client; conn_t *client;
int write_len; int write_len;
client = server - 1; 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); dataEncode(server->ready_data, server->ready_data_len);
write_len = write(client->fd, 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) if (write_len == 0 || errno != EAGAIN)
close_connection(server); close_connection(server);
else else
server->sent_len = 0; server->sent_len = 0;
return; return;
} } else if (write_len < server->ready_data_len) {
else if (write_len < server->ready_data_len)
{
server->sent_len = write_len; server->sent_len = write_len;
ev.events = EPOLLIN|EPOLLOUT|EPOLLET; ev.events = EPOLLIN | EPOLLOUT | EPOLLET;
ev.data.ptr = client; ev.data.ptr = client;
epoll_ctl(epollfd, EPOLL_CTL_MOD, client->fd, &ev); epoll_ctl(epollfd, EPOLL_CTL_MOD, client->fd, &ev);
return; return;
@ -124,26 +115,13 @@ void clientToserver(conn_t * in)
// 判断请求类型 // 判断请求类型
static int8_t request_type(char *data) static int8_t request_type(char *data)
{ {
if (strncmp(data, "GET", 3) == 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)
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 HTTP_TYPE;
return OTHER_TYPE; return OTHER_TYPE;
} }
// Check for valid IPv4 or Iv6 string. Returns AF_INET for IPv4, AF_INET6 for IPv6 // 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; struct in6_addr bindaddr;
@ -157,10 +135,11 @@ int check_ipversion(char * address)
return 0; return 0;
} }
int create_connection6(char *remote_host, int remote_port) { int create_connection6(char *remote_host, int remote_port)
struct addrinfo hints, *res=NULL; {
struct addrinfo hints, *res = NULL;
int sock; int sock;
int validfamily=0; int validfamily = 0;
char portstr[270]; char portstr[270];
memset(&hints, 0x00, sizeof(hints)); memset(&hints, 0x00, sizeof(hints));
@ -176,9 +155,8 @@ int create_connection6(char *remote_host, int remote_port) {
hints.ai_family = validfamily; hints.ai_family = validfamily;
hints.ai_flags |= AI_NUMERICHOST; // remote_host是有效的数字ip跳过解析 hints.ai_flags |= AI_NUMERICHOST; // remote_host是有效的数字ip跳过解析
} }
// 检查指定的主机是否有效。 如果remote_host是主机名尝试解析地址 // 检查指定的主机是否有效。 如果remote_host是主机名尝试解析地址
if (getaddrinfo(remote_host, portstr , &hints, &res) != 0) { if (getaddrinfo(remote_host, portstr, &hints, &res) != 0) {
errno = EFAULT; errno = EFAULT;
perror("getaddrinfo"); perror("getaddrinfo");
return -1; return -1;
@ -201,11 +179,10 @@ int create_connection6(char *remote_host, int remote_port) {
} }
/* 读取到的数据全部就绪将incomplete_data复制到ready_data */ /* 读取到的数据全部就绪将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); dataEncode(ct->incomplete_data, ct->incomplete_data_len);
if (ct->ready_data) if (ct->ready_data) {
{
char *new_data; char *new_data;
new_data = (char *)realloc(ct->ready_data, ct->ready_data_len + ct->incomplete_data_len); 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); memcpy(new_data + ct->ready_data_len, ct->incomplete_data, ct->incomplete_data_len);
ct->ready_data_len += ct->incomplete_data_len; ct->ready_data_len += ct->incomplete_data_len;
free(ct->incomplete_data); free(ct->incomplete_data);
} } else {
else
{
ct->ready_data = ct->incomplete_data; ct->ready_data = ct->incomplete_data;
ct->ready_data_len = ct->incomplete_data_len; ct->ready_data_len = ct->incomplete_data_len;
} }
@ -235,20 +210,18 @@ void tcp_in(conn_t * in, conf * configure)
if (in->fd < 0) if (in->fd < 0)
return; return;
//如果in - cts是奇数那么是服务端触发事件 //如果in - cts是奇数那么是服务端触发事件
if ((in - cts) & 1) if ((in - cts) & 1) {
{ in->timer = (in - 1)->timer = 0;
in->timer = (in-1)->timer = 0;
if (in->ready_data_len <= 0) if (in->ready_data_len <= 0)
serverToClient(in); serverToClient(in);
return; 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); in->incomplete_data = read_data(in, in->incomplete_data, &in->incomplete_data_len);
//printf("%s", in->incomplete_data); //printf("%s", in->incomplete_data);
if (in->incomplete_data == NULL) if (in->incomplete_data == NULL) {
{
close_connection(in); close_connection(in);
return; return;
} }
@ -267,18 +240,16 @@ void tcp_in(conn_t * in, conf * configure)
} }
if (in->incomplete_data == NULL || copy_data(in) != 0) if (in->incomplete_data == NULL || copy_data(in) != 0) {
{
close_connection(in); close_connection(in);
return; return;
} }
// 这个判断是防止 多次读取客户端数据,但是没有和服务端建立连接,导致报错 // 这个判断是防止 多次读取客户端数据,但是没有和服务端建立连接,导致报错
if (server->fd >= 0) if (server->fd >= 0)
tcp_out(server); tcp_out(server);
} }
void tcp_out(conn_t *to) void tcp_out(conn_t * to)
{ {
conn_t *from; conn_t *from;
int write_len; int write_len;
@ -291,38 +262,29 @@ void tcp_out(conn_t *to)
from = to + 1; from = to + 1;
from->timer = to->timer = 0; from->timer = to->timer = 0;
write_len = write(to->fd, from->ready_data + from->sent_len, from->ready_data_len - from->sent_len); 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); serverToClient(from);
if (from->fd >= 0 && from->ready_data_len == 0) if (from->fd >= 0 && from->ready_data_len == 0) {
{ ev.events = EPOLLIN | EPOLLET;
ev.events = EPOLLIN|EPOLLET;
ev.data.ptr = to; ev.data.ptr = to;
epoll_ctl(epollfd, EPOLL_CTL_MOD, to->fd, &ev); epoll_ctl(epollfd, EPOLL_CTL_MOD, to->fd, &ev);
} }
} } else {
else ev.events = EPOLLIN | EPOLLET;
{
ev.events = EPOLLIN|EPOLLET;
ev.data.ptr = to; ev.data.ptr = to;
epoll_ctl(epollfd, EPOLL_CTL_MOD, to->fd, &ev); epoll_ctl(epollfd, EPOLL_CTL_MOD, to->fd, &ev);
free(from->ready_data); free(from->ready_data);
from->ready_data = NULL; from->ready_data = NULL;
from->ready_data_len = 0; from->ready_data_len = 0;
} }
} } else if (write_len > 0) {
else if (write_len > 0)
{
from->sent_len += write_len; from->sent_len += write_len;
ev.events = EPOLLIN|EPOLLOUT|EPOLLET; ev.events = EPOLLIN | EPOLLOUT | EPOLLET;
ev.data.ptr = to; ev.data.ptr = to;
epoll_ctl(epollfd, EPOLL_CTL_MOD, to->fd, &ev); epoll_ctl(epollfd, EPOLL_CTL_MOD, to->fd, &ev);
} } else if (errno != EAGAIN) {
else if (errno != EAGAIN)
{
close_connection(to); close_connection(to);
} }
} }

View File

@ -16,12 +16,9 @@ typedef struct tcp_connection {
char *ready_data, *incomplete_data; char *ready_data, *incomplete_data;
int fd, ready_data_len, incomplete_data_len, sent_len, timer; int fd, ready_data_len, incomplete_data_len, sent_len, timer;
uint16_t destPort; uint16_t destPort;
unsigned reread_data :1, unsigned reread_data:1, request_type:1, keep_alive:1;
request_type :1,
keep_alive :1;
} conn_t; } conn_t;
extern conn_t cts[MAX_CONNECTION]; extern conn_t cts[MAX_CONNECTION];
extern void tcp_in(conn_t * in, conf * configure); extern void tcp_in(conn_t * in, conf * configure);
extern void tcp_out(conn_t * out); extern void tcp_out(conn_t * out);

View File

@ -160,6 +160,17 @@ int extract_host(char *header, char *host, char *port)
{ {
char *_p = strstr(header, "CONNECT"); // 在 CONNECT 方法中解析 隧道主机名称及端口号 char *_p = strstr(header, "CONNECT"); // 在 CONNECT 方法中解析 隧道主机名称及端口号
if (_p) { 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 *_p1 = strchr(_p, ' ');
char *_p2 = strchr(_p1 + 1, ':'); char *_p2 = strchr(_p1 + 1, ':');
char *_p3 = strchr(_p1 + 1, ' '); char *_p3 = strchr(_p1 + 1, ' ');

View File

@ -14,7 +14,7 @@ struct dns_cache *cache, *cache_temp;
socklen_t addr_len = sizeof(dst_addr); socklen_t addr_len = sizeof(dst_addr);
unsigned int cache_using, cacheLimit; unsigned int cache_using, cacheLimit;
dns_t dns_list[DNS_MAX_CONNECTION]; 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() int read_cache_file()
{ {
@ -341,7 +341,7 @@ error:
in->query_type = 0; in->query_type = 0;
} }
void new_client(conf *configure) void new_client(conf * configure)
{ {
dns_t *dns; dns_t *dns;
int i, len; int i, len;
@ -484,7 +484,8 @@ int udp_listen(char *ip, int port)
return fd; return fd;
} }
int httpdns_initialize(conf * configure) { int httpdns_initialize(conf * configure)
{
char *p; char *p;
p = strchr(configure->addr, ':'); p = strchr(configure->addr, ':');
host_value = configure->addr; host_value = configure->addr;
@ -494,11 +495,10 @@ int httpdns_initialize(conf * configure) {
dnsListenFd = udp_listen("0.0.0.0", configure->dns_listen); dnsListenFd = udp_listen("0.0.0.0", configure->dns_listen);
dst_addr.sin_addr.s_addr = inet_addr(configure->addr); dst_addr.sin_addr.s_addr = inet_addr(configure->addr);
dst_addr.sin_family = AF_INET; 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(SIGPIPE, SIG_IGN);
signal(SIGTERM, write_dns_cache); signal(SIGTERM, write_dns_cache);
host_value_len = strlen(host_value); host_value_len = strlen(host_value);
return 0; return 0;
} }

View File

@ -23,7 +23,6 @@
#define DATA_SIZE 512 #define DATA_SIZE 512
#define HTTP_RSP_SIZE 1024 #define HTTP_RSP_SIZE 1024
typedef struct dns_connection { typedef struct dns_connection {
char dns_req[DATA_SIZE]; char dns_req[DATA_SIZE];
struct sockaddr_in src_addr; struct sockaddr_in src_addr;
@ -32,8 +31,8 @@ typedef struct dns_connection {
unsigned int http_request_len, dns_rsp_len; unsigned int http_request_len, dns_rsp_len;
int fd; int fd;
char query_type; char query_type;
unsigned host_len :7; //域名最大长度64位 unsigned host_len:7; //域名最大长度64位
unsigned wait_response_client :1; //已构建好DNS回应等待可写事件 unsigned wait_response_client:1; //已构建好DNS回应等待可写事件
} dns_t; } dns_t;
struct dns_cache { struct dns_cache {
@ -44,11 +43,9 @@ struct dns_cache {
}; };
extern dns_t dns_list[DNS_MAX_CONNECTION]; 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); void *httpdns_loop(void *p);
int httpdns_initialize(conf * configure); int httpdns_initialize(conf * configure);
#endif #endif

8
main.c
View File

@ -166,7 +166,6 @@ void *http_proxy_loop(void *p)
conf *configure = (conf *) p; conf *configure = (conf *) p;
int n; int n;
ev.events = EPOLLIN; ev.events = EPOLLIN;
ev.data.fd = server_sock; ev.data.fd = server_sock;
if (-1 == epoll_ctl(epollfd, EPOLL_CTL_ADD, server_sock, &ev)) { if (-1 == epoll_ctl(epollfd, EPOLL_CTL_ADD, server_sock, &ev)) {
@ -186,8 +185,7 @@ void *http_proxy_loop(void *p)
//printf("accept_client6()!!!\n"); //printf("accept_client6()!!!\n");
accept_client6(); accept_client6();
; ;
} } else if (events[n].data.fd == server_sock) {
else if (events[n].data.fd == server_sock) {
//printf("accept_client()!!!\n"); //printf("accept_client()!!!\n");
accept_client(); accept_client();
} else { } else {
@ -305,7 +303,6 @@ void server_ini()
perror("daemon"); perror("daemon");
return; return;
} }
//while (process-- > 1 && fork() == 0); //while (process-- > 1 && fork() == 0);
} }
@ -424,14 +421,13 @@ void _main(int argc, char *argv[])
} }
server_sock = create_server_socket(configure->tcp_listen); // IPV4 server_sock = create_server_socket(configure->tcp_listen); // IPV4
server_sock6 = create_server_socket6(configure->tcp6_listen);// IPV6 server_sock6 = create_server_socket6(configure->tcp6_listen); // IPV6
epollfd = epoll_create(MAX_CONNECTION); epollfd = epoll_create(MAX_CONNECTION);
if (epollfd == -1) { if (epollfd == -1) {
perror("epoll_create"); perror("epoll_create");
exit(1); exit(1);
} }
if (setegid(configure->uid) == -1 || seteuid(configure->uid) == -1) // 设置uid if (setegid(configure->uid) == -1 || seteuid(configure->uid) == -1) // 设置uid
exit(1); exit(1);

View File

@ -14,8 +14,7 @@ void *tcp_timeout_check(void *nullPtr)
if (cts[i].fd > -1) { if (cts[i].fd > -1) {
if (cts[i].timer >= timeout_minute) { if (cts[i].timer >= timeout_minute) {
close_connection(cts + i); close_connection(cts + i);
} } else
else
cts[i].timer++; cts[i].timer++;
} }
} }