diff --git a/include/dns.h b/include/dns.h new file mode 100644 index 0000000..7996474 --- /dev/null +++ b/include/dns.h @@ -0,0 +1,6 @@ +#ifndef _DNS_H_ +#define _DNS_H_ + +char* dns_resolve(char *domain); + +#endif diff --git a/include/network.h b/include/network.h index c162e5a..1699a5d 100644 --- a/include/network.h +++ b/include/network.h @@ -3,6 +3,7 @@ extern int proxy_exit; +int is_ip_addr(char *address); int get_available_port(unsigned short range_start, unsigned short range_end); void proxy(char *server_ip, int server_port, char *listen_ip, int listen_port); diff --git a/src/dns.c b/src/dns.c new file mode 100644 index 0000000..99f6ac9 --- /dev/null +++ b/src/dns.c @@ -0,0 +1,102 @@ +#include +#include +#include +#include +#include +#include +#include +#include "dns.h" + +char** init_dns_result(); +void add_dns_result(char **dns_result, char *str); +void free_dns_result(char **dns_result); +char** ipv4_dns_resolve(char *domain); +char** ipv6_dns_resolve(char *domain); + +char** init_dns_result() { // 初始化DNS解析存储结构 + char **dns_result = (char**)malloc(sizeof(char*)); + dns_result[0] = NULL; + return dns_result; +} + +void add_dns_result(char **dns_result, char *str) { // 添加DNS解析记录 + int num = 0; + while(dns_result[num++] != NULL); // 获取原存储个数 + dns_result = (char**)realloc(dns_result, sizeof(char**) * (num + 1)); + dns_result[num - 1] = strcpy((char*)malloc(strlen(str) + 1), str); + dns_result[num] = NULL; // 结束标志 +} + +void free_dns_result(char **dns_result) { // 释放DNS解析结果 + int num = 0; + while(dns_result[num] != NULL) { // 逐个释放 + free(dns_result[num++]); + } +} + +char** ipv4_dns_resolve(char *domain) { // DNS解析IPv4地址 + char **result = init_dns_result(); + char ip_str[16]; // IPv4地址字符串 (3 * 4 + 1 * 3 + 1) + struct sockaddr_in *ipv4_addr; + struct addrinfo *answer, hint, *p; + bzero(&hint, sizeof(hint)); // 清空为0x00 + hint.ai_family = AF_INET; + hint.ai_socktype = SOCK_STREAM; + int ret = getaddrinfo(domain, NULL, &hint, &answer); // 发起解析 + if (ret != 0) { // 解析失败 + printf("[Shadowsocks Bootstrap] IPv4 DNS resolve `%s`: %s\n", domain, gai_strerror(ret)); + return result; // 返回空数据 + } + for (p = answer; p != NULL; p = p->ai_next) { // 遍历解析结果 + ipv4_addr = (struct sockaddr_in*)(p->ai_addr); // 获取IPv4地址 + inet_ntop(AF_INET, &ipv4_addr->sin_addr, ip_str, sizeof(ip_str)); // 转化为字符串形式 + add_dns_result(result, ip_str); + } + freeaddrinfo(answer); // 释放解析结果 + return result; +} + +char** ipv6_dns_resolve(char *domain) { // DNS解析IPv6地址 + char **result = init_dns_result(); + char ip_str[40]; // IPv6地址字符串 (4 * 8 + 1 * 7 + 1) + struct sockaddr_in6 *ipv6_addr; + struct addrinfo *answer, hint, *p; + bzero(&hint, sizeof(hint)); // 清空为0x00 + hint.ai_family = AF_INET6; + hint.ai_socktype = SOCK_STREAM; + int ret = getaddrinfo(domain, NULL, &hint, &answer); // 发起解析 + if (ret != 0) { // 解析失败 + printf("[Shadowsocks Bootstrap] IPv6 DNS resolve `%s`: %s\n", domain, gai_strerror(ret)); + return result; // 返回空数据 + } + for (p = answer; p != NULL; p = p->ai_next) { // 遍历解析结果 + ipv6_addr = (struct sockaddr_in6*)(p->ai_addr); // 获取IPv6地址 + inet_ntop(AF_INET6, &ipv6_addr->sin6_addr, ip_str, sizeof(ip_str)); // 转化为字符串形式 + add_dns_result(result, ip_str); + } + freeaddrinfo(answer); // 释放解析结果 + return result; +} + +char* dns_resolve(char *domain) { // DNS解析 返回首个IP地址 IPv4优先 + int num = 0; + char **result = init_dns_result(); + result = ipv4_dns_resolve(domain); // IPv4解析 + while(result[num++] != NULL); // num - 1 为IPv4地址数 + if (num - 1 != 0) { // 存在IPv4解析 + char *tmp = strcpy((char*)malloc(strlen(result[0]) + 1), result[0]); + free_dns_result(result); // 释放IPv4结果 + return tmp; // 返回首个IPv4地址 + } + free_dns_result(result); // 释放IPv4结果 + result = ipv6_dns_resolve(domain); + num = 0; + while(result[num++] != NULL); // num - 1 为IPv6地址数 + if (num - 1 == 0) { // 无IPv6解析 + free_dns_result(result); // 释放IPv6结果 + return NULL; + } + char *tmp = strcpy((char*)malloc(strlen(result[0]) + 1), result[0]); + free_dns_result(result); // 释放IPv6结果 + return tmp; // 返回首个IPv6地址 +} diff --git a/src/network.c b/src/network.c index da0abd4..d262806 100644 --- a/src/network.c +++ b/src/network.c @@ -13,6 +13,20 @@ int proxy_exit; +int get_random_num(int range_start, int range_end); +int check_port_available(unsigned int port, int is_udp, int is_ipv6); +int is_ipv4_addr(char *address); +int is_ipv6_addr(char *address); +int create_ipv4_udp_sock(char *address, int port); +int create_ipv6_udp_sock(char *address, int port); +long ipv4_receive(int fd, char *buffer, int buffer_size, int timeout, struct sockaddr_in sa); +long ipv6_receive(int fd, char *buffer, int buffer_size, int timeout, struct sockaddr_in6 sa); +long ipv4_send_and_receive(char *ipv4_server_ip, int ipv4_server_port, char *send_buffer, long send_len, char *recv_buffer); +long ipv6_send_and_receive(char *ipv6_server_ip, int ipv6_server_port, char *send_buffer, long send_len, char *recv_buffer); +long send_and_receive(char *server_ip, int server_port, char *send_buffer, long send_len, char *recv_buffer); +void ipv4_proxy(void *ipv4_info); +void ipv6_proxy(void *ipv6_info); + typedef struct ipv4_proxy_info { char *server_ip; int server_port; @@ -105,9 +119,23 @@ int get_available_port(unsigned short range_start, unsigned short range_end) { / } } +int is_ipv4_addr(char *address) { // 判断是否为IPv4地址 + if (inet_addr(address) == -1) { + return 0; + } + return 1; +} + int is_ipv6_addr(char *address) { // 判断是否为IPv6地址 - struct sockaddr_in6 temp; - if (!inet_aton(address, (struct in_addr*)&temp.sin6_addr)) { // IPv6 address + char buf[sizeof(struct in6_addr)]; + if (inet_pton(AF_INET6, address, buf) <= 0) { + return 0; + } + return 1; +} + +int is_ip_addr(char *address) { // 判断是否为IP地址 + if (is_ipv4_addr(address) || is_ipv6_addr(address)) { return 1; } return 0; @@ -228,7 +256,7 @@ void ipv4_proxy(void *ipv4_info) { // 代理IPv4客户端 char *recv_buffer = (char*)malloc(BUFFER_SIZE); // 申请接收缓冲区内存 long recv_len = send_and_receive(info->server_ip, info->server_port, info->buffer, info->len, recv_buffer); // 服务端交互 if (recv_len < 0) { // 服务端超时 - printf("[Shadowsocks Bootstrap] Server return timeout\n"); + printf("[Shadowsocks Bootstrap] UDP Proxy: server return timeout\n"); } else { if (sendto(info->ipv4_client_fd, recv_buffer, recv_len, 0, (struct sockaddr*)&(info->ipv4_client_addr), sizeof(info->ipv4_client_addr)) < 0) { // 服务端数据返回给客户端 perror("[Shadowsocks Bootstrap] IPv4 UDP return failed"); diff --git a/src/process.c b/src/process.c index a50df21..8c067cc 100644 --- a/src/process.c +++ b/src/process.c @@ -6,6 +6,7 @@ #include #include "network.h" #include "process.h" +#include "dns.h" char **shadowsocks_args; char *plugin_file; @@ -201,10 +202,26 @@ void start_bootstrap(char *ss_type) { // start shadowsocks and plugin (optional) process_exec(); // exec child process usleep(500 * 1000); // wait 500ms for plugin start if (plugin_file != NULL) { // start udp proxy when using plugin - if (!strcmp(ss_type, "sslocal")) { // local mode - proxy(SS_REMOTE_HOST, atoi(SS_REMOTE_PORT), SS_LOCAL_HOST, atoi(SS_LOCAL_PORT)); - } else { // server mode - proxy(SS_LOCAL_HOST, atoi(SS_LOCAL_PORT), SS_REMOTE_HOST, atoi(SS_REMOTE_PORT)); + char *remote_ip; + if (is_ip_addr(SS_REMOTE_HOST)) { // remote_host -> ip address + remote_ip = SS_REMOTE_HOST; + } else { // remote_host -> domain + printf("[Shadowsocks Bootstrap] DNS Resolve: %s\n", SS_REMOTE_HOST); + remote_ip = dns_resolve(SS_REMOTE_HOST); // dns resolve + if (remote_ip == NULL) { // no result + printf("[Shadowsocks Bootstrap] DNS record not found.\n"); + } else { // dns resolve success + printf("[Shadowsocks Bootstrap] %s => %s\n", SS_REMOTE_HOST, remote_ip); + } + } + if (remote_ip == NULL) { // resolve error + printf("[Shadowsocks Bootstrap] Skip UDP Proxy.\n"); + } else { // udp proxy + if (!strcmp(ss_type, "sslocal")) { // local mode + proxy(remote_ip, atoi(SS_REMOTE_PORT), SS_LOCAL_HOST, atoi(SS_LOCAL_PORT)); + } else { // server mode + proxy(SS_LOCAL_HOST, atoi(SS_LOCAL_PORT), remote_ip, atoi(SS_REMOTE_PORT)); + } } } g_main_loop_run(main_loop); // into main loop for wait