Commit 96242018 authored by Jonathan Frank's avatar Jonathan Frank Committed by Alecs King

Be able to access proxy client IP (including Lua)

Summary:
Pass TransportInfo object through connection setup.  This allows us to
pass along additional info from the setup if necessary.

Test Plan:
Run proxygen on my devserver listening on ipv4 and ipv6 for ports 80 and 443.
Configure it to run a lua request rule with the following lines:

io.stderr:write("jonlog: proxy " .. conn:getClientAddrOriginal() .. "\n")
io.stderr:write("jonlog: client " .. request:getClientIPStr() .. "\n")

Run haproxy also on my devserver, listening on ports 8555-8558, with each
forwarding to one of the four pairs (ipv4-localhost/ipv6-localhost, 80/443)

From my laptop, run curls against each of these four endpoints and make
sure that we print out "127.0.0.1" as the proxy IP, and my laptop's IP
as the client IP.

Reviewed By: cgheorghe@fb.com

Subscribers: jsedgwick, yfeldblum, trunkagent, ruibalp, bmatheny, folly-diffs@, dsp, nbm

FB internal diff: D1746590

Tasks: 5688127

Signature: t1:1746590:1423695880:f647964d95636a69a00304e144aef71ee0213d28
parent c7c65f54
...@@ -57,9 +57,11 @@ class AcceptorHandshakeHelper : ...@@ -57,9 +57,11 @@ class AcceptorHandshakeHelper :
AcceptorHandshakeHelper(AsyncSSLSocket::UniquePtr socket, AcceptorHandshakeHelper(AsyncSSLSocket::UniquePtr socket,
Acceptor* acceptor, Acceptor* acceptor,
const SocketAddress& clientAddr, const SocketAddress& clientAddr,
std::chrono::steady_clock::time_point acceptTime) std::chrono::steady_clock::time_point acceptTime,
TransportInfo& tinfo)
: socket_(std::move(socket)), acceptor_(acceptor), : socket_(std::move(socket)), acceptor_(acceptor),
acceptTime_(acceptTime), clientAddr_(clientAddr) { acceptTime_(acceptTime), clientAddr_(clientAddr),
tinfo_(tinfo) {
acceptor_->downstreamConnectionManager_->addConnection(this, true); acceptor_->downstreamConnectionManager_->addConnection(this, true);
if(acceptor_->parseClientHello_) { if(acceptor_->parseClientHello_) {
socket_->enableClientHelloParsing(); socket_->enableClientHelloParsing();
...@@ -106,36 +108,41 @@ class AcceptorHandshakeHelper : ...@@ -106,36 +108,41 @@ class AcceptorHandshakeHelper :
// fill in SSL-related fields from TransportInfo // fill in SSL-related fields from TransportInfo
// the other fields like RTT are filled in the Acceptor // the other fields like RTT are filled in the Acceptor
TransportInfo tinfo; tinfo_.ssl = true;
tinfo.ssl = true; tinfo_.acceptTime = acceptTime_;
tinfo.acceptTime = acceptTime_; tinfo_.sslSetupTime = std::chrono::duration_cast<std::chrono::milliseconds>(
tinfo.sslSetupTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - acceptTime_); std::chrono::steady_clock::now() - acceptTime_
tinfo.sslSetupBytesRead = sock->getRawBytesReceived(); );
tinfo.sslSetupBytesWritten = sock->getRawBytesWritten(); tinfo_.sslSetupBytesRead = sock->getRawBytesReceived();
tinfo.sslServerName = sock->getSSLServerName() ? tinfo_.sslSetupBytesWritten = sock->getRawBytesWritten();
tinfo_.sslServerName = sock->getSSLServerName() ?
std::make_shared<std::string>(sock->getSSLServerName()) : nullptr; std::make_shared<std::string>(sock->getSSLServerName()) : nullptr;
tinfo.sslCipher = sock->getNegotiatedCipherName() ? tinfo_.sslCipher = sock->getNegotiatedCipherName() ?
std::make_shared<std::string>(sock->getNegotiatedCipherName()) : nullptr; std::make_shared<std::string>(sock->getNegotiatedCipherName()) : nullptr;
tinfo.sslVersion = sock->getSSLVersion(); tinfo_.sslVersion = sock->getSSLVersion();
tinfo.sslCertSize = sock->getSSLCertSize(); tinfo_.sslCertSize = sock->getSSLCertSize();
tinfo.sslResume = SSLUtil::getResumeState(sock); tinfo_.sslResume = SSLUtil::getResumeState(sock);
tinfo.sslClientCiphers = std::make_shared<std::string>(); tinfo_.sslClientCiphers = std::make_shared<std::string>();
sock->getSSLClientCiphers(*tinfo.sslClientCiphers); sock->getSSLClientCiphers(*tinfo_.sslClientCiphers);
tinfo.sslServerCiphers = std::make_shared<std::string>(); tinfo_.sslServerCiphers = std::make_shared<std::string>();
sock->getSSLServerCiphers(*tinfo.sslServerCiphers); sock->getSSLServerCiphers(*tinfo_.sslServerCiphers);
tinfo.sslClientComprMethods = tinfo_.sslClientComprMethods =
std::make_shared<std::string>(sock->getSSLClientComprMethods()); std::make_shared<std::string>(sock->getSSLClientComprMethods());
tinfo.sslClientExts = tinfo_.sslClientExts =
std::make_shared<std::string>(sock->getSSLClientExts()); std::make_shared<std::string>(sock->getSSLClientExts());
tinfo.sslNextProtocol = std::make_shared<std::string>(); tinfo_.sslNextProtocol = std::make_shared<std::string>();
tinfo.sslNextProtocol->assign(reinterpret_cast<const char*>(nextProto), tinfo_.sslNextProtocol->assign(reinterpret_cast<const char*>(nextProto),
nextProtoLength); nextProtoLength);
acceptor_->updateSSLStats(sock, tinfo.sslSetupTime, SSLErrorEnum::NO_ERROR); acceptor_->updateSSLStats(
sock,
tinfo_.sslSetupTime,
SSLErrorEnum::NO_ERROR
);
acceptor_->downstreamConnectionManager_->removeConnection(this); acceptor_->downstreamConnectionManager_->removeConnection(this);
acceptor_->sslConnectionReady(std::move(socket_), clientAddr_, acceptor_->sslConnectionReady(std::move(socket_), clientAddr_,
nextProto ? string((const char*)nextProto, nextProtoLength) : nextProto ? string((const char*)nextProto, nextProtoLength) :
empty_string, tinfo); empty_string, tinfo_);
delete this; delete this;
} }
...@@ -155,6 +162,7 @@ class AcceptorHandshakeHelper : ...@@ -155,6 +162,7 @@ class AcceptorHandshakeHelper :
Acceptor* acceptor_; Acceptor* acceptor_;
std::chrono::steady_clock::time_point acceptTime_; std::chrono::steady_clock::time_point acceptTime_;
SocketAddress clientAddr_; SocketAddress clientAddr_;
TransportInfo tinfo_;
SSLErrorEnum sslError_{SSLErrorEnum::NO_ERROR}; SSLErrorEnum sslError_{SSLErrorEnum::NO_ERROR};
}; };
...@@ -281,14 +289,16 @@ void Acceptor::onDoneAcceptingConnection( ...@@ -281,14 +289,16 @@ void Acceptor::onDoneAcceptingConnection(
int fd, int fd,
const SocketAddress& clientAddr, const SocketAddress& clientAddr,
std::chrono::steady_clock::time_point acceptTime) noexcept { std::chrono::steady_clock::time_point acceptTime) noexcept {
processEstablishedConnection(fd, clientAddr, acceptTime); TransportInfo tinfo;
processEstablishedConnection(fd, clientAddr, acceptTime, tinfo);
} }
void void
Acceptor::processEstablishedConnection( Acceptor::processEstablishedConnection(
int fd, int fd,
const SocketAddress& clientAddr, const SocketAddress& clientAddr,
std::chrono::steady_clock::time_point acceptTime) noexcept { std::chrono::steady_clock::time_point acceptTime,
TransportInfo& tinfo) noexcept {
if (accConfig_.isSSL()) { if (accConfig_.isSSL()) {
CHECK(sslCtxManager_); CHECK(sslCtxManager_);
AsyncSSLSocket::UniquePtr sslSock( AsyncSSLSocket::UniquePtr sslSock(
...@@ -305,9 +315,13 @@ Acceptor::processEstablishedConnection( ...@@ -305,9 +315,13 @@ Acceptor::processEstablishedConnection(
return; return;
} }
new AcceptorHandshakeHelper( new AcceptorHandshakeHelper(
std::move(sslSock), this, clientAddr, acceptTime); std::move(sslSock),
this,
clientAddr,
acceptTime,
tinfo
);
} else { } else {
TransportInfo tinfo;
tinfo.ssl = false; tinfo.ssl = false;
tinfo.acceptTime = acceptTime; tinfo.acceptTime = acceptTime;
AsyncSocket::UniquePtr sock(makeNewAsyncSocket(base_, fd)); AsyncSocket::UniquePtr sock(makeNewAsyncSocket(base_, fd));
......
...@@ -170,7 +170,8 @@ class Acceptor : ...@@ -170,7 +170,8 @@ class Acceptor :
void processEstablishedConnection( void processEstablishedConnection(
int fd, int fd,
const SocketAddress& clientAddr, const SocketAddress& clientAddr,
std::chrono::steady_clock::time_point acceptTime std::chrono::steady_clock::time_point acceptTime,
TransportInfo& tinfo
) noexcept; ) noexcept;
/** /**
......
...@@ -123,6 +123,12 @@ struct TransportInfo { ...@@ -123,6 +123,12 @@ struct TransportInfo {
*/ */
int64_t totalBytes{0}; int64_t totalBytes{0};
/**
* If the client passed through one of our L4 proxies (using PROXY Protocol),
* then this will contain the IP address of the proxy host.
*/
std::shared_ptr<folly::SocketAddress> clientAddrOriginal;
/** /**
* header bytes read * header bytes read
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment