Add support for socks4/4a proxies with stratum, and drop back to socks4 support via the global --socks-proxy command to not break previous configurations.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
diff --git a/README b/README
index 0d48913..7997059 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 <arg> Append share log to file
--shares <arg> Quit after mining N shares (default: unlimited)
---socks-proxy <arg> Set socks proxy (host:port) for all pools without a proxy specified
+--socks-proxy <arg> Set socks4 proxy (host:port) for all pools without a proxy specified
--syslog Use system log for output messages (default: standard error)
--temp-cutoff <arg> 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 d2b7b15..2936eeb 100644
--- a/cgminer.c
+++ b/cgminer.c
@@ -1249,7 +1249,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 52ab46b..d49b09a 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,6 +1851,80 @@ 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;
@@ -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);