Browse Source

feat: dns resolve of udp proxy's remote host

master
dnomd343 3 years ago
parent
commit
618d011bd1
  1. 6
      include/dns.h
  2. 1
      include/network.h
  3. 102
      src/dns.c
  4. 34
      src/network.c
  5. 25
      src/process.c

6
include/dns.h

@ -0,0 +1,6 @@
#ifndef _DNS_H_
#define _DNS_H_
char* dns_resolve(char *domain);
#endif

1
include/network.h

@ -3,6 +3,7 @@
extern int proxy_exit; extern int proxy_exit;
int is_ip_addr(char *address);
int get_available_port(unsigned short range_start, unsigned short range_end); 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); void proxy(char *server_ip, int server_port, char *listen_ip, int listen_port);

102
src/dns.c

@ -0,0 +1,102 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#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地址
}

34
src/network.c

@ -13,6 +13,20 @@
int proxy_exit; 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 { typedef struct ipv4_proxy_info {
char *server_ip; char *server_ip;
int server_port; 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地址 int is_ipv6_addr(char *address) { // 判断是否为IPv6地址
struct sockaddr_in6 temp; char buf[sizeof(struct in6_addr)];
if (!inet_aton(address, (struct in_addr*)&temp.sin6_addr)) { // IPv6 address 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 1;
} }
return 0; return 0;
@ -228,7 +256,7 @@ void ipv4_proxy(void *ipv4_info) { // 代理IPv4客户端
char *recv_buffer = (char*)malloc(BUFFER_SIZE); // 申请接收缓冲区内存 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); // 服务端交互 long recv_len = send_and_receive(info->server_ip, info->server_port, info->buffer, info->len, recv_buffer); // 服务端交互
if (recv_len < 0) { // 服务端超时 if (recv_len < 0) { // 服务端超时
printf("[Shadowsocks Bootstrap] Server return timeout\n"); printf("[Shadowsocks Bootstrap] UDP Proxy: server return timeout\n");
} else { } else {
if (sendto(info->ipv4_client_fd, recv_buffer, recv_len, 0, (struct sockaddr*)&(info->ipv4_client_addr), sizeof(info->ipv4_client_addr)) < 0) { // 服务端数据返回给客户端 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"); perror("[Shadowsocks Bootstrap] IPv4 UDP return failed");

25
src/process.c

@ -6,6 +6,7 @@
#include <sys/prctl.h> #include <sys/prctl.h>
#include "network.h" #include "network.h"
#include "process.h" #include "process.h"
#include "dns.h"
char **shadowsocks_args; char **shadowsocks_args;
char *plugin_file; char *plugin_file;
@ -201,10 +202,26 @@ void start_bootstrap(char *ss_type) { // start shadowsocks and plugin (optional)
process_exec(); // exec child process process_exec(); // exec child process
usleep(500 * 1000); // wait 500ms for plugin start usleep(500 * 1000); // wait 500ms for plugin start
if (plugin_file != NULL) { // start udp proxy when using plugin if (plugin_file != NULL) { // start udp proxy when using plugin
if (!strcmp(ss_type, "sslocal")) { // local mode char *remote_ip;
proxy(SS_REMOTE_HOST, atoi(SS_REMOTE_PORT), SS_LOCAL_HOST, atoi(SS_LOCAL_PORT)); if (is_ip_addr(SS_REMOTE_HOST)) { // remote_host -> ip address
} else { // server mode remote_ip = SS_REMOTE_HOST;
proxy(SS_LOCAL_HOST, atoi(SS_LOCAL_PORT), SS_REMOTE_HOST, atoi(SS_REMOTE_PORT)); } 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 g_main_loop_run(main_loop); // into main loop for wait

Loading…
Cancel
Save