Click here to Skip to main content
15,893,588 members
Articles / Web Development / ASP.NET
Article

xNetServer - VB.NET Web Server for ASP.NET

Rate me:
Please Sign up or sign in to vote.
4.07/5 (9 votes)
10 Apr 20058 min read 223.6K   5.4K   53   46
VB.NET conversion of the Cassini web project with additional security controls.

Image 1

Introduction

The original Cassini project was written and developed by Microsoft in C# to show off the capabilities of the System.Web.Hosting namespace in .NET. VB.NET developers were left in the dark as Microsoft (or anybody else) has not released a VB.NET version of the source (that I could find). Cassini is a basic Web Server delivery platform that allows developers to test their .NET applications without the need for Internet Information Server to be installed on a development machine or server.

The primary goals of this project were to convert the C# development code to VB.NET so developers can read/use the code in this language, I also wanted to add a reasonable amount of security controls into the code so the server was well protected from internal security threats or viruses/worms roaming around the network.

The demo and source code provided includes a working installation wrapped around a Windows Service. The Server has been named xNetServer (extra .NET Server) and uses an XML file to set the configuration and security options for the service.

The following additional functionality has been included into the xNetServer project:

  • XML file to set all security and configuration settings;
  • W3C Format Access logging to write connection data to disk;
  • Enhanced Disk Eventlog debugging (debugging Server errors or .NET handling errors);
  • Built into Windows Service;
  • Basic Windows Eventlog logging for critical server failures;
  • Specify the Port, Virtual Directory and Physical Path of the .NET web application in the XML file;
  • Direct File Handling and content-type handling for any configured file type (e.g.: SWF, JPEG etc.);
  • Security for maximum length of URI (Request);
  • Security for accepting either local or remote IP addresses;
  • Configure only specific IP addresses that are able to connect and process content;
  • Disable/Enable directory browsing;
  • Custom Version/Server Header configuration;
  • Security for handling only specific Request types such as GET, HEAD and POST;
  • Disable certain file extensions from being handled by the server;
  • Define multiple default document names for the server.

Although I don’t believe that changes made to the source ensure the xNetServer is secure, it is certainly more secure than the basic Cassini project and allows developers to easily change the security and server configuration to their specific requirements. I don’t recommend that the project be used to host Web content directly onto the Internet. (Use at your own risk).

Background

Cassini provides the basic hosting capabilities to run an ASP.NET application server on. Though the server itself has very limited security features, it is widely used on development systems and is included in the Visual Studio 2003/2005 releases as the Web Development server. The application serving capabilities are quite efficient and provide a reasonable platform for serving ASP.NET content.

Information on downloading the original Microsoft Cassini Project source code can be found here.

Configuring the Demo

xNetServer is configured by using the XML file located in the service (installation directory) of the server. The XML file contains a number of settings that when the service is started are read into memory and processed by the server.

The configuration section of the XML file consists of:

XML
<Configuration>
    <LoggingDirectory Value="C:\" /> 
    <EnableDebugLogging Value="True" /> 
    <VersionString Value="xNetServer ASP.NET Web Server Version 1.0.1" /> 
    <ServerPort Value="80" /> 
    <VirtualPath Value="/" /> 
    <PhysicalDirectory Value="C:\Inetpub\wwwroot\Chart\" /> 
    <SecurityLocalRequestsOnly Value="False" /> 
    <MaxURILength Value="512" />
    <AllowDirectoryListing Value="True" />
</Configuration>
  • LoggingDirectory – Specifies the root directory where all Access, Security and Debug logs for the server are written.
  • EnableDebugLogging – If set to True, any errors caused in the processing of a request will be written to the disk event log.
  • VersionString – The name the server will use in the Response Header to the client to identify the server type.
  • ServerPort – The TCP port the server will listen for requests.
  • VirtualPath – The virtual directory if any to be used in the server.
  • PhysicalDirectory – The physical root directory of the web server.
  • SecurityLocalRequestsOnly – Set to True if the server is to only accept local security requests, False if any IP is allowed.
  • MaxURILength – Sets the maximum length the URL and querystring can be before a security event is thrown and the request is denied.
  • AllowDirectoryListing – If set to False, the server will not allow directory browsing.

The ContentTypes section of the XML configuration file allows the server to respond to the requesting client with the correct ContentType Headers.

