netnerds.net

4Mar/130

HOW-TO Setup Windows 2012 Server Core Remote Desktop Services to Securely Administer Windows over RDP and SSL

Alright, so I've wanted to setup a Remote Desktop Gateway for years, but the configuration seemed so.. time-intensive. Then I moved to Belgium, my living situation changed and I didn't want to setup a whole new VPN server to access my virtual lab.

Initially, I set up my RD Gateway using too many Remote Desktop Services: Remote Desktop Connection Broker, Remote Desktop Gateway & Remote Desktop Web Access, but that was because was lead astray by Windows 2012's new GUI. Now, I've narrowed it down only to RD Gateway and I'm even fond of Metro (:O)

So to get this going, all you have to do is install and configure the Remote Desktop Gateway Services (RD Gateway) Role. That seems obvious, but Server Manager's interface which prominently displays an unconfigured "Remote Desktop Services" tab made me think I was missing something.

During the Role installation do: Role-based or feature-based installation -> Remote Desktop Services -> Remote Desktop Gateway

Then click Next a bunch of times. Something odd, when it asks you "Do you need an alternate source path?", even if you have the Windows Server 2012 ISO attached, you'll still need to click "Specify an alternate source path" and enter D:\sources\sxs (assuming your ISO is attached to D:)

Click Install and wait for the installation to complete. Now it's time to configure RD Gateway.

OPTIONAL: If you're on a domain with a Certificate Authority, you'll want to configure IIS to use a Domain Certificate. Open IIS Manager -> Select your server -> Server Certificates -> Create Domain Certificate. For "Common Name" make sure you enter your external FQDN. Note: I chose to go with dyndns.org since I have a dynamic IP. It's required that you use an externally resolvable hostname, otherwise Remote Desktop will fail if you try to use an IP or mismatched hosts.

Now, you'll need to configure RD Gateway. Go to Server Manager -> Tasks -> RD Gateway Manager.

Click View or modify certificate properties. If you don't have a Domain Certificate, just click Create and import certificate and ensure you use your external FQDN for the certificate name. Otherwise, choose Select an existing certificate.... Choose your certificate

Click Import -> Apply. Now that you're back at the RD Gateway Manager, expand the tree under your server name. Click Policies then on the right, click Create Authorization Polices for RD Gateway. Create an RD CAP and RD RAP (Recommended). In the name field, you can enter whatever you'd like. I chose "Default" -> Next -> Add Group -> Domain Admins -> (leave Client Computer blank)

Next, you'll be given the option to Enable or Disable Device Redirection. I just choose the default (all clients) and click Next -> Next -> Next - Default -> Next -> Allow users to connect to any network resource -> Next -> Allow Connections only to port 3389 -> Next -> Finish

Finally, open up Services and Start Remote Desktop Gateway

Voila! Now you can go modify your router rules to connect port 443 to your RD Gateway Server and/or read the important notes below.

A few important things to note
As an added security pre-caution, I went into IIS and disabled Anonymous access to my root IIS folder and ensured Windows Authentication was still enabled for the RPC folders.

Configuring the Remote Desktop Client is easy. Open up your Remote Desktop Client -> Advanced -> (Connect from Anywhere) Settings.

Enter the external hostname that you entered earlier during the configuration of RD Gateway. Go back to the general tab, and enter the FQDN of the domain server you wish to connect to. Don't worry about resolving the hostname if you're using an external DNS server -- DNS is resolved at the RD Gateway so if the RD Gateway can resolve the hostname, you're set.

If you choose to use a self-signed cert or you are attempting to connect from a computer that's not on the domain, you'll have to import the SSL cert to your Trusted Root Certification Authority. Otherwise, you'll receive the error "This computer can't verify the identity of the RD Gateway 'sample.server.com'. It's not safe to connect to servers that are not identified. Contact your network administrator for assistance."

There are a few ways to do this, but here's how I do it. I use Chrome to hit my server (ex. https://myserver.dyndns.org)

