Browse Source

Merge pull request #978 from majestrate/http-i2p-outproxy

support i2p outproxy in httpproxy
pull/987/head
orignal 7 years ago committed by GitHub
parent
commit
2930d39ce7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      libi2pd/Destination.cpp
  2. 7
      libi2pd/HTTP.cpp
  3. 9
      libi2pd/HTTP.h
  4. 6
      libi2pd_client/ClientContext.cpp
  5. 33
      libi2pd_client/HTTPProxy.cpp
  6. 10
      libi2pd_client/HTTPProxy.h

1
libi2pd/Destination.cpp

@ -1,5 +1,6 @@
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
#include <string>
#include "Crypto.h" #include "Crypto.h"
#include "Log.h" #include "Log.h"
#include "FS.h" #include "FS.h"

7
libi2pd/HTTP.cpp

@ -29,7 +29,7 @@ namespace http {
inline bool is_http_method(const std::string & str) { inline bool is_http_method(const std::string & str) {
return std::find(HTTP_METHODS.begin(), HTTP_METHODS.end(), str) != std::end(HTTP_METHODS); return std::find(HTTP_METHODS.begin(), HTTP_METHODS.end(), str) != std::end(HTTP_METHODS);
} }
void strsplit(const std::string & line, std::vector<std::string> &tokens, char delim, std::size_t limit = 0) { void strsplit(const std::string & line, std::vector<std::string> &tokens, char delim, std::size_t limit = 0) {
std::size_t count = 0; std::size_t count = 0;
std::stringstream ss(line); std::stringstream ss(line);
@ -195,6 +195,11 @@ namespace http {
return out; return out;
} }
bool URL::is_i2p() const
{
return host.rfind(".i2p") == ( host.size() - 4 );
}
void HTTPMsg::add_header(const char *name, std::string & value, bool replace) { void HTTPMsg::add_header(const char *name, std::string & value, bool replace) {
add_header(name, value.c_str(), replace); add_header(name, value.c_str(), replace);
} }

9
libi2pd/HTTP.h

@ -56,6 +56,11 @@ namespace http
* @note Returns relative url if schema if empty, absolute url otherwise * @note Returns relative url if schema if empty, absolute url otherwise
*/ */
std::string to_string (); std::string to_string ();
/**
* @brief return true if the host is inside i2p
*/
bool is_i2p() const;
}; };
struct HTTPMsg struct HTTPMsg
@ -89,7 +94,7 @@ namespace http
/** @brief Serialize HTTP request to string */ /** @brief Serialize HTTP request to string */
std::string to_string(); std::string to_string();
void write(std::ostream & o); void write(std::ostream & o);
void AddHeader (const std::string& name, const std::string& value); void AddHeader (const std::string& name, const std::string& value);
void UpdateHeader (const std::string& name, const std::string& value); void UpdateHeader (const std::string& name, const std::string& value);
@ -131,7 +136,7 @@ namespace http
std::string to_string(); std::string to_string();
void write(std::ostream & o); void write(std::ostream & o);
/** @brief Checks that response declared as chunked data */ /** @brief Checks that response declared as chunked data */
bool is_chunked() const ; bool is_chunked() const ;

6
libi2pd_client/ClientContext.cpp

