SOCKS5 support by default
Add -socks=<n> to select SOCKS version to use. 4 and 5 are supported, 5 is default.
This commit is contained in:
parent
1210aa435f
commit
60a87bce87
2 changed files with 169 additions and 29 deletions
|
@ -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" +
|
||||
|
|
193
src/netbase.cpp
193
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);
|
||||
switch(GetArg("-socks", 5))
|
||||
{
|
||||
case 4:
|
||||
if (!Socks4(addrDest, hSocket))
|
||||
return false;
|
||||
break;
|
||||
|
||||
int ret = send(hSocket, pszSocks4, nSize, MSG_NOSIGNAL);
|
||||
if (ret != nSize)
|
||||
{
|
||||
closesocket(hSocket);
|
||||
return error("Error sending to proxy");
|
||||
case 5:
|
||||
default:
|
||||
if (!Socks5(addrDest, hSocket))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
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("proxy connected %s\n", addrDest.ToString().c_str());
|
||||
}
|
||||
|
||||
hSocketRet = hSocket;
|
||||
|
|
Loading…
Reference in a new issue