Skip to content

Commit

Permalink
resolver: add an asynchronous resolver to make this a serious project
Browse files Browse the repository at this point in the history
Signed-off-by: hexian000 <hexian000@outlook.com>
  • Loading branch information
hexian000 committed Aug 13, 2023
1 parent da50d91 commit 76dbbad
Show file tree
Hide file tree
Showing 9 changed files with 331 additions and 49 deletions.
20 changes: 11 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@

A lightweight programmable SOCKS4 / SOCKS4A / SOCKS5 / HTTP proxy server that only supports TCP CONNECT requests.

- [Features](#features)
- [Usage](#usage)
- [Basic Usage](#basic-usage)
- [Scripting Usage](#scripting-usage)
- [Runtime Dependencies](#runtime-dependencies)
- [Building from Source](#building-from-source)
- [Dependencies](#dependencies)
- [Building with CMake](#building-with-cmake)
- [Credits](#credits)
- [neosocksd](#neosocksd)
- [Features](#features)
- [Usage](#usage)
- [Basic Usage](#basic-usage)
- [Scripting Usage](#scripting-usage)
- [Runtime Dependencies](#runtime-dependencies)
- [Building from Source](#building-from-source)
- [Dependencies](#dependencies)
- [Building with CMake](#building-with-cmake)
- [Credits](#credits)

## Features

Expand Down Expand Up @@ -120,3 +121,4 @@ See [m.sh](m.sh) for more information about cross compiling support.
Thanks to:
- [libev](http://software.schmorp.de/pkg/libev.html)
- [Lua](https://www.lua.org/)
- [c-ares](https://c-ares.org/)
17 changes: 17 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ add_executable(neosocksd
conf.c conf.h
sockutil.c sockutil.h
dialer.c dialer.h
resolver.c resolver.h
ruleset.c ruleset.h
transfer.c transfer.h
forward.c forward.h
Expand Down Expand Up @@ -68,6 +69,22 @@ endif()
target_include_directories(neosocksd SYSTEM PRIVATE ${LIBEV_INCLUDE_DIR})
target_link_libraries(neosocksd PRIVATE ${LIBEV_LIBRARY})

# find c-ares
find_path(LIBCARES_INCLUDE_DIR NAMES ares.h)
if(BUILD_STATIC OR LINK_STATIC_LIBS)
find_library(LIBCARES_LIBRARY NAMES libcares.a)
else()
find_library(LIBCARES_LIBRARY NAMES cares)
endif()
if((EXISTS ${LIBCARES_INCLUDE_DIR}) AND (EXISTS ${LIBCARES_LIBRARY}))
message(STATUS "c-ares: ${LIBCARES_LIBRARY}")
set(WITH_CARES ON)
else()
message(FATAL_ERROR "c-ares not found")
endif()
target_include_directories(neosocksd SYSTEM PRIVATE ${LIBCARES_INCLUDE_DIR})
target_link_libraries(neosocksd PRIVATE ${LIBCARES_LIBRARY})

# find lua
find_path(LUA_INCLUDE_DIR
NAMES luaconf.h lua.h lualib.h lauxlib.h
Expand Down
42 changes: 24 additions & 18 deletions src/conf.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "conf.h"
#include "utils/slog.h"
#include "utils/minmax.h"

#include <limits.h>
#include <stddef.h>
#include <stdint.h>
Expand Down Expand Up @@ -28,26 +29,31 @@ struct config conf_default(void)
return conf;
}

static bool conf_check_range(
const char *key, const size_t value, const size_t min, const size_t max)
{
if (value < min || value > max) {
LOGE_F("config: %s is out of range (%zu - %zu)", key, min, max);
return false;
}
return true;
}

#define RANGE_CHECK(conf, key, min, max) \
conf_check_range(#key, (conf)->key, min, max)
do { \
if ((intmax_t)((conf)->key) < (intmax_t)(min) || \
(intmax_t)((conf)->key) > (intmax_t)(max)) { \
LOGE_F("config: %s is out of range (%s - %s)", #key, \
#min, #max); \
return false; \
} \
} while (0)

#define RANGE_CHECK_FLOAT(conf, key, min, max) \
do { \
if (!(((conf)->key) >= (min) && ((conf)->key) <= (max))) { \
LOGE_F("config: %s is out of range (%s - %s)", #key, \
#min, #max); \
return false; \
} \
} while (0)

bool conf_check(const struct config *restrict conf)
{
const bool range_ok =
RANGE_CHECK(conf, startup_limit_start, 1, SIZE_MAX) &&
RANGE_CHECK(conf, startup_limit_rate, 0, 100) &&
RANGE_CHECK(conf, startup_limit_full, 1, SIZE_MAX) &&
RANGE_CHECK(
conf, log_level, LOG_LEVEL_SILENCE, LOG_LEVEL_VERBOSE);
return range_ok;
RANGE_CHECK_FLOAT(conf, timeout, 5.0, 86400.0);
RANGE_CHECK(conf, startup_limit_start, 1, INT_MAX);
RANGE_CHECK(conf, startup_limit_rate, 0, 100);
RANGE_CHECK(conf, startup_limit_full, 1, INT_MAX);
RANGE_CHECK(conf, log_level, LOG_LEVEL_SILENCE, LOG_LEVEL_VERBOSE);
return true;
}
2 changes: 2 additions & 0 deletions src/config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#cmakedefine01 HAVE_SO_REUSEPORT
#cmakedefine01 HAVE_TCP_FASTOPEN

#cmakedefine01 WITH_CARES

#define WITH_TPROXY (!TARGET_POSIX && HAVE_IP_TRANSPARENT)
#define WITH_NETDEVICE (!TARGET_POSIX && HAVE_SO_BINDTODEVICE)
#define WITH_REUSEPORT (!TARGET_POSIX && HAVE_SO_REUSEPORT)
Expand Down
49 changes: 27 additions & 22 deletions src/dialer.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "dialer.h"
#include "net/http.h"
#include "proto/domain.h"
#include "resolver.h"
#include "utils/buffer.h"
#include "utils/serialize.h"
#include "utils/slog.h"
Expand Down Expand Up @@ -162,6 +163,7 @@ void dialreq_free(struct dialreq *restrict req)

enum dialer_state {
STATE_INIT,
STATE_RESOLVE,
STATE_CONNECT,
STATE_HANDSHAKE1,
STATE_HANDSHAKE2,
Expand Down Expand Up @@ -758,25 +760,17 @@ static bool connect_sa(
return true;
}

static bool connect_domain(
struct dialer *restrict d, struct ev_loop *loop,
const struct domain_name *domain)
static void
resolve_cb(struct ev_loop *loop, const struct sockaddr *sa, void *data)
{
sockaddr_max_t addr;

char host[FQDN_MAX_LENGTH + 1];
memcpy(host, domain->name, domain->len);
host[domain->len] = '\0';
if (!resolve_hostname(&addr, host, d->conf->resolve_pf)) {
return false;
}

const struct sockaddr *sa = &addr.sa;
if (LOGLEVEL(LOG_LEVEL_DEBUG)) {
char addr_str[64];
format_sa(sa, addr_str, sizeof(addr_str));
LOG_F(LOG_LEVEL_DEBUG, "resolve: \"%.*s\" is \"%s\"",
(int)domain->len, domain->name, addr_str);
struct dialer *restrict d = data;
const struct domain_name *restrict domain =
d->req->num_proxy > 0 ? &d->req->proxy[0].addr.domain :
&d->req->addr.domain;
if (sa == NULL) {
LOGE_F("name resolution failed: \"%.*s\"", (int)domain->len,
domain->name);
return;
}

const uint16_t port = d->req->addr.port;
Expand All @@ -793,7 +787,16 @@ static bool connect_domain(
FAIL();
}

return connect_sa(d, loop, sa);
if (LOGLEVEL(LOG_LEVEL_DEBUG)) {
char addr_str[64];
format_sa(sa, addr_str, sizeof(addr_str));
LOG_F(LOG_LEVEL_DEBUG, "resolve: \"%.*s\" is \"%s\"",
(int)domain->len, domain->name, addr_str);
}

if (!connect_sa(d, loop, sa)) {
dialer_fail(d, loop);
}
}

static void
Expand Down Expand Up @@ -857,9 +860,11 @@ bool dialer_start(
}
} break;
case ATYP_DOMAIN: {
if (!connect_domain(d, loop, &addr->domain)) {
return false;
}
char host[FQDN_MAX_LENGTH + 1];
memcpy(host, addr->domain.name, addr->domain.len);
host[addr->domain.len] = '\0';
d->state = STATE_RESOLVE;
resolver_do(loop, host, d->conf->resolve_pf, resolve_cb, d);
} break;
default:
FAIL();
Expand Down
3 changes: 3 additions & 0 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ static void print_usage(const char *argv0)
" -l, --listen <address> proxy listen address\n"
" --http run a HTTP CONNECT server instead of SOCKS\n"
" -f, --forward <address> run TCP port forwarding instead of SOCKS\n"
// " -x, --proxy [proxy1,[...,[proxyN,]]]<address>\n"
// " run proxy forwarding instead of SOCKS\n"
// " --nameserver <address> ignore resolv.conf\n"
#if WITH_NETDEVICE
" -i, --netdev <name> bind outgoing connections to network device\n"
#endif
Expand Down
Loading

0 comments on commit 76dbbad

Please sign in to comment.