Monday, 15 June 2009

Great place to stay in Northumberland

If you are looking to go to Hadrians Wall, either to housesteads or looking for some climbing, there are some great self-catering cottages nearby http://www.commonhousefarm.com/

Tuesday, 26 May 2009

Hosters Guide to Microsoft Licensing..

Authenticated vs. Unauthenticated
There is a simple distinction between authenticated and unauthenticated, if a server is authenticated, that means it is using Active Directory. Active Directory is the system of centralised user control in Windows. You do not need Active Directory to run windows, but certain systems require AD, these will be covered in this sheet. The most common are:
• Windows Clustering
• Microsoft Exchange
• Microsoft Office Sharepoint Server (Not Sharepoint Services 3.0)
• A cluster of terminal servers
• A domain controller
The following words indicate this is an authenticated environment:
• “In a domain”
• “Active Directory”
• “Not in a workgroup”
• “On AD”
The customer might say the following to indicate this is unauthenticated:
• “In a workgroup environment”

SAL or CAL

• A SAL is a ‘Subscriber access license’; it is the SPLA version of the CAL.
• 1 Windows Standard SAL will grant a user access to all authenticated servers in a hosted platform, for example:
This solution has 5 users
It also has 3 servers (Terminal Server, Domain Controller and Exchange Server) which are all authenticated
The licensing required for this solution is:

5x Windows Standard SAL
5x Terminal Server SAL
5x Exchange SAL

Those SAL’s grant those 5 users access to all 3 servers, regardless of number of processors.
If you added another Domain Controller for example, you would not need extra SALs.

Exchange
Exchange is a system allowing Calendaring, Email, Shared folders. Exchange has the following requirements:
1. You must have an Exchange SAL for each user using Exchange. There is no ‘unlimited’ license.
2. Every Exchange Server MUST be authenticated, Exchange requires Active Directory to operate
3. Because it requires AD, you need both an Exchange SAL AND a Windows SAL.
4. 1 Exchange SAL licenses every Exchange server in that setup.
This example has 10 users, 3 Exchange Servers and 1 Domain controller, you need the following licenses:
• 10x Exchange SAL (Ask customer which version)
• 10x Windows STD SAL

Windows Server 2008 Web Edition
In web edition you can do everything the full version allows, except:
• It must be web facing
• It cannot be a domain controller
• It cannot be a DNS server
• It cannot run Hyper-V
• It cannot be a terminal server

Terminal Services
1. Terminal Services does NOT need to be on an authenticated license
2. It is recommended that for more than 1 terminal server, you use Active Directory.

SQL Server
SQL Server does not need to run on a domain, unless it is in a cluster.
http://www.microsoft.com/sqlserver/2008/en/us/editions-compare.aspx

Clustering
1. Clustering requires Active Directory to run
2. You only need to license the active SQL Server license, say you have 2 SQL Servers in a cluster, you do not need 2 SQL Licenses.
3. You do need to license the Windows License on both nodes.
4. Do NOT run a cluster node as a domain controller as well, or EVER allow a customer to do this. We will not support a solution with this setup.

This solution powers a web site, I have left the web servers out for simplicity.
The Customer does not know how many users will be accessing the website because this is a public site, there are 2 Servers in a cluster providing SQL.
You will need the following licenses:
• 1x Windows Std Proc (Domain Controller)
• 2x Windows Enterprise Proc (Cluster Nodes)
• 1x SQL Server (Standard or Enterprise) License

Domain Controllers
A domain controller is the server that contains a database on the users in the system, if this server fails, any software requiring logins in a domain will fail.
If any of the servers in a solution require Active Directory, there must be a domain controller in the solution. It is important to remember that if the solution only has 1 domain controller; this becomes a single point of failure, so if possible provide 2 domain controllers, especially if the customer is requesting NO single point of failure.
A Domain Controller needs at least 512MB RAM, so it can be a small spec machine.
If you are trying to keep the costs low, you can make both domain controllers virtual machines, speak to any of the Solutions Architects on this.
Virtualisation
For Virtual Guests (ie: the Virtual Machines, not the physical servers) once you license the host, there are a certain number of included licenses for Windows,

