If you replace the winsock initialization code and cleanup code and the WSAGetLastError() function with the linux equivalents the code will run fine under linux, Will post up when I get around to it.
[DIR = ./]
[FILE = ./main.cpp]
#include <iostream>
#include "socksHandler/sHandler.h"
#include <winsock2.h>
#include <vector>
using namespace std;
int main()
{
cout << "Binary SOCKS5 Server V 0.1b" <<endl;
cout <<"Currently only supports TCP connections with the Connect command." <<endl;
WSAData wsaData;
struct sockaddr_in server;
int sockErr;
int accSocket;
unsigned short listenPort = 6666;
FD_SET constSet;
FD_SET retSet;
timeval waitTime;
int socksRdy;
bool running = true;
vector<sHandler*> users;
int tmpSocket;
sockErr = WSAStartup(MAKEWORD(2,2),&wsaData);
if (sockErr == SOCKET_ERROR)
{
cerr <<"ERROR : " <<WSAGetLastError();
return -1;
}
accSocket = socket(AF_INET,SOCK_STREAM,0);
if (accSocket == SOCKET_ERROR)
{
cerr <<"ERROR: " <<WSAGetLastError();
return -2;
}
server.sin_family = AF_INET;
server.sin_port = htons(listenPort);
server.sin_addr.s_addr = INADDR_ANY;
sockErr = bind(accSocket,(sockaddr*)&server,sizeof(server));
if (sockErr == SOCKET_ERROR)
{
cerr <<"Error: Unable to bind Socket: " <<WSAGetLastError() <<endl;
return -3;
}
sockErr = listen(accSocket,10);
if (sockErr == SOCKET_ERROR)
{
cerr <<"Unable to listen on socket: " <<WSAGetLastError() <<endl;
return -4;
}
waitTime.tv_sec = 0;
waitTime.tv_usec = 0;
FD_ZERO(&constSet);
FD_ZERO(&retSet);
FD_SET(accSocket,&constSet);
retSet = constSet;
while(running)
{
retSet = constSet;
socksRdy = select(retSet.fd_count,&retSet,NULL,NULL,&waitTime);
if (socksRdy == SOCKET_ERROR)
{
running = false;
int er = WSAGetLastError();
cerr <<"Unable to select() sockets: " <<er <<endl;
if (er == WSAEINTR)
{
cout <<"WSAEINTR" <<endl;
}
cerr <<"socksRdy = " <<socksRdy <<endl;
return -5;
}
if (retSet.fd_count > 0)
{
cout <<"Accepted User" <<endl;
tmpSocket = accept(accSocket,0,0);
sHandler *usr = new sHandler(tmpSocket);
users.push_back(usr);
}
for(int i = 0; i< users.size();i++)
{
if (users[i]->active)
users[i]->m_HandleTransfers();
else
{
sHandler *tmpHandler;
vector<sHandler*>::iterator it;
for (it = users.begin(); it < users.end(); it++)
{
if ((*it)->unique_id == users[i]->unique_id)
{
tmpHandler = users[i];
users.erase(it);
break;
}
}
delete tmpHandler;
}
}
}
closesocket(accSocket);
WSACleanup();
return 0;
}
[DIR = ./socksHandler/]
[FILE = ./socksHandler/sAuthReply.cpp]
#include "sAuthReply.h"
sAuthReply::sAuthReply()
{
this->m_cMethod = '\0';
this->m_cVer = S_VER;
}
sAuthReply::~sAuthReply()
{
}
[FILE = ./socksHandler/sAuthReply.h]
#ifndef SAUTHREPLY_H_INCLUDED
#define SAUTHREPLY_H_INCLUDED
#include "sProto.h"
class sAuthReply {
public:
sAuthReply();
~sAuthReply();
char m_cVer;
char m_cMethod;
};
#endif // SAUTHREPLY_H_INCLUDED
[FILE = ./socksHandler/sAuthRequest.cpp]
#include "sAuthRequest.h"
sAuthRequest::sAuthRequest()
{
this->m_cNumMethods = '\0';
this->m_cVer = S_VER;
memset(this->m_szMethods,0,sizeof(this->m_szMethods));
}
sAuthRequest::~sAuthRequest()
{
}
[FILE = ./socksHandler/sAuthRequest.h]
#ifndef SAUTHREQUEST_H_INCLUDED
#define SAUTHREQUEST_H_INCLUDED
#include "sProto.h"
#include <cstring>
class sAuthRequest
{
public:
sAuthRequest();
~sAuthRequest();
char m_cVer;
char m_cNumMethods;
char m_szMethods[256];
};
#endif // SAUTHREQUEST_H_INCLUDED
[FILE = ./socksHandler/sHandler.cpp]
#include "sHandler.h"
unsigned int sHandler::g_id = 0;
sHandler::sHandler(int clientSocket)
{
this->isAuthed = false;
this->isConnected = false;
this->usrSocket = clientSocket;
this->dstSocket = socket(AF_INET,SOCK_STREAM,0);
memset(tmpBuffer,0,256);
FD_ZERO(&this->allSocks);
FD_ZERO(&this->rdySocks);
authRequest = new sAuthRequest();
authReply = new sAuthReply();
request = new sRequest();
reply = new sReply();
this->active = true;
unique_id = sHandler::g_id++;
tmpSize = '\0';
rdyCount = 0;
waitTime.tv_sec = 0;
waitTime.tv_usec = 0;
memset(&locallyBoundInfo,0,sizeof(sockaddr));
}
sHandler::~sHandler()
{
if (this->dstSocket != 0)
{
closesocket(this->dstSocket);
}
closesocket(this->usrSocket);
delete authRequest;
delete authReply;
delete request;
delete reply;
cout <<"Deleted" <<endl;
}
void sHandler::m_HandleTransfers()
{
//This function is called in every one of the classes and allows us to transfer the data back and forth
;
if (!this->isAuthed)
{
if (!this->m_Validate())
{
this->active = false;
}
}
else
{
//Connected and Authorized now its time to connect to a server etc..
if (!this->m_HandleTunnel())
{
this->active = false;
}
}
}
//This function handles the authentication process, Currently this server does not support authentication
bool sHandler::m_Validate()
{
if (this->isAuthed)
{
return true;
}
else
{
//Handle the initial authentication of the client here
m_BytesRead = recv(usrSocket,(char*)&authRequest->m_cVer,1,0);
if ((this->m_BytesRead < 1) || (this->m_BytesRead == SOCKET_ERROR))
{
this->m_SockErr = WSAGetLastError();
cerr <<" Reading Version Error: " << this->m_SockErr <<endl;
cout <<"Recived: " <<authRequest->m_cVer <<endl;
cout <<"Bytes Read: " <<m_BytesRead;
return false;
}
else
{
m_BytesRead = recv(this->usrSocket,(char*)&authRequest->m_cNumMethods,1,0);
if ((this->m_BytesRead < 1) || ( this->m_BytesRead > 1))
{
this->m_SockErr = WSAGetLastError();
cerr <<"Reading numMethods Error: " <<this->m_SockErr <<endl;
return false;
}
m_BytesRead = recv(this->usrSocket,(char*)authRequest->m_szMethods,(int)authRequest->m_cNumMethods,0);
cout <<"Recieved " <<m_BytesRead <<"Bytes, expecting " <<(int)authRequest->m_cNumMethods <<endl;
cout <<authRequest->m_szMethods <<endl;
if (this->authRequest->m_cVer != S_VER)
{
this->authReply->m_cMethod = S_NO_OK_METHOD;
}
else
{
this->authReply->m_cMethod = S_NO_AUTH_REQ;
}
this->m_BytesRead = send(this->usrSocket,(char*)&this->authReply->m_cVer,1,0);
if (this->m_BytesRead < 1)
{
this->m_SockErr = WSAGetLastError();
cerr <<"Sending Version Error: " <<this->m_SockErr <<endl;
}
this->m_BytesRead = send(this->usrSocket,(char*)&this->authReply->m_cMethod,1,0);
if (this->m_BytesRead < 1)
{
this->m_SockErr = WSAGetLastError();
cerr <<"Sending Method Error: " <<this->m_SockErr <<endl;
}
cout <<"Connected Successfully to client, waiting CONNECT." <<endl;
//FINISHED AUTH
this->isAuthed = true;
return true;
}
}
}
void sHandler::m_HandleError()
{
cerr <<"Error Occurred: " <<WSAGetLastError();
}
//This function handles the data that will be passed between the usr and the target also it handles the CONNECT CMD
bool sHandler::m_HandleTunnel()
{
if (!isConnected)
{
//Not connected so we have to handle the CONNECT CMD
this->m_BytesRead = recv(this->usrSocket,(char*)&request->m_cVer,1,0);
if ((m_BytesRead < 1) || (m_BytesRead == SOCKET_ERROR))
{
m_HandleError();
return false;
}
if (request->m_cVer != S_VER)
{
cout <<"SOCKS VER: " <<request->m_cVer <<" : " <<(int)request->m_cVer <<endl;
return false;
}
this->m_BytesRead = recv(this->usrSocket,(char*)&request->m_cCmd,1,0);
if ((m_BytesRead < 1) || (m_BytesRead == SOCKET_ERROR))
{
m_HandleError();
return false;
}
cout <<"CMD: " <<(int)request->m_cCmd <<endl;
this->m_BytesRead = recv(this->usrSocket,(char*)&request->m_cReserved,1,0);
if ((m_BytesRead < 1) || (m_BytesRead == SOCKET_ERROR))
{
m_HandleError();
return false;
}
this->m_BytesRead = recv(this->usrSocket, (char*)&request->m_cAddrType,1,0);
if ((m_BytesRead < 1) || (m_BytesRead == SOCKET_ERROR))
{
m_HandleError();
return false;
}
cout <<"ADDR TYPE: " <<request->m_cAddrType <<" : " <<(int)request->m_cAddrType <<endl;
switch(this->request->m_cAddrType)
{
case S_REQ_ADDR_IPV4:
cout <<"Passed IPV4" <<endl;
this->m_BytesRead = recv(this->usrSocket,(char*)&request->m_szDestAddr,S_REQ_IPV4_SIZE,0);
if ((m_BytesRead < S_REQ_IPV4_SIZE) || (m_BytesRead == SOCKET_ERROR))
{
m_HandleError();
return false;
}
hostentry = gethostbyname(request->m_szDestAddr);
break;
case S_REQ_ADDR_IPV6:
cout <<"Passed IPV6 Address Type" <<endl;
this->m_BytesRead = recv(this->usrSocket,(char*)&request->m_szDestAddr,S_REQ_IPV6_SIZE,0);
if ((m_BytesRead < S_REQ_IPV6_SIZE) || (m_BytesRead == SOCKET_ERROR))
{
m_HandleError();
return false;
}
hostentry = gethostbyname(request->m_szDestAddr);
break;
case S_REQ_ADDR_DOMAIN:
m_BytesRead = recv(this->usrSocket,(char*)&this->tmpSize,1,0);
cout <<"tmpSize is " <<(int)this->tmpSize <<endl;
if ((m_BytesRead < 1) || (m_BytesRead == SOCKET_ERROR))
{
m_HandleError();
return false;
}
m_BytesRead = recv(this->usrSocket,(char*)request->m_szDestAddr,(int)tmpSize,0);
if ((m_BytesRead < (int)tmpSize) || (m_BytesRead == SOCKET_ERROR))
{
m_HandleError();
return false;
}
hostentry = gethostbyname(request->m_szDestAddr);
cout <<"request->m_szDestAddr = " <<request->m_szDestAddr <<endl;
if (hostentry == NULL)
{
cout <<"Unable to find host" <<endl;
return false;
}
break;
default:
cout <<"Unknown ADDR_TYPE: " <<request->m_cAddrType <<" : " <<(int)request->m_cAddrType <<endl;
return false;
break;
}
m_BytesRead = recv(this->usrSocket,(char*)request->m_szDestPort,2,0);
if ((m_BytesRead < 2) || (m_BytesRead == SOCKET_ERROR))
{
m_HandleError();
return false;
}
//Recived all the data needed to make the Connection
switch(request->m_cCmd)
{
case S_REQ_CONNECT:
cout <<"Connection request generated!" <<endl;
dstServer.sin_family = AF_INET;
dstServer.sin_addr.s_addr = *(unsigned long*)hostentry->h_addr;
dstServer.sin_port = (*(unsigned short*)&request->m_szDestPort[0]);
this->m_SockErr = connect(this->dstSocket,(sockaddr*)&dstServer,sizeof(dstServer));
if (this->m_SockErr == SOCKET_ERROR)
{
m_HandleError();
return false;
}
reply->m_cVer = S_VER;
reply->m_cReply = S_REPLY_OK;
reply->m_cReserved = S_RSV;
reply->m_cAddrType = S_REPLY_ADDR_IPV4;
localSize = sizeof(locallyBoundInfo);
if (getsockname(dstSocket,&locallyBoundInfo,&localSize))
{
cout <<"can't get locally bound info" <<endl;
}
cout <<"SA DATA " <<(int)locallyBoundInfo.sa_data <<endl;
memcpy(reply->m_szBindAddr,&locallyBoundInfo.sa_data+2,4);
memcpy(reply->m_szBindPort,&locallyBoundInfo.sa_data,2);
this->m_BytesRead = send(usrSocket,(char*)&reply->m_cVer,1,0);
if (this->m_BytesRead > 1)
{
cout <<"More bytes than expected sent!" <<endl;
}
this->m_BytesRead = send(usrSocket,(char*)&reply->m_cReply,1,0);
if (this->m_BytesRead > 1)
{
cout <<"More bytes than expected sent!" <<endl;
}
this->m_BytesRead = send(usrSocket,(char*)&reply->m_cReserved,1,0);
if (this->m_BytesRead > 1)
{
cout <<"More bytes than expected sent!" <<endl;
}
this->m_BytesRead = send(usrSocket,(char*)&reply->m_cAddrType,1,0);
if (this->m_BytesRead > 1)
{
cout <<"More bytes than expected sent!" <<endl;
}
this->m_BytesRead = send(usrSocket,(char*)&reply->m_szBindAddr,4,0);
cout <<"BIND: " <<reply->m_szBindAddr <<endl;
if (this->m_BytesRead > 4)
{
cout <<"More bytes than expected sent!" <<endl;
}
this->m_BytesRead = send(usrSocket,(char*)&reply->m_szBindPort,2,0);
if (this->m_BytesRead > 2)
{
cout <<"More bytes than expected sent!" <<endl;
}
cout <<"Connected!" <<endl;
cout <<"Tmp size is " <<(int)tmpSize <<endl;
this->isConnected = true;
FD_SET(dstSocket,&allSocks);
FD_SET(usrSocket,&allSocks);
cout <<"All Socks set to " <<allSocks.fd_count <<endl;
return true;
break;
case S_REQ_ADDR_DOMAIN:
cout <<"Domain Request Generated" <<endl;
break;
case S_REQ_BIND:
cout <<"Bind Request Generated" <<endl;
break;
default:
cout <<"Not yet handled Request" <<endl;
return false;
break;
}
}
else
{
//Relay Data between the sockets here
rdySocks = allSocks;
rdyCount = select(rdySocks.fd_count,&rdySocks,NULL,NULL,&waitTime);
if (rdyCount == SOCKET_ERROR)
{
m_HandleError();
cout <<"Select()" <<endl;
return false;
}
//cout <<rdyCount <<" sockets Ready" <<endl;
if (rdyCount > 0)
{
for (int i = 0; i < rdyCount; i++)
{
cout <<"reading from " <<i <<endl;
this->m_SockErr = recv(rdySocks.fd_array[i],this->tmpBuffer,256,0);
if (this->m_SockErr == SOCKET_ERROR)
{
if (WSAGetLastError() == WSAECONNRESET)
{
cout <<"Connection closed becuase WSACONNRESET" <<endl;
this->active = false;
}
else{
m_HandleError();
cout <<"recv[" <<i <<"]" <<endl;
}
}
if (this->m_SockErr == 0)
{
cout <<"Connection Closed BECUASE 0" <<endl;
this->active = false;
}
if (rdySocks.fd_array[i] == usrSocket)
{
cout <<"Recived from usrSocket" <<endl;
this->m_SockErr = send(dstSocket,this->tmpBuffer,m_SockErr,0);
cout <<"Sent to usrSocket" <<endl;
}
else
{
cout <<"Recieved From dstSocket" <<endl;
this->m_SockErr = send(usrSocket,this->tmpBuffer,m_SockErr,0);
cout <<"Send to usrSocket" <<endl;
}
memset(this->tmpBuffer,0,256);
}
}
return true;
}
}
[FILE = ./socksHandler/sHandler.h]
#ifndef SHANDLER_H_INCLUDED
#define SHANDLER_H_INCLUDED
#include "sProto.h"
#include "sAuthReply.h"
#include "sAuthRequest.h"
#include "sReply.h"
#include "sRequest.h"
#include "winsock2.h"
#include <iostream>
/* This class handles the SOCKS5 Protocol for an individual tunnel and controls what has happened etc.*/
using namespace std;
class sHandler {
public:
sHandler(int clientSocket);
~sHandler();
void m_HandleTransfers();
bool active;
static unsigned int g_id;
unsigned int unique_id;
private:
bool isConnected; //This will be used to tell if the connection was successful
int usrSocket; //The socket that initially requests the connection
int dstSocket; //The socket that will be used to make the connection
FD_SET allSocks;
FD_SET rdySocks;
struct timeval waitTime;
sRequest *request;
sReply *reply;
sAuthRequest *authRequest;
sAuthReply *authReply;
int m_SockErr;
int m_BytesRead;
bool isAuthed;
bool m_HandleTunnel();
bool m_Validate();
void m_HandleError();
struct hostent *hostentry;
struct sockaddr_in dstServer;
char tmpSize;
char tmpBuffer[256];
int rdyCount;
struct sockaddr locallyBoundInfo;
int localSize;
};
#endif // SHANDLER_H_INCLUDED
[FILE = ./socksHandler/sProto.h]
#ifndef SPROTO_H_INCLUDED
#define SPROTO_H_INCLUDED
//This file contains all of the SOCKS5 Protocol constants and will be included in just about every file.
//This is the SOCKS version and will always be 5 for a SOCKS5 server
#define S_VER 5
//These are the possible SOCKS 5 Server authentication methods
//This server will always use no auth but just for possible future expansion I'm including all the possible auth. methods
#define S_NO_AUTH_REQ 0
#define S_GSSAPI 1
#define S_USERPASS 2
#define S_IANA_ASS_BEG 3
#define S_IANA_ASS_END 127
#define S_PRIVATE_BEG 128
#define S_PRIVATE_END 254
#define S_NO_OK_METHOD 255
//These are the Request constants
#define S_REQ_CONNECT 1
#define S_REQ_BIND 2
#define S_REQ_UDP_ASSOC 3
#define S_REQ_ADDR_IPV4 1
#define S_REQ_ADDR_IPV6 4
#define S_REQ_ADDR_DOMAIN 3
#define S_REQ_IPV4_SIZE 4
#define S_REQ_IPV6_SIZE 16
//No define for domain b/c the 1st octect indicates the size of the domain that immediately follows, no terminating null
//RESERVED WILL ALWAYS BE \x00 So we define it
#define S_RSV 0
//These are the Reply constants that are used
#define S_REPLY_OK 0
#define S_REPLY_GENERAL_FAIL 1
#define S_REPLY_NOT_ALLOWED 2
#define S_REPLY_NET_UNREACHABLE 3
#define S_REPLY_HOST_UNREACHABLE 4
#define S_REPLY_CONN_REFUSED 5
#define S_REPLY_TTL_EXP 6
#define S_REPLY_CMD_NOT_SUPPORTED 7
#define S_REPLY_ADDR_NOT_SUPPORTED 8
#define S_REPLY_ADDR_IPV4 1
#define S_REPLY_ADDR_IPV6 4
#define S_REPLY_ADDR_DOMAIN 3
#endif // SPROTO_H_INCLUDED
[FILE = ./socksHandler/sReply.cpp]
#include "sReply.h"
sReply::sReply()
{
this->m_cAddrType = '\0';
this->m_cReply = '\0';
this->m_cReserved = S_RSV;
this->m_cVer = S_VER;
memset(this->m_szBindAddr,0,sizeof(this->m_szBindAddr));
memset(this->m_szBindPort,0,sizeof(this->m_szBindPort));
}
sReply::~sReply()
{
}
[FILE = ./socksHandler/sReply.h]
#ifndef SREPLY_H_INCLUDED
#define SREPLY_H_INCLUDED
#include "sProto.h"
#include <cstring>
class sReply
{
public:
sReply();
~sReply();
char m_cVer;
char m_cReply;
char m_cReserved;
char m_cAddrType;
char m_szBindAddr[256];
char m_szBindPort[2];
};
#endif // SREPLY_H_INCLUDED
[FILE = ./socksHandler/sRequest.cpp]
#include "sRequest.h"
sRequest::sRequest()
{
this->m_cAddrType = '\0';
this->m_cCmd = '\0';
this->m_cReserved = S_RSV;
this->m_cVer = S_VER;
memset(this->m_szDestAddr,0,256);
memset(this->m_szDestPort,0,2);
}
sRequest::~sRequest()
{
}
[FILE = ./socksHandler/sRequest.h]
#ifndef SREQUEST_H_INCLUDED
#define SREQUEST_H_INCLUDED
#include "sProto.h"
#include <cstring>
class sRequest {
public:
sRequest();
~sRequest();
char m_cVer;
char m_cCmd;
char m_cReserved;
char m_cAddrType;
char m_szDestAddr[256];
char m_szDestPort[2];
};
#endif // SREQUEST_H_INCLUDED