<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Indented! &#187; SysLog</title>
	<atom:link href="http://www.indented.co.uk/index.php/tag/syslog/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.indented.co.uk</link>
	<description></description>
	<lastBuildDate>Fri, 02 Jul 2010 10:45:15 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>SysLog in PowerShell</title>
		<link>http://www.indented.co.uk/index.php/2009/12/01/syslog-in-powershell/</link>
		<comments>http://www.indented.co.uk/index.php/2009/12/01/syslog-in-powershell/#comments</comments>
		<pubDate>Tue, 01 Dec 2009 16:01:07 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[SysLog]]></category>

		<guid isPermaLink="false">http://www.highorbit.co.uk/?p=1215</guid>
		<description><![CDATA[I bumped into a requirement to run a SysLog relay on one of my Windows 2008 R2 systems. After poking around on Google, and after getting a bit bored with the third-party offerings, I threw together a simple server of my own. There is plenty of room for improvement here, but it works (for me [...]


Related posts:<ol><li><a href='http://www.indented.co.uk/index.php/2010/02/17/dhcp-discovery/' rel='bookmark' title='Permanent Link: DHCP Discovery'>DHCP Discovery</a> <small>A PowerShell script to send a DHCP Discover request and...</small></li>
<li><a href='http://www.indented.co.uk/index.php/2010/01/23/powershell-subnet-math/' rel='bookmark' title='Permanent Link: IPv4 subnet math with PowerShell'>IPv4 subnet math with PowerShell</a> <small>Written to complement the VbScript version of this post. This...</small></li>
</ol>

Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p>I bumped into a requirement to run a SysLog relay on one of my Windows 2008 R2 systems. After poking around on Google, and after getting a bit bored with the third-party offerings, I threw together a simple server of my own.<br />
<span id="more-1215"></span><br />
There is plenty of room for improvement here, but it works (for me at least) as it stands.</p>
<p>Written for and tested under PowerShell 2.0. The script could probably use some error handling.</p>
<pre class="brush: powershell;">
# SysLog.ps1
#
# A basic SysLog server. Behaviour should be fairly consistent with
# RFC 3164 (http://www.ietf.org/rfc/rfc3164.txt).

# Network Configuration

$SysLogPort = 514                  # Default SysLog Port
$Buffer = New-Object Byte[] 1024   # Maximum SysLog message size

# Server Configuration

$EnableMessageValidation = $True   # Enable check of the PRI and Header
$EnableRelay = $True               # Enable relay to $RelayTargetIP
$EnableLocalLogging = $True        # Enable local logging of received messages
$EnableConsoleLogging = $False     # Enable logging to the console
$EnableHostNameLookup = $True      # Lookup hostname for connecting IP
$EnableHostNamesOnly = $True       # Uses Host Name only instead of FQDNs

$RelayTargetIP = &quot;10.0.0.1&quot;        # Must be an IP Address
$LogFolder = &quot;C:\SysLog\LogFiles&quot;  # Path must exist

# Global variables used to store day and date-stamp for log roll-over

$Day = (Get-Date).Day
$DateStamp = (Get-Date).ToString(&quot;yyyy.MM.dd&quot;)

# Relay Initialisation

If ($EnableRelay)
{
  $RelayTarget = [Net.IPAddress]::Parse($RelayTargetIP)
  $RelayTargetEndPoint = New-Object Net.IPEndPoint($RelayTarget, $SysLogPort)
}

# A launcher for the process
#
# Caller: Manual / Script

Function Start-SysLog
{
  $Socket = CreateSocket
  StartReceive $Socket
}

# Create and bind to the socket
#
# Caller: Start-SysLog

Function CreateSocket
{
  $Socket = New-Object Net.Sockets.Socket(
    [Net.Sockets.AddressFamily]::Internetwork,
    [Net.Sockets.SocketType]::Dgram,
    [Net.Sockets.ProtocolType]::Udp)

  $ServerIPEndPoint = New-Object Net.IPEndPoint(
    [Net.IPAddress]::Any,
    $SysLogPort)

  $Socket.Bind($ServerIPEndPoint)

  Return $Socket
}

# Recieve a single message
#
# Caller: Start-SysLog

Function StartReceive([Net.Sockets.Socket]$Socket)
{
  # Placeholder to store source of incoming packet
  $SenderIPEndPoint = New-Object Net.IPEndPoint([Net.IPAddress]::Any, 0)
  $SenderEndPoint = [Net.EndPoint]$SenderIPEndPoint

  $ServerRunning = $True
  While ($ServerRunning -eq $True)
  {
    $BytesReceived = $Socket.ReceiveFrom($Buffer, [Ref]$SenderEndPoint)
    $Message = $Buffer[0..$($BytesReceived - 1)]

    $Message = ValidateMessage $Message $SenderEndPoint.Address.IPAddressToString

    If ($EnableRelay)
    {
      RelayMessage $Socket $Message
    }
  }
}

# Relay the message to an upstream SysLog server. Either basic forwarding,
# or full validation.
#
# Caller: StartReceive

Function RelayMessage([Net.Sockets.Socket]$Socket, [Byte[]]$Message)
{
  [Void]$Socket.SendTo($Message, $RelayTargetEndPoint)
}

# Check the validity of the message (if option is enabled). Adjust message
# according to recommendations in RFC 3164.
#
# Caller: StartReceive

Function ValidateMessage([Byte[]]$Message, [String]$HostName)
{
  If ($EnableMessageValidation)
  {
    $MessageString = [Text.Encoding]::ASCII.GetString($Message)

    If (IsValidPRI($MessageString))
    {
      If (!(IsValidDateTime($MessageString)))
      {
        $PRI = [Int]($MessageString -Replace &quot;&lt;|&gt;.*&quot;)
        $HostName = GetHostName $HostName
        $MessageString = &quot;&lt;$PRI&gt;$(NewDateTimeString) $HostName $MessageString&quot;
        $Message = EncodeMessage $MessageString
      }
    }
    Else
    {
      $HostName = GetHostName $HostName
      $MessageString = &quot;&lt;13&gt;$(NewDateTimeString) $HostName $MessageString&quot;
      $Message = EncodeMessage $MessageString
    }
  }
  If ($EnableLocalLogging -Or $EnableConsoleLogging)
  {
    If ($MessageString -eq $Null)
    {
      $MessageString = [Text.Encoding]::ASCII.GetString($Message)
    }
    If ($EnableLocalLogging) { WriteToLog $MessageString $HostName }
    If ($EnableConsoleLogging) { Write-Host $MessageString }
  }
  Return $Message
}

# Validate the PRI (Priority Field - Facility and Severity)
# No parsing is performed. No network prioritisation is implemented
#
# Caller: ValidateMessage

Function IsValidPRI([String]$MessageString)
{
  If ($MessageString.SubString(0, 1) -ne &quot;&lt;&quot;)
  {
    Return $False
  }
  If (!$MessageString.SubString(2, 3).Contains(&quot;&gt;&quot;))
  {
    Return $False
  }

  $PRI = [Int]($MessageString -Replace &quot;&lt;|&gt;.*&quot;)
  # PRI = (Facility * 8) + Severity. Maximum and minimum values from RFC 3164
  If ($PRI -lt 1 -Or $PRI -gt 191)
  {
    Return $False
  }
  Return $True
}

# Validate the TimeStamp formatting
#
# Caller: ValidateMessage

Function IsValidDateTime([String]$MessageString)
{
  $IsValid = $False
  If ($MessageString -Match &quot;(?&lt;=\&gt;)\w{3}\s\s?\d{1,2}\s(\d\d:){2}\d\d(?=\s)&quot;)
  {
    $Date = New-Object DateTime
    ForEach ($Format in @(&quot;MMM  d hh:mm:ss&quot;, &quot;MMM dd hh:mm:ss&quot;))
    {
      $Date = New-Object DateTime
      $IsValid = [DateTime]::TryParseExact(
        $Matches[0],
        $Format,
        [Globalization.CultureInfo]::InvariantCulture,
        [Globalization.DateTimeStyles]::AssumeUniversal,
        [Ref]$Date)
      If ($IsValid) { Return $True }
    }
  }
  Return $False
}

# Create a new DateTime String
#
# Caller: ValidateMessage

Function NewDateTimeString
{
  $Date = (Get-Date).ToUniversalTime()
  If ($Date.Day -lt 10)
  {
    Return $Date.ToString(&quot;MMM  d HH:mm:ss&quot;)
  }
  Return $Date.ToString(&quot;MMM dd HH:mm:ss&quot;)
}

# Attempt to lookup the HostName if an IP value was passed.
# [Net.Dns]::GetHostEntry fails to return if a Forward Lookup record
# does not exist. NsLookup as a simple alternative.
#
# Caller: ValidateMessage

Function GetHostName([String]$HostName)
{
  If (!$EnableHostNameLookup) { Return $HostName }
  If ([Net.IPAddress]::TryParse($HostName, [Ref]$Null))
  {
    $Temp = (nslookup -q=ptr $HostName | ?{ $_ -Like &quot;*name = *&quot; })
    $Temp = $Temp -Replace &quot;.*name = &quot;
    If ($Temp -ne [String]::Empty) { $HostName = $Temp }
  }
  If ($EnableHostNamesOnly)
  {
    Return $HostName.Split(&quot;.&quot;)[0]
  }
  Return $HostName
}

# Returns a Byte Array representation of the original message.
# If the length is greater than 1024 Bytes the array is truncated
# as stipulated under RFC 3164.
#
# Caller: ValidateMessage

Function EncodeMessage([String]$MessageString)
{
  $Message = [Text.Encoding]::ASCII.GetBytes($MessageString)
  If ($Message.Length -gt 1024)
  {
    Return $Message[0..1023]
  }
  Return $Message
}

# Maintain a per-host log file in the $LogFolder
# Script does not clean up old log files
#
# Caller: ValidateMessage

Function WriteToLog([String]$MessageString, [String]$HostName)
{
  # Simple time based roll-over check
  If ((Get-Date).Day -ne $Day)
  {
    $Day = (Get-Date).Day
    $DateStamp = (Get-Date).ToString(&quot;yyyy.MM.dd&quot;)
  }

  $LogFile = &quot;$LogFolder\$HostName-$DateStamp.log&quot;
  $MessageString &gt;&gt; $LogFile
}

# Start the server

Start-SysLog
</pre>


<p>Related posts:<ol><li><a href='http://www.indented.co.uk/index.php/2010/02/17/dhcp-discovery/' rel='bookmark' title='Permanent Link: DHCP Discovery'>DHCP Discovery</a> <small>A PowerShell script to send a DHCP Discover request and...</small></li>
<li><a href='http://www.indented.co.uk/index.php/2010/01/23/powershell-subnet-math/' rel='bookmark' title='Permanent Link: IPv4 subnet math with PowerShell'>IPv4 subnet math with PowerShell</a> <small>Written to complement the VbScript version of this post. This...</small></li>
</ol></p>
<p>Related posts brought to you by <a href='http://mitcho.com/code/yarpp/'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.indented.co.uk/index.php/2009/12/01/syslog-in-powershell/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
