ASP.NET Reverse Proxy ConsiderationsJul4

Sunday, 4 July 2010 by haemoglobin

What is a Reverse Proxy

During lead developer roles of previous ASP.NET projects, I’ve needed to deploy into some fairly heavy enterprise infrastructure - once needing to deal with some unexpected behaviour caused by reverse proxy’s. I’ll describe in this article some things to keep in mind when doing this to ensure everything still runs smoothly and correctly all the way from the development environment to production.

A reverse proxy has a few functions, one function is acting as the network load balancer as I talked about in my previous post Web Farm Considerations. It can also be the point that processes SSL encryption.

Many people might already familiar a standard “proxy” that they may have needed to configure their browser to use to make connections to the internet (typically from inside a company network). More specifically this is known as a “forward proxy” and is to do with outgoing traffic, i.e. instead of the browser making a connection directly to a website, it will send the request first via a proxy server somewhere in the company’s network. The proxy server may be the only machine on the company network that can access the internet and gives the company further control over blocking of certain sites, monitor outgoing requests, virus scanning, caching etc.

A reverse proxy on the other hand sits on the server side – and is essentially the opposite of a forward proxy.

Application Path Issues

image

The scenario described here is when your ASP.NET application (ApplicationX) is to be deployed to a subdirectory of an already existent company wide domain (www.company.com), i.e to http://www.company.com/ApplicationX.

The user’s browser will connect to the reverse proxy which has a public address such as https://www.company.com/ApplicationX (so essentially connecting to it without realising it as opposed to the forward proxy that needs to be configured) – which will then forward the request to a server internal to that network such as http://internal05/ApplicationX to do the real processing of the request and dishing up the web content to the user. Acting as a NLB (Network Load Balancer) the request could also be redirected to http://internal0[1-4]/ApplicationX unbeknown to the user. These internal0[1-5] servers are only accessible within the company network, behind the firewall and not accessible directly from the cloud/internet.

Now – here is the issue to keep in mind when deploying in this type of scenario – it’s quite possible for servers internal01-05.company.com to be servers dedicated to ApplicationX – in this case it would seem natural to simply set the default website on these to serve ApplicationX i.e directly at http://internal05.company.com.

The problem with this is ASP.NET will send virtual addresses such as WebResources.axd (some more info about WebResource.axd in my post Securing Static (Non-ASP.Net) Files) back to the client browser as the absolute address “/WebResource.axd”. This will cause the client browser to make requests to https://www.company.com/WebResource.axd – not good ! Instead it should be https://www.company.com/ApplicationX/WebResource.axd .

To achieve this, the option is to create a virtual directory on the internal server called ApplicationX so that it is served from http://internal05.company.com/ApplicationX (matching the reverse proxy’s URL structure). ASP.NET will now return the absolute address “/ApplicationX/WebResource.axd” back to the client browser which will resolve correctly behind the reverse proxy.

In terms of linking to resources yourself, ensure that you don’t use something like Request.Url. This will work in your development environment, but when deployed behind the reverse proxy – Request.Url will actually return http://internal05.company.com/ApplicationX (as far as the ASP.NET application is concerned, it is serving content from this location as the reverse proxy has made a request to the internal server with this URL). Obviously from the client browser however any references to this address will not work since this server is behind the company firewall.

Instead, make use of the special character “~” wherever possible (in conjuction with ResolveUrl where necessary) which will resolve to “/ApplicationX”. Here are some examples (note that server side controls “~” can be specified and interpreted directly within the properties themselves without use of ResolveUrl):

<asp:Image runat="server" ID="image" ImageUrl="~/Penguins.jpg" /> 
<img alt="Penguins" src='<%=ResolveUrl("~/Penguins.jpg") %>' />

This will mean the client browser will request items back to http://www.company.com/ApplicationX as well as ensure everything still works in the development environment.

Using Request.ApplicationPath instead of “~” will probably cause issues if you are running your Visual Studio web server development environment from the root directory. Linking to resources from the root directory - Request.Application path returns “/” and you end up with with a request to //Penguins.jpg, which will fail, such as below: 

<img alt="Penguins" src='<%=Request.ApplicationPath + "/Penguins.jpg" %>' />