Click Certificate Information -> Details -> Copy to File. Save the cert, then find it using Windows Explorer. Right-click on the cert -> Install Certificate -> Place all Certificate in the Following Store -> Trusted Root Certification Authority -> Next -> Finish -> Yes.

You should now be able to connect and securely manage your network, all over SSL :)

Posted by: Chrissy LeMaire   Filed under: IIS, Security, Windows No Comments
6Feb/122

Map a Secure SharePoint 2010/IIS Network Drive over SSL and WebDAV in Windows 7

Once, after viewing a SharePoint 2010 document library in Windows Explorer, I ran a net use and saw that Windows 7 had stored the credentials of my SSL-secured SharePoint intranet server. It took a bit of fiddling, but I eventually found you can, in fact, map a secure network drive using the command line:

net use W: \\sharepoint.local@SSL\DavWWWRoot\SiteCollectionName\SiteName /user:domain\username *

If your Site Collection is at the root of the server, you can just use \\sharepoint.local@SSL\DavWWWRoot. If you're not a fan of the command line, using the Windows GUI is also an option, as demonstrated here. Each of these methods requires a trusted certificate. I'm betting you can use self-signed cert if you just trust yourself as a root.

Posted by: Chrissy LeMaire   Filed under: IIS, Security, SharePoint 2 Comments
30Sep/092

IIS: Authentication Fails with Error Code 2148074254

Recently, we migrated a web application to a SharePoint server. The web application is a custom built ASP/ASPX app that supports Integrated Windows Authentication. We were able to run the application successfully using Anonymous Access but we were unable to authenticate from remote computers when Anonymous Access was disabled.

I checked the NTFS permissions and double checked the IIS properties for both the Web site and the Virtual directory and everything was setup properly. Different types of domain accounts, even Domain Admins, were attempted and none were able to login successfully from remote machines. Logging in from the server itself, however, worked just fine.

Our SharePoint sites which Windows Authentication and Kerberos were authenticating properly, so it wasn't the server. I checked the web server logs and saw HTTP 401 errors failing with the IIS specific code "2148074254." Searching the web turned up nothing useful. I tried a registry change and even rebooted the server to no avail.

I checked the server again -- local login works just fine, remote logins do not. I recalled experiencing something similar with another application I'd written and the problem had to do with Kerberos' restrictions on double-hop authentication. Maybe this site just needs an SPN?

I created a new application pool, assigned the web application to that pool and ran the pool as a domain user. I then created an SPN using the hostname of the newly migrated site.

Setspn.exe -A HTTP/vieval.domain.com domain\iisservice
Setspn.exe -A HTTP/vieval domain\iisservice

Success! Once the registration was complete, we were able to login to the web application. I find it surprising that the Kerberos setting is server-wide. Anyone know the reasons why?

Posted by: Chrissy LeMaire   Filed under: Active Directory, IIS, Security, SharePoint 2 Comments
29Jul/071

PowerShell 1.0: Adding Virtual FTP Directories to IIS 6 or 7

While my firm explores using WebDAV and SharePoint 2007 for exchanging large amounts of files, we're temporarily using FTP dropboxes to fill the void. Last Monday, I setup 11 new accounts and it took a total of one hour to complete the same 15 step process (give or take) for each account. By the time I was finished, I decided automating FTP account creation would be my first PowerShell project. What you see below is part of that project.

The code below creates a virtual directory in the "Default FTP Site" of the machine that is running the PowerShell script. The virtual directory called "NewUser" is mapped to C:\FTP\NewUser and is set to be both readable and writable. For the record, I couldn't get WMI to work (get-wmiobject) and that's the reason I decided to use the .NET's Directory Services support.

