aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPieter Wuille <pieter.wuille@gmail.com>2012-04-01 20:25:48 +0200
committerPieter Wuille <pieter.wuille@gmail.com>2012-05-04 16:11:54 +0200
commit60a87bce873ce1f76a80b7b8546e83a0cd4e07a5 (patch)
tree524dc5f42db387f3916c2d3240defe2cf78373c4
parent1210aa435f3518080e1b5e2f79397ff68c4978d0 (diff)
SOCKS5 support by default
Add -socks=<n> to select SOCKS version to use. 4 and 5 are supported, 5 is default.
-rw-r--r--src/init.cpp3
-rw-r--r--src/netbase.cpp195
2 files changed, 169 insertions, 29 deletions
diff --git a/src/init.cpp b/src/init.cpp
index 3fe6d1b091..aa1399f813 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -178,7 +178,8 @@ bool AppInit2(int argc, char* argv[])
" -dbcache=<n> \t\t " + _("Set database cache size in megabytes (default: 25)") + "\n" +
" -dblogsize=<n> \t\t " + _("Set database disk log size in megabytes (default: 100)") + "\n" +
" -timeout=<n> \t " + _("Specify connection timeout (in milliseconds)") + "\n" +
- " -proxy=<ip:port> \t " + _("Connect through socks4 proxy") + "\n" +
+ " -proxy=<ip:port> \t " + _("Connect through socks proxy") + "\n" +
+ " -socks=<n> \t " + _("Select the version of socks proxy to use (4 or 5, 5 is default)") + "\n" +
" -dns \t " + _("Allow DNS lookups for addnode and connect") + "\n" +
" -port=<port> \t\t " + _("Listen for connections on <port> (default: 8333 or testnet: 18333)") + "\n" +
" -maxconnections=<n>\t " + _("Maintain at most <n> connections to peers (default: 125)") + "\n" +
diff --git a/src/netbase.cpp b/src/netbase.cpp
index 8b30ffc140..3c818f76f5 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -156,6 +156,161 @@ bool LookupNumeric(const char *pszName, CService& addr, int portDefault)
return Lookup(pszName, addr, portDefault, false);
}
+bool static Socks4(const CService &addrDest, SOCKET& hSocket)
+{
+ printf("SOCKS4 connecting %s\n", addrDest.ToString().c_str());
+ if (!addrDest.IsIPv4())
+ {
+ closesocket(hSocket);
+ return error("Proxy destination is not IPv4");
+ }
+ char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user";
+ struct sockaddr_in addr;
+ addrDest.GetSockAddr(&addr);
+ memcpy(pszSocks4IP + 2, &addr.sin_port, 2);
+ memcpy(pszSocks4IP + 4, &addr.sin_addr, 4);
+ char* pszSocks4 = pszSocks4IP;
+ int nSize = sizeof(pszSocks4IP);
+
+ int ret = send(hSocket, pszSocks4, nSize, MSG_NOSIGNAL);
+ if (ret != nSize)
+ {
+ closesocket(hSocket);
+ return error("Error sending to proxy");
+ }
+ char pchRet[8];
+ if (recv(hSocket, pchRet, 8, 0) != 8)
+ {
+ closesocket(hSocket);
+ return error("Error reading proxy response");
+ }
+ if (pchRet[1] != 0x5a)
+ {
+ closesocket(hSocket);
+ if (pchRet[1] != 0x5b)
+ printf("ERROR: Proxy returned error %d\n", pchRet[1]);
+ return false;
+ }
+ printf("SOCKS4 connected %s\n", addrDest.ToString().c_str());
+ return true;
+}
+
+bool static Socks5(const CService &addrDest, SOCKET& hSocket)
+{
+ printf("SOCKS5 connecting %s\n", addrDest.ToString().c_str());
+ char pszSocks5Init[] = "\5\1\0";
+ char *pszSocks5 = pszSocks5Init;
+ int nSize = sizeof(pszSocks5Init);
+
+ int ret = send(hSocket, pszSocks5, nSize, MSG_NOSIGNAL);
+ if (ret != nSize)
+ {
+ closesocket(hSocket);
+ return error("Error sending to proxy");
+ }
+ char pchRet1[2];
+ if (recv(hSocket, pchRet1, 2, 0) != 2)
+ {
+ closesocket(hSocket);
+ return error("Error reading proxy response");
+ }
+ if (pchRet1[0] != 0x05 || pchRet1[1] != 0x00)
+ {
+ closesocket(hSocket);
+ return error("Proxy failed to initialize");
+ }
+ char pszSocks5IPv4[] = "\5\1\0\1\0\0\0\0\0\0";
+ char pszSocks5IPv6[] = "\5\1\0\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
+ if (addrDest.IsIPv4())
+ {
+ struct sockaddr_in addr;
+ addrDest.GetSockAddr(&addr);
+ memcpy(pszSocks5IPv4 + 4, &addr.sin_addr, 4);
+ memcpy(pszSocks5IPv4 + 8, &addr.sin_port, 2);
+ pszSocks5 = pszSocks5IPv4;
+ nSize = sizeof(pszSocks5IPv4);
+ }
+ else
+ {
+#ifdef USE_IPV6
+ struct sockaddr_in6 addr;
+ addrDest.GetSockAddr6(&addr);
+ memcpy(pszSocks5IPv6 + 4, &addr.sin6_addr, 16);
+ memcpy(pszSocks5IPv6 + 20, &addr.sin6_port, 2);
+ pszSocks5 = pszSocks5IPv6;
+ nSize = sizeof(pszSocks5IPv6);
+#else
+ return error("IPv6 support is not compiled in");
+#endif
+ }
+ ret = send(hSocket, pszSocks5, nSize, MSG_NOSIGNAL);
+ if (ret != nSize)
+ {
+ closesocket(hSocket);
+ return error("Error sending to proxy");
+ }
+ char pchRet2[4];
+ if (recv(hSocket, pchRet2, 4, 0) != 4)
+ {
+ closesocket(hSocket);
+ return error("Error reading proxy response");
+ }
+ if (pchRet2[0] != 0x05)
+ {
+ closesocket(hSocket);
+ return error("Proxy failed to accept request");
+ }
+ if (pchRet2[1] != 0x00)
+ {
+ closesocket(hSocket);
+ switch (pchRet2[1])
+ {
+ case 0x01: return error("Proxy error: general failure");
+ case 0x02: return error("Proxy error: connection not allowed");
+ case 0x03: return error("Proxy error: network unreachable");
+ case 0x04: return error("Proxy error: host unreachable");
+ case 0x05: return error("Proxy error: connection refused");
+ case 0x06: return error("Proxy error: TTL expired");
+ case 0x07: return error("Proxy error: protocol error");
+ case 0x08: return error("Proxy error: address type not supported");
+ default: return error("Proxy error: unknown");
+ }
+ }
+ if (pchRet2[2] != 0x00)
+ {
+ closesocket(hSocket);
+ return error("Error: malformed proxy response");
+ }
+ char pchRet3[256];
+ switch (pchRet2[3])
+ {
+ case 0x01: ret = recv(hSocket, pchRet3, 4, 0) != 4; break;
+ case 0x04: ret = recv(hSocket, pchRet3, 16, 0) != 16; break;
+ case 0x03:
+ {
+ ret = recv(hSocket, pchRet3, 1, 0) != 1;
+ if (ret)
+ return error("Error reading from proxy");
+ int nRecv = pchRet3[0];
+ ret = recv(hSocket, pchRet3, nRecv, 0) != nRecv;
+ break;
+ }
+ default: closesocket(hSocket); return error("Error: malformed proxy response");
+ }
+ if (ret)
+ {
+ closesocket(hSocket);
+ return error("Error reading from proxy");
+ }
+ if (recv(hSocket, pchRet3, 2, 0) != 2)
+ {
+ closesocket(hSocket);
+ return error("Error reading from proxy");
+ }
+ printf("SOCKS5 connected %s\n", addrDest.ToString().c_str());
+ return true;
+}
+
bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout)
{
hSocketRet = INVALID_SOCKET;
@@ -260,35 +415,19 @@ bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout)
if (fProxy)
{
- printf("proxy connecting %s\n", addrDest.ToString().c_str());
- char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user";
- struct sockaddr_in addr;
- addrDest.GetSockAddr(&addr);
- memcpy(pszSocks4IP + 2, &addr.sin_port, 2);
- memcpy(pszSocks4IP + 4, &addr.sin_addr, 4);
- char* pszSocks4 = pszSocks4IP;
- int nSize = sizeof(pszSocks4IP);
-
- int ret = send(hSocket, pszSocks4, nSize, MSG_NOSIGNAL);
- if (ret != nSize)
- {
- closesocket(hSocket);
- return error("Error sending to proxy");
- }
- char pchRet[8];
- if (recv(hSocket, pchRet, 8, 0) != 8)
- {
- closesocket(hSocket);
- return error("Error reading proxy response");
- }
- if (pchRet[1] != 0x5a)
+ switch(GetArg("-socks", 5))
{
- closesocket(hSocket);
- if (pchRet[1] != 0x5b)
- printf("ERROR: Proxy returned error %d\n", pchRet[1]);
- return false;
- }
- printf("proxy connected %s\n", addrDest.ToString().c_str());
+ case 4:
+ if (!Socks4(addrDest, hSocket))
+ return false;
+ break;
+
+ case 5:
+ default:
+ if (!Socks5(addrDest, hSocket))
+ return false;
+ break;
+ }
}
hSocketRet = hSocket;