@ -54,6 +54,7 @@ namespace client
std::string httpProxyAddr; i2p::config::GetOption("httpproxy.address", httpProxyAddr); std::string httpProxyAddr; i2p::config::GetOption("httpproxy.address", httpProxyAddr);
uint16_t httpProxyPort; i2p::config::GetOption("httpproxy.port", httpProxyPort); uint16_t httpProxyPort; i2p::config::GetOption("httpproxy.port", httpProxyPort);
i2p::data::SigningKeyType sigType; i2p::config::GetOption("httpproxy.signaturetype", sigType); i2p::data::SigningKeyType sigType; i2p::config::GetOption("httpproxy.signaturetype", sigType);
std::string httpOutProxyURL; i2p::config::GetOption("httpproxy.outproxy", httpOutProxyURL);
LogPrint(eLogInfo, "Clients: starting HTTP Proxy at ", httpProxyAddr, ":", httpProxyPort); LogPrint(eLogInfo, "Clients: starting HTTP Proxy at ", httpProxyAddr, ":", httpProxyPort);
if (httpProxyKeys.length () > 0) if (httpProxyKeys.length () > 0)
{ {
@ -70,7 +71,7 @@ namespace client
} }
try try
{ {
m_HttpProxy = new i2p::proxy::HTTPProxy(httpProxyAddr, httpProxyPort, localDestination); m_HttpProxy = new i2p::proxy::HTTPProxy(httpProxyAddr, httpProxyPort, httpOutProxyURL, localDestination);
m_HttpProxy->Start(); m_HttpProxy->Start();
} }
catch (std::exception& e) catch (std::exception& e)
@ -536,7 +537,8 @@ namespace client
else if (type == I2P_TUNNELS_SECTION_TYPE_HTTPPROXY) else if (type == I2P_TUNNELS_SECTION_TYPE_HTTPPROXY)
{ {
// http proxy // http proxy
clientTunnel = new i2p::proxy::HTTPProxy(address, port, localDestination); std::string outproxy = section.second.get("outproxy", "");
clientTunnel = new i2p::proxy::HTTPProxy(address, port, outproxy, localDestination);
clientEndpoint = ((i2p::proxy::HTTPProxy*)clientTunnel)->GetLocalEndpoint (); clientEndpoint = ((i2p::proxy::HTTPProxy*)clientTunnel)->GetLocalEndpoint ();
} }
else if (type == I2P_TUNNELS_SECTION_TYPE_WEBSOCKS) else if (type == I2P_TUNNELS_SECTION_TYPE_WEBSOCKS)

33
libi2pd_client/HTTPProxy.cpp

