Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
63415ef868 |
@@ -205,6 +205,7 @@ log-level info
|
||||
# -host-ip [ip]: set dns server host ip.
|
||||
# server 8.8.8.8 -blacklist-ip -check-edns -group g1 -group g2
|
||||
# server tls://dns.google:853
|
||||
# server quic://dns.gooel.com:443
|
||||
# server https://dns.google/dns-query
|
||||
|
||||
# remote tcp dns server list
|
||||
@@ -226,6 +227,20 @@ log-level info
|
||||
# server-tls 8.8.8.8
|
||||
# server-tls 1.0.0.1
|
||||
|
||||
# remote quic dns server list
|
||||
# server-quic [IP]:[PORT] [-blacklist-ip] [-whitelist-ip] [-spki-pin [sha256-pin]] [-group [group] ...] [-exclude-default-group]
|
||||
# -spki-pin: TLS spki pin to verify.
|
||||
# -tls-host-verify: cert hostname to verify.
|
||||
# -host-name: TLS sni hostname.
|
||||
# k|-no-check-certificate: no check certificate.
|
||||
# p|-proxy [proxy-name]: use proxy to connect to server.
|
||||
# -bootstrap-dns: set as bootstrap dns server.
|
||||
# Get SPKI with this command:
|
||||
# echo | openssl s_client -connect '[ip]:443' | openssl x509 -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
|
||||
# default port is 443
|
||||
# server-quic 8.8.8.8
|
||||
# server-quic 1.0.0.1
|
||||
|
||||
# remote https dns server list
|
||||
# server-https https://[host]:[port]/path [-blacklist-ip] [-whitelist-ip] [-spki-pin [sha256-pin]] [-group [group] ...] [-exclude-default-group]
|
||||
# -spki-pin: TLS spki pin to verify.
|
||||
|
||||
@@ -28,7 +28,7 @@ ifndef CFLAGS
|
||||
endif
|
||||
CFLAGS +=-Wall -Wstrict-prototypes -fno-omit-frame-pointer -Wstrict-aliasing -funwind-tables -Wmissing-prototypes -Wshadow -Wextra -Wno-unused-parameter -Wno-implicit-fallthrough
|
||||
endif
|
||||
override CFLAGS +=-Iinclude
|
||||
override CFLAGS +=-Iinclude -I/home/rock/code/build/openssl/openssl-3.2.0/include
|
||||
override CFLAGS += -DBASE_FILE_NAME='"$(notdir $<)"'
|
||||
override CFLAGS += $(EXTRA_CFLAGS)
|
||||
ifdef VER
|
||||
@@ -40,7 +40,7 @@ override CXXFLAGS +=-Iinclude
|
||||
|
||||
# ldflags
|
||||
ifeq ($(STATIC), yes)
|
||||
override LDFLAGS += -lssl -lcrypto -Wl,--whole-archive -lpthread -Wl,--no-whole-archive -ldl -static
|
||||
override LDFLAGS += -lssl -lcrypto -Wl,--whole-archive -lpthread -Wl,--no-whole-archive -ldl -static -L/home/rock/code/build/openssl/openssl-3.2.0
|
||||
else
|
||||
override LDFLAGS += -lssl -lcrypto -lpthread -ldl
|
||||
endif
|
||||
|
||||
190
src/dns_client.c
190
src/dns_client.c
@@ -61,7 +61,7 @@
|
||||
#define DNS_TCP_BUFFER (32 * 1024)
|
||||
#define DNS_TCP_IDLE_TIMEOUT (60 * 10)
|
||||
#define DNS_TCP_CONNECT_TIMEOUT (5)
|
||||
#define DNS_QUERY_TIMEOUT (500)
|
||||
#define DNS_QUERY_TIMEOUT (3000)
|
||||
#define DNS_QUERY_RETRY (4)
|
||||
#define DNS_PENDING_SERVER_RETRY 60
|
||||
#define SOCKET_PRIORITY (6)
|
||||
@@ -423,6 +423,9 @@ static const char *_dns_server_get_type_string(dns_server_type_t type)
|
||||
case DNS_SERVER_HTTPS:
|
||||
type_str = "https";
|
||||
break;
|
||||
case DNS_SERVER_QUIC:
|
||||
type_str = "quic";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -863,6 +866,7 @@ static char *_dns_client_server_get_tls_host_verify(struct dns_server_info *serv
|
||||
struct client_dns_server_flag_https *flag_https = &server_info->flags.https;
|
||||
tls_host_verify = flag_https->tls_host_verify;
|
||||
} break;
|
||||
case DNS_SERVER_QUIC:
|
||||
case DNS_SERVER_TLS: {
|
||||
struct client_dns_server_flag_tls *flag_tls = &server_info->flags.tls;
|
||||
tls_host_verify = flag_tls->tls_host_verify;
|
||||
@@ -895,6 +899,7 @@ static char *_dns_client_server_get_spki(struct dns_server_info *server_info, in
|
||||
spki = flag_https->spki;
|
||||
*spki_len = flag_https->spi_len;
|
||||
} break;
|
||||
case DNS_SERVER_QUIC:
|
||||
case DNS_SERVER_TLS: {
|
||||
struct client_dns_server_flag_tls *flag_tls = &server_info->flags.tls;
|
||||
spki = flag_tls->spki;
|
||||
@@ -955,7 +960,7 @@ static int _dns_client_set_trusted_cert(SSL_CTX *ssl_ctx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SSL_CTX *_ssl_ctx_get(void)
|
||||
static SSL_CTX *_ssl_ctx_get(int is_quic)
|
||||
{
|
||||
pthread_mutex_lock(&client.server_list_lock);
|
||||
SSL_CTX *ssl_ctx = client.ssl_ctx;
|
||||
@@ -965,7 +970,18 @@ static SSL_CTX *_ssl_ctx_get(void)
|
||||
}
|
||||
|
||||
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
|
||||
#if (OPENSSL_VERSION_NUMBER >= 0x30200000L)
|
||||
if (is_quic) {
|
||||
ssl_ctx = SSL_CTX_new(OSSL_QUIC_client_method());
|
||||
} else {
|
||||
ssl_ctx = SSL_CTX_new(TLS_client_method());
|
||||
}
|
||||
#else
|
||||
if (is_quic) {
|
||||
return NULL;
|
||||
}
|
||||
ssl_ctx = SSL_CTX_new(TLS_client_method());
|
||||
#endif
|
||||
#else
|
||||
ssl_ctx = SSL_CTX_new(SSLv23_client_method());
|
||||
#endif
|
||||
@@ -1052,6 +1068,12 @@ static int _dns_client_server_add(char *server_ip, char *server_host, int port,
|
||||
sock_type = SOCK_STREAM;
|
||||
skip_check_cert = flag_https->skip_check_cert;
|
||||
} break;
|
||||
case DNS_SERVER_QUIC: {
|
||||
struct client_dns_server_flag_tls *flag_tls = &flags->tls;
|
||||
spki_data_len = flag_tls->spi_len;
|
||||
sock_type = SOCK_DGRAM;
|
||||
skip_check_cert = flag_tls->skip_check_cert;
|
||||
} break;
|
||||
case DNS_SERVER_TLS: {
|
||||
struct client_dns_server_flag_tls *flag_tls = &flags->tls;
|
||||
spki_data_len = flag_tls->spi_len;
|
||||
@@ -1124,8 +1146,12 @@ static int _dns_client_server_add(char *server_ip, char *server_host, int port,
|
||||
}
|
||||
|
||||
/* if server type is TLS, create ssl context */
|
||||
if (server_type == DNS_SERVER_TLS || server_type == DNS_SERVER_HTTPS) {
|
||||
server_info->ssl_ctx = _ssl_ctx_get();
|
||||
if (server_type == DNS_SERVER_TLS || server_type == DNS_SERVER_HTTPS || server_type == DNS_SERVER_QUIC) {
|
||||
if (server_type == DNS_SERVER_QUIC) {
|
||||
server_info->ssl_ctx = _ssl_ctx_get(1);
|
||||
} else {
|
||||
server_info->ssl_ctx = _ssl_ctx_get(0);
|
||||
}
|
||||
if (server_info->ssl_ctx == NULL) {
|
||||
tlog(TLOG_ERROR, "init ssl failed.");
|
||||
goto errout;
|
||||
@@ -1237,6 +1263,7 @@ static void _dns_client_shutdown_socket(struct dns_server_info *server_info)
|
||||
shutdown(server_info->fd, SHUT_RDWR);
|
||||
}
|
||||
break;
|
||||
case DNS_SERVER_QUIC:
|
||||
case DNS_SERVER_TLS:
|
||||
case DNS_SERVER_HTTPS:
|
||||
if (server_info->ssl) {
|
||||
@@ -1998,6 +2025,138 @@ errout:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int _DNS_client_create_socket_quic(struct dns_server_info *server_info, char *hostname)
|
||||
{
|
||||
#ifdef OSSL_QUIC1_VERSION
|
||||
int fd = 0;
|
||||
struct epoll_event event;
|
||||
SSL *ssl = NULL;
|
||||
struct proxy_conn *proxy = NULL;
|
||||
int ret = -1;
|
||||
|
||||
if (server_info->ssl_ctx == NULL) {
|
||||
tlog(TLOG_ERROR, "create ssl ctx failed, %s", server_info->ip);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (server_info->proxy_name[0] != '\0') {
|
||||
proxy = proxy_conn_new(server_info->proxy_name, server_info->ip, server_info->port, 1);
|
||||
if (proxy == NULL) {
|
||||
tlog(TLOG_ERROR, "create proxy failed, %s, proxy: %s", server_info->ip, server_info->proxy_name);
|
||||
goto errout;
|
||||
}
|
||||
fd = proxy_conn_get_fd(proxy);
|
||||
} else {
|
||||
fd = socket(server_info->ai_family, SOCK_DGRAM, IPPROTO_UDP);
|
||||
}
|
||||
|
||||
ssl = SSL_new(server_info->ssl_ctx);
|
||||
if (ssl == NULL) {
|
||||
tlog(TLOG_ERROR, "new ssl failed, %s", server_info->ip);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (fd < 0) {
|
||||
tlog(TLOG_ERROR, "create socket failed, %s", strerror(errno));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (set_fd_nonblock(fd, 1) != 0) {
|
||||
tlog(TLOG_ERROR, "set socket non block failed, %s", strerror(errno));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (server_info->so_mark >= 0) {
|
||||
unsigned int so_mark = server_info->so_mark;
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_MARK, &so_mark, sizeof(so_mark)) != 0) {
|
||||
tlog(TLOG_DEBUG, "set socket mark failed, %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
if (proxy) {
|
||||
ret = proxy_conn_connect(proxy);
|
||||
} else {
|
||||
ret = connect(fd, &server_info->addr, server_info->ai_addrlen);
|
||||
}
|
||||
|
||||
if (ret != 0) {
|
||||
if (errno != EINPROGRESS) {
|
||||
tlog(TLOG_DEBUG, "connect %s failed, %s", server_info->ip, strerror(errno));
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
|
||||
SSL_set_connect_state(ssl);
|
||||
SSL_set_blocking_mode(ssl, 0);
|
||||
if (SSL_set_fd(ssl, fd) == 0) {
|
||||
tlog(TLOG_ERROR, "ssl set fd failed.");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* reuse ssl session */
|
||||
if (server_info->ssl_session) {
|
||||
SSL_set_session(ssl, server_info->ssl_session);
|
||||
}
|
||||
|
||||
SSL_set_mode(ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE);
|
||||
if (hostname[0] != 0) {
|
||||
SSL_set_tlsext_host_name(ssl, hostname);
|
||||
}
|
||||
|
||||
SSL_set1_host(ssl, hostname);
|
||||
|
||||
static const unsigned char alpn[] = {3, 'd', 'o', 'q'};
|
||||
if (SSL_set_alpn_protos(ssl, alpn, sizeof(alpn))) {
|
||||
tlog(TLOG_INFO, "SSL_set_alpn_protos failed.");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
server_info->fd = fd;
|
||||
server_info->ssl = ssl;
|
||||
server_info->ssl_write_len = -1;
|
||||
server_info->status = DNS_SERVER_STATUS_CONNECTING;
|
||||
server_info->proxy = proxy;
|
||||
|
||||
memset(&event, 0, sizeof(event));
|
||||
event.events = EPOLLIN | EPOLLOUT;
|
||||
event.data.ptr = server_info;
|
||||
if (epoll_ctl(client.epoll_fd, EPOLL_CTL_ADD, fd, &event) != 0) {
|
||||
tlog(TLOG_ERROR, "epoll ctl failed.");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
tlog(TLOG_DEBUG, "tls server %s connecting.\n", server_info->ip);
|
||||
|
||||
return 0;
|
||||
errout:
|
||||
if (server_info->fd > 0) {
|
||||
server_info->fd = -1;
|
||||
}
|
||||
|
||||
if (server_info->ssl) {
|
||||
server_info->ssl = NULL;
|
||||
}
|
||||
|
||||
server_info->status = DNS_SERVER_STATUS_INIT;
|
||||
|
||||
if (fd > 0 && proxy == NULL) {
|
||||
close(fd);
|
||||
}
|
||||
|
||||
if (ssl) {
|
||||
SSL_free(ssl);
|
||||
}
|
||||
|
||||
if (proxy) {
|
||||
proxy_conn_free(proxy);
|
||||
}
|
||||
|
||||
return -1;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int _DNS_client_create_socket_tls(struct dns_server_info *server_info, char *hostname)
|
||||
{
|
||||
int fd = 0;
|
||||
@@ -2150,6 +2309,10 @@ static int _dns_client_create_socket(struct dns_server_info *server_info)
|
||||
struct client_dns_server_flag_tls *flag_tls = NULL;
|
||||
flag_tls = &server_info->flags.tls;
|
||||
return _DNS_client_create_socket_tls(server_info, flag_tls->hostname);
|
||||
} else if (server_info->type == DNS_SERVER_QUIC) {
|
||||
struct client_dns_server_flag_tls *flag_tls = NULL;
|
||||
flag_tls = &server_info->flags.tls;
|
||||
return _DNS_client_create_socket_quic(server_info, flag_tls->hostname);
|
||||
} else if (server_info->type == DNS_SERVER_HTTPS) {
|
||||
struct client_dns_server_flag_https *flag_https = NULL;
|
||||
flag_https = &server_info->flags.https;
|
||||
@@ -2512,7 +2675,8 @@ static int _dns_client_socket_send(struct dns_server_info *server_info)
|
||||
return -1;
|
||||
} else if (server_info->type == DNS_SERVER_TCP) {
|
||||
return send(server_info->fd, server_info->send_buff.data, server_info->send_buff.len, MSG_NOSIGNAL);
|
||||
} else if (server_info->type == DNS_SERVER_TLS || server_info->type == DNS_SERVER_HTTPS) {
|
||||
} else if (server_info->type == DNS_SERVER_TLS || server_info->type == DNS_SERVER_HTTPS ||
|
||||
server_info->type == DNS_SERVER_QUIC) {
|
||||
int write_len = server_info->send_buff.len;
|
||||
if (server_info->ssl_write_len > 0) {
|
||||
write_len = server_info->ssl_write_len;
|
||||
@@ -2540,7 +2704,8 @@ static int _dns_client_socket_recv(struct dns_server_info *server_info)
|
||||
} else if (server_info->type == DNS_SERVER_TCP) {
|
||||
return recv(server_info->fd, server_info->recv_buff.data + server_info->recv_buff.len,
|
||||
DNS_TCP_BUFFER - server_info->recv_buff.len, 0);
|
||||
} else if (server_info->type == DNS_SERVER_TLS || server_info->type == DNS_SERVER_HTTPS) {
|
||||
} else if (server_info->type == DNS_SERVER_TLS || server_info->type == DNS_SERVER_HTTPS ||
|
||||
server_info->type == DNS_SERVER_QUIC) {
|
||||
int ret = _dns_client_socket_ssl_recv(server_info, server_info->recv_buff.data + server_info->recv_buff.len,
|
||||
DNS_TCP_BUFFER - server_info->recv_buff.len);
|
||||
if (ret == -SSL_ERROR_WANT_WRITE && errno == EAGAIN) {
|
||||
@@ -3158,7 +3323,8 @@ static int _dns_client_process(struct dns_server_info *server_info, struct epoll
|
||||
} else if (server_info->type == DNS_SERVER_TCP) {
|
||||
/* receive from tcp */
|
||||
return _dns_client_process_tcp(server_info, event, now);
|
||||
} else if (server_info->type == DNS_SERVER_TLS || server_info->type == DNS_SERVER_HTTPS) {
|
||||
} else if (server_info->type == DNS_SERVER_TLS || server_info->type == DNS_SERVER_HTTPS ||
|
||||
server_info->type == DNS_SERVER_QUIC) {
|
||||
/* receive from tls */
|
||||
return _dns_client_process_tls(server_info, event, now);
|
||||
} else {
|
||||
@@ -3394,6 +3560,11 @@ static int _dns_client_send_https(struct dns_server_info *server_info, void *pac
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _dns_client_send_quic(struct dns_server_info *server_info, void *packet, unsigned short len)
|
||||
{
|
||||
return _dns_client_send_tls(server_info, packet, len);
|
||||
}
|
||||
|
||||
static int _dns_client_setup_server_packet(struct dns_server_info *server_info, struct dns_query_struct *query,
|
||||
void *default_packet, int default_packet_len,
|
||||
unsigned char *packet_data_buffer, void **packet_data, int *packet_data_len)
|
||||
@@ -3567,6 +3738,11 @@ static int _dns_client_send_packet(struct dns_query_struct *query, void *packet,
|
||||
ret = _dns_client_send_https(server_info, packet_data, packet_data_len);
|
||||
send_err = errno;
|
||||
break;
|
||||
case DNS_SERVER_QUIC:
|
||||
/* quic query */
|
||||
ret = _dns_client_send_quic(server_info, packet_data, packet_data_len);
|
||||
send_err = errno;
|
||||
break;
|
||||
default:
|
||||
/* unsupported query type */
|
||||
ret = -1;
|
||||
|
||||
@@ -33,6 +33,7 @@ typedef enum {
|
||||
DNS_SERVER_TCP,
|
||||
DNS_SERVER_TLS,
|
||||
DNS_SERVER_HTTPS,
|
||||
DNS_SERVER_QUIC,
|
||||
DNS_SERVER_TYPE_END,
|
||||
} dns_server_type_t;
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <getopt.h>
|
||||
#include <glob.h>
|
||||
#include <libgen.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -600,6 +601,9 @@ static int _config_server(int argc, char *argv[], dns_server_type_t type, int de
|
||||
if (strcasecmp(scheme, "https") == 0) {
|
||||
type = DNS_SERVER_HTTPS;
|
||||
default_port = DEFAULT_DNS_HTTPS_PORT;
|
||||
} else if (strcasecmp(scheme, "quic")) {
|
||||
type = DNS_SERVER_QUIC;
|
||||
default_port = DEFAULT_DNS_QUIC_PORT;
|
||||
} else if (strcasecmp(scheme, "tls") == 0) {
|
||||
type = DNS_SERVER_TLS;
|
||||
default_port = DEFAULT_DNS_TLS_PORT;
|
||||
@@ -615,6 +619,13 @@ static int _config_server(int argc, char *argv[], dns_server_type_t type, int de
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef OSSL_QUIC1_VERSION
|
||||
if (type == DNS_SERVER_QUIC) {
|
||||
tlog(TLOG_ERROR, "quic not support.");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* if port is not defined, set port to default 53 */
|
||||
if (port == PORT_NOT_DEFINED) {
|
||||
port = default_port;
|
||||
@@ -2455,6 +2466,14 @@ static int _config_server_https(void *data, int argc, char *argv[])
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _config_server_quic(void *data, int argc, char *argv[])
|
||||
{
|
||||
int ret = 0;
|
||||
ret = _config_server(argc, argv, DNS_SERVER_QUIC, DEFAULT_DNS_QUIC_PORT);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _conf_domain_rule_nameserver(char *domain, const char *group_name)
|
||||
{
|
||||
struct dns_nameserver_rule *nameserver_rule = NULL;
|
||||
@@ -4289,6 +4308,7 @@ static struct config_item _config_item[] = {
|
||||
CONF_CUSTOM("server-tcp", _config_server_tcp, NULL),
|
||||
CONF_CUSTOM("server-tls", _config_server_tls, NULL),
|
||||
CONF_CUSTOM("server-https", _config_server_https, NULL),
|
||||
CONF_CUSTOM("server-quic", _config_server_quic, NULL),
|
||||
CONF_CUSTOM("nameserver", _config_nameserver, NULL),
|
||||
CONF_YESNO("expand-ptr-from-address", &dns_conf_expand_ptr_from_address),
|
||||
CONF_CUSTOM("address", _config_address, NULL),
|
||||
|
||||
@@ -56,6 +56,7 @@ extern "C" {
|
||||
#define DEFAULT_DNS_PORT 53
|
||||
#define DEFAULT_DNS_TLS_PORT 853
|
||||
#define DEFAULT_DNS_HTTPS_PORT 443
|
||||
#define DEFAULT_DNS_QUIC_PORT 853
|
||||
#define DNS_MAX_CONF_CNAME_LEN 256
|
||||
#define MAX_QTYPE_NUM 65535
|
||||
#define DNS_MAX_REPLY_IP_NUM 8
|
||||
|
||||
@@ -268,6 +268,7 @@ static int _smartdns_prepare_server_flags(struct client_dns_server_flags *flags,
|
||||
safe_strncpy(flag_http->tls_host_verify, server->tls_host_verify, sizeof(flag_http->tls_host_verify));
|
||||
flag_http->skip_check_cert = server->skip_check_cert;
|
||||
} break;
|
||||
case DNS_SERVER_QUIC:
|
||||
case DNS_SERVER_TLS: {
|
||||
struct client_dns_server_flag_tls *flag_tls = &flags->tls;
|
||||
flag_tls->spi_len = dns_client_spki_decode(server->spki, (unsigned char *)flag_tls->spki);
|
||||
|
||||
Reference in New Issue
Block a user