feat: add basic (unfinished) proxy
This commit is contained in:
@@ -0,0 +1,155 @@
|
|||||||
|
#include "proxy.h"
|
||||||
|
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <ws2tcpip.h>
|
||||||
|
|
||||||
|
#include <nerutils/log.h>
|
||||||
|
|
||||||
|
Proxy::Proxy() {}
|
||||||
|
|
||||||
|
Proxy::~Proxy() {}
|
||||||
|
|
||||||
|
bool Proxy::Init()
|
||||||
|
{
|
||||||
|
WSADATA wsaData;
|
||||||
|
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
|
||||||
|
{
|
||||||
|
Log::error("WSAStartup failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||||
|
if (_listenSocket == INVALID_SOCKET)
|
||||||
|
{
|
||||||
|
Log::error("Error creating listen socket: {0:x}", WSAGetLastError());
|
||||||
|
Shutdown();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sockaddr_in serverAddr;
|
||||||
|
serverAddr.sin_family = AF_INET;
|
||||||
|
serverAddr.sin_port = htons(PROXY_PORT);
|
||||||
|
inet_pton(AF_INET, "127.0.0.1", &serverAddr.sin_addr);
|
||||||
|
|
||||||
|
if (bind(_listenSocket, (sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR)
|
||||||
|
{
|
||||||
|
Log::error("Error binding listen socket: {0:x}", WSAGetLastError());
|
||||||
|
Shutdown();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
listen(_listenSocket, SOMAXCONN);
|
||||||
|
|
||||||
|
Log::verbose("Listening on 127.0.0.1:{}", PROXY_PORT);
|
||||||
|
|
||||||
|
_running = true;
|
||||||
|
_workerThread = std::thread(&Proxy::loop, this);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Proxy::Shutdown()
|
||||||
|
{
|
||||||
|
_running = false;
|
||||||
|
|
||||||
|
if (_listenSocket != INVALID_SOCKET && _listenSocket != 0)
|
||||||
|
{
|
||||||
|
closesocket(_listenSocket);
|
||||||
|
_listenSocket = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_workerThread.joinable()) _workerThread.join();
|
||||||
|
|
||||||
|
WSACleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Proxy::loop()
|
||||||
|
{
|
||||||
|
while (_running)
|
||||||
|
{
|
||||||
|
SOCKET clientSocket = accept(_listenSocket, NULL, NULL);
|
||||||
|
|
||||||
|
if (!_running)
|
||||||
|
{
|
||||||
|
if (clientSocket != INVALID_SOCKET) closesocket(clientSocket);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clientSocket == INVALID_SOCKET) continue;
|
||||||
|
|
||||||
|
std::thread([this, clientSocket]() { this->handleClient(clientSocket); }).detach();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Proxy::handleClient(SOCKET clientSocket)
|
||||||
|
{
|
||||||
|
char buffer[8192];
|
||||||
|
int bytesReceived = recv(clientSocket, buffer, sizeof(buffer) - 1, 0);
|
||||||
|
|
||||||
|
if (bytesReceived <= 0)
|
||||||
|
{
|
||||||
|
closesocket(clientSocket);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string request(buffer, bytesReceived);
|
||||||
|
|
||||||
|
/*
|
||||||
|
get host
|
||||||
|
*/
|
||||||
|
std::string host;
|
||||||
|
size_t hostPos = request.find("Host: ");
|
||||||
|
if (hostPos != std::string::npos)
|
||||||
|
{
|
||||||
|
size_t endPos = request.find("\r\n", hostPos);
|
||||||
|
host = request.substr(hostPos + 6, endPos - (hostPos + 6));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (host.empty())
|
||||||
|
{
|
||||||
|
closesocket(clientSocket);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
handle remote
|
||||||
|
*/
|
||||||
|
struct addrinfo hints = {}, *res;
|
||||||
|
hints.ai_family = AF_INET;
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
|
||||||
|
if (getaddrinfo(host.c_str(), "80", &hints, &res) != 0)
|
||||||
|
{
|
||||||
|
Log::error("Could not resolve host: {}", host);
|
||||||
|
closesocket(clientSocket);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SOCKET remoteSocket = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
|
||||||
|
if (connect(remoteSocket, res->ai_addr, (int)res->ai_addrlen) == SOCKET_ERROR)
|
||||||
|
{
|
||||||
|
Log::error("Connection to {} failed", host);
|
||||||
|
freeaddrinfo(res);
|
||||||
|
closesocket(clientSocket);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
freeaddrinfo(res);
|
||||||
|
|
||||||
|
/*
|
||||||
|
fwd
|
||||||
|
*/
|
||||||
|
send(remoteSocket, buffer, bytesReceived, 0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
recv
|
||||||
|
*/
|
||||||
|
int remoteBytes;
|
||||||
|
while ((remoteBytes = recv(remoteSocket, buffer, sizeof(buffer), 0)) > 0)
|
||||||
|
{
|
||||||
|
// Log::verbose("Forwarding {} bytes from server back to client", remoteBytes);
|
||||||
|
send(clientSocket, buffer, remoteBytes, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
closesocket(remoteSocket);
|
||||||
|
closesocket(clientSocket);
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <thread>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
#define PROXY_PORT 1337
|
||||||
|
|
||||||
|
typedef unsigned __int64 SOCKET;
|
||||||
|
|
||||||
|
class Proxy {
|
||||||
|
public:
|
||||||
|
Proxy();
|
||||||
|
~Proxy();
|
||||||
|
|
||||||
|
bool Init();
|
||||||
|
void Shutdown();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void loop();
|
||||||
|
void handleClient(SOCKET clientSocket);
|
||||||
|
|
||||||
|
SOCKET _listenSocket = 0;
|
||||||
|
std::thread _workerThread;
|
||||||
|
std::atomic<bool> _running;
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user