0

We have an app that allows users from both within the organization or outside.

However, if the user is from our organization, we would like to authenticate the user's account using our Active Directory.

If the user is coming from outside, we would like the user to register to obtain an acount.

We felt that the easiest way to handle this is to track their ip addresses from the subnet of their networks.

This seems simple enough but when I tried running the code below, it is continously showing the screen that is intended for outside users.

What am I doing wrong?

'//relevant markup:

 <table bgcolor="#003366" width="100%">
  <tr><td align="right"><asp:Panel id="pnlLoggedOut" runat="server" Visible="True">
    <a href="login.aspx"><span style="color:#FF8C00;font-weight:bold">Login or Register</span></a>
</asp:Panel>
<asp:Panel id="Panel2" runat="server" Visible="False">
    <a href="login.aspx"><span style="color:#FF8C00;font-weight:bold">Login</span></a>
</asp:Panel>
<asp:Panel id="pnlLoggedIn" runat="server" Visible="False">
    <asp:Label ID="userLB" runat="server" ForeColor="#CC0000"></asp:Label><a href="logout.aspx"><span style="color:#ffffff;font-weight:bold">[Logout]</span></a>
</asp:Panel></td></tr></table> 

'//relevant codeBehind:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load

    'Create a variable to hold your IP address.  

    Dim ipAddress As String = ""


    'Retrieve the user's ip address from Page_Load():

    ipAddress = Request.ServerVariables("REMOTE_ADDR")

    'Then compare the retrieved IP address to the subnet for our network which is usually " 255.255.255.0".

    If ipAddress.Contains(" 255.255.255.0") Then
        pnlLoggedOut.Visible = False
        Panel2.Visible = True
    Else
        pnlLoggedOut.Visible = True
        Panel2.Visible = False
    End If


    'Response.Write(Session("UserRole"))
    If Session("UserName") Is Nothing Or Session("UserName") = "" Then
        pnlLoggedOut.Visible = True
        pnlLoggedIn.Visible = False
    Else
        pnlLoggedIn.Visible = True
        pnlLoggedOut.Visible = False
        userLB.Text = "You are logged in as " & Session("FullName")
        userLB.ForeColor = System.Drawing.Color.DarkOrange
    End If
End Sub
Markus
  • 20,838
  • 4
  • 31
  • 55
Chidi Okeh
  • 1,537
  • 8
  • 28
  • 50
  • Have you checked in the debugger, which value is stored in the `REMOTE_ADDR` header when running? I guess "255.255.255.0" is a customized sample value, isn't it? – Markus Jan 21 '14 at 15:10
  • @Markus, That's actually our subnet address. However, when I tried debugging, REMOTE_ADDR is getting the value of 127.0.0.1. That's not going to help. – Chidi Okeh Jan 21 '14 at 15:13
  • 127.0.0.1 is the localhost address (that is local by definition). 255.255.255.0 usually is a subnet mask that can be used to determine whether two ip addresses belong to the same subnet. – Markus Jan 21 '14 at 15:20
  • @Markus, Right, do you have any idea what changes are neeed in my code then? I thought that using the subnet mask is the best way to determine source of incomng IP Address (inside or outside). – Chidi Okeh Jan 21 '14 at 15:22

2 Answers2

1

IP Address is not a reliable way to catch this so here is an alternative:-

I think it is a better option is to configure IIS to enable integrated security then you can do something like this:

If System.Web.HttpContext.Current.User.Identity.IsAuthenticated Then
    'Internal
Else
    'External
End If
Matt Wilko
  • 26,994
  • 10
  • 93
  • 143
0

In order to solve this based on the IP addresses, you need to retrieve the IP addresses of the server. You can achieve this with this function (see this question and its answer for details):

Dim host = Dns.GetHostEntry(Dns.GetHostName())
Dim ipAddresses = From x In host.AddressList 
                  Where x.AddressFamily = System.Net.Sockets.AddressFamily.InterNetwork 

Then you need to check whether the incoming IP address is part of the same subnet as any of the server's IP addresses. This article on MSDN can show you some useful functions, in particular the IsInSameSubnet extension method. Converted to VB.NET the following code should work:

Imports System.Net