XML
<ContentTypes>
    <!-- Records the Content Types to be handled
         directly by the xNetServer (not the ASP.NET processor)--> 
    <ContentType Extension=".jpg" ContentType="image/jpeg" />
    <ContentType Extension=".gif" ContentType="image/gif" /> 
    <ContentType Extension=".jpe" ContentType="image/jpeg" /> 
    <ContentType Extension=".jpeg" ContentType="image/jpeg" />
    <ContentType Extension=".xml" ContentType="text/xml" />
    <ContentType Extension=".gz" ContentType="application/x-gzip" /> 
    <ContentType Extension=".swf" ContentType="application/x-shockwave-flash" /> 
    <ContentType Extension=".ram" ContentType="audio/x-pn-realaudio" /> 
    <ContentType Extension=".crt" ContentType="application/x-x509-ca-cert" /> 
    <ContentType Extension=".tgz" ContentType="application/x-compressed" />
    <ContentType Extension=".pdf" ContentType="application/pdf" /> 
    <ContentType Extension=".cer" ContentType="application/x-x509-ca-cert" />
    <ContentType Extension=".png" ContentType="image/png" /> 
    <ContentType Extension=".tiff" ContentType="image/tiff" />
    <ContentType Extension=".mpg" ContentType="video/mpeg" /> 
    <ContentType Extension=".mpeg" ContentType="video/mpeg" />
    <!-- All other content types will be handled
                      by the ASP.NET HTTP Worker process.--> 
</ContentTypes>

More content types can be added by simply replicating lines with their specific content types and extensions. If the content type is not listed in this section, the ASP.NET worker process will handle the request and return Application/Octet content types.

The AccessSecurity section defines the IP addresses or global settings for clients making requests against the server.

XML
<AccessSecurity>
    <!-- Defines the access controls by IP Address
                  allowed to connect to the Server.--> 
    <GlobalAllowAll Value="True" /> 
    <AllowedIPAddress Value="127.0.0.1" /> 
    <AllowedIPAddress Value="10.1.1.100" /> 
</AccessSecurity>

If the GlobalAllowAll setting is set to TRUE, then all remote clients can connect and communicate with the server. If this is set to False, then any IP address listed in the AllowedIPAddress can connect to the server. To include additional IP addresses, just add a new entry in the AccessSecurity section like: <AllowedIPAddress Value=”x.x.x.x” />.

The FileAccessSecurity section allows the ability to define the extensions that are authorized to be processed on the server. If the file extension requested is not listed in the configuration file, then a Security event is fired and the request is denied.

XML
<FileAccessSecurity>
    <!-- Defines the File Extensions the server 
            is allowed to handle. All other file types fail.--> 
    <AllowedFileExtension Type=".asmx" /> 
    <AllowedFileExtension Type=".aspx" /> 
    <AllowedFileExtension Type=".ascx" /> 
    <AllowedFileExtension Type=".jpg" /> 
    <AllowedFileExtension Type=".gif" /> 
    <AllowedFileExtension Type=".htm" /> 
    <AllowedFileExtension Type=".html" /> 
    <AllowedFileExtension Type=".asax" /> 
    <AllowedFileExtension Type=".css" /> 
    <AllowedFileExtension Type=".js" /> 
</FileAccessSecurity>

The VERBSecurity configuration section allows the server to be configured to support only specific VERB requests from remote clients.

XML
<VERBSecurity>
    <!-- Defines the request VERBS that are allowed to be used
              against the server. All non defined VERBS Fail.--> 
    <AllowedVERB Type="GET" /> 
    <AllowedVERB Type="HEAD" /> 
    <AllowedVERB Type="POST" /> 
</VERBSecurity>

New VERBs that are supported can be added by simply creating an additional line in the configuration file with the correct VERB.

Default documents can be specified on a per server basis. These are created by simply adding additional document names to the relevant DefaultDocuments section of the XML configuration file.

XML
<DefaultDocuments>
    <!-- Defines the Default document names to be loaded
                   by the server when calling a directory.--> 
    <DefaultFile Name="default.aspx" /> 
    <DefaultFile Name="index.aspx" /> 
    <DefaultFile Name="default.htm" /> 
</DefaultDocuments>

Once you have made the relevant changes to your XML configuration file and installed the service (and configured the xHosting.DLL into the GAC) then you can simply start your server and start processing your HTTP requests. If you wish to customize the hosting DLL or server, please read the ‘Using the Code’ section.

Using the code

Basically, the project is made up of two distinct parts. The Server (xNetServer) and Library (xhosting.dll). The hosting library is directly a VB.NET conversion from the C# Microsoft Cassini project, though a number of security enhancements have been made to ensure the server is much more secure and supports the serving of contents more efficiently.

The xNetServer service is the Windows VB.NET service and is called through the following code:

