Troubleshooting TS Gateway connectivity on Windows 2008, IIS 7.0

Here is something which is not my domain but had to learn the hard way. I recently encountered an issue while enabling Terminal Services Gateway (TSG) on Windows 2008 server. TSG is coupled with IIS 7.0 hosted on Windows 2k8 server and that's how I came into picture. TSG in simple terms is a feature using which one can connect remotely to an internal network over secure HTTPS port 443 from the Internet. Earlier Remote Desktop Protocol (RDP) connections used TCP port 3389. In many corporate environment this port may be blocked by the firewall. However now with TSG connecting on port 443 (common SSL port for http traffic) user should not get into the common issues of port being blocked. In my case we had the TSG installed as one of the roles on the server. The setup was fine.
The only concern was that we already were using the Default Web site for some application. It can also happen otherwise, you have the TSG setup on an IIS 7 web site and if you go ahead and install let's say Exchange on top of it under the same site it may break the TSG functionality.

When you install TSG, it creates two virtual directories called Rpc and RpcWithCert under the web site as shown below.

image

Under the hood it appears a call is made for

https://<server-name>:443/rpc/rpcproxy.dll?localhost:3388 when you try to connect through TSG. So yes IIS is very much involved here.

Now what can you do to fix this, perhaps you can install your web application (say Exchange) on some other web site and a different SSL port like 444 and have TSG site listening on port 443. Or else just the opposite.

In my case we went with the 2nd option since we didn't want Exchange to be reinstalled again.
But even if you use either of the above options it may not go that smoothly as it looks to be.

You may see the error as shown below when you try to use terminal service through TSG.

image Click on OK...

image

If you are seeing something like this, as a workaround create a new web site and copy the settings for the Virtual directories /Rpc and /RpcwithCert from the previous site to the the new web site. You can do this easily by copying the configuration in the applicationHost.config file.

Here are the steps:

1. Copy the following configuration (in the ApplicationHost.config file from C:\<Windows>\System32\inetsrv\config) from the previous site to the new site to add the virtual directories for your new web site.

 <site name="<new-web-site>" id=...>
...
<application path="/Rpc" applicationPool="SomeAppPool">
       <virtualDirectory path="/" physicalPath="C:\Windows\System32\RpcProxy" />
</application>
<application path="/RpcWithCert" applicationPool="SomeAppPool">
        <virtualDirectory path="/" physicalPath="C:\Windows\System32\RpcProxy" />
</application> 
...
</site>

So this will create two virtual directories in your new web site called Rpc and RpcWithCert.

image

Add an SSL binding for the new Web site on port 443 as well. Ensure no other site is listening on port 443.

2. Copy the following for the previous web site in the ApplicationHost.config file to the new web site.

This is the section contained in the Location tag for the Virtual directories /Rpc and /RpcWithCert. You need to copy this section from the location tag for the <previous-web-site> and add it to the location tag for the <new-web-site>.

 <location path="<previous-web-site>/Rpc">
        <system.webServer>
            <directoryBrowse enabled="false" showFlags="Date, Time, Size, Extension" />
            <handlers accessPolicy="Execute">
                <add name="RPCPROXY" path="*" verb="*" modules="IsapiModule" scriptProcessor="C:\Windows\system32\RpcProxy\RpcProxy.dll" requireAccess="Execute" />
            </handlers>
            <serverRuntime uploadReadAheadSize="0" />
            <defaultDocument enabled="true" />
            <modules>
                <add name="PasswordExpiryModule" />
            </modules>
            <security>
                <requestFiltering>
                    <requestLimits maxAllowedContentLength="2147483648" />
                </requestFiltering>
                <authentication>
                    <anonymousAuthentication enabled="false" />
                    <basicAuthentication enabled="false" />
                    <windowsAuthentication enabled="true" useKernelMode="false" />
                </authentication>
                <access sslFlags="Ssl, Ssl128" />
            </security>
            <httpErrors>
                <remove statusCode="401" />
                <error statusCode="401" path="C:\Windows\system32\RpcProxy\Error401.txt" responseMode="File" />
            </httpErrors>
        </system.webServer>
    </location>
 <location path="<previous-web-site>/RpcWithCert">
        <system.webServer>
            <directoryBrowse enabled="false" showFlags="Date, Time, Size, Extension" />
            <handlers accessPolicy="Execute">
                <add name="RPCPROXY" path="*" verb="*" modules="IsapiModule" scriptProcessor="C:\Windows\system32\RpcProxy\RpcProxy.dll" requireAccess="Execute" />
            </handlers>
            <defaultDocument enabled="true" />
            <security>
                <authentication>
                    <anonymousAuthentication enabled="false" />
                    <basicAuthentication enabled="false" />
                    <clientCertificateMappingAuthentication enabled="true" />
                    <digestAuthentication enabled="false" />
                    <windowsAuthentication enabled="false" useKernelMode="false" />
                    <iisClientCertificateMappingAuthentication enabled="true" />
                </authentication>
                <access sslFlags="Ssl, SslNegotiateCert, SslRequireCert, Ssl128" />
                <requestFiltering>
                    <requestLimits maxAllowedContentLength="2147483648" />
                </requestFiltering>
            </security>
            <serverRuntime uploadReadAheadSize="0" />
            <modules>
                <add name="PasswordExpiryModule" />
            </modules>
            <httpErrors>
                <remove statusCode="401" />
                <error statusCode="401" path="C:\Windows\system32\RpcProxy\Error401.txt" responseMode="File" />
            </httpErrors>
        </system.webServer>
    </location> 

