mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-01-19 01:09:58 +00:00
use SOCK5 proxy for upstream
This commit is contained in:
parent
b07530a8a1
commit
075f80aea2
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2023, The PurpleI2P Project
|
* Copyright (c) 2013-2024, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
@ -19,6 +19,7 @@
|
|||||||
#include "I2PTunnel.h"
|
#include "I2PTunnel.h"
|
||||||
#include "I2PService.h"
|
#include "I2PService.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "Socks5.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
@ -27,10 +28,6 @@ namespace proxy
|
|||||||
static const size_t socks_buffer_size = 8192;
|
static const size_t socks_buffer_size = 8192;
|
||||||
static const size_t max_socks_hostname_size = 255; // Limit for socks5 and bad idea to traverse
|
static const size_t max_socks_hostname_size = 255; // Limit for socks5 and bad idea to traverse
|
||||||
|
|
||||||
//static const size_t SOCKS_FORWARDER_BUFFER_SIZE = 8192;
|
|
||||||
|
|
||||||
static const size_t SOCKS_UPSTREAM_SOCKS4A_REPLY_SIZE = 8;
|
|
||||||
|
|
||||||
struct SOCKSDnsAddress
|
struct SOCKSDnsAddress
|
||||||
{
|
{
|
||||||
uint8_t size;
|
uint8_t size;
|
||||||
@ -132,7 +129,6 @@ namespace proxy
|
|||||||
boost::asio::const_buffers_1 GenerateSOCKS5SelectAuth(authMethods method);
|
boost::asio::const_buffers_1 GenerateSOCKS5SelectAuth(authMethods method);
|
||||||
boost::asio::const_buffers_1 GenerateSOCKS4Response(errTypes error, uint32_t ip, uint16_t port);
|
boost::asio::const_buffers_1 GenerateSOCKS4Response(errTypes error, uint32_t ip, uint16_t port);
|
||||||
boost::asio::const_buffers_1 GenerateSOCKS5Response(errTypes error, addrTypes type, const address &addr, uint16_t port);
|
boost::asio::const_buffers_1 GenerateSOCKS5Response(errTypes error, addrTypes type, const address &addr, uint16_t port);
|
||||||
boost::asio::const_buffers_1 GenerateUpstreamRequest();
|
|
||||||
bool Socks5ChooseAuth();
|
bool Socks5ChooseAuth();
|
||||||
void Socks5UserPasswdResponse ();
|
void Socks5UserPasswdResponse ();
|
||||||
void SocksRequestFailed(errTypes error);
|
void SocksRequestFailed(errTypes error);
|
||||||
@ -146,9 +142,6 @@ namespace proxy
|
|||||||
void SocksUpstreamSuccess();
|
void SocksUpstreamSuccess();
|
||||||
void AsyncUpstreamSockRead();
|
void AsyncUpstreamSockRead();
|
||||||
void SendUpstreamRequest();
|
void SendUpstreamRequest();
|
||||||
void HandleUpstreamData(uint8_t * buff, std::size_t len);
|
|
||||||
void HandleUpstreamSockSend(const boost::system::error_code & ecode, std::size_t bytes_transfered);
|
|
||||||
void HandleUpstreamSockRecv(const boost::system::error_code & ecode, std::size_t bytes_transfered);
|
|
||||||
void HandleUpstreamConnected(const boost::system::error_code & ecode,
|
void HandleUpstreamConnected(const boost::system::error_code & ecode,
|
||||||
boost::asio::ip::tcp::resolver::iterator itr);
|
boost::asio::ip::tcp::resolver::iterator itr);
|
||||||
void HandleUpstreamResolved(const boost::system::error_code & ecode,
|
void HandleUpstreamResolved(const boost::system::error_code & ecode,
|
||||||
@ -161,9 +154,6 @@ namespace proxy
|
|||||||
uint8_t *m_remaining_data; //Data left to be sent
|
uint8_t *m_remaining_data; //Data left to be sent
|
||||||
uint8_t *m_remaining_upstream_data; //upstream data left to be forwarded
|
uint8_t *m_remaining_upstream_data; //upstream data left to be forwarded
|
||||||
uint8_t m_response[7+max_socks_hostname_size];
|
uint8_t m_response[7+max_socks_hostname_size];
|
||||||
uint8_t m_upstream_response[SOCKS_UPSTREAM_SOCKS4A_REPLY_SIZE];
|
|
||||||
uint8_t m_upstream_request[14+max_socks_hostname_size];
|
|
||||||
std::size_t m_upstream_response_len;
|
|
||||||
address m_address; //Address
|
address m_address; //Address
|
||||||
std::size_t m_remaining_data_len; //Size of the data left to be sent
|
std::size_t m_remaining_data_len; //Size of the data left to be sent
|
||||||
uint32_t m_4aip; //Used in 4a requests
|
uint32_t m_4aip; //Used in 4a requests
|
||||||
@ -280,37 +270,6 @@ namespace proxy
|
|||||||
return boost::asio::const_buffers_1(m_response, size);
|
return boost::asio::const_buffers_1(m_response, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::asio::const_buffers_1 SOCKSHandler::GenerateUpstreamRequest()
|
|
||||||
{
|
|
||||||
size_t upstreamRequestSize = 0;
|
|
||||||
// TODO: negotiate with upstream
|
|
||||||
// SOCKS 4a
|
|
||||||
m_upstream_request[0] = '\x04'; //version
|
|
||||||
m_upstream_request[1] = m_cmd;
|
|
||||||
htobe16buf(m_upstream_request + 2, m_port);
|
|
||||||
m_upstream_request[4] = 0;
|
|
||||||
m_upstream_request[5] = 0;
|
|
||||||
m_upstream_request[6] = 0;
|
|
||||||
m_upstream_request[7] = 1;
|
|
||||||
// user id
|
|
||||||
m_upstream_request[8] = 'i';
|
|
||||||
m_upstream_request[9] = '2';
|
|
||||||
m_upstream_request[10] = 'p';
|
|
||||||
m_upstream_request[11] = 'd';
|
|
||||||
m_upstream_request[12] = 0;
|
|
||||||
upstreamRequestSize += 13;
|
|
||||||
if (m_address.dns.size <= max_socks_hostname_size - ( upstreamRequestSize + 1) ) {
|
|
||||||
// bounds check okay
|
|
||||||
memcpy(m_upstream_request + upstreamRequestSize, m_address.dns.value, m_address.dns.size);
|
|
||||||
upstreamRequestSize += m_address.dns.size;
|
|
||||||
// null terminate
|
|
||||||
m_upstream_request[++upstreamRequestSize] = 0;
|
|
||||||
} else {
|
|
||||||
LogPrint(eLogError, "SOCKS: BUG!!! m_addr.dns.sizs > max_socks_hostname - ( upstreamRequestSize + 1 ) )");
|
|
||||||
}
|
|
||||||
return boost::asio::const_buffers_1(m_upstream_request, upstreamRequestSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SOCKSHandler::Socks5ChooseAuth()
|
bool SOCKSHandler::Socks5ChooseAuth()
|
||||||
{
|
{
|
||||||
m_response[0] = '\x05'; // Version
|
m_response[0] = '\x05'; // Version
|
||||||
@ -724,32 +683,6 @@ namespace proxy
|
|||||||
std::placeholders::_1, std::placeholders::_2));
|
std::placeholders::_1, std::placeholders::_2));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SOCKSHandler::AsyncUpstreamSockRead()
|
|
||||||
{
|
|
||||||
LogPrint(eLogDebug, "SOCKS: Async upstream sock read");
|
|
||||||
if (m_upstreamSock) {
|
|
||||||
m_upstreamSock->async_read_some(boost::asio::buffer(m_upstream_response, SOCKS_UPSTREAM_SOCKS4A_REPLY_SIZE),
|
|
||||||
std::bind(&SOCKSHandler::HandleUpstreamSockRecv, shared_from_this(), std::placeholders::_1, std::placeholders::_2));
|
|
||||||
} else {
|
|
||||||
LogPrint(eLogError, "SOCKS: No upstream socket for read");
|
|
||||||
SocksRequestFailed(SOCKS5_GEN_FAIL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SOCKSHandler::HandleUpstreamSockRecv(const boost::system::error_code & ecode, std::size_t bytes_transfered)
|
|
||||||
{
|
|
||||||
if (ecode) {
|
|
||||||
if (m_state == UPSTREAM_HANDSHAKE ) {
|
|
||||||
// we are trying to handshake but it failed
|
|
||||||
SocksRequestFailed(SOCKS5_NET_UNREACH);
|
|
||||||
} else {
|
|
||||||
LogPrint(eLogError, "SOCKS: Bad state when reading from upstream: ", (int) m_state);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
HandleUpstreamData(m_upstream_response, bytes_transfered);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SOCKSHandler::SocksUpstreamSuccess()
|
void SOCKSHandler::SocksUpstreamSuccess()
|
||||||
{
|
{
|
||||||
LogPrint(eLogInfo, "SOCKS: Upstream success");
|
LogPrint(eLogInfo, "SOCKS: Upstream success");
|
||||||
@ -776,46 +709,28 @@ namespace proxy
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SOCKSHandler::HandleUpstreamData(uint8_t * dataptr, std::size_t len)
|
|
||||||
{
|
|
||||||
if (m_state == UPSTREAM_HANDSHAKE) {
|
|
||||||
m_upstream_response_len += len;
|
|
||||||
// handle handshake data
|
|
||||||
if (m_upstream_response_len < SOCKS_UPSTREAM_SOCKS4A_REPLY_SIZE) {
|
|
||||||
// too small, continue reading
|
|
||||||
AsyncUpstreamSockRead();
|
|
||||||
} else if (len == SOCKS_UPSTREAM_SOCKS4A_REPLY_SIZE) {
|
|
||||||
// just right
|
|
||||||
uint8_t resp = m_upstream_response[1];
|
|
||||||
if (resp == SOCKS4_OK) {
|
|
||||||
// we have connected !
|
|
||||||
SocksUpstreamSuccess();
|
|
||||||
} else {
|
|
||||||
// upstream failure
|
|
||||||
LogPrint(eLogError, "SOCKS: Upstream proxy failure: ", (int) resp);
|
|
||||||
// TODO: runtime error?
|
|
||||||
SocksRequestFailed(SOCKS5_GEN_FAIL);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// too big
|
|
||||||
SocksRequestFailed(SOCKS5_GEN_FAIL);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// invalid state
|
|
||||||
LogPrint(eLogError, "SOCKS: Invalid state reading from upstream: ", (int) m_state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SOCKSHandler::SendUpstreamRequest()
|
void SOCKSHandler::SendUpstreamRequest()
|
||||||
{
|
{
|
||||||
LogPrint(eLogInfo, "SOCKS: Negotiating with upstream proxy");
|
LogPrint(eLogInfo, "SOCKS: Negotiating with upstream proxy");
|
||||||
EnterState(UPSTREAM_HANDSHAKE);
|
EnterState(UPSTREAM_HANDSHAKE);
|
||||||
if (m_upstreamSock) {
|
if (m_upstreamSock)
|
||||||
boost::asio::write(*m_upstreamSock, GenerateUpstreamRequest());
|
{
|
||||||
AsyncUpstreamSockRead();
|
auto s = shared_from_this ();
|
||||||
} else {
|
i2p::transport::Socks5Handshake (*m_upstreamSock, std::make_pair(m_address.dns.ToString (), m_port),
|
||||||
|
[s](const boost::system::error_code& ec)
|
||||||
|
{
|
||||||
|
if (!ec)
|
||||||
|
s->SocksUpstreamSuccess();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s->SocksRequestFailed(SOCKS5_NET_UNREACH);
|
||||||
|
LogPrint(eLogError, "SOCKS: Upstream proxy failure: ", ec.message ());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
LogPrint(eLogError, "SOCKS: No upstream socket to send handshake to");
|
LogPrint(eLogError, "SOCKS: No upstream socket to send handshake to");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SOCKSHandler::HandleUpstreamConnected(const boost::system::error_code & ecode, boost::asio::ip::tcp::resolver::iterator itr)
|
void SOCKSHandler::HandleUpstreamConnected(const boost::system::error_code & ecode, boost::asio::ip::tcp::resolver::iterator itr)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user