How to write a custom ISAPI filter to replace http header
Background:
UrlScan is usually used to replace/remove http “server” header. But if the server gets Exchange installed, UrlScan could cause various issues and a lot of configuration and testing need to be done to make Exchange functional properly.
We can write a simple ISAPI filter to replace the server header instead of using UrlScan.
For general introduction of ISAPI filter, refer to https://msdn.microsoft.com/en-us/library/ms524610(v=vs.90).aspx
Solution:
- Use Visual Studio to create a C++ empty project and create the following two files.
sample_isapi_filter.DEF
LIBRARY sample_isapi_filter
;DESCRIPTION 'filter to remove server header'
EXPORTS
HttpFilterProc
GetFilterVersion
sample_isapi_filter.C
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <httpfilt.h>
DWORD DoSendResponse(HTTP_FILTER_CONTEXT * pfc,HTTP_FILTER_SEND_RESPONSE * pResponse);
BOOL WINAPI __stdcall GetFilterVersion(HTTP_FILTER_VERSION *pVer)
{
pVer->dwFlags = ( SF_NOTIFY_ORDER_LOW | SF_NOTIFY_SEND_RESPONSE );
pVer->dwFilterVersion = HTTP_FILTER_REVISION;
return TRUE;
}
DWORD WINAPI __stdcall HttpFilterProc(HTTP_FILTER_CONTEXT *pfc, DWORD NotificationType, VOID *pvData)
{
switch (NotificationType)
{
case SF_NOTIFY_SEND_RESPONSE :
return DoSendResponse(pfc, (HTTP_FILTER_SEND_RESPONSE *) pvData);
default :
break;
}
return SF_STATUS_REQ_NEXT_NOTIFICATION;
}
DWORD DoSendResponse(HTTP_FILTER_CONTEXT * pfc,HTTP_FILTER_SEND_RESPONSE * pResponse)
{
BOOL fServer = TRUE;
DWORD dwServerError;
fServer = pResponse->SetHeader(pfc, "Server:", "Apache http 2.4.2");
if ( !fServer )
{
dwServerError = GetLastError();
pfc->pFilterContext = (LPVOID)(DWORD64)pResponse->HttpStatus;
}
return SF_STATUS_REQ_NEXT_NOTIFICATION;
}
- In Build-Configuration Manager choose your target platform (win32 or x64) and build into a dynamic link library (sample_isapi_filter.dll).
- Put this file on the web server and add the filter from IIS Manager – Web Site Properties
- Verify the response header by fiddler. The header is successfully replaced by the filter.
HTTP/1.1 200 OK
Content-Length: 1433
Content-Type: text/html
Content-Location: https://xxxx/iisstart.htm
Last-Modified: Fri, 21 Feb 2003 10:48:30 GMT
Accept-Ranges: bytes
ETag: "05367c596d9c21:a54"
X-Powered-By: ASP.NET
Server: Apache http 2.4.2
Date: Mon, 02 Jul 2012 06:36:52 GMT
Connection: close
Regards,
Aaron from APGC DSI Team
Comments
- Anonymous
July 05, 2012
Sadly this post does not illustrate how to perform step 3 on IIS 7.x/8.0 - Anonymous
January 16, 2013
Thank you for sharing!But what is the purpose of the if block in the DoSendResponse() function?#Lex Li: you can attach the isapi filter using the applicationhost.conf