#include "ProxyHttpSession.h" #include "BoostLog.h" #include "ProxyTcpSession.h" #include #include #include ProxyHttpSession::ProxyHttpSession(boost::asio::io_context &ioContext, boost::asio::ip::tcp::socket &&socket) : m_resolver(ioContext), m_clientStream(std::move(socket)), m_serverStream(boost::asio::make_strand(ioContext)) { } void ProxyHttpSession::run() { doRead(); } void ProxyHttpSession::doRead() { // Construct a new parser for each message m_parser.emplace(); // Apply a reasonable limit to the allowed size // of the body in bytes to prevent abuse. m_parser->body_limit(std::numeric_limits::max()); m_parser->header_limit(std::numeric_limits::max()); m_buffer.clear(); // Set the timeout. // m_stream.expires_after(std::chrono::seconds(30)); m_clientStream.expires_never(); boost::beast::http::async_read( m_clientStream, m_buffer, *m_parser, [self{shared_from_this()}](const boost::system::error_code &ec, std::size_t bytes_transferred) { self->onRead(ec, bytes_transferred); }); } void ProxyHttpSession::onRead(boost::beast::error_code ec, size_t) { // This means they closed the connection if (ec == boost::beast::http::error::end_of_stream) { LOG(info) << ec << " : " << ec.message(); m_clientStream.socket().shutdown(boost::asio::ip::tcp::socket::shutdown_send, ec); return; } if (ec) { if (ec == boost::asio::error::operation_aborted) return; LOG(info) << ec << " : " << ec.message(); return; } auto request = m_parser->release(); if (request.count("Host") <= 0) return; auto host = request.at("Host"); if (host.empty()) { LOG(error) << "Host field not existed."; return; } auto colonPos = host.find_first_of(':'); std::string_view serverAddress; std::string_view serverPort; if (colonPos != std::string_view::npos) { serverAddress = host.substr(0, colonPos); serverPort = host.substr(colonPos + 1); } else { serverAddress = host; serverPort = "80"; } boost::system::error_code ee; auto const results = m_resolver.resolve(serverAddress, serverPort, ee); if (ee) { LOG(error) << ee.message(); return; } m_serverStream.connect(results, ee); if (ee) { LOG(error) << ee.message(); return; } if (request.method() == boost::beast::http::verb::connect) { LOG(info) << "proxy host [" << serverAddress << "], port [" << serverPort << "]"; boost::beast::http::response res{boost::beast::http::status::ok, request.version()}; res.reason("Connection Established"); res.keep_alive(request.keep_alive()); res.set("Proxy-agent", "amass"); res.prepare_payload(); boost::beast::http::write(m_clientStream, res); } else { boost::beast::http::write(m_serverStream, request); } auto tcp = std::make_shared(m_clientStream.release_socket(), m_serverStream.release_socket()); tcp->run(); }