.NET Services March 2009 CTP: Host a Public Website At The Kitchen Table or from a Coffee Shop! No Kidding.
.NET Service Bus Reverse Web Proxy: Click here to download the source
Using the application/service built from the sample linked at the top of this post you can host a publicly discoverable and accessible website or Web service from your Windows notebook or desktop machine from within most network environments without having to open up a port on the firewall, mapping a port on your NAT, or using some type of dynamic DNS service to make the site discoverable. All those essential connectivity features are provided by the .NET Service Bus and with the help of the included sample code.
I’m intentionally not bundling this up as a conveniently installable binary along with a nice configuration UI – that’s not my role here. If you want to grab the code and make it part of a cool personal media sharing app, provide external access to a departmental enterprise app, put a prototype out there for a client to play with, host a web service you want to show off, or or provide an installable version with a nice configuration UI – go ahead.
The attached sample application/service has two key capabilities that I’ve repeatedly been asked for:
a) It is a reverse web proxy that can run either as a console application or as a Windows (NT-) service. The reverse web proxy can sit in front of any web server and forward requests to it. I’ve tested this only with IIS as the backend, but I don’t see a reason why this shouldn’t work with Apache or the Web Server built into some J2EE application server.
b) It is a scripting policy host that projects the crossdomain.xml and ClientPolicyAccess.xml files required by Adobe Flash and Microsoft Silverlight into the root of a .NET Services namespace, permitting cross-domain script access from Flash and Silverlight for all endpoints hosted within the namespace. You can easily adjust the code in the sample to restrict access to particular resources within the namespace.
The fundamental architecture is illustrated in the picture. The web application that you want to project out to the public internet sits on some web server on your machine. “Your machine” may be a desktop machine at home or at work or a notebook in a hotel lobby or an airport on WiFi. As long as you’ve got line-of-sight to the .NET Service Bus and the TCP ports 828 and 818 are available for outbound traffic, you’re good. The reverse web proxy app will map any local HTTP server to a name in the .NET Service Bus and forward the traffic between the .NET Service Bus and the HTTP server. The client (any web browser, but also any HTTP Web Service client) will talk to the .NET Service Bus at the given name, the traffic flows to the reverse proxy on your machine and from there to the HTTP server.
I’m hosting (for a few days) a sample dasBlog site instance at https://clemensv6.servicebus.windows.net/dasblog/. The hosting machine for that blog is one of my personal machines. It’s got a local network address assigned by DHCP, it’s not listed in any NAT mappings, and it’s local Firewall isn’t even open for inbound HTTP traffic.
How to install, build, and run
As a prerequisite you will need three things:
- Visual Studio 2008 SP1 with the .NET Framework 3.5 SP1.
- A .NET Services project account. The quickest route is to go to https://portal.ex.azure.microsoft.com and click “Sign up”. The approval/provisioning is pretty much instantaneous (plus 20 seconds for the provisioning to run through) once you provide your Windows Live ID. No more access codes.
- The .NET Services SDK for the March 2009 CTP. Click here to get it.
Unpack the files, and open ServiceBusReverseWebProxy.sln with Visual Studio 2008. In the ServiceBusReverseWebProxy project, find the app.config file and open it. Here’s where you need to put your project name and password and where you map your sites:
1: <?xml version="1.0" encoding="utf-8" ?>
2: <configuration>
3: <configSections>
4: <section name="reverseWebProxy"
5: type="Microsoft.Samples.ServiceBusReverseWebProxy.ReverseWebProxySection, ServiceBusReverseWebProxy" />
6: </configSections>
7: <!-- Add your .NET Services project account information here -->
8: <!-- Create a project at https://portal.ex.azure.microsoft.com/ -->
9: <reverseWebProxy netServicesProjectName="!!myproject!!" netServicesProjectPassword="!!mypassword!!"
10: enableSilverlightPolicy="true">
11: <pathMappings>
12: <add namespacePath="mysite" localUri="https://localhost/mysite/" />
13: </pathMappings>
14: </reverseWebProxy>
15: </configuration>
Put your .NET Services project/solution name into the netServicesProjectName and the password into netServicesProjectPassword.
Then pick a local HTTP server or site and give it a name in your .NET Service Bus namespace. That mapping is done in the <pathMappings> section. There are a few things that are important to note here:
- If your project name were ‘clemensv6’ and you map some local URI to the namespacePath ‘dasBlog’, the resulting .NET Service Bus URI would be https://clemensv6.servicebus.windows.net/dasblog/.
- The web application should only emit relative paths for links or, otherwise, should have a way to specify the external host address for links. That means that the web application needs to be able to deal with the presence of a reverse proxy. There is no content-level URL rewriter in this sample that would make any corrections to HTML or XML that’s handed upstream. DasBlog allows you to specify the blog site address as some external address and therefore satisfies that requirements.
- Redirects and any other HTTP responses that emit the HTTP ‘Location’ header or any other HTTP headers where URIs are returned are rewritten to map the internal view to the external view.
- If you set enableSilverlightPolicy to true, there will be crossdomain.xml and ClientPolicyAccess.xml endpoints projected into the root of your project’s namespace, ie. https://clemensv6.servicebus.windows.net/crossdomain.xml
Build. Run.
By default, the ServiceBusReverseWebProxy.exe application will simply run as a console application. If you use installutil –i ServiceBusReverseWebProxy.exe the application will be installed as a Windows Service. The default identity that it is installed under is ‘NETWORK SERVICE’. In restricted networks with constrained IPSec policies (such as the Microsoft Corporate Network), you may have to use a user account instead. You may also have to use some special Firewall-gateway software such as the ISA Firewall client to allow for outbound access to ports 828 and 818.
The actual application code isn’t really all that complicated. The ‘beef’ is in ReverseWebProxy.cs. What might be surprising here is that this class doesn’t use the WCF Service Model, but is using naked WCF channels for the upstream traffic to .NET Services and it’s using HttpWebRequest for the downstream traffic to the local Web Server. The reason for using channels is that the app is never doing any processing on the messages, so the channel model is the most straightforward and efficient way. The reason for using HttpWebRequest is that you can’t suppress auto-redirects on a WCF HTTP client. Since the stack needs to be completely transparent to redirects so that it’s the browser client up on top that gets redirected instead of someone on the way, I simply couldn’t use a WCF channel downstream. Seems to be one of these edge cases that the WCF team downstairs didn’t think anyone would ever need.
Let me know whether and how this works for you. Share the code, improve it, re-blog, let me know. @clemensv on Twitter, same name @microsoft.com for email.
Comments
Anonymous
April 05, 2009
Thank you for submitting this cool story - Trackback from DotNetShoutoutAnonymous
April 07, 2009
  Я всегда чуствовал что .net services можно использовать не только для сервисов, но и для обычныхAnonymous