$server = $env:computername
$service = New-Object System.DirectoryServices.DirectoryEntry("IIS://$server/MSFTPSVC")
$site = $service.psbase.children |Where-Object { $_.ServerComment -eq 'Default FTP Site' }
$site = New-Object System.DirectoryServices.DirectoryEntry($site.psbase.path+"/Root") # <-- IIS 6 requires this. Not sure why. Otherwise, it never appears to commit changes. This line is not required for IIS 7.
$virtualdir = $site.psbase.children.Add("NewUser","IIsFtpVirtualDir")
$virtualdir.psbase.CommitChanges()
$virtualdir.put("Path","C:\FTP\NewUser")
$virtualdir.put("AccessRead",$true)
$virtualdir.put("AccessWrite",$false)
$virtualdir.psbase.CommitChanges()
$service.psbase.refreshCache() # OPTIONAL

Alternatively, you could do go straight for the path if you know it (IIS 6 seems to like this):

$service = New-Object DirectoryServices.DirectoryEntry("IIS://localhost/MSFTPSVC/1/Root")
$virtualdir = $service.psbase.children.Add("NewUser", "IIsFtpVirtualDir")
$virtualdir.psbase.CommitChanges()
$virtualdir.put("Path","C:\FTP\NewUser")
$virtualdir.put("AccessRead",$true)
$virtualdir.put("AccessWrite",$false)
$virtualdir.psbase.CommitChanges()

If you would like to iterate through each of the virtual directories on your FTP server, you can use the following code:

$service = New-Object System.DirectoryServices.DirectoryEntry("IIS://$env:computername/MSFTPSVC")
$site = $service.psbase.children | Where-Object { $_.ServerComment -eq 'Default FTP Site' }
$virtualdirs = $site.psbase.children.Find("Root","IIsFtpVirtualDir").psbase.children
foreach ($virtualdir in $virtualdirs) {$virtualdir.psbase.name}

This code is likely applicable to many of the objects in the IIS ADSI provider. While I've only tested this on Vista (IIS 7), this should also work for Windows XP and 2003's IIS 6 as Vista uses IIS 6's MMC for management.

Also, if you are wondering how I know when to use psbase or psbase.children, I really don't. I just fumble around until I get it to work. The 4 lines above, specifically $virtualdirs = $site.psbase.children.Find("Root","IIsFtpVirtualDir").psbase.children took me about seven hours to figure out. I hear PowerShell 2.0 will have much better support for Directory Services and hopefully that will include support the IIS FTP service.

Posted by: Chrissy LeMaire   Filed under: IIS, PowerShell 1 Comment
29Apr/071

Rules for High Performance Websites

Last week, I attended the Web 2.0 Expo at Mascone Center in San Francisco where I watched Steve Souders of Yahoo speak. His workshop was titled High Performance Webpages and has a yet-to-be published O'reilly book by the same name (though the Rough Cuts version is currently available for download). The basis of his presentation is as follows:

These best practices have proven to reduce response times of Yahoo! properties by 25-50%. We focus on the front-end because that's where 80-90% of the end-user response time is spent. This "80-90% front-end" phenomenon is not isolated to just Yahoo!. It holds true for most web sites, including the ten most-visited U.S. web sites. In any optimization effort it’s critical to profile current performance to identify where the greatest improvement can be made. It’s clear that the place to focus for fast web pages is the front-end:
1. There is more potential for improvement by focusing on the front-end. Making the back-end twice as fast reduces response times by 5-10%, whereas making the front-end twice as fast saves 40-45%.
2. Front-end improvements typically require less time and resources than back-end performance projects.
3. Focusing on front-end improvements has proven to work. Over fifty teams at Yahoo! have reduced their end-user response times by following these 14 Rules for High Performance Websites.

Souders' presentation was especially useful for me because it made me realize that I was spending too much time on speeding up the back-end and not enough time speeding up the front-end. I passed this URL on to my developer-in-crime, Brandon, and we'll be using it as a guideline during the redevelopment of RealCajunRecipes.com.

Posted by: Chrissy LeMaire   Filed under: Apache, IIS 1 Comment
22Jan/0727

Classic ASP: "Push" File Downloads from A Directory Outside the Application Root

