diff --git a/src/net/socket/client_socket_pool_manager.cc b/src/net/socket/client_socket_pool_manager.cc index d25b67c819..5422cc75ad 100644 --- a/src/net/socket/client_socket_pool_manager.cc +++ b/src/net/socket/client_socket_pool_manager.cc @@ -243,7 +243,7 @@ int InitSocketPoolHelper(ClientSocketPoolManager::SocketGroupType group_type, // Finally, get the connection started. - if (proxy_info.is_http() || proxy_info.is_https()) { + if (proxy_info.is_http() || proxy_info.is_https() || proxy_info.is_quic()) { HttpProxyClientSocketPool* pool = session->GetSocketPoolForHTTPProxy(socket_pool_type, *proxy_host_port); if (num_preconnect_streams) { diff --git a/src/net/tools/naive/naive_connection.cc b/src/net/tools/naive/naive_connection.cc index 81977723a3..c467e1a894 100644 --- a/src/net/tools/naive/naive_connection.cc +++ b/src/net/tools/naive/naive_connection.cc @@ -12,18 +12,17 @@ #include "base/callback_helpers.h" #include "base/logging.h" #include "base/rand_util.h" +#include "base/strings/strcat.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" #include "net/base/privacy_mode.h" -#include "net/http/http_network_session.h" -#include "net/proxy_resolution/proxy_config.h" #include "net/proxy_resolution/proxy_info.h" -#include "net/proxy_resolution/proxy_list.h" -#include "net/proxy_resolution/proxy_resolution_service.h" #include "net/socket/client_socket_handle.h" #include "net/socket/client_socket_pool_manager.h" #include "net/socket/stream_socket.h" #include "net/spdy/spdy_session.h" +#include "net/tools/naive/http_proxy_socket.h" +#include "net/tools/naive/socks5_server_socket.h" namespace net { @@ -36,14 +35,24 @@ constexpr int kMaxPaddingSize = 255; NaiveConnection::NaiveConnection( unsigned int id, + Protocol protocol, Direction pad_direction, + const ProxyInfo& proxy_info, + const SSLConfig& server_ssl_config, + const SSLConfig& proxy_ssl_config, + HttpNetworkSession* session, + const NetLogWithSource& net_log, std::unique_ptr accepted_socket, - Delegate* delegate, const NetworkTrafficAnnotationTag& traffic_annotation) : id_(id), + protocol_(protocol), pad_direction_(pad_direction), + proxy_info_(proxy_info), + server_ssl_config_(server_ssl_config), + proxy_ssl_config_(proxy_ssl_config), + session_(session), + net_log_(net_log), next_state_(STATE_NONE), - delegate_(delegate), client_socket_(std::move(accepted_socket)), server_socket_handle_(std::make_unique()), sockets_{client_socket_.get(), nullptr}, @@ -166,11 +175,38 @@ int NaiveConnection::DoConnectClientComplete(int result) { } int NaiveConnection::DoConnectServer() { - DCHECK(delegate_); next_state_ = STATE_CONNECT_SERVER_COMPLETE; - return delegate_->OnConnectServer(id_, client_socket_.get(), - server_socket_handle_.get(), io_callback_); + HostPortPair origin; + if (protocol_ == kSocks5) { + const auto* socket = + static_cast(client_socket_.get()); + origin = socket->request_endpoint(); + } else if (protocol_ == kHttp) { + const auto* socket = + static_cast(client_socket_.get()); + origin = socket->request_endpoint(); + } + + if (origin.IsEmpty()) { + LOG(ERROR) << "Connection " << id_ << " to invalid origin"; + return ERR_ADDRESS_INVALID; + } + + LOG(INFO) << "Connection " << id_ << " to " << origin.ToString(); + + auto quic_version = quic::QUIC_VERSION_UNSUPPORTED; + const auto& quic_versions = session_->params().quic_supported_versions; + if (proxy_info_.is_quic() && !quic_versions.empty()) { + quic_version = quic_versions[0]; + } + + // Ignores socket limit set by socket pool for this type of socket. + return InitSocketHandleForRawConnect2( + origin, session_, LOAD_IGNORE_LIMITS, MAXIMUM_PRIORITY, proxy_info_, + quic_version, server_ssl_config_, proxy_ssl_config_, + PRIVACY_MODE_DISABLED, net_log_, server_socket_handle_.get(), + io_callback_); } int NaiveConnection::DoConnectServerComplete(int result) { diff --git a/src/net/tools/naive/naive_connection.h b/src/net/tools/naive/naive_connection.h index 89a92cb856..4561c2695c 100644 --- a/src/net/tools/naive/naive_connection.h +++ b/src/net/tools/naive/naive_connection.h @@ -20,14 +20,23 @@ namespace net { class ClientSocketHandle; class DrainableIOBuffer; +class HttpNetworkSession; class IOBuffer; +class NetLogWithSource; +class ProxyInfo; class StreamSocket; struct NetworkTrafficAnnotationTag; +struct SSLConfig; class NaiveConnection { public: using TimeFunc = base::TimeTicks (*)(); + enum Protocol { + kSocks5, + kHttp, + }; + // From this direction. enum Direction { kClient = 0, @@ -36,24 +45,15 @@ class NaiveConnection { kNone = 2, }; - class Delegate { - public: - Delegate() {} - virtual ~Delegate() {} - - virtual int OnConnectServer(unsigned int connection_id, - const StreamSocket* accepted_socket, - ClientSocketHandle* server_socket, - CompletionRepeatingCallback callback) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(Delegate); - }; - NaiveConnection(unsigned int id, + Protocol protocol, Direction pad_direction, + const ProxyInfo& proxy_info, + const SSLConfig& server_ssl_config, + const SSLConfig& proxy_ssl_config, + HttpNetworkSession* session, + const NetLogWithSource& net_log, std::unique_ptr accepted_socket, - Delegate* delegate, const NetworkTrafficAnnotationTag& traffic_annotation); ~NaiveConnection(); @@ -97,7 +97,13 @@ class NaiveConnection { void OnPushComplete(Direction from, Direction to, int result); unsigned int id_; + Protocol protocol_; Direction pad_direction_; + const ProxyInfo& proxy_info_; + const SSLConfig& server_ssl_config_; + const SSLConfig& proxy_ssl_config_; + HttpNetworkSession* session_; + const NetLogWithSource& net_log_; CompletionRepeatingCallback io_callback_; CompletionOnceCallback connect_callback_; @@ -105,8 +111,6 @@ class NaiveConnection { State next_state_; - Delegate* delegate_; - std::unique_ptr client_socket_; std::unique_ptr server_socket_handle_; diff --git a/src/net/tools/naive/naive_proxy.cc b/src/net/tools/naive/naive_proxy.cc index f202391637..afe1a1d552 100644 --- a/src/net/tools/naive/naive_proxy.cc +++ b/src/net/tools/naive/naive_proxy.cc @@ -14,7 +14,6 @@ #include "net/base/net_errors.h" #include "net/http/http_network_session.h" #include "net/proxy_resolution/proxy_config.h" -#include "net/proxy_resolution/proxy_info.h" #include "net/proxy_resolution/proxy_list.h" #include "net/proxy_resolution/proxy_resolution_service.h" #include "net/socket/client_socket_pool_manager.h" @@ -27,19 +26,32 @@ namespace net { NaiveProxy::NaiveProxy(std::unique_ptr listen_socket, - Protocol protocol, - bool use_proxy, + NaiveConnection::Protocol protocol, + bool use_padding, HttpNetworkSession* session, const NetworkTrafficAnnotationTag& traffic_annotation) : listen_socket_(std::move(listen_socket)), protocol_(protocol), - use_proxy_(use_proxy), + use_padding_(use_padding), session_(session), net_log_( NetLogWithSource::Make(session->net_log(), NetLogSourceType::NONE)), last_id_(0), traffic_annotation_(traffic_annotation), weak_ptr_factory_(this) { + const auto& proxy_config = session_->proxy_resolution_service()->config(); + DCHECK(proxy_config); + const ProxyList& proxy_list = + proxy_config.value().value().proxy_rules().single_proxies; + DCHECK(!proxy_list.IsEmpty()); + proxy_info_.UseProxyList(proxy_list); + proxy_info_.set_traffic_annotation( + net::MutableNetworkTrafficAnnotationTag(traffic_annotation_)); + + HttpRequestInfo req_info; + session_->GetSSLConfig(req_info, &server_ssl_config_, &proxy_ssl_config_); + proxy_ssl_config_.disable_cert_verification_network_fetches = true; + DCHECK(listen_socket_); // Start accepting connections in next run loop in case when delegate is not // ready to get callbacks. @@ -79,19 +91,24 @@ void NaiveProxy::HandleAcceptResult(int result) { void NaiveProxy::DoConnect() { std::unique_ptr socket; NaiveConnection::Direction pad_direction; - if (protocol_ == kSocks5) { + if (protocol_ == NaiveConnection::kSocks5) { socket = std::make_unique(std::move(accepted_socket_), traffic_annotation_); pad_direction = NaiveConnection::kClient; - } else if (protocol_ == kHttp) { + } else if (protocol_ == NaiveConnection::kHttp) { socket = std::make_unique(std::move(accepted_socket_), traffic_annotation_); pad_direction = NaiveConnection::kServer; } else { return; } + if (!use_padding_) { + pad_direction = NaiveConnection::kNone; + } auto connection_ptr = std::make_unique( - ++last_id_, pad_direction, std::move(socket), this, traffic_annotation_); + ++last_id_, protocol_, pad_direction, proxy_info_, server_ssl_config_, + proxy_ssl_config_, session_, net_log_, std::move(socket), + traffic_annotation_); auto* connection = connection_ptr.get(); connection_by_id_[connection->id()] = std::move(connection_ptr); int result = connection->Connect( @@ -102,62 +119,8 @@ void NaiveProxy::DoConnect() { HandleConnectResult(connection, result); } -int NaiveProxy::OnConnectServer(unsigned int connection_id, - const StreamSocket* client_socket, - ClientSocketHandle* server_socket, - CompletionRepeatingCallback callback) { - // Ignores socket limit set by socket pool for this type of socket. - constexpr int request_load_flags = LOAD_IGNORE_LIMITS; - constexpr RequestPriority request_priority = MAXIMUM_PRIORITY; - - ProxyInfo proxy_info; - SSLConfig server_ssl_config; - SSLConfig proxy_ssl_config; - - if (use_proxy_) { - const auto& proxy_config = session_->proxy_resolution_service()->config(); - DCHECK(proxy_config); - const ProxyList& proxy_list = - proxy_config.value().value().proxy_rules().single_proxies; - if (proxy_list.IsEmpty()) - return ERR_MANDATORY_PROXY_CONFIGURATION_FAILED; - proxy_info.UseProxyList(proxy_list); - proxy_info.set_traffic_annotation( - net::MutableNetworkTrafficAnnotationTag(traffic_annotation_)); - - HttpRequestInfo req_info; - session_->GetSSLConfig(req_info, &server_ssl_config, &proxy_ssl_config); - proxy_ssl_config.disable_cert_verification_network_fetches = true; - } else { - proxy_info.UseDirect(); - } - - HostPortPair request_endpoint; - if (protocol_ == kSocks5) { - const auto* socket = static_cast(client_socket); - request_endpoint = socket->request_endpoint(); - } else if (protocol_ == kHttp) { - const auto* socket = static_cast(client_socket); - request_endpoint = socket->request_endpoint(); - } - if (request_endpoint.IsEmpty()) { - LOG(ERROR) << "Connection " << connection_id << " to invalid origin"; - return ERR_ADDRESS_INVALID; - } - - LOG(INFO) << "Connection " << connection_id << " to " - << request_endpoint.ToString(); - - auto quic_version = quic::QUIC_VERSION_UNSUPPORTED; - - return InitSocketHandleForRawConnect2( - request_endpoint, session_, request_load_flags, request_priority, - proxy_info, quic_version, server_ssl_config, proxy_ssl_config, - PRIVACY_MODE_DISABLED, net_log_, server_socket, callback); -} - -void NaiveProxy::OnConnectComplete(int connection_id, int result) { - NaiveConnection* connection = FindConnection(connection_id); +void NaiveProxy::OnConnectComplete(unsigned int connection_id, int result) { + auto* connection = FindConnection(connection_id); if (!connection) return; HandleConnectResult(connection, result); @@ -180,8 +143,8 @@ void NaiveProxy::DoRun(NaiveConnection* connection) { HandleRunResult(connection, result); } -void NaiveProxy::OnRunComplete(int connection_id, int result) { - NaiveConnection* connection = FindConnection(connection_id); +void NaiveProxy::OnRunComplete(unsigned int connection_id, int result) { + auto* connection = FindConnection(connection_id); if (!connection) return; HandleRunResult(connection, result); @@ -191,7 +154,7 @@ void NaiveProxy::HandleRunResult(NaiveConnection* connection, int result) { Close(connection->id(), result); } -void NaiveProxy::Close(int connection_id, int reason) { +void NaiveProxy::Close(unsigned int connection_id, int reason) { auto it = connection_by_id_.find(connection_id); if (it == connection_by_id_.end()) return; @@ -208,19 +171,11 @@ void NaiveProxy::Close(int connection_id, int reason) { connection_by_id_.erase(it); } -NaiveConnection* NaiveProxy::FindConnection(int connection_id) { +NaiveConnection* NaiveProxy::FindConnection(unsigned int connection_id) { auto it = connection_by_id_.find(connection_id); if (it == connection_by_id_.end()) return nullptr; return it->second.get(); } -// This is called after any delegate callbacks are called to check if Close() -// has been called during callback processing. Using the pointer of connection, -// |connection| is safe here because Close() deletes the connection in next run -// loop. -bool NaiveProxy::HasClosedConnection(NaiveConnection* connection) { - return FindConnection(connection->id()) != connection; -} - } // namespace net diff --git a/src/net/tools/naive/naive_proxy.h b/src/net/tools/naive/naive_proxy.h index 877dfdd973..51739403b2 100644 --- a/src/net/tools/naive/naive_proxy.h +++ b/src/net/tools/naive/naive_proxy.h @@ -13,6 +13,8 @@ #include "base/memory/weak_ptr.h" #include "net/base/completion_repeating_callback.h" #include "net/log/net_log_with_source.h" +#include "net/proxy_resolution/proxy_info.h" +#include "net/ssl/ssl_config.h" #include "net/tools/naive/naive_connection.h" namespace net { @@ -24,24 +26,14 @@ class ServerSocket; class StreamSocket; struct NetworkTrafficAnnotationTag; -class NaiveProxy : public NaiveConnection::Delegate { +class NaiveProxy { public: - enum Protocol { - kSocks5, - kHttp, - }; - NaiveProxy(std::unique_ptr server_socket, - Protocol protocol, - bool use_proxy, + NaiveConnection::Protocol protocol, + bool use_padding, HttpNetworkSession* session, const NetworkTrafficAnnotationTag& traffic_annotation); - ~NaiveProxy() override; - - int OnConnectServer(unsigned int connection_id, - const StreamSocket* accepted_socket, - ClientSocketHandle* server_socket, - CompletionRepeatingCallback callback) override; + ~NaiveProxy(); private: void DoAcceptLoop(); @@ -49,21 +41,23 @@ class NaiveProxy : public NaiveConnection::Delegate { void HandleAcceptResult(int result); void DoConnect(); - void OnConnectComplete(int connection_id, int result); + void OnConnectComplete(unsigned int connection_id, int result); void HandleConnectResult(NaiveConnection* connection, int result); void DoRun(NaiveConnection* connection); - void OnRunComplete(int connection_id, int result); + void OnRunComplete(unsigned int connection_id, int result); void HandleRunResult(NaiveConnection* connection, int result); - void Close(int connection_id, int reason); + void Close(unsigned int connection_id, int reason); - NaiveConnection* FindConnection(int connection_id); - bool HasClosedConnection(NaiveConnection* connection); + NaiveConnection* FindConnection(unsigned int connection_id); std::unique_ptr listen_socket_; - Protocol protocol_; - bool use_proxy_; + NaiveConnection::Protocol protocol_; + bool use_padding_; + ProxyInfo proxy_info_; + SSLConfig server_ssl_config_; + SSLConfig proxy_ssl_config_; HttpNetworkSession* session_; NetLogWithSource net_log_; diff --git a/src/net/tools/naive/naive_proxy_bin.cc b/src/net/tools/naive/naive_proxy_bin.cc index e5754cc881..c0c4c86223 100644 --- a/src/net/tools/naive/naive_proxy_bin.cc +++ b/src/net/tools/naive/naive_proxy_bin.cc @@ -4,6 +4,7 @@ // found in the LICENSE file. #include +#include #include #include #include @@ -51,6 +52,7 @@ #include "net/url_request/url_request_context_builder.h" #include "url/gurl.h" #include "url/scheme_host_port.h" +#include "url/url_util.h" #if defined(OS_MACOSX) #include "base/mac/scoped_nsautorelease_pool.h" @@ -67,15 +69,16 @@ constexpr net::NetworkTrafficAnnotationTag kTrafficAnnotation = net::DefineNetworkTrafficAnnotation("naive", ""); struct Params { + net::NaiveConnection::Protocol protocol; std::string listen_addr; int listen_port; - net::NaiveProxy::Protocol protocol; - bool use_proxy; + bool use_padding; std::string proxy_url; std::string proxy_user; std::string proxy_pass; std::string host_resolver_rules; logging::LoggingSettings log_settings; + base::FilePath log_path; base::FilePath net_log_path; base::FilePath ssl_key_path; }; @@ -112,9 +115,7 @@ std::unique_ptr BuildURLRequestContext( builder.set_net_log(net_log); net::ProxyConfig proxy_config; - if (params.use_proxy) { - proxy_config.proxy_rules().ParseFromString(params.proxy_url); - } + proxy_config.proxy_rules().ParseFromString(params.proxy_url); auto proxy_service = net::ProxyResolutionService::CreateWithoutProxyResolver( std::make_unique( net::ProxyConfigWithAnnotation(proxy_config, kTrafficAnnotation)), @@ -131,10 +132,10 @@ std::unique_ptr BuildURLRequestContext( auto context = builder.Build(); - if (params.use_proxy) { - net::HttpNetworkSession* session = - context->http_transaction_factory()->GetSession(); - net::HttpAuthCache* auth_cache = session->http_auth_cache(); + if (!params.proxy_url.empty() && !params.proxy_user.empty() && + !params.proxy_pass.empty()) { + auto* session = context->http_transaction_factory()->GetSession(); + auto* auth_cache = session->http_auth_cache(); GURL auth_origin(params.proxy_url); net::AuthCredentials credentials(base::ASCIIToUTF16(params.proxy_user), base::ASCIIToUTF16(params.proxy_pass)); @@ -150,79 +151,73 @@ bool ParseCommandLineFlags(Params* params) { const base::CommandLine& line = *base::CommandLine::ForCurrentProcess(); if (line.HasSwitch("h") || line.HasSwitch("help")) { - LOG(INFO) << "Usage: naive [options]\n" + std::cout << "Usage: naive [options]\n" "\n" "Options:\n" "-h, --help Show this message\n" "--version Print version\n" - "--addr=
Address to listen on (0.0.0.0)\n" - "--port= Port to listen on (1080)\n" - "--proto=[socks|http] Protocol to accept (socks)\n" - "--proxy=https://:@[:]\n" - " Proxy specification.\n" - "--log Log to stderr, otherwise no log\n" + "--listen=://[addr][:port]\n" + " proto: socks, http\n" + "--proxy=://[:@][:]\n" + " proto: https, quic\n" + "--padding Use padding\n" + "--log[=] Log to stderr, or file\n" "--log-net-log= Save NetLog\n" - "--ssl-key-log-file= Save SSL keys for Wireshark\n"; + "--ssl-key-log-file= Save SSL keys for Wireshark\n" + << std::endl; exit(EXIT_SUCCESS); return false; } if (line.HasSwitch("version")) { - LOG(INFO) << "Version: " << version_info::GetVersionNumber(); + std::cout << "Version: " << version_info::GetVersionNumber() << std::endl; exit(EXIT_SUCCESS); return false; } + params->protocol = net::NaiveConnection::kSocks5; params->listen_addr = "0.0.0.0"; - if (line.HasSwitch("addr")) { - params->listen_addr = line.GetSwitchValueASCII("addr"); - } - if (params->listen_addr.empty()) { - LOG(ERROR) << "Invalid --addr"; - return false; - } - params->listen_port = 1080; - if (line.HasSwitch("port")) { - if (!base::StringToInt(line.GetSwitchValueASCII("port"), - ¶ms->listen_port)) { - LOG(ERROR) << "Invalid --port"; - return false; - } - if (params->listen_port <= 0 || - params->listen_port > std::numeric_limits::max()) { - LOG(ERROR) << "Invalid --port"; - return false; - } - } - - params->protocol = net::NaiveProxy::kSocks5; - if (line.HasSwitch("proto")) { - const auto& proto = line.GetSwitchValueASCII("proto"); - if (proto == "socks") { - params->protocol = net::NaiveProxy::kSocks5; - } else if (proto == "http") { - params->protocol = net::NaiveProxy::kHttp; + url::AddStandardScheme("socks", url::SCHEME_WITH_HOST_AND_PORT); + if (line.HasSwitch("listen")) { + GURL url(line.GetSwitchValueASCII("listen")); + if (url.scheme() == "socks") { + params->protocol = net::NaiveConnection::kSocks5; + params->listen_port = 1080; + } else if (url.scheme() == "http") { + params->protocol = net::NaiveConnection::kHttp; + params->listen_port = 8080; } else { - LOG(ERROR) << "Invalid --proto"; + LOG(ERROR) << "Invalid scheme in --listen"; return false; } + if (!url.host().empty()) { + params->listen_addr = url.host(); + } + if (!url.port().empty()) { + if (!base::StringToInt(url.port(), ¶ms->listen_port)) { + LOG(ERROR) << "Invalid port in --listen"; + return false; + } + if (params->listen_port <= 0 || + params->listen_port > std::numeric_limits::max()) { + LOG(ERROR) << "Invalid port in --listen"; + return false; + } + } } - params->use_proxy = false; + url::AddStandardScheme("quic", + url::SCHEME_WITH_HOST_PORT_AND_USER_INFORMATION); + params->proxy_url = "direct://"; GURL url(line.GetSwitchValueASCII("proxy")); if (line.HasSwitch("proxy")) { - params->use_proxy = true; if (!url.is_valid()) { LOG(ERROR) << "Invalid proxy URL"; return false; } - if (url.scheme() != "https") { - LOG(ERROR) << "Must be HTTPS proxy"; - return false; - } - if (url.username().empty() || url.password().empty()) { - LOG(ERROR) << "Missing user or pass"; + if (url.scheme() != "https" && url.scheme() != "quic") { + LOG(ERROR) << "Must be HTTPS or QUIC proxy"; return false; } params->proxy_url = url::SchemeHostPort(url).Serialize(); @@ -230,6 +225,11 @@ bool ParseCommandLineFlags(Params* params) { params->proxy_pass = url.password(); } + params->use_padding = false; + if (line.HasSwitch("padding")) { + params->use_padding = true; + } + if (line.HasSwitch("host-resolver-rules")) { params->host_resolver_rules = line.GetSwitchValueASCII("host-resolver-rules"); @@ -248,7 +248,14 @@ bool ParseCommandLineFlags(Params* params) { } if (line.HasSwitch("log")) { - params->log_settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG; + params->log_settings.logging_dest = logging::LOG_DEFAULT; + params->log_path = line.GetSwitchValuePath("log"); + if (!params->log_path.empty()) { + params->log_settings.logging_dest = logging::LOG_TO_FILE; + } else if (params->log_settings.logging_dest == logging::LOG_TO_FILE) { + params->log_path = base::FilePath::FromUTF8Unsafe("naive.log"); + } + params->log_settings.log_file = params->log_path.value().c_str(); } else { params->log_settings.logging_dest = logging::LOG_NONE; } @@ -363,6 +370,7 @@ int main(int argc, char* argv[]) { net::NetLogCaptureMode::Default()); auto context = BuildURLRequestContext(params, &net_log); + auto* session = context->http_transaction_factory()->GetSession(); auto listen_socket = std::make_unique(&net_log, net::NetLogSource()); @@ -374,9 +382,8 @@ int main(int argc, char* argv[]) { return EXIT_FAILURE; } - net::NaiveProxy naive_proxy( - std::move(listen_socket), params.protocol, params.use_proxy, - context->http_transaction_factory()->GetSession(), kTrafficAnnotation); + net::NaiveProxy naive_proxy(std::move(listen_socket), params.protocol, + params.use_padding, session, kTrafficAnnotation); base::RunLoop().Run();