|
|
|
@ -29,7 +29,87 @@ namespace transport
@@ -29,7 +29,87 @@ namespace transport
|
|
|
|
|
const size_t SOCKS5_UDP_IPV4_REQUEST_HEADER_SIZE = 10; |
|
|
|
|
const size_t SOCKS5_UDP_IPV6_REQUEST_HEADER_SIZE = 22; |
|
|
|
|
|
|
|
|
|
const uint8_t SOCKS5_REPLY_SUCCESS = 0x00; |
|
|
|
|
const uint8_t SOCKS5_REPLY_SERVER_FAILURE = 0x01; |
|
|
|
|
const uint8_t SOCKS5_REPLY_CONNECTION_NOT_ALLOWED = 0x02; |
|
|
|
|
const uint8_t SOCKS5_REPLY_NETWORK_UNREACHABLE = 0x03; |
|
|
|
|
const uint8_t SOCKS5_REPLY_HOST_UNREACHABLE = 0x04; |
|
|
|
|
const uint8_t SOCKS5_REPLY_CONNECTION_REFUSED = 0x05; |
|
|
|
|
const uint8_t SOCKS5_REPLY_TTL_EXPIRED = 0x06; |
|
|
|
|
const uint8_t SOCKS5_REPLY_COMMAND_NOT_SUPPORTED = 0x07; |
|
|
|
|
const uint8_t SOCKS5_REPLY_ADDRESS_TYPE_NOT_SUPPORTED = 0x08; |
|
|
|
|
|
|
|
|
|
// SOCKS5 handshake
|
|
|
|
|
template<typename Socket, typename Handler> |
|
|
|
|
void Socks5ReadReply (Socket& s, Handler handler) |
|
|
|
|
{ |
|
|
|
|
auto readbuff = std::make_shared<std::vector<int8_t> >(258); // max possible
|
|
|
|
|
boost::asio::async_read(s, boost::asio::buffer(readbuff->data (), 5), boost::asio::transfer_all(), // read 4 bytes of header + first byte of address
|
|
|
|
|
[readbuff, &s, handler](const boost::system::error_code& ec, std::size_t transferred) |
|
|
|
|
{ |
|
|
|
|
if (!ec) |
|
|
|
|
{ |
|
|
|
|
if ((*readbuff)[1] == SOCKS5_REPLY_SUCCESS) |
|
|
|
|
{ |
|
|
|
|
size_t len = 0; |
|
|
|
|
switch ((*readbuff)[3]) // ATYP
|
|
|
|
|
{ |
|
|
|
|
case SOCKS5_ATYP_IPV4: len = 3; break; // address length 4 bytes
|
|
|
|
|
case SOCKS5_ATYP_IPV6: len = 15; break; // address length 16 bytes
|
|
|
|
|
case SOCKS5_ATYP_NAME: len += (*readbuff)[4]; break; // first byte of address is length
|
|
|
|
|
default: ; |
|
|
|
|
} |
|
|
|
|
if (len) |
|
|
|
|
{ |
|
|
|
|
len += 2; // port
|
|
|
|
|
boost::asio::async_read(s, boost::asio::buffer(readbuff->data (), len), boost::asio::transfer_all(), |
|
|
|
|
[readbuff, &s, handler](const boost::system::error_code& ec, std::size_t transferred) |
|
|
|
|
{ |
|
|
|
|
if (!ec) |
|
|
|
|
handler (boost::system::error_code ()); // success
|
|
|
|
|
else |
|
|
|
|
handler (boost::asio::error::make_error_code (boost::asio::error::connection_aborted)); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
handler (boost::asio::error::make_error_code (boost::asio::error::fault)); // unknown address type
|
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
switch ((*readbuff)[1]) // REP
|
|
|
|
|
{ |
|
|
|
|
case SOCKS5_REPLY_SERVER_FAILURE: |
|
|
|
|
handler (boost::asio::error::make_error_code (boost::asio::error::access_denied )); |
|
|
|
|
break; |
|
|
|
|
case SOCKS5_REPLY_CONNECTION_NOT_ALLOWED: |
|
|
|
|
handler (boost::asio::error::make_error_code (boost::asio::error::no_permission)); |
|
|
|
|
break; |
|
|
|
|
case SOCKS5_REPLY_HOST_UNREACHABLE: |
|
|
|
|
handler (boost::asio::error::make_error_code (boost::asio::error::host_unreachable)); |
|
|
|
|
break; |
|
|
|
|
case SOCKS5_REPLY_NETWORK_UNREACHABLE: |
|
|
|
|
handler (boost::asio::error::make_error_code (boost::asio::error::network_unreachable)); |
|
|
|
|
break; |
|
|
|
|
case SOCKS5_REPLY_CONNECTION_REFUSED: |
|
|
|
|
handler (boost::asio::error::make_error_code (boost::asio::error::connection_refused)); |
|
|
|
|
break; |
|
|
|
|
case SOCKS5_REPLY_TTL_EXPIRED: |
|
|
|
|
handler (boost::asio::error::make_error_code (boost::asio::error::timed_out)); |
|
|
|
|
break; |
|
|
|
|
case SOCKS5_REPLY_COMMAND_NOT_SUPPORTED: |
|
|
|
|
handler (boost::asio::error::make_error_code (boost::asio::error::operation_not_supported)); |
|
|
|
|
break; |
|
|
|
|
case SOCKS5_REPLY_ADDRESS_TYPE_NOT_SUPPORTED: |
|
|
|
|
handler (boost::asio::error::make_error_code (boost::asio::error::no_protocol_option)); |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
handler (boost::asio::error::make_error_code (boost::asio::error::connection_aborted)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
handler (ec); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template<typename Socket, typename Handler> |
|
|
|
|
void Socks5Connect (Socket& s, Handler handler, std::shared_ptr<std::vector<uint8_t> > buff, uint16_t port) |
|
|
|
|
{ |
|
|
|
@ -44,31 +124,7 @@ namespace transport
@@ -44,31 +124,7 @@ namespace transport
|
|
|
|
|
{ |
|
|
|
|
(void) transferred; |
|
|
|
|
if (!ec) |
|
|
|
|
{ |
|
|
|
|
auto readbuff = std::make_shared<std::vector<int8_t> >(262); // max possible
|
|
|
|
|
boost::asio::async_read(s, boost::asio::buffer(readbuff->data (), 7), boost::asio::transfer_all(), // read min reply size
|
|
|
|
|
[readbuff, &s, handler](const boost::system::error_code& ec, std::size_t transferred) |
|
|
|
|
{ |
|
|
|
|
if (!ec) |
|
|
|
|
{ |
|
|
|
|
if (!(*readbuff)[1]) // succeeded
|
|
|
|
|
{ |
|
|
|
|
boost::system::error_code ec; |
|
|
|
|
size_t moreBytes = s.available(ec); |
|
|
|
|
if (!ec && moreBytes) // read remaining portion of reply
|
|
|
|
|
boost::asio::read (s, boost::asio::buffer(readbuff->data (), moreBytes), boost::asio::transfer_all (), ec); |
|
|
|
|
if (!ec) |
|
|
|
|
handler (boost::system::error_code ()); |
|
|
|
|
else |
|
|
|
|
handler (boost::asio::error::make_error_code (boost::asio::error::connection_aborted)); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
handler (boost::asio::error::make_error_code (boost::asio::error::connection_refused)); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
handler (ec); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
Socks5ReadReply (s, handler); |
|
|
|
|
else |
|
|
|
|
handler (ec); |
|
|
|
|
}); |
|
|
|
|