Support TCP transparent proxying

Enable with naive --listen=redir:// and iptables ... -j REDIRECT
--to-ports 1080.
This commit is contained in:
klzgrad 2019-06-23 05:20:30 +08:00
parent f47ad0c5c0
commit d921ec4f92
4 changed files with 36 additions and 0 deletions

View File

@ -26,6 +26,16 @@
#include "net/tools/naive/http_proxy_socket.h" #include "net/tools/naive/http_proxy_socket.h"
#include "net/tools/naive/socks5_server_socket.h" #include "net/tools/naive/socks5_server_socket.h"
#if defined(OS_LINUX)
#include <linux/netfilter_ipv4.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include "net/base/ip_endpoint.h"
#include "net/base/sockaddr_storage.h"
#include "net/socket/tcp_client_socket.h"
#endif
namespace net { namespace net {
namespace { namespace {
@ -187,6 +197,23 @@ int NaiveConnection::DoConnectServer() {
const auto* socket = const auto* socket =
static_cast<const HttpProxySocket*>(client_socket_.get()); static_cast<const HttpProxySocket*>(client_socket_.get());
origin = socket->request_endpoint(); origin = socket->request_endpoint();
} else if (protocol_ == kRedir) {
#if defined(OS_LINUX)
const auto* socket =
static_cast<const TCPClientSocket*>(client_socket_.get());
int sd = socket->SocketDescriptorForTesting();
SockaddrStorage dst;
int rv;
rv = getsockopt(sd, SOL_IP, SO_ORIGINAL_DST, dst.addr, &dst.addr_len);
if (rv == 0) {
IPEndPoint ipe;
if (ipe.FromSockAddr(dst.addr, dst.addr_len)) {
origin = HostPortPair::FromIPEndPoint(ipe);
}
}
#else
static_cast<void>(resolver_);
#endif
} }
if (origin.IsEmpty()) { if (origin.IsEmpty()) {

View File

@ -35,6 +35,7 @@ class NaiveConnection {
enum Protocol { enum Protocol {
kSocks5, kSocks5,
kHttp, kHttp,
kRedir,
}; };
// From this direction. // From this direction.

View File

@ -99,6 +99,9 @@ void NaiveProxy::DoConnect() {
socket = std::make_unique<HttpProxySocket>(std::move(accepted_socket_), socket = std::make_unique<HttpProxySocket>(std::move(accepted_socket_),
traffic_annotation_); traffic_annotation_);
pad_direction = NaiveConnection::kServer; pad_direction = NaiveConnection::kServer;
} else if (protocol_ == NaiveConnection::kRedir) {
socket = std::move(accepted_socket_);
pad_direction = NaiveConnection::kClient;
} else { } else {
return; return;
} }

View File

@ -170,6 +170,7 @@ void GetCommandLine(const base::CommandLine& proc, CommandLine* cmdline) {
"--version Print version\n" "--version Print version\n"
"--listen=<proto>://[addr][:port]\n" "--listen=<proto>://[addr][:port]\n"
" proto: socks, http\n" " proto: socks, http\n"
" redir (Linux only)\n"
"--proxy=<proto>://[<user>:<pass>@]<hostname>[:<port>]\n" "--proxy=<proto>://[<user>:<pass>@]<hostname>[:<port>]\n"
" proto: https, quic\n" " proto: https, quic\n"
"--padding Use padding\n" "--padding Use padding\n"
@ -255,6 +256,7 @@ bool ParseCommandLine(const CommandLine& cmdline, Params* params) {
params->listen_addr = "0.0.0.0"; params->listen_addr = "0.0.0.0";
params->listen_port = 1080; params->listen_port = 1080;
url::AddStandardScheme("socks", url::SCHEME_WITH_HOST_AND_PORT); url::AddStandardScheme("socks", url::SCHEME_WITH_HOST_AND_PORT);
url::AddStandardScheme("redir", url::SCHEME_WITH_HOST_AND_PORT);
if (!cmdline.listen.empty()) { if (!cmdline.listen.empty()) {
GURL url(cmdline.listen); GURL url(cmdline.listen);
if (url.scheme() == "socks") { if (url.scheme() == "socks") {
@ -263,6 +265,9 @@ bool ParseCommandLine(const CommandLine& cmdline, Params* params) {
} else if (url.scheme() == "http") { } else if (url.scheme() == "http") {
params->protocol = net::NaiveConnection::kHttp; params->protocol = net::NaiveConnection::kHttp;
params->listen_port = 8080; params->listen_port = 8080;
} else if (url.scheme() == "redir") {
params->protocol = net::NaiveConnection::kRedir;
params->listen_port = 1080;
} else { } else {
std::cerr << "Invalid scheme in --listen" << std::endl; std::cerr << "Invalid scheme in --listen" << std::endl;
return false; return false;