diff --git a/README b/README index 0abac0df..4fadbcfd 100644 --- a/README +++ b/README @@ -185,7 +185,7 @@ Options for both config file and command line: --scrypt Use the scrypt algorithm for mining (litecoin only) --sharelog Append share log to file --shares Quit after mining N shares (default: unlimited) ---socks-proxy Set socks proxy (host:port) for all pools without a proxy specified +--socks-proxy Set socks4 proxy (host:port) for all pools without a proxy specified --syslog Use system log for output messages (default: standard error) --temp-cutoff Temperature where a device will be automatically disabled, one value or comma separated list (default: 95) --text-only|-T Disable ncurses formatted screen output diff --git a/cgminer.c b/cgminer.c index 54e1db7c..786e8267 100644 --- a/cgminer.c +++ b/cgminer.c @@ -1288,7 +1288,7 @@ static struct opt_table opt_config_table[] = { "Quit after mining N shares (default: unlimited)"), OPT_WITH_ARG("--socks-proxy", opt_set_charp, NULL, &opt_socks_proxy, - "Set socks proxy (host:port)"), + "Set socks4 proxy (host:port)"), #ifdef HAVE_SYSLOG_H OPT_WITHOUT_ARG("--syslog", opt_set_bool, &use_syslog, diff --git a/util.c b/util.c index 52ab46b2..fc488a49 100644 --- a/util.c +++ b/util.c @@ -347,7 +347,7 @@ json_t *json_rpc_call(CURL *curl, const char *url, curl_easy_setopt(curl, CURLOPT_PROXYTYPE, pool->rpc_proxytype); } else if (opt_socks_proxy) { curl_easy_setopt(curl, CURLOPT_PROXY, opt_socks_proxy); - curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); + curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4); } if (userpass) { curl_easy_setopt(curl, CURLOPT_USERPWD, userpass); @@ -1851,9 +1851,83 @@ static bool socks5_negotiate(struct pool *pool, int sockd) return true; } +static bool socks4_negotiate(struct pool *pool, int sockd, bool socks4a) +{ + unsigned short port; + in_addr_t inp; + char buf[515]; + int i, len; + + buf[0] = 0x04; + buf[1] = 0x01; + port = atoi(pool->stratum_port); + buf[2] = port >> 8; + buf[3] = port & 0xff; + sprintf(&buf[8], "CGMINER"); + + /* See if we've been given an IP address directly to avoid needing to + * resolve it. */ + inp = inet_network(pool->sockaddr_url); + if ((int)inp != -1) + socks4a = false; + else { + /* Try to extract the IP address ourselves first */ + struct addrinfo servinfobase, *servinfo, hints; + + servinfo = &servinfobase; + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_INET; /* IPV4 only */ + if (!getaddrinfo(pool->sockaddr_url, NULL, &hints, &servinfo)) { + struct sockaddr_in *saddr_in = (struct sockaddr_in *)servinfo->ai_addr; + + inp = ntohl(saddr_in->sin_addr.s_addr); + socks4a = false; + freeaddrinfo(servinfo); + } + } + + if (!socks4a) { + if ((int)inp == -1) { + applog(LOG_WARNING, "Invalid IP address specified for socks4 proxy: %s", + pool->sockaddr_url); + return false; + } + buf[4] = (inp >> 24) & 0xFF; + buf[5] = (inp >> 16) & 0xFF; + buf[6] = (inp >> 8) & 0xFF; + buf[7] = (inp >> 0) & 0xFF; + send(sockd, buf, 16, 0); + } else { + /* This appears to not be working but hopefully most will be + * able to resolve IP addresses themselves. */ + buf[4] = 0; + buf[5] = 0; + buf[6] = 0; + buf[7] = 1; + len = strlen(pool->sockaddr_url); + if (len > 255) + len = 255; + memcpy(&buf[16], pool->sockaddr_url, len); + len += 16; + buf[len++] = '\0'; + send(sockd, buf, len, 0); + } + + if (recv_byte(sockd) != 0x00 || recv_byte(sockd) != 0x5a) { + applog(LOG_WARNING, "Bad response from %s:%s SOCKS4 server", + pool->sockaddr_proxy_url, pool->sockaddr_proxy_port); + return false; + } + + for (i = 0; i < 6; i++) + recv_byte(sockd); + + return true; +} + static bool setup_stratum_socket(struct pool *pool) { - struct addrinfo servinfobase, *servinfo, *hints, pbase, *p; + struct addrinfo servinfobase, *servinfo, *hints, *p; char *sockaddr_url, *sockaddr_port; int sockd; @@ -1869,7 +1943,7 @@ static bool setup_stratum_socket(struct pool *pool) hints->ai_family = AF_UNSPEC; hints->ai_socktype = SOCK_STREAM; servinfo = &servinfobase; - p = &pbase; + if (!pool->rpc_proxy && opt_socks_proxy) { pool->rpc_proxy = opt_socks_proxy; extract_sockaddr(pool->rpc_proxy, &pool->sockaddr_proxy_url, &pool->sockaddr_proxy_port); @@ -1933,6 +2007,14 @@ static bool setup_stratum_socket(struct pool *pool) if (!socks5_negotiate(pool, sockd)) return false; break; + case CURLPROXY_SOCKS4: + if (!socks4_negotiate(pool, sockd, false)) + return false; + break; + case CURLPROXY_SOCKS4A: + if (!socks4_negotiate(pool, sockd, true)) + return false; + break; default: applog(LOG_WARNING, "Unsupported proxy type for %s:%s", pool->sockaddr_proxy_url, pool->sockaddr_proxy_port);