April 07, 2009
  Я всегда чувствовал что .net services можно использовать не только для сервисов, но и для обычныхAnonymous
April 07, 2009
Я всегда чувствовал что .net services можно использовать не только для сервисов,Anonymous
April 08, 2009
too many requirements are needed to share something from your kitchen. at http://roboshare.com you can share with a click of a button and within seconds have your entire picture or video folder available on the web. As an identity you can use your Facebook ID or create an account. On Facebook this utility is available at http://apps.facebook.com/roboshare Roboshare tunnel works through any http proxy, no need for ISA client. And btw, only .NET 2.0 is required.Anonymous
April 08, 2009
We've got a dead-simple file-sharing tool in the samples that shares out a directory as an Atom feed. No client too required, you just use your browser to navigate and download. This here is about sharing any HTTP endpoint, not a file folder. We don't need ISA Firewall client, either. As of M5 there is a full-duplex HTTP tunnel that snaps into place whenever necessary.Anonymous
April 08, 2009
make a simple test. Put an mp3 file in your http endoint hosted in the kitchen. Then go to iPhone and listen to that mp3. Let me know how it works :) I had this working on http://roboshare.com, (see http://roboshare.com/homehosting.aspx) but I removed this feature in last release for several reasons:
- chunked posts and chunked responses don't work. (same for plain responses which are very long)
- it makes the website really slow, which is ok for development purposes, but doesn't make sense at all in production.
- several forum posts and threads with other website owners made me think nobody wants this.
- there are other ways people can host websites at home, like dyndns. yet people chose to have a hosting plan with 99.9 uptime.
- your upload speed in your kitchen will be a killer bottleneck for your website.
Anonymous
April 09, 2009
Well, from my kitchen I can spool HD video to Starbucks via the Service Bus. I've got 15 MBit/s symmetric, which means that my upload speed isn't an issue. The Service Bus is for ISVs like you. There's no competition here. I like your app.Anonymous
April 09, 2009
The comment has been removed