This is some super old code but I used it recently and figured I'd archive it on this site for my future reference. The sample code below aims to allow authenticated users to download files which are not available via direct download (ie. files within the web root). The script accomplishes this by doing the following:

1. Checks to see if the user is logged in (your method may vary)
2. Sets the root directory location
3. Checks to see if the file exists, if so...
4. Retrieves the filesize and adds the appropriate HTTP headers including content disposition, filename, content type and filesize.
5. Uses a binary stream to "push" the download

Save this file as download.asp and call it with the filename in the querystring. Example: http://domain.com/downloads/download.asp?filename=myfile.pdf. Also, be sure to give read permissions to IUSR_SvrName to the root directory. Change the authentication requirements as needed:

download.asp

<%
If session("loggedIn") = True Then

strFilePath = "D:\webfiles\downloads"  & request.querystring("filename")

Set objFSO = Server.CreateObject("Scripting.FileSystemObject")
If objFSO.FileExists(strFilePath) Then
Set objFile = objFSO.GetFile(strFilePath)
intFileSize = objFile.Size
Set objFile = Nothing

strFileName = request.querystring("filename")
strFileName = replace(request.querystring("filename")," ","-")
Response.AddHeader "Content-Disposition","attachment; filename=" & strFileName

Response.ContentType = "application/x-msdownload"
Response.AddHeader "Content-Length", intFileSize

Set objStream = Server.CreateObject("ADODB.Stream")
objStream.Open
objStream.Type = 1 'adTypeBinary
objStream.LoadFromFile strFilePath
Do While Not objStream.EOS And Response.IsClientConnected
Response.BinaryWrite objStream.Read(1024)
Response.Flush()
Loop
objStream.Close
Set objStream = Nothing
Else
Response.write "Error finding file."
End if
Set objFSO = Nothing
End If
%>

Note: Even if the file is a PDF and a third-party application such as Adobe Reader is set to open the file within the browser, the code below will override that and force a download (by using the "application/x-msdownload" content type).

[The UPDATE below is no longer accurate as an alternative solution has been given below in the comments and subsequently, was added to the code (Thanks a bunch, David!). I wanted to leave it for Googlers looking for a solution, however]

UPDATE: Someone wrote to let me know that they were encountering the error "Response Buffer Limit Exceeded". As it turns out, IIS 6's ASPBufferingLimit is set to a measly 4MB (4194304 bits) so any file over 4MB would produce this error. To fix this issue, you will have to have access to IIS either via the command line or the MMC. Here's how to change the buffering limit via the command line:

************ NOTE: An easier solution is to use the updated Do While/Flush procedure given in the code *****************

cd C:\inetpub\adminscripts
cscript adsutil.vbs set /w3svc/aspbufferinglimit 4294967295

That's a buffering limit of more than 4 Gigabytes. Personally, I'd lop off the last digit and make that number closer to 430MB. Running that script worked immediately on my test machine, even though I do not have "Enable Direct Metabase Edit" checked in IIS' Properties. If it doesn't work for you, restart IIS and see if it works.

Posted by: Chrissy LeMaire   Filed under: IIS, VBScript 27 Comments
16Jan/070

OWA: Expired Password Causes Execute Access Forbidden

Recently, a user trying to login to OWA encountered the following error:

HTTP 403.1 Forbidden: Execute Access Forbidden
You have attempted to execute a CGI, ISAPI, or other executable program from a directory that does not allow programs to be executed.

Another network administrator noticed that the URL was strange too. The user had been directed to:

https://owa.mydomain.com /iisadmpwd/aexp.htr?https:// owa.mydomain.com/exchange/USA/

A quick Googling showed mentions of an expired password but the user was able to login to the domain so we were a bit baffled. As it turns out, we're in the middle of a migration and the user's account on the old domain which still hosts OWA/Exchange was expired but his password on the new domain account was still valid. The user was also not prompted to change his password in OWA because we did not enable that feature. So if you run into something similar, ensure that the user's account does not have "User Must Change Password At Next Logon" checked.

