Browse Source

Validate SOCKS5 authentication and destination addresses

proxy
evgeny 3 days ago
parent
commit
10b66e2ad0
  1. 29
      src/proxy/socks_proxy.c

29
src/proxy/socks_proxy.c

@ -130,9 +130,18 @@ static int write_to_client(struct socks_proxy_conn* c, const uint8_t* data, uint
// SOCKS5 handshake // SOCKS5 handshake
// ==================================================================== // ====================================================================
static void process_socks_greeting(struct socks_proxy_conn* c) { static void process_socks_greeting(struct socks_proxy_conn* c) {
if (c->buf_len < 3) return; if (c->buf_len < 2) return;
uint8_t ver = c->buf[0], nmethods = c->buf[1]; uint8_t ver = c->buf[0], nmethods = c->buf[1];
if (ver != 5 || c->buf_len < (uint16_t)(2 + nmethods)) return; if (ver != 5 || !nmethods) {
DEBUG_WARN(DEBUG_CATEGORY_PROXY, "socks_proxy: invalid greeting sid=%08x ver=%u methods=%u", c->stream_id, ver, nmethods);
c->rem_closed = 1; tcp_conn_push_close(c->tc); return;
}
if (c->buf_len < (uint16_t)(2 + nmethods)) return;
if (!memchr(c->buf + 2, 0, nmethods)) {
uint8_t reject[] = {5, 255};
DEBUG_WARN(DEBUG_CATEGORY_PROXY, "socks_proxy: no supported authentication sid=%08x", c->stream_id);
write_to_client(c, reject, sizeof(reject)); c->rem_closed = 1; tcp_conn_push_close(c->tc); return;
}
DEBUG_DEBUG(DEBUG_CATEGORY_PROXY, "socks_proxy: greeting ver=%d nmethods=%d", ver, nmethods); DEBUG_DEBUG(DEBUG_CATEGORY_PROXY, "socks_proxy: greeting ver=%d nmethods=%d", ver, nmethods);
uint8_t reply[] = { 0x05, 0x00 }; uint8_t reply[] = { 0x05, 0x00 };
write_to_client(c, reply, 2); write_to_client(c, reply, 2);
@ -141,15 +150,16 @@ static void process_socks_greeting(struct socks_proxy_conn* c) {
} }
static void process_socks_request(struct socks_proxy_conn* c) { static void process_socks_request(struct socks_proxy_conn* c) {
if (c->buf_len < 10) return; if (c->buf_len < 4) return;
uint8_t ver = c->buf[0], cmd = c->buf[1], atyp = c->buf[3]; uint8_t ver = c->buf[0], cmd = c->buf[1], atyp = c->buf[3];
if (ver != 5) { DEBUG_ERROR(DEBUG_CATEGORY_PROXY, "socks_proxy: bad ver=%d", ver); goto error; } if (ver != 5 || c->buf[2] != 0) { DEBUG_ERROR(DEBUG_CATEGORY_PROXY, "socks_proxy: bad ver=%d", ver); goto error; }
if (cmd != 1) { DEBUG_ERROR(DEBUG_CATEGORY_PROXY, "socks_proxy: unsupported cmd=%d (only CONNECT supported)", cmd); goto error; } if (cmd != 1) { DEBUG_ERROR(DEBUG_CATEGORY_PROXY, "socks_proxy: unsupported cmd=%d (only CONNECT supported)", cmd); goto error; }
uint16_t need; uint16_t need;
if (atyp == 1) need = 10; // IPv4: 4+2=6 more bytes if (atyp == 1) need = 10; // IPv4: 4+2=6 more bytes
else if (atyp == 3) { // domain: 1+len+2 else if (atyp == 3) { // domain: 1+len+2
if (c->buf_len < 5) return; if (c->buf_len < 5) return;
if (!c->buf[4]) { DEBUG_WARN(DEBUG_CATEGORY_PROXY, "socks_proxy: empty domain"); goto error; }
need = (uint16_t)(5 + c->buf[4] + 2); need = (uint16_t)(5 + c->buf[4] + 2);
} }
else if (atyp == 4) need = 22; // IPv6: 16+2=18 more else if (atyp == 4) need = 22; // IPv6: 16+2=18 more
@ -164,14 +174,9 @@ static void process_socks_request(struct socks_proxy_conn* c) {
socks_finalize(c); socks_finalize(c);
return; return;
} else if (atyp == 4) { } else if (atyp == 4) {
// Извлекаем первые 4 байта IPv6 в dest_ip (для упрощения: IPv6 mapped IPv4 или реальный IPv6) uint8_t reply[] = {5, 8, 0, 1, 0, 0, 0, 0, 0, 0};
memcpy(c->dest_ip, c->buf + 12, 4); DEBUG_WARN(DEBUG_CATEGORY_PROXY, "socks_proxy: IPv6 destination unsupported sid=%08x", c->stream_id);
memcpy(&c->dest_port, c->buf + 20, 2); write_to_client(c, reply, sizeof(reply)); c->rem_closed = 1; tcp_conn_push_close(c->tc); return;
// TODO: proper IPv6 support
DEBUG_ERROR(DEBUG_CATEGORY_PROXY, "socks_proxy: IPv6 unsupported, using last 4 bytes of addr");
c->buf_len = 0;
socks_finalize(c);
return;
} }
// atyp == 3 (domain) // atyp == 3 (domain)

Loading…
Cancel
Save