The solution is to either use “~” or alternatively run your development environment from a virtual path instead of the root directory if you do prefer using Request.ApplicationPath.

In summary, before deploying to a more complicated infrastructure than a simple single server scenario, it pays to think through any potentially surprising behaviour you might see. To save potential delays further down the track it can be wise to put the time aside to setup a test environment first that includes the reverse proxy, load balancing servers etc to ensure everything still works as expected.

Good luck! Hamish

Categories:   Development
Actions:   E-mail | Permalink | Comments

ClickOnce Not Installing Latest VersionsJun29

Tuesday, 29 June 2010 by haemoglobin

I have recently had an interesting experience debugging some ClickOnce issues with my WPF Inspirational Quote Management System.  Essentially, I would deploy a new version of the application - but some users after choosing File -> Check For Updates, would receive a message saying that the latest version is already installed - which I know was not the case.

I could not figure out why it would not be picking up the new version of the application. One user being a friend, I was able to work with them using TeamViewer to try a few things on their computer, including inspecting the contents of the ClickOnce installer file (http://www.hamishgraham.net/files/WPFQuoteManagement/WPFQuoteManagement.application) that they receive on their computer after browsing to the URL. I noticed that the contents of the file downloaded was quite old compared to what I would get if I downloaded from the same URL on my computer. Straight away this was smelling of caching problems. 

No amounts of Control-F5 would fix this – only appending a question mark on the end of the URL would retrieve the latest version (common trick to bypass web caches), but this still does not help the WPF application which browses to the aforementioned URL (under the hood using ClickOnce) without any question mark for the update. 

I needed to confirm that this was indeed a web cache issue, so I did this by firing up Fiddler, and running the WPF application’s check for updates function again. Fiddler intercepts all HTTP traffic to/from the computer from all applications and not just a web browser - very handy in this case.

On my friends computer, the WPF application would receive the following HTTP headers for the ClickOnce .application file when checking for updates:

HTTP/1.1 200 OK
Content-Type: application/x-ms-application
Last-Modified: Tue, 01 Jun 2010 05:21:36 GMT
Accept-Ranges: bytes
ETag: "aeb494e4a1cb1:0"
Server: Microsoft-IIS/7.5
X-Powered-By: ASP.NET
Date: Fri, 25 Jun 2010 04:20:46 GMT
Via: 1.1 bc5
Content-Length: 5769
Connection: Keep-Alive
Age: 343128

On my computer on the other hand, it would look like:
HTTP/1.1 200 OK
Content-Type: application/x-ms-application
Last-Modified: Mon, 28 Jun 2010 05:41:10 GMT
Accept-Ranges: bytes
ETag: "eec57e838416cb1:0"
Server: Microsoft-IIS/7.5
X-Powered-By: ASP.NET
Date: Tue, 29 Jun 2010 04:08:22 GMT
Content-Length: 5765
Connection: Keep-Alive
Age: 0

I’ve highlighted the problem areas on my friend’s HTTP response. The file was being served from “1.1 bc5” which is the name of TelstraClear’s web cache (my friend being with TelstraClear), which by the looks of it holds a version that I last modified on the 1st June. The date field (25th June) indicates when the web cache last checked that the file was still valid.

Now, here is the problem, without explicitly setting a cache expiry for the file, the web cache is at its own liberty to decide when it deems appropriate to check whether the file is still valid. Without any explicit cache expiry existent in the HTTP header, web caches use heuristics are used to determine when to check validity again by doing calculations on Date and Last-Modified… i.e if the gap between the time I last checked validity of the cached file and when the file was last modified is large, it probably means the file isn’t changing very much, so wait even longer before checking for validity again.

I found someone who has already solved this issue http://www.codeproject.com/KB/dotnet/ClickOnceContentExpiratn.aspx which I implemented, however slightly differently by adding the following line instead into the web.config under the <handlers> node:

<add name="ClickOnce" verb="*" path="*.application" type="CustomHttpHandlers.ClickOnceApplicationHandler" resourceType="Unspecified" preCondition="integratedMode"/>

I then needed to enable the IIS7 Integrated Pipeline on the webserver which ensures all file types are routed through ASP.NET runtime for the HTTP Handler to be executed for the .application file, and the cache expiration explicitly set.

Retrieving the ClickOnce .application file now comes back with the following HTTP headers:

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/x-ms-application
Expires: -1
Server: Microsoft-IIS/7.5
X-Powered-By: ASP.NET
Date: Tue, 29 Jun 2010 09:49:23 GMT
Content-Length: 5765
Connection: Keep-Alive

This should hopefully tell any web caches ISP’s are using that this file mustn’t be cached – meaning latest versions of the application can be deployed promptly to all users. It will take a few days until the web caches finally refresh before I can test this works as expected, but hopefully this will be a win.


Extra Resources

Categories:   Development
Actions:   E-mail | Permalink | Comments

Delete the Currently Playing FileApr26

Monday, 26 April 2010 by haemoglobin

For years now I’ve had songs in my music collection that are so terrible I shudder when they come on – but the process of actually deleting the file so I’d never hear it again has always been so painful I never do it. So end up listening to the thing again and again.

Applications like iTunes, VLC and Windows Media Player all work the same way by deleting the song from the play list and not the file system itself. To delete from the file system you usually have to go through some complicated process to find the file path, open windows explorer and then delete it from there.

I’ve googled a bit over time for plugins and so on that let you actually delete the currently playing song but I’ve never really had much luck so thought I would bite the bullet and make something up.

I had grand plans of having a lovely little WPF application that sits in the system tray with an assigned keyboard hotkey to delete the currently playing song. I thought I would do this by just scanning the file handles the media playing application has hold of, find the mp3 / wma file and then delete it. Since .NET isn’t very capable at getting low level file handle information without going into a whole lot of unmanaged code I thought I would just use the output from the sysinternals Handle application. This needs administrative privileges however to run, and I subsequently found out that it is impossible to run an external process from .NET with elevated privileges (contrary to many posts around the internet) – on Windows 7 with UAC enabled anyway. This guy also found this out the hard way.

So I’m sorry, I didn’t end up making a pretty application but I did end up getting something going that works (a console application) – but is a bit geeky for the average user unfortunately.

However I thought I would share it anyway. Here are some steps to set it up:

  1. First of all, download DeleteCurrentlyPlaying.zip and extract to a directory. If you get an error when running it later, you may not have the .NET Framework 3.5 installed. 
  2. Open a command prompt with Administrative rights. This guide tells you how to do this. On Windows XP you won’t need to worry about this.
  3. Navigate to the folder with the files in it e.g “cd c:\path\to\downloads\DeleteCurrentlyPlaying”
  4. Now run the following if your song is currently playing in Windows Media Player, VLC Player or iTunes respectively (this is just the process name changing):
    handle –p wmplayer | DeleteCurrentlyPlaying
    handle –p vlc | DeleteCurrentlyPlaying
    handle –p itunes | DeleteCurrentlyPlaying
  5. For your piece of mind, the file isn’t actually deleted, it is moved to a subfolder “To Delete” for you to delete at some point. Also if you would rather download the source and compile it yourself, you can find it here.

The application will wait until the file has been released by the application before it is moved (in the case of Windows Media Player it seems it can be moved while it is being played).

It should look something like this:

image

You can just leave this console window open, and then hit the up arrow to repeat the last command and hit enter again when the next one to go comes on.

Categories:   Development
Actions:   E-mail | Permalink | Comments

Understanding Action<T> and Func<T, TResult>Apr22

Thursday, 22 April 2010 by haemoglobin

In .NET 3.5 there are two new delegate types Action<T> and Func<T, TResult>. 

There are other overloads for Action<T> and Func<T, TResult> if you need to provide more than one parameter, e.g:
- Action<T1, T2, T3>
- Func<T1, T2, T3, TResult>

I wanted to test my understanding of these by making a quick console app that uses them. The example below is extremely contrived and something you would not do in practice of course but I believe it to break down the core essence of their use, so you can use your imagination from there as to how you would use them.

It actually started off much more simple but then I intentionally beefed it up including plenty of generics, and multi-lined / multi-parameter lamba’s so if you understand this snippet you know you also have a good grasp of those too.

        static void Main(string[] args)
        {
            int result = DoStuffToSomething<DateTime, DateTime, int>(
                DateTime.Now, 
                DateTime.MaxValue,
                date => {
                        Console.WriteLine(date.ToShortDateString()); 
                        Console.WriteLine(date.ToLongTimeString());
                    }, 
                (date1, date2) => (date2 - date1).Days);

            Console.WriteLine(result.ToString() + " days before .NET DateTime explodes."); 

            Console.Read();
        }

        static R DoStuffToSomething<T1, T2, R>(T1 something, T2 somethingElse, Action<T1> myAction, Func<T1, T2, R> myFunction)
        {
            myAction(something);
            return myFunction(something, somethingElse);
        }

Prints:
  22/04/2010
  12:48:12 p.m.
  2918175 days before .NET DateTime explodes.

Good to know I guess.

Also note Action<T>’s use in the framework such as the ForEach method on a generic List. This can be used like so (as taken from http://msdn.microsoft.com/en-us/library/bwabdf9z.aspx):

    static void Main()
    {
        List<String> names = new List<String>();
        names.Add("Bruce");
        names.Add("Alfred");
        names.Add("Tim");
        names.Add("Richard");

        // Display the contents of the list using the Print method.
        names.ForEach(Print);

        // The following demonstrates the anonymous method feature of C#
        // to display the contents of the list to the console.
        names.ForEach(delegate(String name)
        {
            Console.WriteLine(name);
        });
    }

    private static void Print(string s)
    {
        Console.WriteLine(s);
    }

I would also add to the MSDN example to show how the same can be done using a lambda expression:

    names.ForEach(name => Console.WriteLine(name));

When these new language features come out, I think it is good practice to at least get an understanding of them, so when the right situation presents itself you have a new and possibly more efficient/readable option to use.

Categories:   Development
Actions:   E-mail | Permalink | Comments

WMD Markdown Editor SyntaxHighlighter IntegrationApr21

Wednesday, 21 April 2010 by haemoglobin

For my blog, I use SyntaxHighlighter to format code snippets (which I believe to be the best code formatting solution out there for a few reasons). The problem is however that it requires you to wrap your code in <pre class="brush: c#"> your code goes here </pre> tags – which can be a pain.

The WMD Editor control (or the stackoverflow open source port) on the other hand has a convenient button for "code" (or using the Ctl-K hotkey) that will indent the snippet in such a way that when rendered by Markdown (whether in the WMD Editor’s preview pane with the server side MarkdownSharp for example) it will be wrapped in <pre><code>your code snippet</code></pre> tags.

This format won't be highlighted by SyntaxHighlighter by default however.

Without wanting to modify SyntaxHighlighter my solution to this was to use jQuery to transform all instances of:

<pre><code>code snippet</code></pre>

rendered on the page to:

<pre class="brush: c#">code snippet</pre>

After this has been done, SyntaxHighlighter will be able to format the code snippet as it usually would.

I’ve created the following jQuery snippet to do this (which also goes to demonstrate the power of jQuery):

	//Find all <pre> tags that have a <code> tag child, and add the "brush: c#" class to the <pre> tag.	
	$('pre:has(code)').addClass('brush: c#'); 
	//Find each <code> tag (with a <pre> parent), and replace it’s contents with itself leaving only the <pre> tag behind. 
	$('pre>code').each(function(index) { 
		var cnt = $(this).contents(); 	
		$(this).replaceWith(cnt);    
	});  

The end result being you will have beautiful syntax highlighting or your code snippets with a simple click of the WMD Editor's 'code' button (or the Ctl-K hotkey).
If you wish to use another brush, you can still explicitly define a <pre> tag as normal specifying a different SyntaxHighlighter brush.

ASP.NET Wiki Control with Markdown

I am hosting an open source project that wraps the WMD Editor and MarkdownSharp projects together into a convenient wiki control over Linq to SQL that you can embed in any ASP.NET website (also with special instructions for installing into BlogEngine.NET for a better page editing solution).

I have just updated the latest version to include SyntaxHighlighter integration and will use javascript to detect for the presence of jQuery and SyntaxHighlighter and, if found, will run the jQuery code mentioned above to format your code snippets automatically through SyntaxHighlighter.

More information on the control can be found on the ASP.NET Wiki Control with Markdown download page.

Categories:   Development
Actions:   E-mail | Permalink | Comments

Web Farm ConsiderationsApr8

Thursday, 8 April 2010 by haemoglobin

Background

I have been involved with ASP.NET deployments for some high load scenarios where the same exact copy of a web application is deployed to multiple servers and placed behind a network load balancer (NLB) – also known as a web farm.

Requests to the website first arrive at the NLB, and are then directed off to a web server that is available to handle the request (the web server allocated depends on a number of load balancing algorithms the NLB server can use).

When deploying an ASP.NET application to a web farm for load balancing there are a few things to consider.

Session State

Session information in ASP.NET simply speaking is the ability to associate some information against a particular user as they are clicking through your site by using the .NET Session object. Behind the scenes the user session is tracked through a single non-persistent cookie (removed when the browser is closed) named ASP.NET_SessionId. The cookie contains a single ID that associates that user back to their session information on the server.

The actual information can be stored on the server in one of three ways – but only two of which will work when deploying to a web farm:

InProcThis is the default. InProc stores the session information in memory of the ASP.NET worker process on the server. This cannot be used with load balanced servers since if the user is sent to another server on a subsequent request, that server will not have that user’s session information available in its local worker process memory space.

StateServerWith this option, all web servers in the web farm store session information in the memory of a single process (a Windows service called “ASP.NET State Server”) preferably on a separate machine. This option works for web farms, but is 15% slower than InProc. This however of course is offset by having the extra servers processing requests.

SQLServer Using SQL Server, session information is serialized and stored to a SQL Server database. This is 25% slower than InProc, however SQL Server can be setup as a failover cluster which has reliability advantages over StateServer which is a single point of failure. This option can also survive a SQL Server restart; if StateServer on the other hand is restarted all session information will be lost.

Whether you choose StateServer or SQLServer is a trade-off between reliability and speed.

Machine Key

ASP.NET hashes ViewState by default to ensure that it hasn’t been tampered with before being sent back to the server. Out of the box the key used to generate the hash is a random one generated when the application pool starts. There is also a decryption key that is used to encrypt forms authentication tokens (also auto generated).

This has two problems:

  1. If the Application Pool restarts (by sysadmin or automatically through inactivity or scheduled recycling) a new validation/decryption key will be generated, and a user on a subsequent post back will receive a ViewState validation error or be logged out.
  2. If the user is sent to another server in the web farm on post back, the other server will have it’s own validation/decryption key, and the user will receive a ViewState validation error or be logged out.

So in order to work with a web farm it is necessary that all servers in the farm use the same validationKey and decryptionKey values and not have them auto generated.

A good codeproject article describes how to do this here http://www.codeproject.com/KB/aspnet/machineKey.aspx

<machineKey 
validationKey="E36B… CE0260028"
decryptionKey="DEF1F… 7F7C0BCCF85"
validation="SHA1" decryption="AES"/>

Also note that it is possible to encrypt ViewState (instead of just making it tamper proof) by setting the validation property to 3DES. This however incurs a performance hit so it is better to store sensitive information in the Session to avoid having to do this.

Storing / Sharing Files

Another problem exists when dealing with file uploads / downloads (when using the file system and not storing files in the database). All servers in the web farm need to be pointing to a common directory for the file store, otherwise if they are pointing to local directories the files will be split across them and sometimes exist and sometimes not depending on what server the user was sent to.

This can be overcome by setting up IIS Virtual Directories on the websites in the web farm that point to a common network share (on a file server somewhere on the network).

In order to test this concept locally for this blog post, I first created a directory c:\Test and turned on network sharing on this directory so that I can now browse to it through the UNC path \\HAEMOGLOBIN-PC\Test (in practice this would point to a share on another machine).

Within IIS7, the virtual directory “Uploads” can then be added that points to this share and will look something like this:

image

This allows the network share location to be maintained and controlled by system administrators – the only other thing to be aware of is setting up the correct permissions for the file share to be accessed and written to. This will depend on whether identity impersonation is enabled or what account the anonymous user is running as.

Coding against this is simple, saving a file is simply a process of using MapPath and the virtual directory name (this allows the system administrator to change the UNC location at a later point through IIS):

FileUpload1.SaveAs(MapPath(@"/Uploads/" + FileUpload1.FileName)); 

The above will be saved by IIS to \\HAEMOGLOBIN-PC\Test (as configured before and this could be on another machine) which in turn resolves to c:\Test on that machine.

In terms of providing a link to download a file - it would simply look like:

<a href="/Uploads/uploadedFile.zip">Uploaded File</a>

This will (once again through the IIS virtual directory mapping) download the file from the common file share location on the network and work for any server the user happens to be on in the web farm.

Hope this helps :)

Categories:   Development
Actions:   E-mail | Permalink | Comments

Versioning a Multi-Component SystemJan21

Thursday, 21 January 2010 by Haemoglobin

1  A lot of the systems that I have worked on have involved more than one component. For example, instead of just an ASP.NET website, there would also be some sort of windows service, maybe a windows forms component, or independent modules and libraries working within those components – all working together to form a final solution.

This tends to create a bit of a versioning and deployment nightmare and you need to have a good solid strategy around it before launching into things. I have tried a couple of approaches.

For one project, I had an automated build script that would go through and modify the version number of all the assemblies, build all the components and label the version from the root in source control. All components would then be redeployed for every release, regardless of whether they have changed or not. This removed human error in deployments as everything was automated, and the deployment steps were always exactly the same for each release so even those could be automated.

This worked pretty well for this project, because there were so many developers that it would have been too time consuming to do a full version to version diff to figure out which components have changed for each release and to deploy only those. Yes there would be release notes on what has changed for each of the components as written by project management or the developer, but that would be reliant on how dutiful Mr developer happened to be at the time, and it’s possible little “tidy” ups were done, or refactorings in components that do not end up appearing on release notes. So one answer is just to test and redeploy everything (this is where automated testing can be very useful also to test for regressions across the system). The only problem with it is you potentially end up deploying a lot of unchanged stuff – albeit just with updated version numbers, all for potentially one small change in one of the components.

For another project – there were far fewer developers, and it was quite easy to just know what components were being changed for each release – so it was possible to just deploy those that were being updated. I came up with the concept of a system version.

Say if you have the following structure in your source control repository for your software solution:

  • MySolution
    • ASP.NET Website
    • Windows Forms Application
    • Windows Service
    • Reporting Services Reports
    • Database Scripts

When you deployed the first version to production, imagine everything was versioned at 1.0.0. All assemblies / exe’s would have been deployed as version 1.0.0 (or using other techniques for database scripts like updating the database version row to this), and the label Version_1_0_0 (or similar) then applied to the MySolution root in source control.

This is in contrast to labelling each subcomponent separately in source control and keeping a configuration management register updated with what versions are deployed where and what versions are all working and tested with what other component versions – uggh.

Now – say that a bug in the windows forms application is reported – it makes sense to just send out a new version of just that, not everything. You make the change, and update the windows forms application’s version to 1.0.1. Now, the solution is is labelled with Version_1_0_1 from the root where 1.0.1 is effectively the new system version. Note however that the rest of the sub-components are still set at version 1.0.0 (literally within the AssemblyInfo.cs classes) – but the 1.0.1 label spans across them, effectively grouping the various current sub-component versions under the 1.0.1 system version umbrella.

Now – lets say a whole lot of work is done across all the different components to create a new feature asked for that will become version 1.1.0. During this time, another small issue is found in production – this time in the windows service. Since we are in the middle of development of version 1.1.0, which is subsequently unstable – we must branch the solution from version 1.0.1 (using the source control branching functionality). Here we make our change to the windows service, update it’s assembly version to 1.0.2 and then label the root of the branch as system version 1.0.2. We then deploy just the windows service to the client.

If we were deploying this solution to multiple clients, who for some reason were running on different versions, you can easily recreate in the development environment the version that they have running in their environment as long as you know their system version. Note that this must be recorded somewhere – but in this case it’s just one number per system deployment, as opposed to a complex set of versions of all the components installed. Pulling that label out of source control will retrieve all the subcomponents in their correct version as deployed for that system version, and consequently retrieve exactly what is running in production for each component.

The only danger with this technique is the possibility of a component being changed (maybe a developer deciding to re-factor some previous work), and not having this component deployed along with the next system version. This would effectively create a mismatch between what is deployed and running on the client’s system and the code associated with that system version in source control. This creates unreproducible bugs and other issues. To solve this, a quick and easy technique should be devised to query source control to see what components have been “touched” since the last release.

I would be interested to hear how others go about versioning in these sorts of situations. I may make a follow up post at some point about database versioning, and UAT deployment techniques.

Categories:   Development
Actions:   E-mail | Permalink | Comments

Monitoring ADSL Drop OutsNov18

Wednesday, 18 November 2009 by haemoglobin

At home we have previously had issues with our ADSL dropping out intermittently and have had the ISP send technicians around to fiddle test and rewire etc. This seemed to make a difference for a good while, but as of the last two days we are back to square one with frequent and annoying ADSL disconnections (no changes to anything in the house).

What I’m afraid of doing now is ringing the ISP again and being told the standard “restart the router”, “pull all the phones out of the wall”, “turn the oven off”/”Pray to the Gods” etc etc, all of which I know most likely has nothing to do with it (tried it all before).

I decided to do my own internet research for reasons why ADSL might drop out. I learnt all sorts of interesting things about noise margin’s, line attenuation, data sync rates etc that all have an impact on how stable the line is.

Checking my Belkin router’s status page, I note that it actually gives me this information - cool:

image

Of course, I start rapidly refreshing the page to see how the numbers are changing as the ADSL internet connection drops in and out. The Data rate is different on each reconnect, and the noise margin is fluctuating all over the place.

Refreshing is no good, tonight I decided that this goodness needed to be graphed!

Window’s inbuilt performance counters are ideal for this sort of thing. We just need a custom performance counter for the ADSL connection data, poll the router’s status page and feed the new performance counter with data.

I fired up Visual Studio and started plugging away at a windows app that will do this for me – easy to do – behold the ADSL Monitor:
image

The following code creates the new ADSL performance object, with the four counters I’m interested in (noise margin up/down and data rate up/down):

 

CounterCreationDataCollection counters = new CounterCreationDataCollection();

counters.Add(new CounterCreationData("Noise Margin Down", "Noise Margin Down", PerformanceCounterType.NumberOfItems64));
counters.Add(new CounterCreationData("Noise Margin Up", "Noise Margin Up", PerformanceCounterType.NumberOfItems64));
counters.Add(new CounterCreationData("Data Rate Down", "Data Rate Down", PerformanceCounterType.NumberOfItems64));
counters.Add(new CounterCreationData("Data Rate Up", "Data Rate Up", PerformanceCounterType.NumberOfItems64));

string _performanceCategory = "ADSL"; 

if (PerformanceCounterCategory.Exists(_performanceCategory))
{
PerformanceCounterCategory.Delete(_performanceCategory); 
}

PerformanceCounterCategory.Create(_performanceCategory, "ADSL Diagnostics", PerformanceCounterCategoryType.SingleInstance, counters);

 

I then fire off a thread and have it looping over the following every second:

	           
	while (running)
	{
		WebRequest request = WebRequest.Create("http://192.168.2.1/status.stm");
		WebResponse webResponse = request.GetResponse();
		StreamReader stream = new StreamReader(webResponse.GetResponseStream());
		string statusPage = stream.ReadToEnd();
		stream.Close();
		webResponse.Close();

		//Providing data to the performance counter 
		PerformanceCounter pc = new PerformanceCounter(_performanceCategory, "Noise Margin Down", false);
		pc.RawValue = Convert.ToInt32(GetDataResult(DataMatch.adsl_noise_margin_ds, statusPage));
		...

		Thread.Sleep(1000); 
	}

A simple Regex is used in GetDataResult to pull the appropriate data off the router’s status page.

Now, browsing to the inbuilt windows Performance Monitor, we can add our newly created ADSL performance object and graph what is really going on. For me, it was looking like this:

image

What the ! !  It seems more than half the time I’m without internet. The most important lines I believe are the blue and red. The blue shows the synced data downstream rate (higher the better), and the red shows the downstream noise margin (once again, higher the better – apparently anything below 6 is quite unstable).

Where the blue line is at rock bottom is where I don’t have any internet at all. What a pain – as you can see towards the end it started to stabilise with quite a high noise margin, albeit a low data rate :(
This will hopefully give me more information to provide the ISP however when I finally do ring as well as letting me monitor the situation and not even bother surfing the internet while it is ridiculously unstable. 

Sigh.

Categories:   Development
Actions:   E-mail | Permalink | Comments

Enabling HttpOnly & RequireSSL on CookiesSep12

Friday, 12 September 2008 by Haemoglobin

Unless you have any specific reason to access cookies from javascript - it is a good idea to turn on HttpOnly on the cookie to help prevent cross site scripting attacks to send your cookie content elsewhere - have a read of Jeff Atwood's post here: http://www.codinghorror.com/blog/archives/001167.html

On top of this however, there is another setting that is not mentioned, and that is RequireSSL. This will mean that the web browser will only send the cookie to the website if it is requested over SSL. 

The idea of that didn't make much sense to me - since surely the user would need to purposely change it from https to http for this to be an issue, until you consider the following scenario (it still seems like a long shot, but hey):

1) You log in as as administrator on the HTTPS site.
2) The website sets a cookie on your browser with your administrator session token. This is transmitted encrypted for each request back to the website.
3) While your session is open you browse to dodgy website (or directed to it somehow, by the hacker)
4) Dodgy website redirects you to the same site you logged in as an administrator, but using HTTP instead of HTTPS. The site might throw an error at this point saying that it can only be accessed over HTTP but the damage has already been done as per the next point (there might be ways of hiding this web request from the user however).
5) Your administrator session token in the cookie is now submitted across the network in plain text.
6) Dodgy hacker now intercepts this through a man in the middle attack (using ARP poisoning or similar)
7) Hacker now has your administrator session token and can use this to browse the site as yourself. 

