Skip to content
Open
Binary file modified 2.0/ModCloudFlareIIS2.dll
Binary file not shown.
Binary file added 2.0/eExNetworkLibrary.dll
Binary file not shown.
Binary file modified 3.0/ModCloudFlareIIS3.dll
Binary file not shown.
Binary file added 3.0/eExNetworkLibrary.dll
Binary file not shown.
Binary file modified 3.5/ModCloudFlareIIS3_5.dll
Binary file not shown.
Binary file added 3.5/eExNetworkLibrary.dll
Binary file not shown.
Binary file modified 4.0/ModCloudFlareIIS4.dll
Binary file not shown.
Binary file added 4.0/eExNetworkLibrary.dll
Binary file not shown.
Binary file modified 4.5/ModCloudFlareIIS4_5.dll
Binary file not shown.
Binary file added 4.5/eExNetworkLibrary.dll
Binary file not shown.
86 changes: 0 additions & 86 deletions ModCloudFlare.cs

This file was deleted.

157 changes: 157 additions & 0 deletions ModCloudFlareIIS.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Web;
using LukeSkywalker.IPNetwork;
using System.Net;
using eExNetworkLibrary;
using System.Net.Sockets;
using System.Collections;
using eExNetworkLibrary.IP;

namespace ModCloudFlareIIS
{
public class ModCloudFlareIIS : IHttpModule
{
#region IHttpModule Members

public void Dispose()
{
}

public void Init(HttpApplication context)
{
context.PreRequestHandlerExecute += new EventHandler(OnPreRequestHandlerExecute);
context.PostLogRequest += new EventHandler(PostLogEvent);
}

#endregion

private static List<string> CloudFlareIPRanges = new List<string>()
{
"204.93.240.0/24",
"204.93.177.0/24",
"199.27.128.0/21",
"173.245.48.0/20",
"103.21.244.0/22",
"103.22.200.0/22",
"103.31.4.0/22",
"141.101.64.0/18",
"108.162.192.0/18",
"190.93.240.0/20",
"188.114.96.0/20",
"197.234.240.0/22",
"198.41.128.0/17",
"162.158.0.0/15",
"104.16.0.0/12"
};

private static List<string> CloudFlareIPv6Ranges = new List<string>()
{
"2400:cb00::/32",
"2606:4700::/32",
"2803:f800::/32",
"2405:b500::/32",
"2405:8100::/32",
};

public static bool IsCloudFlareIP(string ip)
{
IPAddress address = IPAddress.Parse(ip);

if (address.AddressFamily == AddressFamily.InterNetwork) // IPv4
{
// Check if IPv4 address is in CloudFlareIPRanges
foreach (string block in CloudFlareIPRanges)
{
IPNetwork network = IPNetwork.Parse(block);

if (IPNetwork.Contains(network, address))
return true;
}
}
else if (address.AddressFamily == AddressFamily.InterNetworkV6) // IPv6
{
// Check if IPv6 input address is in CloudFlare ranges
foreach (string block in CloudFlareIPv6Ranges)
{
if (GetIPv6Range(block).Contains(address))
return true;
}
}
return false;
}

private static IPAddress[] GetIPv6Range(string strIn)
{
//Split the string in parts for address and prefix
string strAddress = strIn.Substring(0, strIn.IndexOf('/'));
string strPrefix = strIn.Substring(strIn.IndexOf('/') + 1);

int ipPrefix = Int32.Parse(strPrefix);
IPAddress ipAddress = IPAddress.Parse(strAddress);

//Convert the prefix length to a valid SubnetMask
int ipMaskLength = 128;

BitArray btArray = new BitArray(ipMaskLength);
for (int iC1 = 0; iC1 < ipMaskLength; iC1++)
{
//Index calculation is a bit strange, since you have to make your mind about byte order.
int iIndex = (int)((ipMaskLength - iC1 - 1) / 8) * 8 + (iC1 % 8);

if (iC1 < (ipMaskLength - ipPrefix))
{
btArray.Set(iIndex, false);
}
else
{
btArray.Set(iIndex, true);
}
}

byte[] bMaskData = new byte[ipMaskLength / 8];

btArray.CopyTo(bMaskData, 0);

//Create subnetmask
Subnetmask smMask = new Subnetmask(bMaskData);

//Get the IP range
IPAddress ipAddressStart = IPAddressAnalysis.GetClasslessNetworkAddress(ipAddress, smMask);
IPAddress ipAddressEnd = IPAddressAnalysis.GetClasslessBroadcastAddress(ipAddress, smMask);

//Omit the following lines if your network range is large
return IPAddressAnalysis.GetIPRange(ipAddressStart, ipAddressEnd);
}

public void OnPreRequestHandlerExecute(Object source, EventArgs e)
{
HttpApplication app = (HttpApplication)source;
HttpRequest request = app.Context.Request;

if (request.HttpMethod != "POST" && !String.IsNullOrEmpty(request["HTTP_CF_CONNECTING_IP"]))
{
if (IsCloudFlareIP(request["REMOTE_ADDR"]))
{
request.ServerVariables.Set("REMOTE_ADDR", request["HTTP_CF_CONNECTING_IP"]);
request.ServerVariables.Set("REMOTE_HOST", request["HTTP_CF_CONNECTING_IP"]);
}
}
}

public void PostLogEvent(Object source, EventArgs e)
{
HttpApplication app = (HttpApplication)source;
HttpRequest request = app.Context.Request;

if (!String.IsNullOrEmpty(request["HTTP_CF_CONNECTING_IP"]))
app.Response.AppendToLog("[CloudFlare_Visitor_IP:" + request["HTTP_CF_CONNECTING_IP"] + "]");

if (!String.IsNullOrEmpty(request["HTTP_CF_RAY"]))
app.Response.AppendToLog("[CF_RAY:" + request["HTTP_CF_RAY"] + "]");

}
}
}
9 changes: 4 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
IIS Module for CloudFlare users
================================

*Restores original visitor IP address to web applications running on IIS and using CloudFlare's performance and security service.
*Restores original visitor IP address to web applications running on IIS and using CloudFlare's performance and security service, even on IPv6!

*Adds original visitor IP address to logs

Expand All @@ -13,7 +13,7 @@ Rough installation instructions
------------------------------

1. Compile, if needed.
2. Copy both .dll files to the BIN folder in the root of your desired application/website folder. If this folder doesn't exist, then create it.
2. Copy all .dll files to the BIN folder in the root of your desired application/website folder. If this folder doesn't exist, then create it.
3. In the IIS Manager, go to the website/application's "Modules" section.
4. Right click, or use the interface to "Add Managed Module"
5. Use "ModCloudFlare" as the name. (This is actually arbitrary.)
Expand All @@ -27,15 +27,13 @@ Potential issues

*This module is likely far from complete and may not cover all methods of retrieving a visitor's IP using ServerVariables

*IPv4 only, for now.

Feedback
------------------------------

Feedback encouraged, preferably via [CloudFlare Support](http://support.cloudflare.com).


__This module uses the IPNetwork library by Luke Skywaler: http://ipnetwork.codeplex.com__
__This module uses the IPNetwork library by Luke Skywalker: http://ipnetwork.codeplex.com__

Copyright (c) 2009, Luke Skywalker
All rights reserved.
Expand All @@ -50,3 +48,4 @@ Redistribution and use in source and binary forms, with or without modification,

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

__This module uses the eEx Network Library by icefex: https://eex.codeplex.com, licensed under the LGPL.__
Binary file added eExNetworkLibrary.dll
Binary file not shown.