3. Ensure that we replace <previous-web-site> with the <new-web-site> in the following tags above:

<location path=" <previous-web-site> /RpcWithCert"> -----> <location path=" <new-web-site> /RpcWithCert">

<location path=" <previous-web-site> /Rpc">  -----> <location path=" <new-web-site> /Rpc">

4. Run iisreset from the cmd prompt. Or it may also work with just restarting W3SVC service (net stop w3svc, net start w3svc).

Go ahead and test RDP over TSG from the client. If it still doesn't work you may have to try the 5th step as below.

5. Add the following registry entry. Run this from the cmd prompt:
> reg add HKLM\Software\Microsoft\RPC\RpcProxy /v Website /t REG_SZ /d  <new-web-site>

One last thing, ensure that the certificate issued to the TS server gateway is trusted on the client from where we are doing a terminal login.

Happy troubleshooting!

Cheers Martini Glass

Comments

  • Anonymous
    October 24, 2008
    Nice article.  Just what I needed.  I'm limited when it comes to IIS.  Lo, I was unable to get it to work.  Do you need two IPs, one for each site for this to work?  I figured not if you you separate ports. It seems that ports 80 and ports 443 are in contention in my situation because I have two apps, ACT! and TSG wanting these as defaults.  Moving ACT! to new ports is possible.  TSG, not so. There just wasn't enough in your article (with my limited IIS background) for me to get it working. I had ACT! on the default site at ports 80/443, I moved them to  81/444 and left TSG at 80/443. Verified each site had a certificate.  Careful to iisreset and restart the websites manually after changes.  Double checked the ACT! configuration and port forward on the router. Router 80->80     IP Server    TSG Listening ,           81->81     IP Server    ACT! Listening .         443->443   IP Server    TSG Listening          444->444   IP Server    ACT! Listening Seems to make sense to use those forwardings, assuming the following is true, https://<act!site>:81/apfw  connects to ACT site and establishes SSL over 444. RDC client connects over 80 to TSG and established SSL over 443. I create a site called TSG and used C:inetpubtsgroot and tsg.<mydomain>.biz. Wasn't sure what the equivalent of wwwroot was so I created tsgroot and added IIS_IUSRS readonly.  I didn't copy or move any files, all my work was done editing the mentioned config file.  You mention copying above, but I don't see any files to be copied, so I assume you just meant to change XML. Connecting to ACT!, I get :Service Unavailable.  HTTP Error 503. The service is unavailable." No luck with TSG either. Sigh. I didn't put anything into the inetputtsgroot directory because there didn't seem to be anything to put there. Wonder where I went wrong? I did google a doc that mentioned doing a registry edit before installing TSG inorder to make it not install in the default site. Your method sounded so easy.

  • Anonymous
    February 18, 2009
    The comment has been removed

  • Anonymous
    February 18, 2009
    Hi CB, You need to run TS Gateway application on port 443 and not any other port. You can run the SharePoint app on port 444 if you want to use SSL for it. Hope this helps!

  • Anonymous
    May 09, 2009
    What I'd like to see is a generic ApplicationHost.config with the TS Gateway Settings so I can see what it looks like without having to completely reinstall TS Gateway after the ApplicationHost.config gets messed up.

  • Anonymous
    June 09, 2009
    Fantastic advice, worked the first time, many thanks.

  • Anonymous
    September 17, 2009
    THANK YOU - this solved an issue for Exchange 2007 on Windows 2008 using RPC over HTTPS proxy (aka Outlook Anywhere) on a non-default website as well.  THANKS.  I may re-blog this and give you credit.

  • Anonymous
    April 07, 2010
    I have a website that I would like to virtualize that is currently only available inside the network or to user outside the network that I create an AD account for. I have built a 2008 server and just added just added all the roles to it. I have a 'remote' user account in AD created. What I want to do is allow "outside" users to login onto the gateway server that is pointed to an internal web page. Will you kindly lay out the best method for doing this? Many thanks! Dennis

  • Anonymous
    November 02, 2011
    You saved my live, man! Thanks a lot for publishing this one. More Information on a couple of lines as in the whole MS -well- docu...

  • Anonymous
    July 27, 2012
    Works great Thanks for this solution!!! spending hours on google ;-)

  • Anonymous
    June 06, 2014
    Could you not just do a Use get-outlookanywhere | set-outlookanywhere -IISAuthenticationMethods: Basic, Ntlm so that both authentications are enabled and the ExchangeServerHost will leave the settings alone

  • Anonymous
    November 27, 2014
    Hi All, Really Nice finding. I did try this in my live environment. I have done same thing but still my RPC is not working. OWA and active sync on other website are working fine. I created RPC and RPCWithCert directory as mentioned but still RPC does not work from external world. Does RPC path for Default and new website are same in your scenario or you copied RPC folder to new location and tried? Please confirm as I really need to get it working.