Standard Authenticated (1 Web or Standard VM)
Enterprise Authenticated (4 Web, Standard or Enterprise VM's)
Datacenter Unauthenticated (Unlimited Unauthenticated Web,Standard,Enterprise or Datacenter VMs)

Also for SQL Server, there are benefits, if you license the host with Enterprise Edition SQL, any Virtual Machines on that host do not need SQL Licenses.

Friday, 3 April 2009

Quick C# Twitter API

Quick little class I knocked together to do 2 basic functions in twitter but can easily do more. Add this to a cmdlet in powershell or command line app to integrate with anything else!!

///
/// Twitter.cs
/// A simple C# class with 2 basic methods, add away with other methods-
/// http://apiwiki.twitter.com/REST+API+Documentation#statuses/update
///

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net;
using System.Collections.Specialized;
using System.Web;

namespace Net.Ant.Twitter
{
public class Twitter
{
protected string _username;
protected string _password;

/// <summary>
/// Creates a new instance of the Twitter API class
/// </summary>
/// <param name="username">Your Twitter username</param>
/// <param name="password">Your Twitter password</param>
public Twitter(string username, string password)
{
_username = username;
_password = password;
}

#region Twitter API functions

/// <summary>
/// Sends a private message
/// </summary>
/// <param name="user">User to message</param>
/// <param name="text">Message text</param>
public void SendMessage(string user, string text)
{
NameValueCollection col = new NameValueCollection();
col.Add("user",user);
col.Add("text",text);
HttpPOSTRequest("http://twitter.com/direct_messages/new.xml", col);
}

/// <summary>
/// Tweet/Update!
/// </summary>
/// <param name="message">Message text</param>
public void Tweet(string message)
{
NameValueCollection col = new NameValueCollection();
col.Add("message", message);
HttpPOSTRequest("http://twitter.com/statuses/update.xml", col);
}

#endregion

#region Internal functions for HTTP requests

/// <summary>
/// Make a call to the twitter website, will used the username/pass in the class
/// </summary>
/// <param name="url">The URL to request</param>
protected string HttpPOSTRequest(string url,NameValueCollection post_parameters )
{
HttpWebRequest req = (HttpWebRequest) WebRequest.Create(url);
req.Credentials = new NetworkCredential(_username, _password);
req.PreAuthenticate = true;

string postData = PostEncodeArray(post_parameters);

req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
req.ContentLength = postData.Length;
using(Stream writeStream = req.GetRequestStream())
{
UTF8Encoding encoding = new UTF8Encoding();
byte[] bytes = encoding.GetBytes(postData);
writeStream.Write(bytes, 0, bytes.Length);
}

// make request
string result=string.Empty;
using (HttpWebResponse response = (HttpWebResponse) req.GetResponse())
{
using (Stream responseStream = response.GetResponseStream())
{
using (StreamReader readStream = new StreamReader (responseStream, Encoding.UTF8))
{
result = readStream.ReadToEnd();
}
}
}
return result;
}

/// <summary>
/// Posts the supplied data to specified url.
/// </summary>
/// <returns>a string containing the result of the post.</returns>
protected string PostEncodeArray(NameValueCollection m_values)
{
StringBuilder parameters=new StringBuilder();

for (int i=0;i < m_values.Count;i++)
{
if (parameters.Length != 0) parameters.Append("&");
parameters.Append(m_values.AllKeys[i] + "=" + HttpUtility.HtmlEncode(m_values.Get(i)));
}
return parameters.ToString();
}
#endregion
}
}

Wednesday, 4 March 2009

IPQ Tutorial

Before I start the tutorial, a couple of notes:
Only attempt this if you are familiar with:
* C/C++
* IP Tables
* IP Networking

And I really don't recommend doing this on a live server! If, once you've coded your funky new firewall it drops packets and you can't get SSH access to kill it, then you'll see why.

Right, now here's an interesting library which comes with IP Route 2 for linux. Using this library you can tell your IP stack to put packets in a queue, you can then write an app to read through the packets and either drop or accept them (even modify them if you read further into it). The great thing is, this is all in user space so there's none of that messy kernel re-compiling.

Why? Well I'll give you an example.
Say you find IP tables limiting for example, because you can't tell it to allow packets to port 666 only when there's a full moon. Bad example, infact as you can get your firewall todo pretty much anything you can possibly think of its quite an interesting concept. I ended up using this todo pattern recognition on the packet size and source address to detect dDos attacks and it worked pretty well. As its all in user space you can load config files and make a fully blown firewall.

Now to continue, you're going to need all the usual tools suchas gcc and you can write this in either C or C++.

You're also going to need the libraries and IP route 2 installed.

Once you've installed the devel libraries for netfilter and networking etc. You will need to check that you have both the iptable_filter and ip_queue modules loaded:

# lsmod | grep iptable_filter
# lsmod | grep ip_queue

If not, then load them!
# modprobe iptable_filter
# modprobe ip_queue

Right now, you can use the action 'QUEUE' in iptables, for example to queue any tcp packets:
# iptables -A OUTPUT -p tcp -j QUEUE

Note that these packets will sit in the queue until the application runs, so as I mentioned, don't do this unless you're on a terminal.

Now for the code.

Include some standard libraries, which you will probably need

#include <iostream>
#include <cstdlib>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>


Right now we include some standard socket libraries

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>


Include the netfilter library, make sure this is installed

#include <linux/netfilter.h>


Now we include the ip queue library, note if you're compiling in c++ then tell the compiler to pretend its C like so:

extern "C" { // compile in c
#include <libipq.h>
}


Or for those just keeping it in C:

#include <libipq.h>


Now we include the structs for ip, tcp and udp packets (obviously icmp and others are available as well.
If you want to know what the structs are then read the header files which should give you a good pointer.

#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>


Define the buffer size for reading off the queue

#define BUFSIZE 2048



using namespace std;


Here's a clean function which makes sure the handle is destroyed incase we need to quit, pass the handle to the function to die

static void die(struct ipq_handle *h)
{
ipq_perror("passer");
ipq_destroy_handle(h);
exit(1);
}


Now here's another function which you might find helpful for easily converting between an int and a readable IP. Pass it an unsigned 32 and it returns the string.


char * inttoip ( __u32 ip ) {
in_addr src_addr;
src_addr.s_addr = (ip);
return inet_ntoa(src_addr);
}



int main() {

// packet counter
unsigned short int packet_count = 0;

int status;
unsigned char buf[BUFSIZE];

struct ipq_handle *h;

cout << "Creating IP Queue handle..\n";
h = ipq_create_handle(0, PF_INET);

if (!h)
die(h);

cout << "Handle created, setting mode to " << IPQ_COPY_PACKET << " .\n";
status = ipq_set_mode(h, IPQ_COPY_PACKET, BUFSIZE);
if (status < 0)
die(h);
cout << "IP Queue ready, listening for all queued packets. \n";
do{
status = ipq_read(h, buf, BUFSIZE, 0);
if (status < 0)
die(h);
if (ipq_message_type(buf) == NLMSG_ERROR ){
fprintf(stderr, "Received error message %d\n", ipq_get_msgerr(buf));
cout <<"make sure you are root and ip_queue module is loaded.\n";
exit(1);
}
else if (ipq_message_type(buf) == IPQM_PACKET) {

ipq_packet_msg_t *m = ipq_get_packet(buf);

struct iphdr *ip = (struct iphdr*) m->payload;



Now for quick reference, here's the struct for iphdr:
__u8 tos;
__u16 tot_len;
__u16 id;
__u16 frag_off;
__u8 ttl;
__u8 protocol;
__u16 check;
__u32 saddr;
__u32 daddr;
And if, for example, the protocol was TCP, then you can typecast the packet to a tcp struct like so:

struct tcphdr *tcp = (struct tcphdr*) (m->payload + (4 * ip->ihl));


Once we have that we can do:

if ( tcp->dport == '666' && IS_FULL_MOON && USER_IS_WEARING_SOCKS)
status = ipq_set_verdict(h, m->packet_id,NF_ACCEPT, 0, NULL);
else
status = ipq_set_verdict(h, m->packet_id,NF_DROP, 0, NULL);
}
else{
fprintf(stderr, "Unknown message type :\n");
}

} while (1);

ipq_destroy_handle(h);
return 0;
}