Posted by: Chrissy LeMaire   Filed under: Exchange, IIS, Security No Comments
9Jan/0711

VBScript: Windows XP/IIS 5.1 DOES Support Denying Access by IP Addresses

In helping a visitor to troubleshoot running my IIS FTP ban script, I realized that while XP makes it appear as though it doesn't support banning users by IP address, it actually does provide that support; you just have to ban the IPs programatically.

Here, you can see that the IP address and domain name restrictions section is greyed out. However, you can use the following VBScript to enable and ban users in IIS' Default Web SIte. The first script listed does the following:

1. Ensures that AllowByDefault is set to true (which is the default anyway)
2. Bans a few example IP addresses
3. Confirms the addresses were successfully banned

Ban-a-rama

strComputer = "localhost"
arrBanTheseIPs = Array("10.0.0.200","42.42.42.42")

'Set Objects
Set objWebSite = GetObject("IIS://" & strComputer & "/W3SVC/1")
Set objIPRestrict = objWebSite.IPSecurity

objIPRestrict.GrantByDefault = True
objIPRestrict.IPDeny = arrBanTheseIPs
objWebSite.IPSecurity = objIPRestrict
objWebSite.SetInfo

WScript.Echo "The following IP addresses are now banned:"
arrDeniedIPs = objIPRestrict.IPDeny
for i = 0 to Ubound(arrDeniedIPs)
  WScript.Echo arrDeniedIPs(i)
next

'Kill Objects
Set objIPRestrict = Nothing
Set objWebSite = Nothing

To Delete All Previously Banned IPs, you would use the following code which overwrites all the IPs with one invalid IP.

Mass Unban

strComputer = "localhost"

'Set Objects
Set objWebSite = GetObject("IIS://" & strComputer & "/W3SVC/1")
Set objIPRestrict = objWebSite.IPSecurity

objIPRestrict.GrantByDefault = True
objIPRestrict.IPDeny = Array("0.0.0.0")
objWebSite.IPSecurity = objIPRestrict
objWebSite.SetInfo

'Kill Objects
Set objIPRestrict = Nothing
Set objWebSite = Nothing

If you find yourself needing to unban a single IP address, you can use the following code which gathers all the banned IPs except the one you want to delete and rebans them (IPDeny requires a full list each time you set it).

Unban One IP

strComputer = "localhost"

'Set Objects
Set objWebSite = GetObject("IIS://" & strComputer & "/W3SVC/1")
Set objIPRestrict = objWebSite.IPSecurity

strUnbanSingleIP = "10.0.0.200"
arrIPAddresses = objIPRestrict.IPDeny

For i = 0 to ubound(arrIPAddresses)
strClientIP = Left(arrIPAddresses(i),InStr(arrIPAddresses(i),",")-1)
  If strClientIP <> strUnbanSingleIP Then
   If Len(strStillBanned) = 0 Then
   strStillBanned = strClientIP
   Else
   strStillBanned = strStillBanned & "," & strClientIP
End If
  End If
Next

If Len(strStillBanned) = 0 Then strStillBanned = "0.0.0.0" 'just in case it was the only one
arrStillBannedIPs = split(strStillBanned,",")

objIPRestrict.IPDeny = arrStillBannedIPs
objWebSite.IPSecurity = objIPRestrict
objWebSite.SetInfo

'Kill Objects
Set objIPRestrict = Nothing
Set objWebSite = Nothing

If your script is successful, banned users will see the following message:

You are not authorized to view this page

HTTP 403.6 - Forbidden: IP address rejected

To show all of the current IPs which have been banned, run the following script

View Banned IPs

strComputer = "localhost"

'Set Objects
Set objWebSite = GetObject("IIS://" & strComputer & "/W3SVC/1")
Set objIPRestrict = objWebSite.IPSecurity

