|
|
|
@ -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)
|
|
|
|
|