C++ HTTP over SOCKS5 (TOR) 400 Bad Request
I have working C++ code getting the HTML source of a specific website. One function creates the HTTP Request and other functions send it.
But when I try to access the website the same way, except with TOR (SOCKS5), I'm getting HTTP 400 Bad Request response
. The request is identical both times, and I can see it is correct via Wiresahrk/debugging.
It seems like TOR may be messing something up, but other tools that need to send HTTP/HTTPS Requests over TOR seem to work correctly.
Here are some snippets of my code:
Main
int main(int argc, const char * argv[]) {
bool use_tor = false;
if(argc < 3){
std::cout << "[!] Please supply a url and 0 for no tor or 1 for tor." << std::endl;
return -1;
}
if(strcmp(argv[2],"1")==0){
use_tor = true;
}
int sock = createSocket();
if(use_tor){
SOCKS5_Greeting_Response socks_gresp;
SOCKS5_Command_Response socks_cresp;
socketConnect(sock, "127.0.0.1", 9050);
socks_gresp = socketWriteSOCKS5Greeting_TOR(sock);
if(socks_gresp.Version != 5){
std::cout << std::endl << "[!] SOCKS5 Version mismatch!" << std::endl;
closeSocket(sock);
return -1;
}
socks_cresp = SOCKS5_Connect(sock, get_IPv4(argv[1]), 80);
if(socks_cresp.Reply != 0){
std::cout << std::endl << "[!] SOCKS5 Connection failed!" << std::endl;
closeSocket(sock);
return -1;
}
}
else{
socketConnect(sock, argv[1], 80);
}
socketWrite(sock, generate_basic_GET_request("url","UA",""));
socketRead(sock)
closeSocket(sock);
}
http stuff
std::string generate_basic_GET_request(std::string url, std::string UA, std::string Cookie){
splitted_host info = parse_host(url);
std::string request;
request = "GET " + info.GET + " HTTP/1.1rn";
request = request + "Host: " + info.Host + "rn";
request = request + "User-Agent: " + UA + "rn";
request = request + "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8rn";
request = request + "Accept-Language: en-US;q=0.7,en;q=0.3rn";
if(Cookie != ""){
request = request + "Cookie: " + Cookie + "rn";
}
request = request + "Connection: closernrn";
std::cout << std::endl << request << "----END-----" << std::endl << std::endl;
return request;
}
This is the output of my code:
GET / HTTP/1.1
Host: www.host.de
User-Agent: UA
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US;q=0.7,en;q=0.3
Connection: close
----END-----
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>400 Bad Request</title>
</head><body>
<h1>Bad Request</h1>
<p>Your browser sent a request that this server could not understand.<br />
</p>
</body></html>
Here is a picture of the request in Wireshark:
As i sayed, with exactly the same functions, just without the SOCKS5 proxy, i can get the HTML source just as it should work.
Some news on this:
I'll post my SOCKS5 Code below, but first things first.
I setup portforwarding and connected to myself, listening on an 'ncat -vvl 80' and was able to receive the send header either with or without the SOCKS5 proxy. The header looked correct, so all should be fine.
Now I know that I actually can connect successfully to the SOCKS5 proxy; the proxy connects to the desired website and sends the data. Thats not the problem. As the header arrives as it should be, I really have no idea why this 400 bad request error happens. Since exactly the same header is working with a direct connection, and the proxy is not the problem, this error shouldn't be happening.
The same error happens when using some of those free SOCKS5 proxies from the public lists that you can find on Google. So it must be something with my SOCKS5 code.
But as it IS happening, something MUST be wrong. I hope someone can find it!
Here is my code (and yes it's not perfect and sometimes not the best way of implementation):
struct SOCKS5_Greeting{
unsigned char Version;
unsigned char NumberOfMethods;
unsigned char Methods[256];
};
struct SOCKS5_Greeting_Response{
unsigned char Version;
unsigned char Method;
};
struct SOCKS5_Command{
unsigned char Version;
unsigned char Cmd;
unsigned char Reserved = 0x00;
unsigned char AddrType;
union{
in_addr_t IPv4;
} DestAddr;
unsigned short DestPort;
};
struct SOCKS5_Command_Response{
unsigned char Version;
unsigned char Reply;
unsigned char Reserved = 0x00;
unsigned char AddrType;
union{
in_addr_t IPv4;
} BindAddr;
unsigned short BindPort;
};
SOCKS5_Greeting_Response socketWriteSOCKS5Greeting_TOR(int sock){
SOCKS5_Greeting req;
SOCKS5_Greeting_Response resp;
req.Version = 5;
req.NumberOfMethods = 1;
req.Methods[0] = 0x00; //No Auth
send(sock, &req, 2+req.NumberOfMethods, 0);
recv(sock, &resp, sizeof(resp), 0);
return resp;
}
SOCKS5_Command_Response SOCKS5_Connect(int sock, std::string dest_str, unsigned short port){
SOCKS5_Command req;
SOCKS5_Command_Response resp;
in_addr_t dest = inet_addr(dest_str.c_str());
req.Version = 5;
req.Cmd = 1;
req.AddrType = 1;
req.DestAddr.IPv4 = dest;
req.DestPort = htons(port);
send(sock, &req, sizeof(req), 0);
recv(sock, &resp, sizeof(resp), 0);
return resp;
}
int createSocket(){
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
return sockfd;
}
void closeSocket(int sock){
close(sock);
}
int socketConnect(int sock, const char *address, int port){
struct hostent *server;
struct sockaddr_in serv_addr;
server = gethostbyname(address);
if(server == NULL){
return -1;
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
serv_addr.sin_port = htons(port);
if(connect(sock,(struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0){
return -1;
}
else{
return 0;
}
}
int socketWrite(int sock, std::string data){
char buffer[512];
int error;
std::string chunk;
if(data.length() > 511){
while(data.length() > 0){
if(data.length() >= 511){
chunk = data.substr(0, 511);
data = data.substr(511, data.length());
}
else{
chunk = data;
data = "";
}
bzero(buffer, 512);
chunk.copy(buffer, chunk.length());
error = write(sock, buffer, strlen(buffer));
if(error < 0){
return error;
}
}
}
else{
bzero(buffer, 512);
data.copy(buffer, 512);
error = write(sock, buffer, strlen(buffer));
}
return error;
}
std::string socketRead(int sock){
std::string response = "";
char buffer[512];
int bytes;
while((bytes = read(sock, buffer, 511)) > 0){
std::string temp(buffer, bytes);
response = response + temp;
bzero(buffer, 512);
}
return response;
}
UPDATE 2:
Just another update. Without changing anything in my code, I reran my program, and now it seems to work for most sites, although I sometimes get the following response:
HTTP/1.1 501 Not Implemented
Date: Sat, 06 Feb 2016 21:43:08 GMT
Server: Apache
Allow: OPTIONS,GET,HEAD,POST
Vary: Accept-Encoding
Content-Length: 240
Content-Type: text/html; charset=iso-8859-1
Connection: close
This actually makes this even more strange...
Another update: Now it's no longer working, 400 bad request, 1 minute after it seemed to work. I don't get it...
Just another Update: I set up port forwarding, opened a port via ncat (nmap tools), monitored the outgoing request on lo0 (to TOR's socks5 proxy port) with Wireshark, and the incoming on en1 with tcpdump, and they are both exactly the same, byte-for-byte. So the problem does not rely on TOR or the socks5 proxy. The request arrives as it should and as it is send, but produces a 400 bad request.
Just as the whole world of server knew im behind the proxy and blocking me...
Another Update, maybe the most important one: Apache in debug erro_log reports: AH00566: request failed: invalid characters in URI
But again, looking at the request/response, there are no invalid characters...
链接地址: http://www.djcxy.com/p/62650.html