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 :
AcceptorHandshakeHelper(AsyncSSLSocket::UniquePtr socket,
Acceptor* acceptor,
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),
acceptTime_(acceptTime), clientAddr_(clientAddr) {
acceptTime_(acceptTime), clientAddr_(clientAddr),
tinfo_(tinfo) {
acceptor_->downstreamConnectionManager_->addConnection(this, true);
if(acceptor_->parseClientHello_) {
socket_->enableClientHelloParsing();
......@@ -106,36 +108,41 @@ class AcceptorHandshakeHelper :
// fill in SSL-related fields from TransportInfo
// the other fields like RTT are filled in the Acceptor
TransportInfo tinfo;
tinfo.ssl = true;
tinfo.acceptTime = acceptTime_;
tinfo.sslSetupTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - acceptTime_);
tinfo.sslSetupBytesRead = sock->getRawBytesReceived();
tinfo.sslSetupBytesWritten = sock->getRawBytesWritten();
tinfo.sslServerName = sock->getSSLServerName() ?
tinfo_.ssl = true;
tinfo_.acceptTime = acceptTime_;
tinfo_.sslSetupTime = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now() - acceptTime_
);
tinfo_.sslSetupBytesRead = sock->getRawBytesReceived();
tinfo_.sslSetupBytesWritten = sock->getRawBytesWritten();
tinfo_.sslServerName = sock->getSSLServerName() ?
std::make_shared<std::string>(sock->getSSLServerName()) : nullptr;
tinfo.sslCipher = sock->getNegotiatedCipherName() ?
tinfo_.sslCipher = sock->getNegotiatedCipherName() ?
std::make_shared<std::string>(sock->getNegotiatedCipherName()) : nullptr;
tinfo.sslVersion = sock->getSSLVersion();
tinfo.sslCertSize = sock->getSSLCertSize();
tinfo.sslResume = SSLUtil::getResumeState(sock);
tinfo.sslClientCiphers = std::make_shared<std::string>();
sock->getSSLClientCiphers(*tinfo.sslClientCiphers);
tinfo.sslServerCiphers = std::make_shared<std::string>();
sock->getSSLServerCiphers(*tinfo.sslServerCiphers);
tinfo.sslClientComprMethods =
tinfo_.sslVersion = sock->getSSLVersion();
tinfo_.sslCertSize = sock->getSSLCertSize();
tinfo_.sslResume = SSLUtil::getResumeState(sock);
tinfo_.sslClientCiphers = std::make_shared<std::string>();
sock->getSSLClientCiphers(*tinfo_.sslClientCiphers);
tinfo_.sslServerCiphers = std::make_shared<std::string>();
sock->getSSLServerCiphers(*tinfo_.sslServerCiphers);
tinfo_.sslClientComprMethods =
std::make_shared<std::string>(sock->getSSLClientComprMethods());
tinfo.sslClientExts =
tinfo_.sslClientExts =
std::make_shared<std::string>(sock->getSSLClientExts());
tinfo.sslNextProtocol = std::make_shared<std::string>();
tinfo.sslNextProtocol->assign(reinterpret_cast<const char*>(nextProto),
tinfo_.sslNextProtocol = std::make_shared<std::string>();
tinfo_.sslNextProtocol->assign(reinterpret_cast<const char*>(nextProto),
nextProtoLength);
acceptor_->updateSSLStats(sock, tinfo.sslSetupTime, SSLErrorEnum::NO_ERROR);
acceptor_->updateSSLStats(
sock,
tinfo_.sslSetupTime,
SSLErrorEnum::NO_ERROR
);
acceptor_->downstreamConnectionManager_->removeConnection(this);
acceptor_->sslConnectionReady(std::move(socket_), clientAddr_,
nextProto ? string((const char*)nextProto, nextProtoLength) :
empty_string, tinfo);
empty_string, tinfo_);
delete this;
}
......@@ -155,6 +162,7 @@ class AcceptorHandshakeHelper :
Acceptor* acceptor_;
std::chrono::steady_clock::time_point acceptTime_;
SocketAddress clientAddr_;
TransportInfo tinfo_;
SSLErrorEnum sslError_{SSLErrorEnum::NO_ERROR};
};
......@@ -281,14 +289,16 @@ void Acceptor::onDoneAcceptingConnection(
int fd,
const SocketAddress& clientAddr,
std::chrono::steady_clock::time_point acceptTime) noexcept {
processEstablishedConnection(fd, clientAddr, acceptTime);
TransportInfo tinfo;
processEstablishedConnection(fd, clientAddr, acceptTime, tinfo);
}
void
Acceptor::processEstablishedConnection(
int fd,
const SocketAddress& clientAddr,
std::chrono::steady_clock::time_point acceptTime) noexcept {
std::chrono::steady_clock::time_point acceptTime,
TransportInfo& tinfo) noexcept {
if (accConfig_.isSSL()) {
CHECK(sslCtxManager_);
AsyncSSLSocket::UniquePtr sslSock(
......@@ -305,9 +315,13 @@ Acceptor::processEstablishedConnection(
return;
}
new AcceptorHandshakeHelper(
std::move(sslSock), this, clientAddr, acceptTime);
std::move(sslSock),
this,
clientAddr,
acceptTime,
tinfo
);
} else {
TransportInfo tinfo;
tinfo.ssl = false;
tinfo.acceptTime = acceptTime;
AsyncSocket::UniquePtr sock(makeNewAsyncSocket(base_, fd));
......
......@@ -170,7 +170,8 @@ class Acceptor :
void processEstablishedConnection(
int fd,
const SocketAddress& clientAddr,
std::chrono::steady_clock::time_point acceptTime
std::chrono::steady_clock::time_point acceptTime,
TransportInfo& tinfo
) noexcept;
/**
......
......@@ -123,6 +123,12 @@ struct TransportInfo {
*/
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
*/
......
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