mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-13 05:40:42 +01:00
Remove SOCKS5 support
Bug: webrtc:15726 Change-Id: Icd3aca433966f76e1b200b0f4790013cce12095a Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/331820 Reviewed-by: Tomas Gunnarsson <tommi@webrtc.org> Commit-Queue: Harald Alvestrand <hta@webrtc.org> Cr-Commit-Position: refs/heads/main@{#41655}
This commit is contained in:
parent
c1cc6a36b2
commit
b5f2b17fd8
10 changed files with 14 additions and 537 deletions
|
@ -119,11 +119,7 @@ AsyncPacketSocket* BasicPacketSocketFactory::CreateClientTcpSocket(
|
||||||
<< socket->GetError();
|
<< socket->GetError();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If using a proxy, wrap the socket in a proxy socket.
|
if (proxy_info.type == PROXY_HTTPS) {
|
||||||
if (proxy_info.type == PROXY_SOCKS5) {
|
|
||||||
socket = new AsyncSocksProxySocket(
|
|
||||||
socket, proxy_info.address, proxy_info.username, proxy_info.password);
|
|
||||||
} else if (proxy_info.type == PROXY_HTTPS) {
|
|
||||||
socket =
|
socket =
|
||||||
new AsyncHttpsProxySocket(socket, user_agent, proxy_info.address,
|
new AsyncHttpsProxySocket(socket, user_agent, proxy_info.address,
|
||||||
proxy_info.username, proxy_info.password);
|
proxy_info.username, proxy_info.password);
|
||||||
|
|
|
@ -286,14 +286,6 @@ class P2PTransportChannelTestBase : public ::testing::Test,
|
||||||
main_(ss_.get()),
|
main_(ss_.get()),
|
||||||
stun_server_(TestStunServer::Create(ss_.get(), kStunAddr, main_)),
|
stun_server_(TestStunServer::Create(ss_.get(), kStunAddr, main_)),
|
||||||
turn_server_(&main_, ss_.get(), kTurnUdpIntAddr, kTurnUdpExtAddr),
|
turn_server_(&main_, ss_.get(), kTurnUdpIntAddr, kTurnUdpExtAddr),
|
||||||
socks_server1_(ss_.get(),
|
|
||||||
kSocksProxyAddrs[0],
|
|
||||||
ss_.get(),
|
|
||||||
kSocksProxyAddrs[0]),
|
|
||||||
socks_server2_(ss_.get(),
|
|
||||||
kSocksProxyAddrs[1],
|
|
||||||
ss_.get(),
|
|
||||||
kSocksProxyAddrs[1]),
|
|
||||||
force_relay_(false) {
|
force_relay_(false) {
|
||||||
ep1_.role_ = ICEROLE_CONTROLLING;
|
ep1_.role_ = ICEROLE_CONTROLLING;
|
||||||
ep2_.role_ = ICEROLE_CONTROLLED;
|
ep2_.role_ = ICEROLE_CONTROLLED;
|
||||||
|
@ -330,7 +322,6 @@ class P2PTransportChannelTestBase : public ::testing::Test,
|
||||||
BLOCK_UDP_AND_INCOMING_TCP, // Firewall, UDP in/out and TCP in blocked
|
BLOCK_UDP_AND_INCOMING_TCP, // Firewall, UDP in/out and TCP in blocked
|
||||||
BLOCK_ALL_BUT_OUTGOING_HTTP, // Firewall, only TCP out on 80/443
|
BLOCK_ALL_BUT_OUTGOING_HTTP, // Firewall, only TCP out on 80/443
|
||||||
PROXY_HTTPS, // All traffic through HTTPS proxy
|
PROXY_HTTPS, // All traffic through HTTPS proxy
|
||||||
PROXY_SOCKS, // All traffic through SOCKS proxy
|
|
||||||
NUM_CONFIGS
|
NUM_CONFIGS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1028,8 +1019,6 @@ class P2PTransportChannelTestBase : public ::testing::Test,
|
||||||
PendingTaskSafetyFlag::Create();
|
PendingTaskSafetyFlag::Create();
|
||||||
TestStunServer::StunServerPtr stun_server_;
|
TestStunServer::StunServerPtr stun_server_;
|
||||||
TestTurnServer turn_server_;
|
TestTurnServer turn_server_;
|
||||||
rtc::SocksProxyServer socks_server1_;
|
|
||||||
rtc::SocksProxyServer socks_server2_;
|
|
||||||
Endpoint ep1_;
|
Endpoint ep1_;
|
||||||
Endpoint ep2_;
|
Endpoint ep2_;
|
||||||
RemoteIceParameterSource remote_ice_parameter_source_ = FROM_CANDIDATE;
|
RemoteIceParameterSource remote_ice_parameter_source_ = FROM_CANDIDATE;
|
||||||
|
@ -1179,7 +1168,6 @@ class P2PTransportChannelTest : public P2PTransportChannelTestBase {
|
||||||
case BLOCK_UDP_AND_INCOMING_TCP:
|
case BLOCK_UDP_AND_INCOMING_TCP:
|
||||||
case BLOCK_ALL_BUT_OUTGOING_HTTP:
|
case BLOCK_ALL_BUT_OUTGOING_HTTP:
|
||||||
case PROXY_HTTPS:
|
case PROXY_HTTPS:
|
||||||
case PROXY_SOCKS:
|
|
||||||
AddAddress(endpoint, kPublicAddrs[endpoint]);
|
AddAddress(endpoint, kPublicAddrs[endpoint]);
|
||||||
// Block all UDP
|
// Block all UDP
|
||||||
fw()->AddRule(false, rtc::FP_UDP, rtc::FD_ANY, kPublicAddrs[endpoint]);
|
fw()->AddRule(false, rtc::FP_UDP, rtc::FD_ANY, kPublicAddrs[endpoint]);
|
||||||
|
@ -1202,13 +1190,6 @@ class P2PTransportChannelTest : public P2PTransportChannelTestBase {
|
||||||
fw()->AddRule(false, rtc::FP_TCP, rtc::FD_ANY,
|
fw()->AddRule(false, rtc::FP_TCP, rtc::FD_ANY,
|
||||||
kPublicAddrs[endpoint]);
|
kPublicAddrs[endpoint]);
|
||||||
SetProxy(endpoint, rtc::PROXY_HTTPS);
|
SetProxy(endpoint, rtc::PROXY_HTTPS);
|
||||||
} else if (config == PROXY_SOCKS) {
|
|
||||||
// Block all TCP to/from the endpoint except to the proxy server
|
|
||||||
fw()->AddRule(true, rtc::FP_TCP, kPublicAddrs[endpoint],
|
|
||||||
kSocksProxyAddrs[endpoint]);
|
|
||||||
fw()->AddRule(false, rtc::FP_TCP, rtc::FD_ANY,
|
|
||||||
kPublicAddrs[endpoint]);
|
|
||||||
SetProxy(endpoint, rtc::PROXY_SOCKS5);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -1253,42 +1234,28 @@ class P2PTransportChannelMatrixTest : public P2PTransportChannelTest,
|
||||||
const P2PTransportChannelMatrixTest::Result*
|
const P2PTransportChannelMatrixTest::Result*
|
||||||
P2PTransportChannelMatrixTest::kMatrix[NUM_CONFIGS][NUM_CONFIGS] = {
|
P2PTransportChannelMatrixTest::kMatrix[NUM_CONFIGS][NUM_CONFIGS] = {
|
||||||
// OPEN CONE ADDR PORT SYMM 2CON SCON !UDP !TCP HTTP PRXH
|
// OPEN CONE ADDR PORT SYMM 2CON SCON !UDP !TCP HTTP PRXH
|
||||||
// PRXS
|
/*OP*/
|
||||||
/*OP*/ {LULU, LUSU, LUSU, LUSU, LUPU, LUSU, LUPU, LTPT, LTPT, LSRS,
|
{LULU, LUSU, LUSU, LUSU, LUPU, LUSU, LUPU, LTPT, LTPT, LSRS, NULL},
|
||||||
NULL, LTPT},
|
|
||||||
/*CO*/
|
/*CO*/
|
||||||
{SULU, SUSU, SUSU, SUSU, SUPU, SUSU, SUPU, NULL, NULL, LSRS, NULL,
|
{SULU, SUSU, SUSU, SUSU, SUPU, SUSU, SUPU, NULL, NULL, LSRS, NULL},
|
||||||
LTRT},
|
|
||||||
/*AD*/
|
/*AD*/
|
||||||
{SULU, SUSU, SUSU, SUSU, SUPU, SUSU, SUPU, NULL, NULL, LSRS, NULL,
|
{SULU, SUSU, SUSU, SUSU, SUPU, SUSU, SUPU, NULL, NULL, LSRS, NULL},
|
||||||
LTRT},
|
|
||||||
/*PO*/
|
/*PO*/
|
||||||
{SULU, SUSU, SUSU, SUSU, RUPU, SUSU, RUPU, NULL, NULL, LSRS, NULL,
|
{SULU, SUSU, SUSU, SUSU, RUPU, SUSU, RUPU, NULL, NULL, LSRS, NULL},
|
||||||
LTRT},
|
|
||||||
/*SY*/
|
/*SY*/
|
||||||
{PULU, PUSU, PUSU, PURU, PURU, PUSU, PURU, NULL, NULL, LSRS, NULL,
|
{PULU, PUSU, PUSU, PURU, PURU, PUSU, PURU, NULL, NULL, LSRS, NULL},
|
||||||
LTRT},
|
|
||||||
/*2C*/
|
/*2C*/
|
||||||
{SULU, SUSU, SUSU, SUSU, SUPU, SUSU, SUPU, NULL, NULL, LSRS, NULL,
|
{SULU, SUSU, SUSU, SUSU, SUPU, SUSU, SUPU, NULL, NULL, LSRS, NULL},
|
||||||
LTRT},
|
|
||||||
/*SC*/
|
/*SC*/
|
||||||
{PULU, PUSU, PUSU, PURU, PURU, PUSU, PURU, NULL, NULL, LSRS, NULL,
|
{PULU, PUSU, PUSU, PURU, PURU, PUSU, PURU, NULL, NULL, LSRS, NULL},
|
||||||
LTRT},
|
|
||||||
/*!U*/
|
/*!U*/
|
||||||
{LTPT, NULL, NULL, NULL, NULL, NULL, NULL, LTPT, LTPT, LSRS, NULL,
|
{LTPT, NULL, NULL, NULL, NULL, NULL, NULL, LTPT, LTPT, LSRS, NULL},
|
||||||
LTRT},
|
|
||||||
/*!T*/
|
/*!T*/
|
||||||
{PTLT, NULL, NULL, NULL, NULL, NULL, NULL, PTLT, LTRT, LSRS, NULL,
|
{PTLT, NULL, NULL, NULL, NULL, NULL, NULL, PTLT, LTRT, LSRS, NULL},
|
||||||
LTRT},
|
|
||||||
/*HT*/
|
/*HT*/
|
||||||
{LSRS, LSRS, LSRS, LSRS, LSRS, LSRS, LSRS, LSRS, LSRS, LSRS, NULL,
|
{LSRS, LSRS, LSRS, LSRS, LSRS, LSRS, LSRS, LSRS, LSRS, LSRS, NULL},
|
||||||
LSRS},
|
|
||||||
/*PR*/
|
/*PR*/
|
||||||
{NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
{NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
|
||||||
NULL},
|
|
||||||
/*PR*/
|
|
||||||
{LTRT, LTRT, LTRT, LTRT, LTRT, LTRT, LTRT, LTRT, LTRT, LSRS, NULL,
|
|
||||||
LTRT},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// The actual tests that exercise all the various configurations.
|
// The actual tests that exercise all the various configurations.
|
||||||
|
@ -1316,8 +1283,7 @@ const P2PTransportChannelMatrixTest::Result*
|
||||||
P2P_TEST(x, BLOCK_UDP) \
|
P2P_TEST(x, BLOCK_UDP) \
|
||||||
P2P_TEST(x, BLOCK_UDP_AND_INCOMING_TCP) \
|
P2P_TEST(x, BLOCK_UDP_AND_INCOMING_TCP) \
|
||||||
P2P_TEST(x, BLOCK_ALL_BUT_OUTGOING_HTTP) \
|
P2P_TEST(x, BLOCK_ALL_BUT_OUTGOING_HTTP) \
|
||||||
P2P_TEST(x, PROXY_HTTPS) \
|
P2P_TEST(x, PROXY_HTTPS)
|
||||||
P2P_TEST(x, PROXY_SOCKS)
|
|
||||||
|
|
||||||
P2P_TEST_SET(OPEN)
|
P2P_TEST_SET(OPEN)
|
||||||
P2P_TEST_SET(NAT_FULL_CONE)
|
P2P_TEST_SET(NAT_FULL_CONE)
|
||||||
|
@ -1330,7 +1296,6 @@ P2P_TEST_SET(BLOCK_UDP)
|
||||||
P2P_TEST_SET(BLOCK_UDP_AND_INCOMING_TCP)
|
P2P_TEST_SET(BLOCK_UDP_AND_INCOMING_TCP)
|
||||||
P2P_TEST_SET(BLOCK_ALL_BUT_OUTGOING_HTTP)
|
P2P_TEST_SET(BLOCK_ALL_BUT_OUTGOING_HTTP)
|
||||||
P2P_TEST_SET(PROXY_HTTPS)
|
P2P_TEST_SET(PROXY_HTTPS)
|
||||||
P2P_TEST_SET(PROXY_SOCKS)
|
|
||||||
|
|
||||||
INSTANTIATE_TEST_SUITE_P(
|
INSTANTIATE_TEST_SUITE_P(
|
||||||
All,
|
All,
|
||||||
|
|
|
@ -2088,7 +2088,6 @@ if (rtc_include_tests) {
|
||||||
"nat_unittest.cc",
|
"nat_unittest.cc",
|
||||||
"network_route_unittest.cc",
|
"network_route_unittest.cc",
|
||||||
"network_unittest.cc",
|
"network_unittest.cc",
|
||||||
"proxy_unittest.cc",
|
|
||||||
"rolling_accumulator_unittest.cc",
|
"rolling_accumulator_unittest.cc",
|
||||||
"rtc_certificate_generator_unittest.cc",
|
"rtc_certificate_generator_unittest.cc",
|
||||||
"rtc_certificate_unittest.cc",
|
"rtc_certificate_unittest.cc",
|
||||||
|
|
|
@ -149,8 +149,4 @@ void ProxyBinding::Destroy() {
|
||||||
SignalDestroyed(this);
|
SignalDestroyed(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncProxyServerSocket* SocksProxyServer::WrapSocket(Socket* socket) {
|
|
||||||
return new AsyncSocksProxyServerSocket(socket);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace rtc
|
} // namespace rtc
|
||||||
|
|
|
@ -89,22 +89,6 @@ class ProxyServer : public sigslot::has_slots<> {
|
||||||
std::vector<std::unique_ptr<ProxyBinding>> bindings_;
|
std::vector<std::unique_ptr<ProxyBinding>> bindings_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// SocksProxyServer is a simple extension of ProxyServer to implement SOCKS.
|
|
||||||
class SocksProxyServer : public ProxyServer {
|
|
||||||
public:
|
|
||||||
SocksProxyServer(SocketFactory* int_factory,
|
|
||||||
const SocketAddress& int_addr,
|
|
||||||
SocketFactory* ext_factory,
|
|
||||||
const SocketAddress& ext_ip)
|
|
||||||
: ProxyServer(int_factory, int_addr, ext_factory, ext_ip) {}
|
|
||||||
|
|
||||||
SocksProxyServer(const SocksProxyServer&) = delete;
|
|
||||||
SocksProxyServer& operator=(const SocksProxyServer&) = delete;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
AsyncProxyServerSocket* WrapSocket(Socket* socket) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace rtc
|
} // namespace rtc
|
||||||
|
|
||||||
#endif // RTC_BASE_PROXY_SERVER_H_
|
#endif // RTC_BASE_PROXY_SERVER_H_
|
||||||
|
|
|
@ -1,68 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2009 The WebRTC Project Authors. All rights reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by a BSD-style license
|
|
||||||
* that can be found in the LICENSE file in the root of the source
|
|
||||||
* tree. An additional intellectual property rights grant can be found
|
|
||||||
* in the file PATENTS. All contributing project authors may
|
|
||||||
* be found in the AUTHORS file in the root of the source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "rtc_base/gunit.h"
|
|
||||||
#include "rtc_base/proxy_server.h"
|
|
||||||
#include "rtc_base/socket_adapters.h"
|
|
||||||
#include "rtc_base/test_client.h"
|
|
||||||
#include "rtc_base/test_echo_server.h"
|
|
||||||
#include "rtc_base/virtual_socket_server.h"
|
|
||||||
|
|
||||||
using rtc::Socket;
|
|
||||||
using rtc::SocketAddress;
|
|
||||||
|
|
||||||
static const SocketAddress kSocksProxyIntAddr("1.2.3.4", 1080);
|
|
||||||
static const SocketAddress kSocksProxyExtAddr("1.2.3.5", 0);
|
|
||||||
static const SocketAddress kBogusProxyIntAddr("1.2.3.4", 999);
|
|
||||||
|
|
||||||
// Sets up a virtual socket server and a SOCKS5 proxy server.
|
|
||||||
class ProxyTest : public ::testing::Test {
|
|
||||||
public:
|
|
||||||
ProxyTest() : ss_(new rtc::VirtualSocketServer()), thread_(ss_.get()) {
|
|
||||||
socks_.reset(new rtc::SocksProxyServer(ss_.get(), kSocksProxyIntAddr,
|
|
||||||
ss_.get(), kSocksProxyExtAddr));
|
|
||||||
}
|
|
||||||
|
|
||||||
rtc::SocketServer* ss() { return ss_.get(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::unique_ptr<rtc::SocketServer> ss_;
|
|
||||||
rtc::AutoSocketServerThread thread_;
|
|
||||||
std::unique_ptr<rtc::SocksProxyServer> socks_;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Tests whether we can use a SOCKS5 proxy to connect to a server.
|
|
||||||
TEST_F(ProxyTest, TestSocks5Connect) {
|
|
||||||
rtc::Socket* socket =
|
|
||||||
ss()->CreateSocket(kSocksProxyIntAddr.family(), SOCK_STREAM);
|
|
||||||
rtc::AsyncSocksProxySocket* proxy_socket = new rtc::AsyncSocksProxySocket(
|
|
||||||
socket, kSocksProxyIntAddr, "", rtc::CryptString());
|
|
||||||
// TODO: IPv6-ize these tests when proxy supports IPv6.
|
|
||||||
|
|
||||||
rtc::TestEchoServer server(rtc::Thread::Current(),
|
|
||||||
SocketAddress(INADDR_ANY, 0));
|
|
||||||
|
|
||||||
std::unique_ptr<rtc::AsyncTCPSocket> packet_socket(
|
|
||||||
rtc::AsyncTCPSocket::Create(proxy_socket, SocketAddress(INADDR_ANY, 0),
|
|
||||||
server.address()));
|
|
||||||
EXPECT_TRUE(packet_socket != nullptr);
|
|
||||||
rtc::TestClient client(std::move(packet_socket));
|
|
||||||
|
|
||||||
EXPECT_EQ(Socket::CS_CONNECTING, proxy_socket->GetState());
|
|
||||||
EXPECT_TRUE(client.CheckConnected());
|
|
||||||
EXPECT_EQ(Socket::CS_CONNECTED, proxy_socket->GetState());
|
|
||||||
EXPECT_EQ(server.address(), client.remote_address());
|
|
||||||
client.Send("foo", 3);
|
|
||||||
EXPECT_TRUE(client.CheckNextPacket("foo", 3, nullptr));
|
|
||||||
EXPECT_TRUE(client.CheckNoPacket());
|
|
||||||
}
|
|
|
@ -55,135 +55,4 @@ void AsyncSSLServerSocket::ProcessInput(char* data, size_t* len) {
|
||||||
BufferInput(false);
|
BufferInput(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncSocksProxyServerSocket::AsyncSocksProxyServerSocket(Socket* socket)
|
|
||||||
: AsyncProxyServerSocket(socket, kBufferSize), state_(SS_HELLO) {
|
|
||||||
BufferInput(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AsyncSocksProxyServerSocket::ProcessInput(char* data, size_t* len) {
|
|
||||||
RTC_DCHECK(state_ < SS_CONNECT_PENDING);
|
|
||||||
|
|
||||||
ByteBufferReader response(
|
|
||||||
rtc::MakeArrayView(reinterpret_cast<const uint8_t*>(data), *len));
|
|
||||||
if (state_ == SS_HELLO) {
|
|
||||||
HandleHello(&response);
|
|
||||||
} else if (state_ == SS_AUTH) {
|
|
||||||
HandleAuth(&response);
|
|
||||||
} else if (state_ == SS_CONNECT) {
|
|
||||||
HandleConnect(&response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Consume parsed data
|
|
||||||
*len = response.Length();
|
|
||||||
if (response.Length() > 0) {
|
|
||||||
memmove(data, response.DataView().data(), *len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AsyncSocksProxyServerSocket::DirectSend(const ByteBufferWriter& buf) {
|
|
||||||
BufferedReadAdapter::DirectSend(buf.Data(), buf.Length());
|
|
||||||
}
|
|
||||||
|
|
||||||
void AsyncSocksProxyServerSocket::HandleHello(ByteBufferReader* request) {
|
|
||||||
uint8_t ver, num_methods;
|
|
||||||
if (!request->ReadUInt8(&ver) || !request->ReadUInt8(&num_methods)) {
|
|
||||||
Error(0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ver != 5) {
|
|
||||||
Error(0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle either no-auth (0) or user/pass auth (2)
|
|
||||||
uint8_t method = 0xFF;
|
|
||||||
if (num_methods > 0 && !request->ReadUInt8(&method)) {
|
|
||||||
Error(0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SendHelloReply(method);
|
|
||||||
if (method == 0) {
|
|
||||||
state_ = SS_CONNECT;
|
|
||||||
} else if (method == 2) {
|
|
||||||
state_ = SS_AUTH;
|
|
||||||
} else {
|
|
||||||
state_ = SS_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AsyncSocksProxyServerSocket::SendHelloReply(uint8_t method) {
|
|
||||||
ByteBufferWriter response;
|
|
||||||
response.WriteUInt8(5); // Socks Version
|
|
||||||
response.WriteUInt8(method); // Auth method
|
|
||||||
DirectSend(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AsyncSocksProxyServerSocket::HandleAuth(ByteBufferReader* request) {
|
|
||||||
uint8_t ver, user_len, pass_len;
|
|
||||||
std::string user, pass;
|
|
||||||
if (!request->ReadUInt8(&ver) || !request->ReadUInt8(&user_len) ||
|
|
||||||
!request->ReadString(&user, user_len) || !request->ReadUInt8(&pass_len) ||
|
|
||||||
!request->ReadString(&pass, pass_len)) {
|
|
||||||
Error(0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SendAuthReply(0);
|
|
||||||
state_ = SS_CONNECT;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AsyncSocksProxyServerSocket::SendAuthReply(uint8_t result) {
|
|
||||||
ByteBufferWriter response;
|
|
||||||
response.WriteUInt8(1); // Negotiation Version
|
|
||||||
response.WriteUInt8(result);
|
|
||||||
DirectSend(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AsyncSocksProxyServerSocket::HandleConnect(ByteBufferReader* request) {
|
|
||||||
uint8_t ver, command, reserved, addr_type;
|
|
||||||
uint32_t ip;
|
|
||||||
uint16_t port;
|
|
||||||
if (!request->ReadUInt8(&ver) || !request->ReadUInt8(&command) ||
|
|
||||||
!request->ReadUInt8(&reserved) || !request->ReadUInt8(&addr_type) ||
|
|
||||||
!request->ReadUInt32(&ip) || !request->ReadUInt16(&port)) {
|
|
||||||
Error(0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ver != 5 || command != 1 || reserved != 0 || addr_type != 1) {
|
|
||||||
Error(0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SignalConnectRequest(this, SocketAddress(ip, port));
|
|
||||||
state_ = SS_CONNECT_PENDING;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AsyncSocksProxyServerSocket::SendConnectResult(int result,
|
|
||||||
const SocketAddress& addr) {
|
|
||||||
if (state_ != SS_CONNECT_PENDING)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ByteBufferWriter response;
|
|
||||||
response.WriteUInt8(5); // Socks version
|
|
||||||
response.WriteUInt8((result != 0)); // 0x01 is generic error
|
|
||||||
response.WriteUInt8(0); // reserved
|
|
||||||
response.WriteUInt8(1); // IPv4 address
|
|
||||||
response.WriteUInt32(addr.ip());
|
|
||||||
response.WriteUInt16(addr.port());
|
|
||||||
DirectSend(response);
|
|
||||||
BufferInput(false);
|
|
||||||
state_ = SS_TUNNEL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AsyncSocksProxyServerSocket::Error(int error) {
|
|
||||||
state_ = SS_ERROR;
|
|
||||||
BufferInput(false);
|
|
||||||
Close();
|
|
||||||
SetError(SOCKET_EACCES);
|
|
||||||
SignalCloseEvent(this, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace rtc
|
} // namespace rtc
|
||||||
|
|
|
@ -38,40 +38,6 @@ class AsyncSSLServerSocket : public BufferedReadAdapter {
|
||||||
void ProcessInput(char* data, size_t* len) override;
|
void ProcessInput(char* data, size_t* len) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Implements a proxy server socket for the SOCKS protocol.
|
|
||||||
class AsyncSocksProxyServerSocket : public AsyncProxyServerSocket {
|
|
||||||
public:
|
|
||||||
explicit AsyncSocksProxyServerSocket(Socket* socket);
|
|
||||||
|
|
||||||
AsyncSocksProxyServerSocket(const AsyncSocksProxyServerSocket&) = delete;
|
|
||||||
AsyncSocksProxyServerSocket& operator=(const AsyncSocksProxyServerSocket&) =
|
|
||||||
delete;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void ProcessInput(char* data, size_t* len) override;
|
|
||||||
void DirectSend(const ByteBufferWriter& buf);
|
|
||||||
|
|
||||||
void HandleHello(ByteBufferReader* request);
|
|
||||||
void SendHelloReply(uint8_t method);
|
|
||||||
void HandleAuth(ByteBufferReader* request);
|
|
||||||
void SendAuthReply(uint8_t result);
|
|
||||||
void HandleConnect(ByteBufferReader* request);
|
|
||||||
void SendConnectResult(int result, const SocketAddress& addr) override;
|
|
||||||
|
|
||||||
void Error(int error);
|
|
||||||
|
|
||||||
static const int kBufferSize = 1024;
|
|
||||||
enum State {
|
|
||||||
SS_HELLO,
|
|
||||||
SS_AUTH,
|
|
||||||
SS_CONNECT,
|
|
||||||
SS_CONNECT_PENDING,
|
|
||||||
SS_TUNNEL,
|
|
||||||
SS_ERROR
|
|
||||||
};
|
|
||||||
State state_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace rtc
|
} // namespace rtc
|
||||||
|
|
||||||
#endif // RTC_BASE_SERVER_SOCKET_ADAPTERS_H_
|
#endif // RTC_BASE_SERVER_SOCKET_ADAPTERS_H_
|
||||||
|
|
|
@ -469,198 +469,4 @@ void AsyncHttpsProxySocket::Error(int error) {
|
||||||
SignalCloseEvent(this, error);
|
SignalCloseEvent(this, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
AsyncSocksProxySocket::AsyncSocksProxySocket(Socket* socket,
|
|
||||||
const SocketAddress& proxy,
|
|
||||||
absl::string_view username,
|
|
||||||
const CryptString& password)
|
|
||||||
: BufferedReadAdapter(socket, 1024),
|
|
||||||
state_(SS_ERROR),
|
|
||||||
proxy_(proxy),
|
|
||||||
user_(username),
|
|
||||||
pass_(password) {}
|
|
||||||
|
|
||||||
AsyncSocksProxySocket::~AsyncSocksProxySocket() = default;
|
|
||||||
|
|
||||||
int AsyncSocksProxySocket::Connect(const SocketAddress& addr) {
|
|
||||||
int ret;
|
|
||||||
dest_ = addr;
|
|
||||||
state_ = SS_INIT;
|
|
||||||
BufferInput(true);
|
|
||||||
ret = BufferedReadAdapter::Connect(proxy_);
|
|
||||||
// TODO: Set state_ appropriately if Connect fails.
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
SocketAddress AsyncSocksProxySocket::GetRemoteAddress() const {
|
|
||||||
return dest_;
|
|
||||||
}
|
|
||||||
|
|
||||||
int AsyncSocksProxySocket::Close() {
|
|
||||||
state_ = SS_ERROR;
|
|
||||||
dest_.Clear();
|
|
||||||
return BufferedReadAdapter::Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
Socket::ConnState AsyncSocksProxySocket::GetState() const {
|
|
||||||
if (state_ < SS_TUNNEL) {
|
|
||||||
return CS_CONNECTING;
|
|
||||||
} else if (state_ == SS_TUNNEL) {
|
|
||||||
return CS_CONNECTED;
|
|
||||||
} else {
|
|
||||||
return CS_CLOSED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AsyncSocksProxySocket::OnConnectEvent(Socket* socket) {
|
|
||||||
SendHello();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AsyncSocksProxySocket::ProcessInput(char* data, size_t* len) {
|
|
||||||
RTC_DCHECK(state_ < SS_TUNNEL);
|
|
||||||
|
|
||||||
ByteBufferReader response(
|
|
||||||
rtc::MakeArrayView(reinterpret_cast<uint8_t*>(data), *len));
|
|
||||||
|
|
||||||
if (state_ == SS_HELLO) {
|
|
||||||
uint8_t ver, method;
|
|
||||||
if (!response.ReadUInt8(&ver) || !response.ReadUInt8(&method))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (ver != 5) {
|
|
||||||
Error(0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (method == 0) {
|
|
||||||
SendConnect();
|
|
||||||
} else if (method == 2) {
|
|
||||||
SendAuth();
|
|
||||||
} else {
|
|
||||||
Error(0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (state_ == SS_AUTH) {
|
|
||||||
uint8_t ver, status;
|
|
||||||
if (!response.ReadUInt8(&ver) || !response.ReadUInt8(&status))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if ((ver != 1) || (status != 0)) {
|
|
||||||
Error(SOCKET_EACCES);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SendConnect();
|
|
||||||
} else if (state_ == SS_CONNECT) {
|
|
||||||
uint8_t ver, rep, rsv, atyp;
|
|
||||||
if (!response.ReadUInt8(&ver) || !response.ReadUInt8(&rep) ||
|
|
||||||
!response.ReadUInt8(&rsv) || !response.ReadUInt8(&atyp))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if ((ver != 5) || (rep != 0)) {
|
|
||||||
Error(0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t port;
|
|
||||||
if (atyp == 1) {
|
|
||||||
uint32_t addr;
|
|
||||||
if (!response.ReadUInt32(&addr) || !response.ReadUInt16(&port))
|
|
||||||
return;
|
|
||||||
RTC_LOG(LS_VERBOSE) << "Bound on " << addr << ":" << port;
|
|
||||||
} else if (atyp == 3) {
|
|
||||||
uint8_t length;
|
|
||||||
std::string addr;
|
|
||||||
if (!response.ReadUInt8(&length) || !response.ReadString(&addr, length) ||
|
|
||||||
!response.ReadUInt16(&port))
|
|
||||||
return;
|
|
||||||
RTC_LOG(LS_VERBOSE) << "Bound on " << addr << ":" << port;
|
|
||||||
} else if (atyp == 4) {
|
|
||||||
std::string addr;
|
|
||||||
if (!response.ReadString(&addr, 16) || !response.ReadUInt16(&port))
|
|
||||||
return;
|
|
||||||
RTC_LOG(LS_VERBOSE) << "Bound on <IPV6>:" << port;
|
|
||||||
} else {
|
|
||||||
Error(0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
state_ = SS_TUNNEL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Consume parsed data
|
|
||||||
*len = response.Length();
|
|
||||||
memmove(data, response.Data(), *len);
|
|
||||||
|
|
||||||
if (state_ != SS_TUNNEL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
bool remainder = (*len > 0);
|
|
||||||
BufferInput(false);
|
|
||||||
SignalConnectEvent(this);
|
|
||||||
|
|
||||||
// FIX: if SignalConnect causes the socket to be destroyed, we are in trouble
|
|
||||||
if (remainder)
|
|
||||||
SignalReadEvent(this); // TODO: signal this??
|
|
||||||
}
|
|
||||||
|
|
||||||
void AsyncSocksProxySocket::SendHello() {
|
|
||||||
ByteBufferWriter request;
|
|
||||||
request.WriteUInt8(5); // Socks Version
|
|
||||||
if (user_.empty()) {
|
|
||||||
request.WriteUInt8(1); // Authentication Mechanisms
|
|
||||||
request.WriteUInt8(0); // No authentication
|
|
||||||
} else {
|
|
||||||
request.WriteUInt8(2); // Authentication Mechanisms
|
|
||||||
request.WriteUInt8(0); // No authentication
|
|
||||||
request.WriteUInt8(2); // Username/Password
|
|
||||||
}
|
|
||||||
DirectSend(request.Data(), request.Length());
|
|
||||||
state_ = SS_HELLO;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AsyncSocksProxySocket::SendAuth() {
|
|
||||||
ByteBufferWriterT<ZeroOnFreeBuffer<char>> request;
|
|
||||||
request.WriteUInt8(1); // Negotiation Version
|
|
||||||
request.WriteUInt8(static_cast<uint8_t>(user_.size()));
|
|
||||||
request.WriteString(user_); // Username
|
|
||||||
request.WriteUInt8(static_cast<uint8_t>(pass_.GetLength()));
|
|
||||||
size_t len = pass_.GetLength() + 1;
|
|
||||||
char* sensitive = new char[len];
|
|
||||||
pass_.CopyTo(sensitive, true);
|
|
||||||
request.WriteString(std::string(sensitive, pass_.GetLength())); // Password
|
|
||||||
ExplicitZeroMemory(sensitive, len);
|
|
||||||
delete[] sensitive;
|
|
||||||
DirectSend(request.Data(), request.Length());
|
|
||||||
state_ = SS_AUTH;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AsyncSocksProxySocket::SendConnect() {
|
|
||||||
ByteBufferWriter request;
|
|
||||||
request.WriteUInt8(5); // Socks Version
|
|
||||||
request.WriteUInt8(1); // CONNECT
|
|
||||||
request.WriteUInt8(0); // Reserved
|
|
||||||
if (dest_.IsUnresolvedIP()) {
|
|
||||||
std::string hostname = dest_.hostname();
|
|
||||||
request.WriteUInt8(3); // DOMAINNAME
|
|
||||||
request.WriteUInt8(static_cast<uint8_t>(hostname.size()));
|
|
||||||
request.WriteString(hostname); // Destination Hostname
|
|
||||||
} else {
|
|
||||||
request.WriteUInt8(1); // IPV4
|
|
||||||
request.WriteUInt32(dest_.ip()); // Destination IP
|
|
||||||
}
|
|
||||||
request.WriteUInt16(dest_.port()); // Destination Port
|
|
||||||
DirectSend(request.Data(), request.Length());
|
|
||||||
state_ = SS_CONNECT;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AsyncSocksProxySocket::Error(int error) {
|
|
||||||
state_ = SS_ERROR;
|
|
||||||
BufferInput(false);
|
|
||||||
Close();
|
|
||||||
SetError(SOCKET_EACCES);
|
|
||||||
SignalCloseEvent(this, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace rtc
|
} // namespace rtc
|
||||||
|
|
|
@ -137,42 +137,6 @@ class AsyncHttpsProxySocket : public BufferedReadAdapter {
|
||||||
std::string unknown_mechanisms_;
|
std::string unknown_mechanisms_;
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Implements a socket adapter that speaks the SOCKS proxy protocol.
|
|
||||||
class AsyncSocksProxySocket : public BufferedReadAdapter {
|
|
||||||
public:
|
|
||||||
AsyncSocksProxySocket(Socket* socket,
|
|
||||||
const SocketAddress& proxy,
|
|
||||||
absl::string_view username,
|
|
||||||
const CryptString& password);
|
|
||||||
~AsyncSocksProxySocket() override;
|
|
||||||
|
|
||||||
AsyncSocksProxySocket(const AsyncSocksProxySocket&) = delete;
|
|
||||||
AsyncSocksProxySocket& operator=(const AsyncSocksProxySocket&) = delete;
|
|
||||||
|
|
||||||
int Connect(const SocketAddress& addr) override;
|
|
||||||
SocketAddress GetRemoteAddress() const override;
|
|
||||||
int Close() override;
|
|
||||||
ConnState GetState() const override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void OnConnectEvent(Socket* socket) override;
|
|
||||||
void ProcessInput(char* data, size_t* len) override;
|
|
||||||
|
|
||||||
void SendHello();
|
|
||||||
void SendConnect();
|
|
||||||
void SendAuth();
|
|
||||||
void Error(int error);
|
|
||||||
|
|
||||||
private:
|
|
||||||
enum State { SS_INIT, SS_HELLO, SS_AUTH, SS_CONNECT, SS_TUNNEL, SS_ERROR };
|
|
||||||
State state_;
|
|
||||||
SocketAddress proxy_, dest_;
|
|
||||||
std::string user_;
|
|
||||||
CryptString pass_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace rtc
|
} // namespace rtc
|
||||||
|
|
||||||
#endif // RTC_BASE_SOCKET_ADAPTERS_H_
|
#endif // RTC_BASE_SOCKET_ADAPTERS_H_
|
||||||
|
|
Loading…
Reference in a new issue