Skip to content
Permalink
Browse files

Include failed TLS handshakes in the access log

Failed TLS handshakes are logged with the following information:
- status 400
- start time close to the connection failure
- duration 0

All other fields apart from network related fields (e.g. IP address etc)
obtained from the SocketWrapper are empty.
  • Loading branch information...
markt-asf committed Jul 31, 2019
1 parent 22301d2 commit acf6076d7118571ebc881984b96792f861b72bb2
@@ -149,7 +149,7 @@ public Adapter getAdapter() {
* Set the socket wrapper being used.
* @param socketWrapper The socket wrapper
*/
protected final void setSocketWrapper(SocketWrapperBase<?> socketWrapper) {
protected void setSocketWrapper(SocketWrapperBase<?> socketWrapper) {
this.socketWrapper = socketWrapper;
}

@@ -944,6 +944,7 @@ protected boolean isTrailerFieldsSupported() {
*/
protected abstract boolean flushBufferedWrite() throws IOException ;


/**
* Perform any necessary clean-up processing if the dispatch resulted in the
* completion of processing for the current request.
@@ -955,4 +956,18 @@ protected boolean isTrailerFieldsSupported() {
* request
*/
protected abstract SocketState dispatchEndRequest() throws IOException;


@Override
protected final void logAccess(SocketWrapperBase<?> socketWrapper) throws IOException {
// Set the socket wrapper so the access log can read the socket related
// information (e.g. client IP)
setSocketWrapper(socketWrapper);
// Setup the minimal request information
request.setStartTime(System.currentTimeMillis());
// Setup the minimal response information
response.setStatus(400);
response.setError();
getAdapter().log(request, response, 0);
}
}
@@ -62,8 +62,10 @@ public SocketState process(SocketWrapperBase<?> socketWrapper, SocketEvent statu
} else if (status == SocketEvent.OPEN_WRITE) {
// Extra write event likely after async, ignore
state = SocketState.LONG;
} else if (status == SocketEvent.OPEN_READ){
} else if (status == SocketEvent.OPEN_READ) {
state = service(socketWrapper);
} else if (status == SocketEvent.CONNECT_FAIL) {
logAccess(socketWrapper);
} else {
// Default to closing the socket if the SocketEvent passed in
// is not consistent with the current state of the Processor
@@ -129,6 +131,19 @@ protected void clearDispatches() {
}


/**
* Add an entry to the access log for a failed connection attempt.
*
* @param socketWrapper The connection to process
*
* @throws IOException If an I/O error occurs during the processing of the
* request
*/
protected void logAccess(SocketWrapperBase<?> socketWrapper) throws IOException {
// NO-OP by default
}


/**
* Service a 'standard' HTTP request. This method is called for both new
* requests and for requests that have partially read the HTTP request line
@@ -276,8 +276,6 @@ public SocketState service(SocketWrapperBase<?> socketWrapper)

// Setting up the I/O
setSocketWrapper(socketWrapper);
inputBuffer.init(socketWrapper);
outputBuffer.init(socketWrapper);

// Flags
keepAlive = true;
@@ -505,6 +503,14 @@ public SocketState service(SocketWrapperBase<?> socketWrapper)
}


@Override
protected final void setSocketWrapper(SocketWrapperBase<?> socketWrapper) {
super.setSocketWrapper(socketWrapper);
inputBuffer.init(socketWrapper);
outputBuffer.init(socketWrapper);
}


private Request cloneRequest(Request source) throws IOException {
Request dest = new Request();

@@ -373,6 +373,7 @@ public SocketState upgradeDispatch(SocketEvent status) {
case ERROR:
case TIMEOUT:
case STOP:
case CONNECT_FAIL:
close();
break;
}
@@ -1982,13 +1982,15 @@ public void run() {
getConnectionTimeout(), Poll.APR_POLLIN);
} else {
// Close socket and pool
getHandler().process(socket, SocketEvent.CONNECT_FAIL);
closeSocket(socket.getSocket().longValue());
socket = null;
}
} else {
// Process the request from this socket
if (!setSocketOptions(socket)) {
// Close socket and pool
getHandler().process(socket, SocketEvent.CONNECT_FAIL);
closeSocket(socket.getSocket().longValue());
socket = null;
return;
@@ -1682,6 +1682,7 @@ protected void doRun() {
launch = true;
}
} else if (handshake == -1 ) {
getHandler().process(socketWrapper, SocketEvent.CONNECT_FAIL);
socketWrapper.close();
}
} catch (VirtualMachineError vme) {
@@ -1590,6 +1590,7 @@ protected void doRun() {
poller.cancelledKey(key, socketWrapper);
}
} else if (handshake == -1 ) {
getHandler().process(socketWrapper, SocketEvent.CONNECT_FAIL);
poller.cancelledKey(key, socketWrapper);
} else if (handshake == SelectionKey.OP_READ){
socketWrapper.registerReadInterest();
@@ -60,5 +60,14 @@
* during Servlet 3.0 asynchronous processing.</li>
* </ul>
*/
ERROR
ERROR,

/**
* A client attempted to establish a connection but failed. Examples of
* where this is used include:
* <ul>
* <li>TLS handshake failures</li>
* </ul>
*/
CONNECT_FAIL
}
@@ -178,6 +178,7 @@ public SocketState upgradeDispatch(SocketEvent status) {
//$FALL-THROUGH$
case DISCONNECT:
case TIMEOUT:
case CONNECT_FAIL:
return SocketState.CLOSED;

}
@@ -252,6 +252,7 @@ public SocketState upgradeDispatch(SocketEvent status) {
case DISCONNECT:
case ERROR:
case TIMEOUT:
case CONNECT_FAIL:
return SocketState.CLOSED;
}
return SocketState.UPGRADED;
@@ -129,6 +129,10 @@
Fix h2spec test suite failure. It is an error if a Huffman encoded
string literal contains the EOS symbol. (jfclere)
</fix>
<add>
Connections that fail the TLS handshake will now appear in the access
logs with a 400 status code. (markt)
</add>
</changelog>
</subsection>
<subsection name="Cluster">

0 comments on commit acf6076

Please sign in to comment.
You can’t perform that action at this time.