2010 2013 EWS exchange exchange online hybrid IAmMEC iis Kemp Load Master Office 365 tmg

Exchange Web Services (EWS) and 501 Error

As is common with a lot that I write in this blog, it is based on noting down the answers to stuff I could not find online. For this issue, I did find something online by Michael Van “Hybrid”, but finding it was the challenge.

So rather than detailing the issue and the reason (you can read that on Michael’s blog) this talks about the steps to troubleshoot this issue.

So first the issue. When starting a migration test from an Exchange 2010 mailbox with an Exchange 2013 hybrid server (running the mailbox and CAS roles) behind a Kemp load balancing (running 7.16 – the latest release at the time of writing, but recently upgraded from version 5 through 6 to 7) I got the following error:


The server name will be different (thanks Michael for the screenshot). In my case this was my clients UK datacentre. My clients Hong Kong datacentre was behind a Kemp load balancer as well, but is only running Exchange 2010 and the New York datacentre has an F5 load balancer. Moves from HK worked, but UK and NY failed for different reasons.

The issue shown above is not easy to solve as the migration dialog tells you nothing. In my case it was also telling me the wrong server name. It should have been returning the External EWSUrl from Autodiscover for the mailbox I was trying to move, instead it was returning the Outlook Anywhere external URL from the New York site (as the UK is proxied via NY for the OA connections). For moves to the cloud, we added the External URL for EWS to each site directly so we would move direct and not via the only site that offered internet connected email.

So troubleshooting started with – the Microsoft Connectivity Analyser. Autodiscover worked most of the time in the UK but Synchronization, Notification, Availability, and Automatic Replies tests (to test EWS) always failed after six and a half seconds.

Autodiscover returned the following error:

A Web exception occurred because an HTTP 400 – BadRequest response was received from Unknown.
HTTP Response Headers:
Connection: close
Content-Length: 87
Content-Type: text/html
Date: Tue, 24 Jun 2014 09:03:40 GMT

Elapsed Time: 108 ms.

And EWS, when AutoDiscover was returning data correctly, was as follows:

Creating a temporary folder to perform synchronization tests.

Failed to create temporary folder for performing tests.

Additional Details

