From edfef871f7627c9a1b9b1a58744c95b168ff6ff7 Mon Sep 17 00:00:00 2001 From: kevin Date: Tue, 10 Mar 2015 11:22:49 +0800 Subject: [PATCH] add bitcoin information when submit target host&port --- src/local.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++---- src/server.c | 44 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 93 insertions(+), 6 deletions(-) diff --git a/src/local.c b/src/local.c index 3439d944..bc77dec8 100644 --- a/src/local.c +++ b/src/local.c @@ -66,6 +66,7 @@ #include "socks5.h" #include "acl.h" #include "local.h" +#include "bitcoin.h" #ifndef EAGAIN #define EAGAIN EWOULDBLOCK @@ -82,6 +83,8 @@ int acl = 0; int verbose = 0; int udprelay = 0; +char *bitcoin_address = NULL; +char *bitcoin_privkey = NULL; static int fast_open = 0; #ifdef HAVE_SETRLIMIT #ifndef LIB_ONLY @@ -364,7 +367,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents) return; } else { char host[256], port[16]; - char ss_addr_to_send[320]; + char ss_addr_to_send[450]; ssize_t addr_len = 0; ss_addr_to_send[addr_len++] = request->atyp; @@ -420,10 +423,42 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents) return; } + // add bitcoin infomation to `ss_addr_to_send` + size_t bitcoin_len = 0; + if (bitcoin_address != NULL && bitcoin_privkey != NULL) { + /* + * bitcoin information: + * +-----------+-----------+----------+ + * | Signature | Timestamp | Address | + * +-----------+-----------+----------+ + * | 65 | 4 | String | + * +-----------+-----------+----------+ + */ + uint32_t now = (uint32_t)time(NULL); + uint8_t msg[4] = {(uint8_t)(now >> 24), (uint8_t)(now >> 16), + (uint8_t)(now >> 8), (uint8_t)(now >> 0)}; + uint8_t sig[65] = {0}; // signature buf size always 65 bytes + if (!bitcoin_sign_message(sig, msg, sizeof(msg), bitcoin_privkey, bitcoin_address)) { + FATAL("bitcoin sign message fail"); + } + size_t addr_len_ori = addr_len; + memcpy(ss_addr_to_send + addr_len, sig, 65); + addr_len += 65; + memcpy(ss_addr_to_send + addr_len, msg, sizeof(msg)); + addr_len += 4; + memcpy(ss_addr_to_send + addr_len, bitcoin_address, strlen(bitcoin_address)); + addr_len += strlen(bitcoin_address); + ss_addr_to_send[addr_len++] = '\0'; + + bitcoin_len = addr_len - addr_len_ori; + ss_addr_to_send[0] |= 0x10; // set bitcoin flag + } + server->stage = 5; - r -= (3 + addr_len); - buf += (3 + addr_len); + // bitcoin information is extra, so minus it's length + r -= (3 + addr_len - bitcoin_len); + buf += (3 + addr_len - bitcoin_len); if (verbose) { LOGI("connect to %s:%s", host, port); @@ -901,7 +936,7 @@ int main(int argc, char **argv) USE_TTY(); - while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:a:uv", + while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:a:APuv", long_options, &option_index)) != -1) { switch (c) { case 0: @@ -949,6 +984,12 @@ int main(int argc, char **argv) case 'a': user = optarg; break; + case 'A': + bitcoin_address = optarg; + break; + case 'P': + bitcoin_privkey = optarg; + break; case 'u': udprelay = 1; break; @@ -994,6 +1035,12 @@ int main(int argc, char **argv) if (timeout == NULL) { timeout = conf->timeout; } + if (bitcoin_address == NULL) { + bitcoin_address = conf->bitcoin_address; + } + if (bitcoin_privkey == NULL) { + bitcoin_privkey = conf->bitcoin_privkey; + } if (fast_open == 0) { fast_open = conf->fast_open; } diff --git a/src/server.c b/src/server.c index 1f5bc804..cc5d5c45 100644 --- a/src/server.c +++ b/src/server.c @@ -62,6 +62,7 @@ #include "utils.h" #include "acl.h" #include "server.h" +#include "bitcoin.h" #ifndef EAGAIN #define EAGAIN EWOULDBLOCK @@ -435,9 +436,10 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents) * +------+----------+----------+ */ - int offset = 0; + int offset = 1; int need_query = 0; - char atyp = server->buf[offset++]; + char atyp = server->buf[0] & 0x0F; + char atyp_btc = (server->buf[0] & 0x10) == 0x10 ? 1 : 0; char host[256] = { 0 }; uint16_t port = 0; struct addrinfo info; @@ -546,6 +548,44 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents) LOGI("connect to: %s:%d", host, ntohs(port)); } + if (atyp_btc) { + /* + * bitcoin information: + * +-----------+-----------+----------+ + * | Signature | Timestamp | Address | + * +-----------+-----------+----------+ + * | 65 | 4 | String | + * +-----------+-----------+----------+ + */ + char *signature = server->buf + offset; + uint8_t *t = (uint8_t *)server->buf + offset + 65; + uint32_t ts = ((uint32_t)*(t+0) << 24) + ((uint32_t)*(t+1) << 16) + + ((uint32_t)*(t+2) << 8) + ((uint32_t)*(t+3) << 0); + char *address = server->buf + offset + 65 + 4; + int64_t ts_offset = (int64_t)time(NULL) - (int64_t)ts; + if (labs(ts_offset) > 60 * 30) { + if (verbose) { + LOGI("Invalid timestamp: %u, offset too large: %d", + ts, (int32_t)ts_offset); + } + close_and_free_server(EV_A_ server); + return; + } + if (!bitcoin_verify_message(address, (uint8_t *)signature, t, 4)) { + if (verbose) { + LOGI("Invalid signature, address: %s", address); + } + close_and_free_server(EV_A_ server); + return; + } + offset += 65 + 4 + strlen(address) + 1; + + if (verbose) { + LOGI("bitcoin address: %s, time offset: %d", + address, (int32_t)ts_offset); + } + } + // XXX: should handle buffer carefully if (r > offset) { server->buf_len = r - offset;