提问人:Mojo Baggins 提问时间:10/31/2023 更新时间:10/31/2023 访问量:29
反向代理服务器 SOCK4 与 asio c++ (用于 foxyproxy chrome browseR)
reverse proxy server SOCK4 with asio c++ (for foxyproxy chrome browseR)
问:
“首先,我知道它是同步的,它只意味着一次只能处理一个页面。它不应该是健壮的或任何东西。
我正在尝试编写一个 c++ asio 反向代理服务器,它可以与 foxyproxy chrome 浏览器客户端一起使用,我从互联网上挑选了一些东西,并准备好了这段代码。我的问题如下:
- 建立 SOCK4 连接后的 http 响应为 null(自从我添加了 SSL 支持以来发生)
- 如果没有SSL支持,它就会卡住将数据写回客户端,除其他外,它仅适用于自定义SSL客户端,FoxyProxy客户端与https(端口443)通信,所以我想我应该匹配它(我有一个同步的HTTP套接字)。
代码:
#pragma once
#define BOOST_NETWORK_ENABLE_HTTPS 1#include <asio/ssl.hpp>
#include <asio.hpp>
#include <filesystem>
#include <iostream>
#include <regex>
// https://social.msdn.microsoft.com/Forums/en-US/bd8e498b-32f8-4384-94bb-fcbcb0ff98e8/cant-link-with-crypt32lib?forum=windowssdk
#pragma comment(lib, "crypt32.lib")#include <wincrypt.h>
void add_windows_root_certs(asio::ssl::context & ctx) {
HCERTSTORE hStore = CertOpenSystemStore(0, L "ROOT");
if (hStore == NULL) {
return;
}
X509_STORE * store = X509_STORE_new();
PCCERT_CONTEXT pContext = NULL;
while ((pContext = CertEnumCertificatesInStore(hStore, pContext)) != NULL) {
X509 * x509 = d2i_X509(NULL,
(const unsigned char ** ) & pContext -> pbCertEncoded,
pContext -> cbCertEncoded);
if (x509 != NULL) {
X509_STORE_add_cert(store, x509);
X509_free(x509);
}
}
CertFreeCertificateContext(pContext);
CertCloseStore(hStore, 0);
SSL_CTX_set_cert_store(ctx.native_handle(), store);
}
using namespace std::literals::chrono_literals;
int main() {
asio::io_context incoming_proxy_io, outcoming_proxy_io;
asio::ip::tcp::acceptor incoming_proxy_acceptor_ {
incoming_proxy_io,
asio::ip::tcp::endpoint(asio::ip::tcp::v4(), 40000)
};
std::filesystem::path cert_path = std::filesystem::current_path() / "Debug\\server.crt";
std::filesystem::path key_path = std::filesystem::current_path() / "Debug\\server.key";
std::filesystem::path dh_2048 = std::filesystem::current_path() / "Debug\\dh_pem2048.pem";
// tls
asio::ssl::context context_(asio::ssl::context::tlsv12_client);
context_.set_options(asio::ssl::context::default_workarounds |
asio::ssl::context::no_sslv2 |
asio::ssl::context::no_sslv3 |
asio::ssl::context::tlsv12_client);
add_windows_root_certs(context_);
asio::ssl::stream < asio::ip::tcp::socket > m_socket {
incoming_proxy_io,
context_
};
try {
std::string username = "";
std::string user;
user.resize(username.size());
unsigned char version, command, port_high_byte, port_low_byte, null_byte;
asio::ip::address_v4::bytes_type bytes_address;
std::error_code ec;
incoming_proxy_acceptor_.accept(m_socket.lowest_layer(), ec);
if (ec) {
std::cout << "error accepting client.." << std::endl;
return -1;
}
std::array < asio::mutable_buffer, 7 > bufsRead = {
{
asio::buffer( & version, 1),
asio::buffer( & command, 1),
asio::buffer( & port_high_byte, 1),
asio::buffer( & port_low_byte, 1),
asio::buffer(bytes_address),
asio::buffer( & user[0], user.size()),
asio::buffer( & null_byte, 1)
}
};
ec = std::error_code();
asio::read(m_socket, bufsRead, ec);
if (ec || null_byte != 0 || version != 0x04 || command != 0x01) {
std::cout << "problem reading data.. error: " << ec.message() << std::endl;
return -1;
}
unsigned short received_port = port_high_byte;
received_port = (received_port << 8) | port_low_byte;
if (received_port != 443) {
std::cout << "port is bad?" << std::endl;
return -1;
}
// address
asio::ip::address_v4 true_address(bytes_address);
assert(true_address.to_string() != m_socket.lowest_layer().local_endpoint().address().to_string());
unsigned char status = 0x5a;
std::array < asio::const_buffer, 5 > bufsWrite = {
{
asio::buffer( & null_byte, 1),
asio::buffer( & status, 1),
asio::buffer( & port_high_byte, 1),
asio::buffer( & port_low_byte, 1),
asio::buffer(bytes_address)
}
};
ec = std::error_code();
asio::write(m_socket, bufsWrite, ec);
if (ec) {
std::cout << ec.message() << "error writing" << std::endl;
}
// Continue reading data from the client and forward to the destination (web server)
while (true) {
ec = std::error_code();
asio::streambuf request;
asio::read(m_socket, request, ec);
if (ec) {
std::cout << "failed from scoket.." << std::endl;
continue;
}
std::cout << "Reading from socket was succesful..." << std::endl;
std::string endp;
std::istream request_stream( & request);
std::string request_line;
std::vector < std::string > request_line_temp;
while (std::getline(request_stream, request_line)) {
request_line_temp.push_back(request_line);
}
request_line = request_line_temp[1];
size_t start = 0, end;
std::string delimeter("\r");
if ((end = request_line.find(delimeter, start)) != std::string::npos) {
endp = request_line.substr(start + 6, end - start);
}
if (ec) {
std::cout << "Error reading data from the client: " << ec.message() << std::endl;
continue;
}
if (endp.empty()) {
std::cout << "No host.." << std::endl;
continue;
}
auto query = asio::ip::tcp::resolver::query(endp, "http");
asio::error_code ec;
asio::ip::tcp::resolver resolver {
outcoming_proxy_io
};
asio::ip::tcp::resolver::results_type results = resolver.resolve(query, ec);
asio::ssl::context context_(asio::ssl::context::tlsv12_client);
context_.set_options(
asio::ssl::context::default_workarounds |
asio::ssl::context::no_sslv2 |
asio::ssl::context::single_dh_use);
context_.set_password_callback([ & ](auto, auto) -> std::string {
return "Dani!eelordrarequiver195709059Dad";
});
context_.use_certificate_chain_file(cert_path.string());
context_.use_private_key_file(key_path.string(), asio::ssl::context::pem);
context_.use_tmp_dh_file(dh_2048.string());
asio::ssl::stream < asio::ip::tcp::socket > out {
outcoming_proxy_io,
context_
};
std::cout << "connecting to.. " << endp << std::endl;
asio::connect(out.lowest_layer(), results, ec);
if (ec || !out.lowest_layer().is_open()) {
std::cout << "Error connecting to client error: " << ec.message() << std::endl;
continue;
}
std::this_thread::sleep_for(0 s);
std::cout << "writing to.. " << endp << std::endl;
// Send the HTTP request to the destination server.
size_t i = asio::write(out, asio::buffer(request.data(), request.size()), ec);
if (ec || i <= 0) {
std::cout << "failed to write.." << std::endl;
}
std::this_thread::sleep_for(0 s);
std::cout << "reading from.. " << endp << std::endl;
// Read the response from the destination server and send it back to the client.
std::vector < char > response_from_server;
size_t bytes_transferred = asio::read(out, asio::buffer(response_from_server), ec);
if (!ec && bytes_transferred >= 0) {
std::cout << "writing back to.. " << endp << std::endl;
// Send the response back to the client.
bytes_transferred = asio::write(m_socket, asio::buffer(response_from_server, bytes_transferred), ec);
if (ec || bytes_transferred <= 0) {
std::cout << "failed to write back.." << std::endl;
}
}
std::cout << "data succesfully red from the server.." << std::endl;
outcoming_proxy_io.post([ & ]() {
out.lowest_layer().close();
// As long as outstanding completion handlers do not
// invoke operations on socket_, then socket_ can be
// destroyed.
//out.release();
});
}
std::thread t_([ & ]() {
incoming_proxy_io.run();
});
if (t_.joinable()) {
t_.join();
}
std::thread t_2([ & ]() {
outcoming_proxy_io.run();
});
if (t_2.joinable()) {
t_2.join();
}
} catch (asio::system_error & ec) {
std::cout << "exception caught when accepting a new incoming_proxy" << ec.what() << std::endl;
}
return 0;
}
答: 暂无答案
评论