arrDeny = objWebSite.Get("IPSecurity").IPDeny
   For i = 0 to Ubound(arrDeny)
      strBannedIPs = strBannedIPs & arrDeny(i) & vbCrlf
   Next

   If len(strBannedIPs) > 0 Then
      msgbox "IP, Subnet: " & vbCrLF & strBannedIPs
   Else
      msgbox "No IPs have been banned."
   End if

'Kill Objects
Set objIPRestrict = Nothing
Set objWebSite = Nothing

While I haven't tested it, the same scripts should work if you want to deny all IPs except those explicitly listed. To do so, simply set objIPRestrict.GrantByDefault to False and replace the above mentions of IPDeny with IPGrant. Same goes for MSFTPSVC -- if you want to modify the FTP service settings, just change the above instances of "W3SVC" to "MSFTPSVC".

Posted by: Chrissy LeMaire   Filed under: IIS, Security, VBScript 11 Comments
13Dec/060

VBScript: Kerberos, Delegation, IIS and User Authentication

Recently, I wanted to write a web-based front end to AD User Management for our help desk. The way that I set it up apparently broke some Kerberos delegation rules and even though Microsoft wrote a step-by-step guide on how to get IIS and Kerberos delegation going, the solution didn't work for me. If I turned off Anonymous access and authenticated as myself against a remote webserver (local webserver totally worked), I would get the error 0x80040E37 - Table Does Not Exist. The table does exist, of course, I just don't have the rights to see it. Well, I do but not in the "double hop" manner that I'm attempting it. Kerberos sees that IIS != me.. IIS is only pretending to be me and it doesn't approve.

After a few days of tinkering, this is the solution I decided on. I set the ASP page in IIS to Anonymous Access but ran that access as a user with the privleges to make changes to user accounts. This can be dangerous in more than one way -- if a lesser-privleged user were to somehow have the ability to edit that page, he or she could use it to run any script under the power of that user. So I ensured that unauthorized users were not able to access that file. But now how can I detect who's running that page? Request.servervariables("REMOTE_USER") would be useless since the page is running as that privleged user. I considered what client variables I did have access to and realized that request.servervariables("REMOTE_HOST") would be the handiest. I figured that, using WMI and the IP address, it would be possible to figure out what user is actively logged into the client machine. Sure enough...

Function getLoggedInUser(ipaddr)
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!"& ipaddr & "\root\cimv2")
Set colSessions = objWMIService.ExecQuery("Select * from Win32_LogonSession Where LogonType = 2 OR LogonType = 10" )

For Each objSession in colSessions
Set colList = objWMIService.ExecQuery("Associators of {Win32_LogonSession.LogonId=" & objSession.LogonId & "} Where AssocClass=Win32_LoggedOnUser Role=Dependent")
For Each objItem in colList
getLoggedInUser = lcase(objItem.Name)
Next
Next
End Function

This script, which was derived from a tek-tips.com post, worked flawlessly! FWIT, LoginType 2 is console and 10 is remote desktop.

Posted by: Chrissy LeMaire   Filed under: Active Directory, IIS, VBScript No Comments
31Oct/0613

VBScript: Stop Dictionary FTP Attacks in IIS using VBScript

Spencer Ruport of netortech.com modified my FTP ban script into one that stops dictionary attacks. And he chooses not to ban via the problematic IIS way but instead creating a bad route for the offending IP address. Pretty darn ingenius.

ftpdprotection.vbs