@ -86,6 +86,7 @@ namespace proxy {
std::shared_ptr<boost::asio::ip::tcp::socket> m_sock; std::shared_ptr<boost::asio::ip::tcp::socket> m_sock;
std::shared_ptr<boost::asio::ip::tcp::socket> m_proxysock; std::shared_ptr<boost::asio::ip::tcp::socket> m_proxysock;
boost::asio::ip::tcp::resolver m_proxy_resolver; boost::asio::ip::tcp::resolver m_proxy_resolver;
std::string m_OutproxyUrl;
i2p::http::URL m_ProxyURL; i2p::http::URL m_ProxyURL;
i2p::http::URL m_RequestURL; i2p::http::URL m_RequestURL;
uint8_t m_socks_buf[255+8]; // for socks request/response uint8_t m_socks_buf[255+8]; // for socks request/response
@ -99,7 +100,8 @@ namespace proxy {
HTTPReqHandler(HTTPProxy * parent, std::shared_ptr<boost::asio::ip::tcp::socket> sock) : HTTPReqHandler(HTTPProxy * parent, std::shared_ptr<boost::asio::ip::tcp::socket> sock) :
I2PServiceHandler(parent), m_sock(sock), I2PServiceHandler(parent), m_sock(sock),
m_proxysock(std::make_shared<boost::asio::ip::tcp::socket>(parent->GetService())), m_proxysock(std::make_shared<boost::asio::ip::tcp::socket>(parent->GetService())),
m_proxy_resolver(parent->GetService()) {} m_proxy_resolver(parent->GetService()),
m_OutproxyUrl(parent->GetOutproxyURL()) {}
~HTTPReqHandler() { Terminate(); } ~HTTPReqHandler() { Terminate(); }
void Handle () { AsyncSockRead(); } /* overload */ void Handle () { AsyncSockRead(); } /* overload */
}; };
@ -324,10 +326,9 @@ namespace proxy {
return true; /* request processed */ return true; /* request processed */
} }
} else { } else {
std::string outproxyUrl; i2p::config::GetOption("httpproxy.outproxy", outproxyUrl); if(m_OutproxyUrl.size()) {
if(outproxyUrl.size()) { LogPrint (eLogDebug, "HTTPProxy: use outproxy ", m_OutproxyUrl);
LogPrint (eLogDebug, "HTTPProxy: use outproxy ", outproxyUrl); if(m_ProxyURL.parse(m_OutproxyUrl))
if(m_ProxyURL.parse(outproxyUrl))
ForwardToUpstreamProxy(); ForwardToUpstreamProxy();
else else
GenericProxyError("Outproxy failure", "bad outproxy settings"); GenericProxyError("Outproxy failure", "bad outproxy settings");
@ -379,10 +380,19 @@ namespace proxy {
if (m_ProxyURL.schema == "" || m_ProxyURL.schema == "http") { if (m_ProxyURL.schema == "" || m_ProxyURL.schema == "http") {
// handle upstream http proxy // handle upstream http proxy
if (!m_ProxyURL.port) m_ProxyURL.port = 80; if (!m_ProxyURL.port) m_ProxyURL.port = 80;
boost::asio::ip::tcp::resolver::query q(m_ProxyURL.host, std::to_string(m_ProxyURL.port)); if (m_ProxyURL.is_i2p())
m_proxy_resolver.async_resolve(q, std::bind(&HTTPReqHandler::HandleUpstreamProxyResolved, this, std::placeholders::_1, std::placeholders::_2, [&](boost::asio::ip::tcp::endpoint ep) { {
m_proxysock->async_connect(ep, std::bind(&HTTPReqHandler::HandleUpstreamHTTPProxyConnect, this, std::placeholders::_1)); m_send_buf = m_recv_buf;
})); GetOwner()->CreateStream (std::bind (&HTTPReqHandler::HandleStreamRequestComplete,
shared_from_this(), std::placeholders::_1), m_ProxyURL.host, m_ProxyURL.port);
}
else
{
boost::asio::ip::tcp::resolver::query q(m_ProxyURL.host, std::to_string(m_ProxyURL.port));
m_proxy_resolver.async_resolve(q, std::bind(&HTTPReqHandler::HandleUpstreamProxyResolved, this, std::placeholders::_1, std::placeholders::_2, [&](boost::asio::ip::tcp::endpoint ep) {
m_proxysock->async_connect(ep, std::bind(&HTTPReqHandler::HandleUpstreamHTTPProxyConnect, this, std::placeholders::_1));
}));
}
} else if (m_ProxyURL.schema == "socks") { } else if (m_ProxyURL.schema == "socks") {
// handle upstream socks proxy // handle upstream socks proxy
if (!m_ProxyURL.port) m_ProxyURL.port = 9050; // default to tor default if not specified if (!m_ProxyURL.port) m_ProxyURL.port = 9050; // default to tor default if not specified
@ -572,8 +582,9 @@ namespace proxy {
Done (shared_from_this()); Done (shared_from_this());
} }
HTTPProxy::HTTPProxy(const std::string& address, int port, std::shared_ptr<i2p::client::ClientDestination> localDestination): HTTPProxy::HTTPProxy(const std::string& address, int port, const std::string & outproxy, std::shared_ptr<i2p::client::ClientDestination> localDestination):
TCPIPAcceptor(address, port, localDestination ? localDestination : i2p::client::context.GetSharedLocalDestination ()) TCPIPAcceptor(address, port, localDestination ? localDestination : i2p::client::context.GetSharedLocalDestination ()),
m_OutproxyUrl(outproxy)
{ {
} }

10
libi2pd_client/HTTPProxy.h

@ -6,14 +6,20 @@ namespace proxy {
class HTTPProxy: public i2p::client::TCPIPAcceptor class HTTPProxy: public i2p::client::TCPIPAcceptor
{ {
public: public:
HTTPProxy(const std::string& address, int port, const std::string & outproxy, std::shared_ptr<i2p::client::ClientDestination> localDestination);
HTTPProxy(const std::string& address, int port, std::shared_ptr<i2p::client::ClientDestination> localDestination = nullptr); HTTPProxy(const std::string& address, int port, std::shared_ptr<i2p::client::ClientDestination> localDestination = nullptr) :
HTTPProxy(address, port, "", localDestination) {} ;
~HTTPProxy() {}; ~HTTPProxy() {};
std::string GetOutproxyURL() const { return m_OutproxyUrl; }
protected: protected:
// Implements TCPIPAcceptor // Implements TCPIPAcceptor
std::shared_ptr<i2p::client::I2PServiceHandler> CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket); std::shared_ptr<i2p::client::I2PServiceHandler> CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket);
const char* GetName() { return "HTTP Proxy"; } const char* GetName() { return "HTTP Proxy"; }
private:
std::string m_OutproxyUrl;
}; };
} // http } // http
} // i2p } // i2p

Loading…
Cancel
Save