Public Module IPAddressExtensions

    <System.Runtime.CompilerServices.Extension> _
    Public Function IsInSameSubnet(address2 As IPAddress, address As IPAddress, _
                                   subnetMask As IPAddress) As Boolean
        Dim network1 As IPAddress = address.GetNetworkAddress(subnetMask)
        Dim network2 As IPAddress = address2.GetNetworkAddress(subnetMask)
        Return network1.Equals(network2)
    End Function

    <System.Runtime.CompilerServices.Extension> _
    Public Function GetNetworkAddress(address As IPAddress, subnetMask As IPAddress) As IPAddress
        Dim ipAdressBytes As Byte() = address.GetAddressBytes()
        Dim subnetMaskBytes As Byte() = subnetMask.GetAddressBytes()

        If ipAdressBytes.Length <> subnetMaskBytes.Length Then
            Throw New ArgumentException("Lengths of IP address and subnet mask do not match.")
        End If

        Dim broadcastAddress As Byte() = New Byte(ipAdressBytes.Length - 1) {}
        For i As Integer = 0 To broadcastAddress.Length - 1
            broadcastAddress(i) = CByte(ipAdressBytes(i) And (subnetMaskBytes(i)))
        Next
       Return New IPAddress(broadcastAddress)
    End Function

End Module

In order to check whether an IPAddress is internal or external, do the following. Note that interalIP denotes an IP address from the subnet that you want to define as the internal subnet. If your server is located in a DMZ that has its own subnet, you need to configure the IP address instead of getting it dynamically as shown above.

Dim internalIP = new IPAddress("192.168.1.1") ' Taken from configuration or determined as above
Dim externalIP = new IPAddress(Request.ServerVariables("REMOTE_ADDR"))
Dim subnetMask = new IPAddress("255.255.255.0")
If internalIP.IsSameSubnet(externalIP, subnet) Then
    pnlLoggedOut.Visible = False
    Panel2.Visible = True
Else
    pnlLoggedOut.Visible = True
    Panel2.Visible = False
End If
Community
  • 1
  • 1
Markus
  • 20,838
  • 4
  • 31
  • 55
  • @MattWilko, your solution is very cool but I can't use it because the app will be out on dmz. It is outside of our domain. Markus, I getting errors on the function, something like: `etNetworkAddress is not a member of the System.Net.IpAddress` Thanks to you guys for your assistance. – Chidi Okeh Jan 21 '14 at 16:01
  • @ChidiOkeh: The errors were due to another extension method that is needed. After you add it, it should work. However, if it will run in the DMZ, be sure to check whether the IP addresses of the server (in the DMZ) are relevant for checking the subnet (an alternative would be to configure the relevant subnet). Also, authentication against AD might be difficult from the DMZ. – Markus Jan 21 '14 at 16:07
  • about authenticating against AD, you are right. However, we are dumping employee details from AD to SQL Server and authenticating against this SQL Server table instead. Works just fine as we have done it before. Still getting the error though even after adding the additional method. `GetNetworkAddress is not a member of the System.Net.IpAddress` – Chidi Okeh Jan 21 '14 at 16:23
  • @ChidiOkeh: the error says that the extension method cannot be found. This might be related to namespace imports in the file; also the type and method should be public. I've pasted the complete class from the MSDN page into a file in a test project and it worked. – Markus Jan 21 '14 at 16:33
  • how many namespaces did you import? I have already imported the two that I am aware: `Imports System.Net Imports System.Net.IPAddress` and they are all public. Thanks again. – Chidi Okeh Jan 21 '14 at 16:39
  • @ChidiOkeh: it is impotant that the Namespace that contains the class with the extension methods is imported. Either create a new class in your project and copy-paste the complete class from the MSDN article over it or convert the extension methods to normal ones by removing the `this` in front of the 1st parameter and supply the parameter explicitly. Hope this helps. – Markus Jan 21 '14 at 19:59
  • thanks for all your help. Maybe, the reason I am running into the error that I showed above is because I am converting the codes to vb.net since that's the flavor I am using for my app. I tried pretty much everything you recommended but no love. Thanks for all your help though.Much appreciated. – Chidi Okeh Jan 22 '14 at 16:21
  • @ChidiOkeh: sorry, I missed that. I've converted the code in the answer. Extension methods are defined in another way in VB.NET. Hope this solves the issues. – Markus Jan 22 '14 at 16:34
  • super! I put the module in App_Code folder to resolve this new error: `module can only occur at file or namespace levels` Then I put the other code in page_load() event. Now, no more errors but just one last question - I promise! How do I use it then to compare internal vs external IP Addresses? Thanks alot Markus for your resolve and patience. – Chidi Okeh Jan 22 '14 at 18:24
  • @ChidiOkeh: I've updated the sample. I didn't test it, so I hope it works. – Markus Jan 22 '14 at 19:20