Set objFTPSVC = GetObject("IIS://localhost/MSFTPSVC")
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    Set objLog = CreateObject("MSWC.IISLog")
    Set objDictionary = CreateObject("Scripting.Dictionary")

    Dim Attempts(), IP(), LastAttempt(), IPs
    Dim AlreadyBanned, InProcess, Session
    Dim CutOff, x, i
    IPs = 0

    'Iterate through each FTP site.
      For Each objSITE in objFTPSVC
        If lcase(objSITE.class) = "iisftpserver" Then
          ftpLogFilePath =  objSITE.LogFileDirectory & "\msftpsvc" & objSITE.Name
          Set objFolder = objFSO.GetFolder(ftpLogFilePath)
            Set objFiles = objFolder.Files
              For Each fileName In objFiles
                lastFile = fileName
              Next
            strLogFile = lastFile
            Set file = Nothing
          Set objFolder = Nothing

          'Use the IIS log file parser provided by MSFT
          objLog.OpenLogFile strLogFile, 1, "MSFTPSVC", 1, 0
            '(FileName,IOMode,ServiceName,ServiceInstance,OutputLogFileFormat)
            ' 0 = NotApplicable, 1 = ForReading
            Do While NOT objLog.AtEndOfLog
              objLog.ReadLogRecord
              If instr(ucase(objLog.Method), "USER") Then
  'Someone is attempting to authenticate with the FTP server
InProcess = False
AlreadyBanned = False
For x = 0 to IPs - 1
'Check to see if this IP address has already attempted to log in.
If objLog.ClientIP = IP(x) Then
'To be nice this code will give the user
'another attempt every minute.
'This is to avoid banning a person who
'attempts to log in multiple times
'in a day but keeps forgetting their password.
Attempts(x) = Attempts(x) + datediff("n", objLog.DateTime, lastattempt(x))
LastAttempt(x) = objLog.DateTime
InProcess = True
End If
Next
If Not InProcess Then
'If we aren't keeping track of this IP
'it's possible the IP has already been
'added to the ban list.
AlreadyBanned = objDictionary.Exists(objLog.ClientIP)
End If
If Not InProcess And Not AlreadyBanned Then
'First authentication attempt by this IP
IPs = IPs + 1
Redim Preserve IP(IPs)
Redim Preserve Attempts(IPs)
Redim Preserve LastAttempt(IPs)
IP(IPs - 1) = objLog.ClientIP
Attempts(IPs - 1) = 1
LastAttempt(IPs - 1) = objLog.DateTime
End If
      ElseIf instr(ucase(objLog.Method), "PASS") Then
'The server is responding to an authentication
'attempt.
For x = 0 to IPs - 1
'See if we're keeping track of this IP
    If IP(x) = objLog.ClientIP Then
'Increment the authentication attempts
Attempts(x) = Attempts(x) + 1
If Attempts(x) = 10 Then
'Ban if necessary
WScript.Echo "Banning " & objLog.ClientIP & "..."
objDictionary.Add objLog.ClientIP, "255.255.255.255"
AddDeadRoute objLog.ClientIP
    For i = x to (IPs - 2)
IP(i) = IP(i + 1)
Attempts(i) = Attempts(i + 1)
Next
IPs = IPs - 1
Redim Preserve IP(IPs)
Redim Preserve Attempts(IPs)
End If
End If
Next
              End If
            Loop
          objLog.CloseLogFiles 1
        End If
      Next

    Set objDictionary = Nothing
    Set objLog = Nothing
    Set objFSO = Nothing
    Set objFTPSVC = Nothing

    Function addDeadRoute(IP)
dim adoDBConn, sConnStr, objFSO, objBanBatch, cmdShell, WshShell
Dim fakeGateway
'I've been told that IPSec could be used to block certain IPs
'but 1) I'm not sure WMI can interface with it and 2) I don't
'know how to begin with. Someone gave me a much easier solution
'Simply add a route to the routing table pointing to a gateway
'that doesn't exist.

'Ensure that this IP is on the same subnet as the server
fakeGateway = "192.168.1.101"

Set WshShell = WScript.CreateObject("WScript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objBanBatch = objFSO.CreateTextFile("W:\config files\blocks\addRoute.bat", True)
objBanBatch.WriteLine "ROUTE ADD " & IP & " MASK 255.255.255.255 " & fakeGateWay
objBanBatch.Close
WshShell.Run """W:\config files\blocks\addRoute.bat""", 1, True
Set objFSO = Nothing
    End Function
Posted by: Chrissy LeMaire   Filed under: IIS, VBScript 13 Comments