Now, I think there are further protections the HTTPS site could make, for example, check that the I.P address & browser user agent remain consistent for a particular session - however it is possible to fake these as well. 

Seems difficult to achieve, but hmm - if you have an HTTPS site, just put the following line in the web.config and you will be right (at least for all browsers that support it):
<httpCookies httpOnlyCookies="true" requireSSL="true"/>

This will set the options on all cookies leaving the site - or you can turn the settings on each cookie individually, or on the FormsAuthentication component like so.

It's an interesting example to think about however, as it gets you thinking about all things security after that.

[Update: It pays to also be aware of XSRF]

 

Tags:   ,
Categories:   Development
Actions:   E-mail | Permalink | Comments

Securing Static (non-ASP.Net) FilesAug13

Wednesday, 13 August 2008 by Haemoglobin

When you have forms authentication setup in ASP.NET, you might have a folder containing static content, such as PDF/zip files etc. You might try to protect these files using the following item in the web.config to allow access to authenticated users only:

            <authorization path="PDFFolder">
                  <deny users="?"/>
            </authorization>

This will not work however since IIS serves non ASP.NET file types directly, and will not pass the request through to ASP.NET to carry out any authentication first.

In order to protect all static content in the site (if you have any), you need to setup the following Wildcard application map on the virtual directory to pass all file types through to ASP.NET so that everything is protected:

It is important however that “Verify that file exists” is NOT ticked, since there are some ASP.NET files such as:

  • WebResource.axd
  • Trace.axd

Which don’t physically exist.

WebResource.axd it seems is responsible from .NET 2 onwards for dishing up ASP.NET framework js files, (in 1/1.1 these were served from the C:\Inetpub\wwwroot\aspnet_client\system_web\1_1_4322 folder)

If it is ticked, you will have missing javascript object errors all over the place (because IIS will scrap the request to WebResource.axd) and may be tempting to incorrectly think the empty C:\Inetpub\wwwroot\aspnet_client\system_web\2_0_50727 folder is where the problem lies.

So there you go.

Also, if you are curious what AXD stands for which of course I was, here it is from the man himself:

“Hi Wouter,

I'm somewhat embarrased to say that I don't think it stands for anything. I think we choose it because it sounded cool, and used the leters a & x -- which we usually incorporate in other file extension names.

Hope this helps!

Scott”

http://blogs.infosupport.com/wouterv/archive/2005/08/11/918.aspx
Tags:   ,
Categories:   Development
Actions:   E-mail | Permalink | Comments