Exception details:
Message: The request failed. The remote server returned an error: (501) Not Implemented.
Type: Microsoft.Exchange.WebServices.Data.ServiceRequestException
Stack trace:
at Microsoft.Exchange.WebServices.Data.ServiceRequestBase.GetEwsHttpWebResponse(IEwsHttpWebRequest request)
at Microsoft.Exchange.WebServices.Data.ServiceRequestBase.ValidateAndEmitRequest(IEwsHttpWebRequest& request)
at Microsoft.Exchange.WebServices.Data.ExchangeService.InternalFindFolders(IEnumerable`1 parentFolderIds, SearchFilter searchFilter, FolderView view, ServiceErrorHandling errorHandlingMode)
at Microsoft.Exchange.WebServices.Data.ExchangeService.FindFolders(FolderId parentFolderId, SearchFilter searchFilter, FolderView view)
at Microsoft.Exchange.WebServices.Data.Folder.FindFolders(SearchFilter searchFilter, FolderView view)
at Microsoft.Exchange.Tools.ExRca.Tests.GetOrCreateSyncFolderTest.PerformTestReally()
Exception details:
Message: The remote server returned an error: (501) Not Implemented.
Type: System.Net.WebException
Stack trace:
at System.Net.HttpWebRequest.GetResponse()
at Microsoft.Exchange.WebServices.Data.EwsHttpWebRequest.Microsoft.Exchange.WebServices.Data.IEwsHttpWebRequest.GetResponse()
at Microsoft.Exchange.WebServices.Data.ServiceRequestBase.GetEwsHttpWebResponse(IEwsHttpWebRequest request)

Elapsed Time: 6249 ms.

What was interesting here was the 501 and that it was always approx. 6 seconds before it failed.

Looking in the IIS logs from the 2010 servers that hold the UK mailboxes there were no 501 errors logged. The same was true for the EWS logs as well. So where is the 501 coming from. I decided to bypass Exchange 2013 for the test (as my system is not yet live and that is easy to do) and so in Kemp pointed the EWS SubVDir directly to a specific Exchange 2010 server. Everything worked. So I decided it was an Exchange 2013 issue, apart from the fact I have lab environments the same as this (without Kemp) and it works fine there. So I decided to search for “Kemp EWS 501” and that was the bingo keyword combination. EWS and 501 or Exchange EWS and 501 got nothing at all.

With my environment back to Kemp >  2013 >  2010 I looked at Michaels suggestions. The first was to run Test-MigrationServerAvailability –ExchangeRemoteMove –RemoteServer I changed this slightly, as I was not convinced that I was connecting to the correct endpoint. The migration reported the wrong server name and the Exrca tests do not tell you what endpoint they are connecting to. So I tried Test-MigrationServerAvailability –ExchangeRemoteMove –Autodiscover –EmailAddress

As AutoDiscover is reporting errors at times, the second of these cmdlets sometimes reported the following:

RunspaceId         : a711bdd3-b6a1-4fb8-96b8-f669239ea534
Result             : Failed
Message            : AutoDiscover failed with a configuration error: The migration service failed to detect the
migration endpoint using the Autodiscover service. Please enter the migration endpoint settings
or go back to the first step and retry using the Autodiscover service. Consider using the
Exchange Remote Connectivity Analyzer ( to diagnose the
connectivity issues.
ConnectionSettings :
SupportsCutover    : False
ErrorDetail        : internal error:Microsoft.Exchange.Migration.AutoDiscoverFailedConfigurationErrorException:
AutoDiscover failed with a configuration error: The migration service failed to detect the
migration endpoint using the Autodiscover service. Please enter the migration endpoint settings
or go back to the first step and retry using the Autodiscover service. Consider using the
Exchange Remote Connectivity Analyzer ( to diagnose the
connectivity issues.
at Microsoft.Exchange.Migration.DataAccessLayer.MigrationEndpointBase.InitializeFromAutoDiscove
r(SmtpAddress emailAddress, PSCredential credentials)
at Microsoft.Exchange.Management.Migration.TestMigrationServerAvailability.InternalProcessExcha
IsValid            : True
Identity           :
ObjectState        : New

And when AutoDiscover was working (as it was random) I would get this:

RunspaceId         : a711bdd3-b6a1-4fb8-96b8-f669239ea534
Result             : Failed
Message            : The ExchangeRemote endpoint settings could not be determined from the autodiscover response. No
MRSProxy was found running at ‘’.
ConnectionSettings :
SupportsCutover    : False
ErrorDetail        : internal error:Microsoft.Exchange.Migration.MigrationRemoteEndpointSettingsCouldNotBeAutodiscovere
dException: The ExchangeRemote endpoint settings could not be determined from the autodiscover
response. No MRSProxy was found running at ‘’. —>
Microsoft.Exchange.Migration.MigrationServerConnectionFailedException: The connection to the
server ‘’ could not be completed. —>
Microsoft.Exchange.MailboxReplicationService.RemoteTransientException: The call to’ failed. Error details: The HTTP request is
unauthorized with client authentication scheme ‘Negotiate’. The authentication header received
from the server was ‘Basic Realm=””‘. –> The remote server returned an
error: (401) Unauthorized.. —>
Microsoft.Exchange.MailboxReplicationService.RemotePermanentException: The HTTP request is
unauthorized with client authentication scheme ‘Negotiate’. The authentication header received
from the server was ‘Basic Realm=””‘. —>
Microsoft.Exchange.MailboxReplicationService.RemotePermanentException: The remote server returned
an error: (401) Unauthorized.
— End of inner exception stack trace —
— End of inner exception stack trace —
at Microsoft.Exchange.MailboxReplicationService.MailboxReplicationServiceFault.<>c__DisplayClas
at Microsoft.Exchange.MailboxReplicationService.ExecutionContext.Execute(Action operation)
at Microsoft.Exchange.MailboxReplicationService.MailboxReplicationServiceFault.ReconstructAndTh
row(String serverName, VersionInformation serverVersion)
at Microsoft.Exchange.MailboxReplicationService.WcfClientWithFaultHandling`2.<>c__DisplayClass1
at Microsoft.Exchange.Net.WcfClientBase`1.CallService(Action serviceCall, String context)
at Microsoft.Exchange.Migration.MigrationExchangeProxyRpcClient.CanConnectToMrsProxy(Fqdn
serverName, Guid mbxGuid, NetworkCredential credentials, LocalizedException& error)
— End of inner exception stack trace —
at Microsoft.Exchange.Migration.DataAccessLayer.ExchangeRemoteMoveEndpoint.VerifyConnectivity()
at Microsoft.Exchange.Management.Migration.TestMigrationServerAvailability.InternalProcessEndpo
int(Boolean fromAutoDiscover)
— End of inner exception stack trace —
IsValid            : True
Identity           :
ObjectState        : New

This was returning the URL’ which is not correct for this mailbox (this was the OA endpoint in a different datacentre) and external Outlook access is not allowed at this company and so the TMG server in front of the F5 load balancer in the NY datacentre was not configured for OA anyway and browsing the the above URL returned the following picture, which is a well broken scenario but not the issue at hand here!


If OA (Outlook Anywhere) was available for this company, this is not what I would expect to see when browsing to the External EWS URL. To that end we have EWS URL’s are bypass TMG and go direct to the load balancer.

So now we have either no valid AutoDiscover response or EWS using the wrong URL. Back to the version of the cmdlet Michael was using as that ignores AutoDiscover: Test-MigrationServerAvailability –ExchangeRemoteMove –RemoteServer

RunspaceId         : 5874c796-54ce-420f-950b-1d300cf0a64a
Result             : Failed
Message            : The connection to the server ‘’ could not be completed.
ConnectionSettings :
SupportsCutover    : False
ErrorDetail        : Microsoft.Exchange.Migration.MigrationServerConnectionFailedException: The connection to the
server ‘’ could not be completed. —>
Microsoft.Exchange.MailboxReplicationService.RemoteTransientException: The call to’ failed. Error details: The remote server returned
an unexpected response: (501) Invalid Request. –> The remote server returned an error: (501) Not
                     Implemented.. —> Microsoft.Exchange.MailboxReplicationService.RemotePermanentException: The
remote server returned an unexpected response: (501) Invalid Request. —>
Microsoft.Exchange.MailboxReplicationService.RemotePermanentException: The remote server returned
an error: (501) Not Implemented.
— End of inner exception stack trace —
— End of inner exception stack trace —
at Microsoft.Exchange.MailboxReplicationService.MailboxReplicationServiceFault.<>c__DisplayClas
at Microsoft.Exchange.MailboxReplicationService.ExecutionContext.Execute(Action operation)
at Microsoft.Exchange.MailboxReplicationService.MailboxReplicationServiceFault.ReconstructAndTh
row(String serverName, VersionInformation serverVersion)
at Microsoft.Exchange.MailboxReplicationService.WcfClientWithFaultHandling`2.<>c__DisplayClass1
at Microsoft.Exchange.Net.WcfClientBase`1.CallService(Action serviceCall, String context)
at Microsoft.Exchange.Migration.MigrationExchangeProxyRpcClient.CanConnectToMrsProxy(Fqdn
serverName, Guid mbxGuid, NetworkCredential credentials, LocalizedException& error)
— End of inner exception stack trace —
at Microsoft.Exchange.Migration.DataAccessLayer.ExchangeRemoteMoveEndpoint.VerifyConnectivity()
at Microsoft.Exchange.Management.Migration.TestMigrationServerAvailability.InternalProcessEndpo
int(Boolean fromAutoDiscover)
IsValid            : True
Identity           :
ObjectState        : New

Now we can see the 501 error that exrca was returning. It would seem that the 501 is coming from the Kemp and not from the endpoint servers, which is why I could not located it in IIS or EWS logs and so in the Kemp System Message File (logging options > system log files) I found the 501 error:

kernel: L7: badrequest-client_read [>] (-501): <s:Envelope ? , 0 [hlen 1270, nhdrs 8]

Where the first IP address was a Microsoft datacentre IP and the second was the Kemp listener IP.

It turns out this is due to the Kemp load balancer not returning to Microsoft the Continue-100 status that it should get. Microsoft waits 5 seconds and then sends the data it would have done if it got the response back. At this point the Kemp blocks this data with a 501 error.

It is possible to turn off Kemp’s processing of Continue-100 HTTP packets so it lets them through and this is covered in


In the version at my clients which was upgraded to version 7.0-16 from a v5 to v6 to v7 it was defaulting to RFC Conformant, but needs to be Ignore Continue-100 to work with Office 365. In versions of Kemp 7.1 and later the value needs to be changed to RFC-7231 Compliant from the default of “RFC-2616 Compliant”. Now EWS works, hybrid mailbox moves work, and AutoDiscover is always working on that server – so a mix of issues caused by differing interpretations of an RFC. To cover all these issues the Kemp load balancer started to include this 100-Continue Handling setting. We as ITPro’s need to ensure that we set the correct setting for our environment based on the software we use.

2013 Edge exchange firewall IAmMEC iis networking powershell transport

Secret NSA Listening Ports in Exchange Server 2013? Of Course Not…

But what do those extra ports in Exchange Server 2013 that are listening actually do.

If you bring up a command prompt on an Exchange Server 2013 machine and run netstat –ano | find “:25”. You will get back a list of IP addresses that are listening on any port starting 25. The last number on the line is the process ID for that listening port. So for Mailbox only role servers you are interested in the row that shows and for a multirole (CAS and Mailbox) server, the row that shows as shown:


Above you can see that process 21476 is listening on 2525 and as this is a multirole server this process ID will be EdgeTransport.exe – you can verify this in Task Manager if you want.

Repeat the netstat cmd, this time for the process ID you have selected: netstat –ano | find “xxxxx” where xxxxx is the process ID for EdgeTransport.exe, as shown:


You will now see that EdgeTransport.exe is listening in on a range of ports for both IPv4 and the same ports for IPv6. These ports are 25 or 2525, which is used by 2007 or 2010 Edge role servers, or by other 2007/2010 Hub Transport role servers or by other 2013 Mailbox role servers or by 2013 CAS role servers to send emails to this server via SMTP. Port 465 is the port that 2013 CAS servers proxy authenticated SMTP connections to that they receive on port 587 from mail clients. But what about port 29952 in my example (and on your servers a different port) which changes each time the service is restarted?

If you do netstat again just for this port you will see something like the following:


This shows that nothing is connected currently to these ports, and so they seem to be doing nothing. But if on a different Exchange 2013 server you do some viewing of the transport queues then these ports will start to show some activity.

On a different server in my environment I ran Get-Queue –Server remoteservername. If I do this on the local server, then nothing special happens as Exchange does not need to connect to these ports, but if it is run from a different server and I ask it to show the queue on the first server that we have been looking at above, then these ports become used:



Above we can see Exchange Management Shell on mail5 connecting to mail4 (the original server in this blog post). The second picture from mail4 shows that port 29952 have received a connection from the IPv6  address of mail5 and specifically from port 65172 on that remote server.

If I look finally at the second server in this exercise and see what process is connecting from port 65172 (and again, your ports will be different) I see that process 15156 is doing this (the process ID is the last column in the output)


Taking this process ID to Task Manager, I see process 15156 is the IIS Worker Process, which is the process that PowerShell connects to to do its work.


Therefore, the random and changing port that EdgeTransport.exe listens on is nothing to do with PRISM, but all to do with your management of remote queues.

DNS draytek exchange iis ip ipv4 ipv6 mcm mcsm rras windows

IPv6 Routed LAN with Windows

This blog is written to note down the steps needed to configure IPv6 on the whole of your LAN using Windows Server 2008 R2 as the router, but without installing RRAS.

It also uses Hurricane Electric’s IPv6 tunnel broker service to provide the IPv6 connectivity via an IPv4 tunnel as my internet provider (Virgin Media in the UK) does not provide direct IPv6 connectivity at the time of writing (Dec 2012).

Originally the plan was to do all this with the Draytek 2920 router on my network, but after days of trying I gave up as it was unable to connect to SixXS over AICCU or Freenet6/gogo via TSPC even though I had made accounts and entered the information as shown on various websites and forum. Draytek do not provide a 6in4 tunnel mode, so I needed to move to using Windows or Linux, as I have both on my LAN – though I am way more familiar with Windows!

Configuring Your Internet Router

You will need control over your internet connection as you will need to enable inbound PING responses before you can create an IPv6 tunnel. On a Draytek router this is System Maintenance > Management > untick Disable PING from the internet.

Also to allow a tunnel to traverse a NATed router, you need to allow Protocol 41 to pass the firewall. On a Draytek router this involves creating a new rule in the Default Call Filter rule set and the same under the Default Data Filter set. The settings are Direction: WAN –> LAN/RT/VPN; Source IP: Any; Destination IP: Any; Service Type: Protocol: 41; Filter: Pass Immediately.

Getting a Hurricane Electric Tunnel

Visit and create an account and request a tunnel. Once you have requested a tunnel you will get the following information on the IPv6 Tunnel tab (of which only the important information is shown, and where I have changed the values to be generic):

  • IPv6 Tunnel Endpoints
    • Server IPv4 Address: a.b.c.d (the endpoint of the tunnel at Hurricane Electric)
    • Server IPv6 Address: 2001:xxxx:wwww:65b::1/64 (this has wwww shown in bold and is the Hurricane Electric end of the tunnel they have created for you, and it will end in a 1.)
    • Client IPv4 Address: w.x.y.z (this is your external IP address of your internet connection)
    • Client IPv6 Address: 2001:xxxx:wwww:65b::2/64 (this has wwww shown in bold and is your end of the tunnel they have created for you, and it will end in a 2.)
  • Routed IPv6 Prefixes
    • Routed /64: 2001:xxxx:yyyy:65b::/64 (this has yyyy in bold and yyyy is one number higher than wwww in the IPv6 tunnel endpoints above).

On the Example Configurations tab you will get the choice of operating system to use, and you need to select Windows Vista/2008/7 from the dropdown list. This will present you with some netsh commands as shown (where the values will be your specific values rather than the generic values I show here):

netsh interface teredo set state disabled
netsh interface ipv6 add v6v4tunnel IP6Tunnel w.x.y.z a.b.c.d
netsh interface ipv6 add address IP6Tunnel 2001:xxxx:wwww:65b::2
netsh interface ipv6 add route ::/0 IP6Tunnel 2001:xxxx:wwww:65b::1

If you are behind a NATed router then you need to change the w.x.y.z value which will show your public IP address for the private IP address of the Windows Server you are going to run this set of commands on.

Run these commands from an elevated command prompt. Once complete you should be able to reach the IPv6 internet from that machine. Try ping and you should get back the IPv6 address for Facebook (showing your DNS server is IPv6 aware – Windows DNS will return AAAA, the IPv6 version of the A record, responses if your client has a valid global IPv6 address). Another destination you can attempt to ping is

You now have working IPv6 from a single server on your LAN.

Configuring The Windows Router

The next step is to enable this single server as a router. This will allow the forwarding of packets between the LAN and the IPv6 Tunnel that exists on this server.

NOTE: This series of steps does not use RRAS, and therefore there is no firewall on this router. Therefore these steps should be for lab environments only, as you need to ensure that Windows Firewall on all your endpoints is secure (remote admin [DCOM], RPC Endpoing and 445 have default rules for open to anyone) – these will need securing to a suitably valid range, or implment IPSec on the servers so connections cannot be made from non domain members. A good IPv6 port scanner is available at

Continuing in your elevated command prompt on the tunnel Windows machine enter the following command:

netsh interface ipv6 set route ::/0 IP6Tunnel publish=yes

This adds a route for the entire IPv6 address space to go via this machine, and publishes it so that it can be see by other machines on the LAN. The publish=yes command is the only bit of this that is different from the commands provided by Hurricane Electric.

The next command to enter is:

netsh interface ipv6 add address interface=”Local Area Connection” address=2001:xxxx:yyyy:65b::1

This command adds an IP address from the Routed /64 range to the network card on the machine (called “Local Area Connection” here. If your network card has a different name then change the name, and use the correct address that you want to use rather than the generic one I show here). I have chosen to end my routers IPv6 address with ::1. This means that the full address in my example is 2001:xxxx:yyyy:065b:0000:0000:0000:0001 and therefore I could choose anything for the 0000:0000:0000:0001 bit, remembering that one long list of zero’s can be collapsed to :: and leading zero’s can be removed.

Continue with:

netsh interface ipv6 set interface “Local Area Connection” forwarding=enabled advertise=enabled routerdiscovery=enabled advertisedefaultroute=enabled privacy=disabled

The command (which is long and probably wrapped on your web browser) enables forwarding on the Local Area Connection interface (forwards packets arriving on this interface to others, i.e. makes this box a router) and it will also advertise it’s routes and that it is a router. Router advertisement (both advertise=enabled routerdiscovery=enabled) allow clients on your network to find the router and generate their own IPv6 address. In this example this will therefore turn on IPv6 for your entire LAN. If you wish to do this test on just a few servers then add a valid IPv6 address using DHCPv6 with reservations or add the addresses manually on the machines you want to test IPv6 from (valid addresses are 2001:xxxx:yyyy:065b:z:z:z:z, where z:z:z:z is up to four blocks of four hex digits each). Privacy (see later) is disabled for this NIC as well.

NOTE: For any website that is IPv6 enabled, any computer that gets an IPv6 address will now use the tunnel to get to the internet. If the tunnel is down or slow then internet connectivity on all your machines will suffer. Your tunnel will be slower than your WAN speed and latency is likely to be higher. Consider carefully the advertise and routerdiscovery settings. You can always change them to disabled later if you wish (and reset your client network card to pick up the changes with netsh int ipv6 reset). I managed two days with IPv6 for every client before I changed back to IPv4. There are steps on line to change the prefix policy (netsh int ipv6 show prefix) to put IPv4 above IPv6 as an alternative to turning advertising and router discovery off.

The next command to enter is:

netsh interface ipv6 set route 2001:xxxx:yyyy:65b::/64 “Local Area Connection” publish=yes

This command publishes the route to your LAN so that the IP6Tunnel network that you created earlier can route packets to the correct interface. This is the opposite command the the first publish command you ran previously, as that one published the outbound route, this publishes the inbound route.

Finally you need to run this last command:

netsh int ipv6 set interface “IP6Tunnel” forwarding=enabled

This allows packets arriving on the IP6Tunnel from the internet to be forwarded to other networks on the machine. Again, this is the opposite of the earlier forwarding=enabled command and allows forwarding of packets arriving on the IP6Tunnel adapter to be forwarded into the LAN.

Connecting to the IPv6 Internet

Finally you are ready to go. If you open a command prompt on a Windows Vista or later client on the LAN and run ipconfig you should see an IPv6 address (and maybe a temporary IPv6 address) as well as a default gateway listing your newly configured router (reached via the Link Local address rather than the global IP address of the router if routerdiscovery is enabled on the router).

The IPv6 address you have is calculated from your Routed /64 subnet (the network portion of the address) and your MAC address. This local portion will therefore always be the same for you. This means that you are therefore trackable on the internet, as your local portion does not change. Therefore Windows 7 generates a temporary address which changes every 7 days (netsh int ipv6 show addresses and the Pref. Life column for Preferred Lifetime). After seven days the temporary address is recreated.

Open your web browser and visit to see if you have IPv6 connectivity.

You should now be able to ping or ping and get a response back from the IPv6 internet.

Note that if you reboot your router or your client they will take a short while to pick up a valid IPv6 configuration from the Router Advertisements (RADV) that are running on the router (advertising the Routed /64 range you have – no requirement for DHCPv6 in this example).

Having the IPv6 Internet Connect To You (i.e. Publishing IPv6 Services)

On any machine with a valid global IPv6 address you should be able to enable the File and Printer Sharing (Echo Request – ICMPv6-In) rule in Windows Firewall and then visit (or another IPv6 online ping test tool) and be able to ping your server or client.

Disable the ping firewall rule if needed and enable or create a firewall rule to allow a port of your choice to be published over IPv6. Configure the server to support listening on IPv6 if needed and then attempt to browse that service from another IPv6 enabled client.

Got this far – have a go at the IPv6 certification at Hurricane Electric

IPv6 Certification Badge for brainier


Running Offline Web Applications from IIS Server

A feature of HTML 5 based applications is the ability to ensure that applications can still run even if internet connectivity is not present. How to do this is covered on the website.

A requirement of offline access is the creation of the offline cache manifest file. This manifest file is listed in the HTML tag on the page as such:

<html manifest="offline.appcache">

And a page is saved to the web server with the same name (offline.appcache in this example). This .appcache file follows the conventions described in the above web page, but this page needs to be served from the web server with a specific MIME type (text/cache-manifest). If the web server is IIS 5.0 or later then it will only serve content that has been listed as a valid MIME type in Windows. If you used a shared hosted webserver then making that change is probably impossible – so from IIS 7.0 or later you can add your own MIME type in the admin UI or modify the web.config file in the root of your web server to add this MIME type. This is just a text file that you upload and so requires no access to the IIS admin application (again, typically something you do not get with  shared hosted web server).

Note: In the example given below, the web.config file changes two properties. If you have an existing web.config file then merge these changes into your file and do not replace your file.

The web.config file needs to be as follows:

xml version="1.0" encoding="UTF-8"?>
<mimeMap fileExtension=".appcache" mimeType="text/cache-manifest" />
<location path="offline.appcache">
<clientCache cacheControlMode="DisableCache" />

The two changes set in this web.config file are, firstly, mimeMap in the staticContent section of system.webServer. This adds the .appcache extension as text/cache-manifest. The second change is clientCache in staticContent section of system.webServer (but this time in a location section, limiting the effect of the setting to the named file – offline.appcache). This change stops the web server or client from caching the page, ensuring that the web server always serves the latest copy of the page.

Upload web.config and your appcache manifest file, along with any page that needs to be viewed offline (or indeed any page that you want to speed up loading for, by causing the pages to be cached on the client) and check that when you browse to the .appcache file directly in a HTML 5 aware browser it is visible. If you get a 404 error on this page then you have not set the MIME type or uploaded the correct web.config file.

certificates exchange hosting https iis networking SSL

GoDaddy SSL Certificate Approval with TXT Records

I had a bit of an issue with Go Daddy yesterday in that they took 5 days to approve a Subject Alternative Name change to a certificate, and as the usual route of adding a file to a website was unavailable to me I decided to prove ownership of the domain by the addition of a new TXT record to the domain.

Go Daddy’s instructions for doing this are only suitable for domains hosted at Go Daddy and there are no clear instructions for doing this if you do not use Go Daddy for your DNS hosting.

So how do you create an SSL approval with TXT record? You do it by creating a TXT record for a subzone. The subzone is DZC and the value of the record is the seven character string that Go Daddy sent you via email. For example TXT AbCdEfG.

Once DNS has replicated to ALL of your DNS servers you can return to Go Daddy’s web form and approve your SSL certificate. You can check if all your DNS servers have your new data by using NSLookup or Dig, but preferred is the use of either of these two tools from an independent third party on the internet – for example or

2008 https iis remote web workplace rww sbs 2008 terminal server ts gateway windows

SBS 2008 SharePoint Install Breaks Default SBS Web Site

A recent installation of a second SharePoint site on Small Business Server 2008 broke the Remote Web Workplace site for access from the internet. Intranet access to the site worked fine, but from the internet where the http request to the site is redirected to https had stopped working.

Opening up IIS 7 Manager and checking the bindings of the SBS Web Applications site showed that the site had two http bindings and a https binding. The https binding was for * under IP Addresses and port 443. Clicking the Edit button on this binding showed that the certificate was not correct. This was the reason the site was not working, as a https site requires a certificate.

So I selected the correct certificate and clicked OK. And got the following error:

A specified logon session does not exist. It may already have been terminated. (Exception from HRESULT: 0x80070520)

The reason is that the installation of the SharePoint site, and the installation of the certificate to support that site broke the binding for the TS Gateway role on the Windows 2008 machine. The broken binding on the SBS Web Applications site was because of this broken TS Gateway configuration and to fix the above error in IIS required fixing the TS Gateway issue. Note that at no point in the configuration of the SharePoint application was the TS Gatway role configuration changed – the installation of another certificate on the server broke the TS Gatway which broke the Remote Web Workplace SBS Web Applications site.

Opening Server Manager and navigating to the Roles/Terminal Services/TS Gateway/Servername area showed a message in the middle pane of the Server Manager saying that configuration of the TS Gateway was not complete. Clicking this link brought up the TS Gateway SSL Certificate page of the Properties dialog. Click Browse Certificates and select the correct certificate. In SBS 2008 this will be the Remote Web Workplace certificate. Click OK to close the dialog and you will now be able to check the https binding on the SBS Web Applications website. The error will now not occur, and the https binding will be bound to the correct certificate.

If you are not running SBS 2008 then the above is possible, just it is more likely to be a problem with the Default Web Site bindinging instead.

Additionally, I noticed after I had written the above that this error also occurs if you delete the certificate used by the TS Gateway from the IIS box and as well as breaking TS Gateway (which would be expected) it also breaks the “Add a trusted certificate” wizard in the SBS Server Console. The Add a trusted certificate wizard crashes when started with just a failed application message and nothing in the event log. To fix make sure the SBS Web Application IIS site is bound to a valid digital certificate.

2008 64 bit access iis oledb proxy sql express windows x64

Windows 2008, IIS 7.0, 64 bit Server, Terminal Services Web Application and Access Databases

This is a long list of pre-requisites, but for your information they do not work together.

  1. If you have a web site that uses Access as its data storage and you migrate that site to an x64 Windows machine then access to the Access MDB file ceases with the following error: “‘Microsoft.Jet.OLEDB.4.0’ provider is not registered on the local machine”.
  2. On IIS 6.0 you need to set the entire web server to 32 bit mode, but on Windows 2008/IIS 7.0 you can set each application pool to 32 or 64 bit. This is a property found under Advanced Settings for the application pool. To gain access to Access MDB files the application pool needs to run in 32 bit mode.
  3. If you have TSWeb installed, then you also have installed the RPC/HTTP proxy component.
  4. If you have the RPC/HTTP proxy component installed any 32 bit application pool will fail upon starting – Error 5139 for Microsoft-Windows-WAS.

So to use Access databases in a legacy web application migrated to Windows 2008, 64 bit, with TSWeb also installed either uninstall TSWeb (and RPC/HTTP proxy), or use a different server, or rewrite the web application to use SQL Express. Supposedly this will be fixed in the first service pack for Windows 2008.

There – it only took 6 hours to work that one out!

2008 iis rras sbs 2008 sstp vpn windows

SSTP (SSL VPN) on SBS 2008 RC0

Updated 31st March 2008: Please see as this new article replaces the below, as the below refers to a pre-release version of SBS 2008. The working instructions for configuring SSTP on SBS 2008 is much more complicated than the steps below.

SSL based VPN’s are great. In short it is VPN without firewall or NAT issues (both of which you get with PPTP and IPSec VPN’s). But the current release of SBS 2008 (RC0) does not enable SSTP VPN’s by default. It uses RRAS, so SSTP is possible, but it is not as easy as it first looks!

  1. Ensure that you have run the connecting to the internet wizard, and that you are using a third party certificate (as there are less steps if you do this).
  2. Enable remote access from the SBS Console > Network > Connectivity page.
  3. Add some SSTP ports to the VPN in the Routing And Remote Access management program. Right-click Ports and choose Properties and enable SSTP for remote access inbound connections. Leave PPTP enabled as Windows XP does not support SSTP VPN tunnels (only Vista SP1 does at this time).
  4. View the properties of your certificate and note down the Thumbprint value.
  5. Ensure that this certificate is associated with and [::]:443: certificate bindings on the server. Type “netsh http show ssl” from elevated command prompt to get this information. You typically get four entries with IP:port being the first line of each. Check for IP:port reading “” and [::]:443 as this shows the IPv4
    and IPv6 mappings for SSL certificates on the server. Ignore the :8172 and :987 entries (these are for IIS Management Service and companyweb).
  6. For both “” and [::]:443 make a note of the Certificate Hash. It needs to be the same for both and the same as the earlier Thumbprint value (ignore any spaces).If not see for instructions on resetting this, noting that you need to ensure that the correct certificate is bound to the SBS Web Applications website on the SBS 2008 server (in IIS manager).
  7. Install the “Certificate Authority Web Enrollment” role service to Active Directory Certificate Services snapin within Server Manager. This adds a virtual directory to the default website in IIS called CertEnroll which contains the certificate revocation list for the certificate you are using. Only do this if you are using the built in default issued certificate. If you are using certificates from a third party then you need to ensure you can reach
    their CRL publishing site without issue – see the certificate details for information on the CRL publishing site location.
  8. Expand the Certificate Authority on your server and right-click Revocated Certificates. Under tasks choose Publish. This updates the CRL with the new publishing location that SSTP needs to connected to. Again, use a third party certificate to make this easy!
  9. On a Vista SP1 client create a new VPN connection and in properties > networking ensure that the Type of VPN is set to SSTP (for normal use set this to Auto, and it will find the best (starting with PPTP), but for testing set it specifically to SSTP). Also ensure that the name of the server you are connecting to is the same name that the certificate uses for the certificate common name.
  10. Connect the VPN and all should work.

Windows SharePoint Services 3.0 Search Not Indexing

If you get the following error on a WSS 3.0 site:

Access is denied. Check that the Default Content Access Account has access to this content, or add a crawl rule to crawl this content. (0x80041205)

Then check that you are not being blocked from searching due to Kerberos restrictions. The search service indexes the content of the site using the default URL for the WSS site, so if this is sts3://servername:port then all should be well, but if this is a FQDN style URL (such as sts3:// then you need to either delete the site and recreate with NTLM security or add a SPN to the server.

To add an SPN use setspn from the Windows Server Support Tools. The command is:


Where SERVERNAME is the server running WSS and is the default URL of the site. See alternative access mappings in Central Admin for the default URL.

certificates https iis ISA Server 2004 ISA Server 2006 SSL Windows Server 2003

Error Code: 500 Internal Server Error. The network logon failed. (1790)

This is an error visible in the web browser when connecting to a HTTPS web site behind an ISA Server.

The problem is that the firewall access rule for this web site in ISA Server is forwarding the requests to an internal server on a port that it is not listening on. For example you connect to and the ISA Server forwards this request to http://internalsrv. On the Bridging tab check that the mentioned port(s) are actually working on the internal server. For example if you are listening in ISA Server on 443 for a SSL connection and the SSL/HTTPS port is ticked make sure that the port is 443, and that the web server internally is listening on 443. If its another number make sure that it is meant to be the other number and not really 443 or not ticked at all. Ditto for the HTTP port, which is 80 by default.

2007 certificates exchange iis microsoft pkcs powershell web

Creating Subject Alternative Name Certificates with Microsoft Certificate Server

A new feature in digital certificates is the Subject Alternative Name property. This allows you to have a certificate for more than one URI (i.e. and in the same certificate. It also means that in web servers such as IIS you can bind this certificate to the site and use up only one IP address.

A number of commercial companies now sell certificates with the Subject Alternative Name field set, but this article describes how to use the Exchange Server 2007 command line to create certificate requests for other web sites that can be uploaded to Microsoft Certificate Server (which does not support this property in its own web pages) to create certificates for web servers such as IIS (which also do not support this property in the requests that they make).

The command that you need to run is via PowerShell, and specifically via the Microsoft Exchange Server 2007 extensions to PowerShell. So start up the Microsoft Management Shell and enter the following (replacing your domain names as indicated:

New-ExchangeCertificate -GenerateRequest:$true -Path c:\newCert.req -DomainName,, -PrivateKeyExportable:$true -FriendlyName “My New Certificate” -IncludeAcceptedDomains:$false -Force:$true

The DomainName property is set to each URL that you want the certificate to be valid for, with the first value in the string being the value for the Subject field and all the values each being used in the Subject Alternative Name field.

Once you have executed the command above you will have a file with the name set in the Path property. This file can be opened in Notepad and used in Microsoft Certificate Services:

  1. Browse to your Microsoft Certificate Services URL and click Request a certificate
  2. Click advanced certificate request
  3. Click submit a certificate…
  4. Copy and paste the entire text of the certificate request from notepad into the Saved Request field on this page and select Web Server as the Certificate Template. Click Submit.
  • With a default installation the Web Server template value will not be present and that needs to be enabled by your Certificate Services administrator for your user account
  • With the default installation of Certificate Services, the certificate will now be ready to download. Click Download certificate (or Download Certificate Chain if the end server does not trust your issuer) to save your certificate to the computer.
  • Install the certificate on to the same computer that you issued the request from (this is a very important step), and then you can export the certificate and import it on your web server or firewalls.

To install the certificate, run the Import-ExchangeCertificate powershell command on the same computer as the request was issued from (this is a very important, it must be on the same computer). This is a simpler command to run that the creation of the request above.

The syntax of this command is (where the filename is the name of the file downloaded above):

Import-ExchangeCertificate c:\newCert.cer

To export the certificate to your web server or firewall you need to open the local computer certificate store in the Microsoft Management Console – run mmc, add a snap-in and choose Certificates, Computer account. You will find your certificates under the Personal store. You can right-click these certificates and export them (with the private key) to a .pfx file. This file can then be imported using the MMC tool on the web server or firewall ready for importing using an mmc with the certificates/computer account snap-in load into it.


Improving the Performance of IIS 6.0 Applications

Whilst working at a client doing some performance testing of an intranet, web-based, application we came across a little documented way to improve the network performance of the application if the web server is running IIS 6.0 on the Windows Server 2003 platform.

When the IIS 6.0 web server uses Windows Integrated authentication to log users onto a web application it goes through the following process, which is different to how it behaved on IIS 4.0, IIS 5.0 and IIS 5.1 (the versions that run on Windows NT 4.0, Windows 2000 and Windows XP):

  1. Client connects to the web server with an anonymous connection for the first object required.
  2. The web server rejects the connection with a 401 status message, which means that authentication is required.
  3. The client sends the request for the page to the server again, along with the current authentication information. The format of this authentication will differ based on whether NTLM or Kerberos is being used.
  4. Server responds with a 200 status indicating success and the object is transferred from the server to the client.
  5. So far nothing has changed in IIS 6.0 compared to the earlier versions of the software, but now the client makes the request for the second object (maybe a graphic within the page, or a second page on the same server). This second request, even if it is across the same HTTP session as the first, will be seen by the server as an anonymous request and it will be rejected with a 401 status message. In earlier versions of IIS this second (and subsequent requests on the same HTTP connection) were treated as being authenticated because the first object request was successfully authenticated.

This can be seen using the following information from an IIS 6.0 log file that was generated by a web browser making a GET request for four pages called auth1.htm through to auth4.htm.


cs-uri-stem cs-username sc-status sc-bytes cs-bytes
/auth1.htm  -           401       1872     516
/auth1.htm  DOMAIN\user 200       509      2307
/auth2.htm  -           401       1872     557
/auth2.htm  DOMAIN\user 200       510      2348
/auth3.htm  -           401       1872     557
/auth3.htm  DOMAIN\user 200       510      2348
/auth4.htm  -           401       1872     557
/auth4.htm  DOMAIN\user 200       510      2348

The client makes a request for the page auth1.htm. This page is only available to a user via Windows Integrated authentication and so the request is seen as rejected with a 401 status. The second line shows the successful request for the same page and the fact that a Windows domain account was used to authenticate the request. From that point on, each request can be seen first as an authentication failure and then a success. This means additional round trips to the web server, and longer page load times – especially to web servers that are across low latency WAN connections. For example, the above log data shows that the total bytes sent and received by the web server (the sum of the sc-bytes and the cs-bytes columns) is 21065 bytes. We will compare this value to one where the IIS 6.0 server has had performance changes made to it later in this article.

IIS 4.0, IIS 5.0 and IIS 5.1 worked by allowing all subsequent requests for objects over a single HTTP session that had already been authenticated to use the authentication information of the first successful request. With the increase in security that is part of IIS 6.0 this potential security hole has been closed – it might be possible to take over another session and become authenticated with the credentials of that previous session. This security improvement though, as with many security changes, decreases performance by an increases the number of round trips to the server and the bytes transferred on the network. If the risk is considered unlikely within your environment and users connect to the web server from remote locations then you can set the IIS metabase setting AuthPersistSingleRequest to false. This means that the IIS 6.0 web server acts in terms of authentication persistence like an IIS 5.0 web server.

The two metabase keys that need to be set are:

  • NTAuthenticationProviders
  • AuthPersistSingleRequest

NTAuthenticationProviders can be set at the web service or web site level and AuthPersistSingleRequest can be set at the web service, web site, virtual or real directory or at the file level.

To set these two metabase values open a command prompt, change to the \inetpub\adminscripts folder and run each of the following commands:

  1. cscript adsutil.vbs SET w3svc/1/NTAuthenticationProviders “NTLM”
  2. cscript adsutil.vbs SET w3svc/1/AuthPersistSingleRequest FALSE

The “1” in both the above commands will cause the property to be set on the Default Web Site. Change “1” to affect another web site or remove “1/” from the command to affect the entire server.

Once the two commands have been executed enter the following to ensure that they have run correctly:

  1. cscript adsutil.vbs GET w3svc/1/NTAuthenticationProviders
  2. cscript adsutil.vbs GET w3svc/1/AuthPersistSingleRequest

Finally run IISRESET from the command line to restart the web server.

The following data from an IIS 6.0 log file shows the same sequence of GET requests as described above after the NTAuthenticationProviders value has been set to NTLM and the AuthPersistSingleRequest value set to false.


cs-uri-stem cs-username sc-status sc-bytes cs-bytes
/auth1.htm  -           401       2043     622
/auth1.htm  DOMAIN\user 200       259      774
/auth2.htm  DOMAIN\user 200       260      557
/auth3.htm  DOMAIN\user 200       260      557
/auth4.htm  DOMAIN\user 200       260      557

This data can be compared to that above quite easily. First you can see that the number of round trips is just over half the number on an IIS 6.0 server in its default configuration, as only the first request fails with a 401 status message – the subsequent requests now use the authentication of the first request within the session rather than per request authentication. Secondly the total number of bytes required within the HTTP session to download these four objects is 6149 bytes. This is 29% of the bytes transferred under the default IIS 6.0 configuration.

Therefore, if you run web applications that use NTLM authentication and have high latency networks then you can generate significant improvements in page load time at the browser, and at the client I am working at we reduced page load times from their India offices to the USA servers from 18 seconds to less than 10 seconds.


2003 2008 2008 R2 iis SQL

Enabling ASP.NET Session State without Installing IIS

At a client site, I needed to enable within a web cluster the ASP.NET session state service (ASP.NET State Service) and initially this was going to go on one server within the web cluster. The only problem though, as this configuration is easy, was what happens if the one server in the cluster that this is running on is the server that fails!

The solution we decided was to place the service on the SQL Server back-end database. Though this is not clustered (as it is not mission critical), if the database is unavailable then so is the application so why not run the ASP.NET State Service on that machine.

So we changed the web.config file to read:


We went to the SQL Server (which was running Windows Server 2003 and so had the .NET Framework installed), but found that the service did not exist as ASP.NET was not installed.

So we ran the following, which claims to require IIS to be installed, but successfully enabled the ASP.NET State Service:

aspnet_regiis -i (this is in WINDOWS\Microsoft.NET\Framework\version folder

Set “HKEY_LOCAL_MACHINE\SYSTEM \ CurrentControlSet \ Services \ aspnet_state \ Parameters \ AllowRemoteConnection” to 1 on the server in the above step, set the service to Automatic and started it running.

And it all worked fine.