VB
Dim fullExecPath As String = _
   System.Reflection.Assembly.GetExecutingAssembly.Location.ToString
Dim lastSlh As Integer = fullExecPath.LastIndexOf("\"c) + 1
Dim startLocation As String = Left(fullExecPath, lastSlh)

'Lets check and ensure the xNetServer.XML File 
'is in the local directory and we can read it.
xConfigXMLReader.ReadXMLAttributesfromXMLFile(startLocation _
                      & "xNetServerConfig.XML")

If xConfigXMLReader._XMLPhysicalPath.Length <= 1 Then
'We didn't get values out of the XML Document 
'(we can't find the document) fail the server.
  WindowsEventLog.CreateError("Failed to read the XML Configuration" & _ 
       " File correctly for Startup. Check the directory," & _ 
       " file location and permissions and try again.", 1)
  SrvController.Stop()
End If

'Start the Service.
Try
  Dim myServer As New Server(xConfigXMLReader._XMLServerPort, _
        xConfigXMLReader._XMLVirtualPath, _
        xConfigXMLReader._XMLPhysicalPath, _
        xConfigXMLReader._XMLLoggingDirectory, _
        startLocation)
  myServer.Start()

Catch ex As Exception
  WindowsEventLog.CreateError("Unable to successfully start" & _ 
      " and bind to the Server Port. Check your configuration file" & _ 
      " and ensure nothing is currently listening on the configured port." _
      & vbCrLf & ex.Message & vbCrLf & _
      ex.Source & vbCrLf & ex.StackTrace, 2)
  SrvController.Stop()
End Try

To start the xHosting.DLL service, you will need to call the Server object and pass the basic configuration settings (server port, virtual path, physical path, logging directory and the start location of the service). Once the service loads, you will be able to connect via your web browser to the service.

To start the service, the xHosting.DLL class library needs to be installed into the machines GAC cache. To do this, use the gacutil.exe program like so: gacutil.exe /I xhosting.dll. See the reason for the GAC cache on the official Microsoft .NET forums site.

The code inside the class library is very similar to the Cassini project, I have provided a brief diagram below that explains how the Web Hosting library functions and calls content.

Image 2

(Server)

This provides the initial startup and operation commands for the server.

(Host)

Controls the AppDomain for hosting ASP.NET web content. Also provides some of the header content parsing etc.

(Connection)

Provides the TCP connection handling for each connection made to the server.

(Messages)

Creates and stores any messages that are returned back to the requesting client, such as directly listing content or error messages.

(Request)

This is the primary event handling module and handles each request being made against the server. Includes parsing of data, reading and responding to headers and also checking the security of the request.

(DebugWriter)

Simple class that provides disk event logging for debug events.

(w3Logging)

Allows the server to write request events and security related events to the disk. Each W3log is written with a date-time stamp for the filename and is recorded in W3C logging format.

(xXMLReader)

A basic XML reader class that parses the XML configuration file upon startup and places the configuration settings into memory.

If you recompile the xHosting.dll, I have included (and already scripted) the xhosting.dll strong name file (.SNK). This file is needed to sign the xHosting.dll file before it can be loaded into the system's GAC Cache. All files in the source should simply unzip into a directory and use Visual Studio 2003 to load the project file.

Overall, the purpose of this project was to convert the Microsoft open shared library Cassini C# project into VB.NET so I could learn about the way it was built. At the same time, I identified that there was no security in the Cassini project, so I decided to add a number of features for logging, debugging and security.

I welcome any sensible criticism or recommendations to make this code better. If you are planning on using this code, ensure you read the license agreements from Microsoft (EULA) in the ZIP files.

History

Currently version 1.0.1. (However, plans are to increase security and fix all the bugs everyone finds. Also plans are to create a Microsoft .NET Framework 2 version as well.)

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Australia Australia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionCan xNetServer run on a CD-ROM? Pin
FabFreddy22-May-05 2:42
FabFreddy22-May-05 2:42 
AnswerRe: Can xNetServer run on a CD-ROM? Pin
JDOnline26-May-05 12:54
JDOnline26-May-05 12:54 
QuestionWill This Work On WinXP home Edition? Pin
fwh217-May-05 0:47
fwh217-May-05 0:47 
AnswerRe: Will This Work On WinXP home Edition? Pin
JDOnline17-May-05 12:50
JDOnline17-May-05 12:50 
GeneralError when start from VS.Net 2003 Pin
5-May-05 5:25
suss5-May-05 5:25 
GeneralRe: Error when start from VS.Net 2003 Pin
JDOnline5-May-05 12:19
JDOnline5-May-05 12:19 
GeneralRe: Error when start from VS.Net 2003 Pin
Member 57225713-May-05 2:48
Member 57225713-May-05 2:48 
GeneralQuestions For xNetServer Pin
supernova56661-May-05 1:44
supernova56661-May-05 1:44 
I Tried To Send This Via Email However Server Rejected:

xNetServer@intratools.net

My Email Is supernova@eazynetwork.com, Contact Me For Mentioned Source Etc...

My Name Is Bobby, I Am A Programmer From FL. I Work For Alot Of Adult Websites, Doing Affiliate Systems, Adult service Membership Type Systems, Security And Creditcard Billing etc.. Please Excuse The Way I Type(The Caps Annoy Some People) And Read On Smile | :)

I Made A Streaming Server With VB.net, I Am Including The Code, Its Old(Made This 3-4 Years Ago) So I See No Reason Someone Who Could Make xNetServer Would Really Steal From My Designs... The Server Used Traditional Threading Practices, NON ASYNC, But Actual Loading Of 500-800 Threads And Having A HTTP Request Model, It Delivered The JAVA Applet That I Wrote To PLAY The Live Video, And It Distributed Also LIVE Video From VB6 Capture Applications.(.NET Was In Beta During This Time). Our Previous Feed Technology Relied On A Win32 Build Of Apache And Again Windows Based(VB6) Capture Apps.

I Recently Began Work To Recreate This Server, And I Started Already Making A New Chat Server. I Have The Chat Server Almost Completed Using NO RFC Compliant Communication Between A .Net Service And A Swing Based Java Applet. After This I Plan On Recreating The VIDEO Server In A New Threading Model. The New Chat Server Uses Async Socket Calls(BeginRecieve, BeginAccept Etc..) Similar To The QueueUserWorkItem I THINK.

So Here's A Question, I Am Obviously Looking To Your App For Examples Of Handling A Server/Client Application, Server Being .Net And Client Being JAVA(Until I Figure Out To Get .Net In A Browser). And I Found It Interesting That Cassinni And xNetServer While Handling Stan Web Structure(GET, POST, HTML/IMAGE Return) It Also Handles ASP.Net Through System.Web.Hosting. However How Is The Server At Alot Of Connections? Lets Say It Was Processing 800 Concurrent Users. This May Seem Unlikly In A HTTP Model, However A Streaming Video Server, Not So Much. HTTP Is Request/Response/Disconnect, While VIDEO Is Request/Stream(Indefinite)/Disconnect. Is Using ASYNC Able To Handle Such Stress, Or Are Thread Pools Gonna Slow Down Processing?

Not Sure If I Need A VideoServer That Has The Ability To Call ASP.Net, Have To Look Into The Ability If Any To Populate Application Data Relevent FOR The VIDEO Server Into Executing Scripts, Would Seem Very Useful If This Were Possible...

Anyway I Hope Maybe You Can Enlighten Me, Although The Older Video Server Runs And Takes Connections The Newer One Will Be Way More Busy, And I Am Looking Into Ways Of Minimizing The Server CPU, Memory But Still Be Able To Keep Response Time Viable For VIDEO Streaming.

Please Take A Look At My OLD Code, This Code Is From When .Net Was In Beta 2(My Beta 1 Version WAS UNSTABLE!!, And In Beta 2 My String.ToInt Int.ToString Stopped Working), So Please Be Gentle, My New Chat Server Looks More Like Yours, And If Your Interested In Talking With Me I Would Be Happy To Show You That Code As Well, Its Tested Locally But Unreleased In The Real World...

Thanks IN Advance For Atleast Allowing Me To See A HTTP Server Model Other Then My Own In VB Smile | :)
Bobby


GeneralRe: Questions For xNetServer Pin
JDOnline2-May-05 13:21
JDOnline2-May-05 13:21 
GeneralRe: Questions For xNetServer Pin
supernova56663-May-05 13:31
supernova56663-May-05 13:31 
GeneralRe: Questions For xNetServer Pin
supernova56666-Jun-05 22:52
supernova56666-Jun-05 22:52 
GeneralSecurity Pin
Dave Bacher11-Apr-05 3:39
Dave Bacher11-Apr-05 3:39 
GeneralRe: Security Pin
JDOnline11-Apr-05 18:29
JDOnline11-Apr-05 18:29 
QuestionMultiple Web Apps? Pin
hotel9611-Apr-05 2:48
hotel9611-Apr-05 2:48 
AnswerRe: Multiple Web Apps? Pin
JDOnline11-Apr-05 18:31
JDOnline11-Apr-05 18:31 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.