Wednesday, December 29, 2010

VBScript: Hyper-V VM Status Script

I did a little research on how to start and shutdown a virtual machine via WMI. Below are two links to the classes that control these Hyper-V functions. Using these classes, came up with a script that is basically an interface for starting, stopping, or viewing the status of Hyper-V virtual machines. This should allow someone more control of our Windows Core Hyper-V servers when they lose network connection or they have to shut down all the servers.

Msvm_ComputerSystem Class
http://msdn.microsoft.com/en-us/library/cc136822%28v=VS.85%29.aspx

Msvm_ShutdownComponent Class
http://msdn.microsoft.com/en-us/library/cc136893%28VS.85%29.aspx


'***********************************************************************************************************
'Script Name: Hyper-V_VM_Status.vbs
'Author: Dean Bunn
'Last Edited: 12/29/10
'Description: Interface for Starting, Stopping, or Viewing Status of Hyper-V Virtual Machines
'***********************************************************************************************************

on error resume next

dim strOption, strHVServer, strVMState, strStatus

''Variable for Hyper-V Server Name..."." is for Local System
strHVServer = "."

''Connect to Hyper-V Server
set WMIService = GetObject("winmgmts:\\" & strHVServer & "\root\virtualization")

''Error Checking on the Connection to Hyper-V Server
if Err.Number <> 0 then
msgbox "Problem Accessing the Hyper-V Server. The Script will Quit Now" , vbExclamation + vbOkOnly , "Hyper-V VM Status"
wscript.quit
end if

''Do Loop to Ease of Use When Starting or Stopping Numerous Systems
do
''Prompt User: Start, Shutdown, or Status Only
strOption = inputbox("Type an Option:" & VbCrLf & VbCrLf & """Start"" to Start a Virtual Machine" _
& VbCrLf & VbCrLf & """Stop"" to Shutdown a Virtual Machine" & VbCrLf & VbCrLf _
& """Status"" to View Status Only" & VbCrLf & VbCrLf _
& "Press Cancel to Quit the Script" & VbCrLf & VbCrLf, "Hyper-V VM Status")

''If User Clicks Cancel or Closes Window Script Quits
if strOption = vbEmpty then
msgbox "User Cancelled Script. Quitting Now" , vbExclamation + vbOkOnly , "Hyper-V VM Status"
wscript.quit
end if

''Query Hyper-V Server for All Virtual Systems, Which Includes Hyper-V Server)
set VMList = WMIService.ExecQuery("SELECT * FROM Msvm_ComputerSystem")

''Start Status of Virtual Systems Message
strStatus = "Current Virtual Machine Status:" & VbCrLf & VbCrLf

''Loop Through All VMs and Add System Name and Current State to Status
''Excluding Hyper-V Server by Checking for Non Matching ElementName and Name
for each VM in VMList

if VM.ElementName <> VM.Name then


select case VM.EnabledState

case 0
strVMState = "unknown"
case 2
strVMState = "running"
case 3
strVMState = "powered off"
case 32768
strVMState = "paused"
case 32770
strVMState = "starting"
case 32773
strVMState = "saving"
case 32774
strVMState = "stopping"
case 32776
strVMState = "pausing"
case 32777
strVMState = "resuming"
case else
strVMState = "don't know"
end select

''Check Length of Virtual System Name for Status Report Formatting
if Len(VM.ElementName) <= 6 then
strStatus = strStatus & VM.ElementName & vbtab & vbtab & vbtab & strVMState & VbCrLf
else
strStatus = strStatus & VM.ElementName & vbtab & vbtab & strVMState & VbCrLf
end if

end if

next

''Remove Extra Spaces and Lowercase Option Choice
strOption = Lcase(Trim(strOption))

''If Option is Start or Stop then Prompt for System Name
if strOption = "start" OR strOption = "stop" then

strStatus = strStatus & VbCrLf & VbCrLf & "Type in the Name of the VM to " & Ucase(strOption)


''Inputbox for VM System Name

strVMSystem = inputbox(strStatus, "Hyper-V VM Status")

''If User Clicks Cancel or Close Script Quits
if strVMSystem = vbEmpty then
msgbox "User Cancelled Script. Quitting Now" , vbExclamation + vbOkOnly , "Hyper-V VM Status"
wscript.quit
end if

''Remove Extra Spaces and Lowercase VM System Name
strVMSystem = Lcase(Trim(strVMSystem))

''Start Option Uses the RequestStateChange Method with 2 (Start Up)
if strOption = "start" then
set VMStartList = WMIService.ExecQuery("SELECT * FROM Msvm_ComputerSystem WHERE ElementName='" & strVMSystem & "'")
VMStartList.ItemIndex(0).RequestStateChange(2)

''Stop Option Uses InitiateShutdown Method Which is a Clean Shutdown
elseif strOption = "stop" then
set VMStopList = WMIService.ExecQuery("SELECT * FROM Msvm_ComputerSystem WHERE ElementName='" & strVMSystem & "'")
vmGUID = VMStopList.ItemIndex(0).Name
set VMShutdown = WMIService.ExecQuery("SELECT * FROM Msvm_ShutdownComponent WHERE SystemName='" & vmGUID & "'")
varResult = VMShutdown.ItemIndex(0).InitiateShutdown(True,"Shutdown")
end if

''Informs User of Command Status and on Error Quits Script
if Err.Number = 0 then
msgbox UCase(strOption) & " Command Successfully Sent" , vbOkOnly , "Hyper-V VM Status"
else
msgbox "Problem Sending Command for " & strVMSystem & ". Please Try Script Again" , vbExclamation + vbOkOnly , "Hyper-V VM Status"
wscript.quit
end if

''Status Option Reports Only Status of Systems
elseif strOption = "status" then
''Variable to Check If User Clicks Cancel or Closes Window
varStat = msgbox(strStatus, vbOKCancel , "Hyper-V VM Status")

''If Cancel or Close Quits Script

if varStat = vbCancel then
msgbox "User Cancelled Script. Quitting Now" , vbExclamation + vbOkOnly , "Hyper-V VM Status"
wscript.quit
end if

''Error Checking for Non Option Typed In
else
msgbox "You Didn't Type Start, Stop, or Status. Quitting Now" , vbExclamation + vbOkOnly , "Hyper-V VM Status"
wscript.quit
end if

loop

Tuesday, December 21, 2010

VBScript: IPv4 Network Cards MAC Addresses

Since both ipconfig -all and getmac commands didn't make it easy for users to tell us their network card(s) MAC address, my unit needed to come up with a quick script that would report all the IPv4 network cards and their MAC addresses on a Windows system. This way a user can easily download the script from a website and then run it and send us the reporting text file. The script will save the results file in the same directory as the script and doesn't require admin rights to get the information.


'********************************************************************************
'Script Name: Network_Cards.vbs
'Last Edited: 12/21/10
'Description: Reports via text file all IPv4 network cards
'********************************************************************************

const for_appending = 8

'Creates the text File in the Current Directory
set objFSO = CreateObject("Scripting.FileSystemObject")
set objFile = objFSO.OpenTextFile(".\Network_Cards.txt", for_appending, true)

'Query the local system for all IPv4 Network Cards with a MAC Address
set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
set colNetworkCards = objWMIService.ExecQuery _
("Select * from Win32_NetworkAdapterconfiguration Where MACAddress is Not Null")

for each netcard in colNetworkCards

objFile.WriteLine("Network Card: " & netcard.Description)
objFile.WriteLine("MAC Address: " & netCard.MACAddress)
objFile.WriteBlankLines(1)

next

objFile.Close

msgbox "Information was saved to the Network_Cards.txt file", vbOkOnly , "Network Cards"

Tuesday, September 28, 2010

PF Block Report (Perl Script) V2

I’ve been running PF Blocked Report script for well over a month on my firewalls and have made a few improvements. Version 1.0 of the script didn’t take into account legitimate blocked traffic (e.g. FIN ACK web server traffic). So I modified the tcpdump command to only look for TCP with only SYN flag set, ICMP, and UDP traffic. Additionally, I added general reporting for outbound hosts. The script is designed to be ran as a cron job, right before the log rotates. The size of your report will depend of what numbers you choose for the blocked limits. I’m using 100 as the inbound threshold to limit the size of my reports and taking into consideration even a quick NMAP scan will create well over a thousand entries it should catch port scans.

----------pfblocked.pl-------------------------------


#!/usr/bin/perl -w

# pfblocked.pl version 3.0
# last modified 09/28/10

use strict;

use File::Copy;
use Net::SMTP;
use Sys::Hostname;

my @log = ();
my @blockTemp = ();
my @obTemp = ();
my %blockedIPs;
my %obIPs;
my $pktLimit = 100;
my $obPktLimit = 50;
my ($year, $month, $day, $hour, $min) = (localtime)[5,4,3,2,1];
my $timestamp = sprintf ("%02d-%02d-%02d %02d:%02d", $month+1, $day, $year+1900, $hour, $min);
my $to = "userid\@mycompany.com";
#my $to2 = "deptaccount\@mycompany.com"; #additional recipient (if needed)
my $from = "pfblocked\@mycompany.com";
my $smtpserver = "smtp.mycompany.com";
my $hstname = hostname();
my $subject = "PF Block Report for $hstname";

#start of html report
my $message = "<p>PF Block Report for $hstname on $timestamp</p> \n" .
"Inbound Hosts<br /> \n" .
"<table border\=\"2\" width\=\"650\"><tr><td>Blocked IP</td><td align\=\"center\">Blocked In</td>" .
"<td align\=\"center\">Passed In</td><td align\=\"center\">Blocked Out</td><td align\=\"center\">Passed Out</td></tr> \n";

#copy over current pf log file
#run tcpdump on log file and create output file
#then load array with output file data

copy("/var/log/pflog","pflogfile");
system("tcpdump -neltttr pflogfile 'tcp[13] & 2 !=0' or icmp or udp > tcpdumpfile.txt");

open(TDF,"tcpdumpfile.txt");
@log = <TDF>;
close TDF;

#parse each entry with regex looking for IPv4 blocked traffic
#load those source IPs into arrays

foreach my $line(@log)
{

my ($action, $srcIP);

if ($line =~ /(\w+ \d+ \d+:.\d:.\d+)\.(\d+) rule (\d+)\/\(match\) (\w+ \w+) \w+ (\w+)\: (\d+\.\d+\.\d+\.\d+)(.*)/)
{
($action, $srcIP) = ($4, $6);

if ($action eq "block in")
{
push(@blockTemp,$srcIP);
}

if ($action eq "block out")
{
push(@obTemp,$srcIP);
}

}

}

#load hash to get unique blocked in IPs
#IP address is the hash key and 1 is value for all

%blockedIPs = map { $_ => 1 } @blockTemp;

#find how many blocked entries per blocked in IP
#add that to the value of the hash

foreach my $key (keys(%blockedIPs))
{

my $pkt = 0;
my $host = $key;

foreach my $tmpip(@blockTemp)
{
if ($host eq $tmpip)
{
$pkt++;
}
}

$blockedIPs{$key} = $pkt;
}

#look for blocked IPs that are over the bad entries limit
#then go back through logfile and check to see how many entries
#have those IPs as source with pass in or destination with pass out.
#then report formatting check based upon length of IP address

foreach my $key (sort (keys(%blockedIPs)))
{

my $blkIP = $key;
my $x = length ($blkIP);
my $pktNum = $blockedIPs{$key};
my $inCnt = 0;
my $outCnt = 0;
my $boCnt = 0;

if ($pktNum > $pktLimit)
{

foreach my $line(@log)
{

my ($action, $srcHost, $dstHost);

#regex for tcp and udp traffic

if ($line =~ /(\w+ \d+ \d+:.\d:.\d+)\.(\d+) rule (\d+)\/\(match\) (\w+ \w+) \w+ (\w+)\: (\d+\.\d+\.\d+\.\d+)\.(\d+) > (\d+\.\d+\.\d+\.\d+)\.(\d+)\:(.*)/)
{

($action, $srcHost, $dstHost) = ($4, $6, $8);

if ($blkIP eq $srcHost and $action eq "pass in")
{
$inCnt++;
}


if ($blkIP eq $dstHost and $action eq "pass out")
{
$outCnt++;
}

if ($blkIP eq $dstHost and $action eq "block out")
{
$boCnt++;
}


}

#regex for icmp

if ($line =~ /(\w+ \d+ \d+:.\d:.\d+)\.(\d+) rule (\d+)\/\(match\) (\w+ \w+) \w+ (\w+)\: (\d+\.\d+\.\d+\.\d+) > (\d+\.\d+\.\d+\.\d+)\:(.*)/)
{

($action, $srcHost, $dstHost) = ($4, $6, $7);

if ($blkIP eq $srcHost and $action eq "pass in")
{
$inCnt++;
}


if ($blkIP eq $dstHost and $action eq "pass out")
{
$outCnt++;

}

if ($blkIP eq $dstHost and $action eq "block out")
{
$boCnt++;
}

}


}


$message = $message . "<tr><td>$key</td><td align\=\"center\">$blockedIPs{$key}</td>" .
"<td align\=\"center\">$inCnt</td><td align\=\"center\">$boCnt</td>" .
"<td align\=\"center\">$outCnt</td></tr> \n";

}

}

$message = $message . "</table>";

#load hash to get unique blocked out IPs
#IP address is the hash key and 1 is value for all

%obIPs = map { $_ => 1 } @obTemp;

$message = $message . "<br /><br /> \n" .
"Outbound Hosts \n".
"<table border\=\"2\" width\=\"300\"><tr><td>Blocked IP</td><td align\=\"center\">Blocked Out</td></tr> \n";

#find how many entries per blocked out IP
#add that to the value of the hash
#if value is over outbound limit add to report data

foreach my $key (sort(keys(%obIPs)))
{

my $pkt = 0;
my $host = $key;

foreach my $tmpip(@obTemp)
{

if ($host eq $tmpip)
{
$pkt++;
}
}

$obIPs{$key} = $pkt;

if($pkt > $obPktLimit)
{
$message = $message . "<tr><td>$key</td><td align\=\"center\">$obIPs{$key}</td></tr> \n";
}
}

$message = $message . "</table> \n";

#open SMTP connection and mail information

my $smtp = Net::SMTP->new($smtpserver);
$smtp->mail( $from );
$smtp->to( $to ); # for single recipient
#$smtp->to( $to,$to2 ); # for two or more recipients
$smtp->data();
$smtp->datasend("MIME-Version: 1.0\n");
$smtp->datasend("Content-Type: text/html; charset=us-ascii\n");
$smtp->datasend("From: " . $from . "\n");
$smtp->datasend("To: " . $to . "\n");
$smtp->datasend("Subject: " . $subject . "\n");
$smtp->datasend("\n");
$smtp->datasend("\n");
$smtp->datasend( $message );
$smtp->datasend("\n");
$smtp->dataend();
$smtp->quit();

#delete tcpdump output and copied over pflog files
unlink("tcpdumpfile.txt");
unlink("pflogfile");












-------------------------------------------------------------------

Sunday, August 15, 2010

PF Block Report (Perl Script)

I wanted to come up with an easy solution to help me review the PF logs on my OpenBSD firewalls. A quick search came up with Hatchet; however, it required SQLite modules and I really wanted to write something myself. So I borrowed a few regexes from Hatchet and wrote my own little Perl script which reports on IPs with over a certain number of blocked entries in the PF log.

How the script works:

  1. Copies over the current pflog file to the working directory

  2. Runs tcpdump on the copied pflog file and creates a tcpdump text file

  3. Creates an array of the file and then goes through it looking for all blocked in traffic

  4. Creates a hash table of the unique blocked IPs and then determines how many blocked entries for each IP

  5. For those blocked IPs with over a certain number of blocked entries it goes back through the log array and finds how many passed in, blocked out, and passed out entries

  6. Reports that information via an HTML formatted email to an address of your choice

  7. Deletes the tcpdump output and copied over pflog files


This script is designed to be ran as a cron job, right before the log rotates.


----------pfblockreport.pl------------------------

#!/usr/bin/perl -w

use strict;

use File::Copy;
use Net::SMTP;
use Sys::Hostname;

my @blockTemp = ();
my @log = ();
my %blockedIPs;
my $pktLimit = 100;
my $crdt = localtime;
my $to = "dean\@company.com";
#additional recipient (if needed)
#my $to2 = "deptaccount\@company.com";
my $from = "pfblocked\@company.com";
my $hstname = hostname();
my $subject = "PF Block Report for $hstname";

#start of html report
my $message = "<p>PF Block Report for $hstname on $crdt</p> \n" .
"<table border\=\"2\" width\=\"650\"><tr><td>Blocked IP</td><td align\=\"center\">Blocked In</td>" .
"<td align\=\"center\">Passed In</td><td align\=\"center\">Blocked Out</td><td align\=\"center\">Passed Out</td></tr> \n";

#copy over current pf log file
#run tcpdump on output file
#then load array with data

copy("/var/log/pflog","pflogfile");
system("tcpdump -neltttr pflogfile > tcpdumpfile.txt");
open(TDF,"tcpdumpfile.txt");
@log = <TDF>;
close TDF;

#parse each entry with regex looking for IPv4 blocked in only
#load those source IPs into array

foreach my $line(@log)
{

my ($action, $srcIP);

if ($line =~ /(\w+ \d+ \d+:.\d:.\d+)\.(\d+) rule (\d+)\/\(match\) (\w+ \w+) \w+ (\w+)\: (\d+\.\d+\.\d+\.\d+)(.*)/)
{
($action, $srcIP) = ($4, $6);

if ($action eq "block in")
{
push(@blockTemp,$srcIP);
}
}

}

#load hash to get unique blocked IPs
#IP address is the hash key and 1 is value for all

%blockedIPs = map { $_ => 1 } @blockTemp;

#find how many blocked entries per blocked IP
#add that to the value of the hash

foreach my $key (keys(%blockedIPs))
{

my $pkt = 0;
my $host = $key;

foreach my $tmpip(@blockTemp)
{
if ($host eq $tmpip)
{
$pkt++;
}
}

$blockedIPs{$key} = $pkt;
}

#look for blocked IPs that are over the bad entries limit
#then go back through logfile and check to see how many entries
#have those IPs as source with pass in or destination with pass or out


foreach my $key (sort (keys(%blockedIPs)))
{

my $blkIP = $key;
my $x = length ($blkIP);
my $pktNum = $blockedIPs{$key};
my $inCnt = 0;
my $outCnt = 0;
my $boCnt = 0;

if ($pktNum > $pktLimit)
{

foreach my $line(@log)
{

my ($action, $srcHost, $dstHost);

if ($line =~ /(\w+ \d+ \d+:.\d:.\d+)\.(\d+) rule (\d+)\/\(match\) (\w+ \w+) \w+ (\w+)\: (\d+\.\d+\.\d+\.\d+)\.(\d+) > (\d+\.\d+\.\d+\.\d+)\.(\d+)\:(.*)/)
{

($action, $srcHost, $dstHost) = ($4, $6, $8);

if ($blkIP eq $srcHost and $action eq "pass in")
{
$inCnt++;
}


if ($blkIP eq $dstHost and $action eq "pass out")
{
$outCnt++;
}

if ($blkIP eq $dstHost and $action eq "block out")
{
$boCnt++;
}


}


if ($line =~ /(\w+ \d+ \d+:.\d:.\d+)\.(\d+) rule (\d+)\/\(match\) (\w+ \w+) \w+ (\w+)\: (\d+\.\d+\.\d+\.\d+) > (\d+\.\d+\.\d+\.\d+)\:(.*)/)
{

($action, $srcHost, $dstHost) = ($4, $6, $7);

if ($blkIP eq $srcHost and $action eq "pass in")
{
$inCnt++;
}


if ($blkIP eq $dstHost and $action eq "pass out")
{
$outCnt++;

}

if ($blkIP eq $dstHost and $action eq "block out")
{
$boCnt++;
}

}


}


$message = $message . "<tr><td>$key</td><td align\=\"center\">$blockedIPs{$key}</td>" .
"<td align\=\"center\">$inCnt</td><td align\=\"center\">$boCnt</td>" .
"<td align\=\"center\">$outCnt</td></tr> \n";

}

}

$message = $message . "</table>";

#open SMTP connection and mail information

my $smtp = Net::SMTP->new("smtp.company.com");
$smtp->mail( $from );
#for single recipient
$smtp->to( $to );
#for two or more recipients
#$smtp->to( $to,$to2 );
$smtp->data();
$smtp->datasend("MIME-Version: 1.0\n");
$smtp->datasend("Content-Type: text/html; charset=us-ascii\n");
$smtp->datasend("From: " . $from . "\n");
$smtp->datasend("To: " . $to . "\n");
$smtp->datasend("Subject: " . $subject . "\n");
$smtp->datasend("\n");
$smtp->datasend("\n");
$smtp->datasend( $message );
$smtp->datasend("\n");
$smtp->dataend();
$smtp->quit();

#delete tcpdump output and copied over pflog files
unlink("tcpdumpfile.txt");
unlink("pflogfile");

Tuesday, June 29, 2010

OpenBSD 4.7 PF Changes for Gateway Firewall

So yesterday evening I finally got around to updating one of my OpenBSD gateway firewalls to 4.7. On the gateway the PF rules only needed changes in the scrub and proxy sections. Below are the changes. Hopefully this will help you out if you haven’t already updated.

######4.6 pf.conf###############
# Normalize all incoming/outgoing traffic to prevent malformed packets
scrub in on $ext_if all random-id fragment reassemble no-df min-ttl 5
scrub out on $ext_if all random-id fragment reassemble no-df

# FTP-Proxy
nat-anchor "ftp-proxy/*"
rdr-anchor "ftp-proxy/*"
rdr on $int_if proto tcp from $mynet to any port 21 -> 127.0.0.1 port 8021

# Squid Redirect
rdr on $int_if inet proto tcp from <webproxyusers> to !<nonproxysites> port { 80 8080 }-> 127.0.0.1 port 3128

#######4.7 pf.conf##########

# Normalizing packets
match in on $ext_if scrub (random-id min-ttl 5 no-df)
match out on $ext_if scrub (random-id no-df)

# FTP-Proxy

anchor "ftp-proxy/*"
pass in quick on $int_if proto tcp from $mynet to any port 21 rdr-to 127.0.0.1 port 8021

# Squid Redirect
pass in quick on $int_if proto tcp from <webproxyusers> to !<nonproxysites> port { 80 8080 } rdr-to 127.0.0.1 port 3128



Export Man Page to Text File

Needed a quick way to exporting a man page to a text file. Below is the command for exporting the man page for pf.conf (need to research a few things before upgrading to OpenBSD 4.7)

$ man pf.conf | col -bx > pf.conf.txt

Monday, June 21, 2010

C# ARP Request

I started working on version 3 of my ARPCheck application yesterday. Forgot that I never got around to posting a code example.

==========ARPCheckDemo.cs============

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.NetworkInformation;
using System.Runtime.InteropServices;

namespace ArpCheckDemo
{
class Program
{
//Configure the SendARP from the iphlpapi.dll
//Currently .NET Doesn't have a Framework Method for Sending an ARP Request
[DllImport("iphlpapi.dll", ExactSpelling = true)]
public static extern int SendARP(int dstIP, int srcIP, [Out] byte[] macAddr, ref int hwAddrLength);

static void Main(string[] args)
{
//IP Address for Destination IP
IPAddress addr = IPAddress.Parse("192.168.2.1");
//Byte Array for MAC Address of Destination IP
byte[] mac = new byte[6];
//Variable for the Hardware Address Length (in Octets)
int hwLength = 6;
//Sending ARP Request for Destination IP Address and Getting Back MAC Byte Array
SendARP(BitConverter.ToInt32(addr.GetAddressBytes(),0), 0, mac, ref hwLength);
//Converting the Byte Array to Hexademical String
String macAddress = BitConverter.ToString(mac, 0, hwLength);
//Display MAC Address for Remote IP
Console.WriteLine(macAddress);
Console.ReadLine();
}
}
}

Friday, June 11, 2010

Exchange 2007 Database Defragmentation

Last week due to an issue with the anti-spam client on my exchange server, I had to defrag the default "Mailbox Database". Below are the steps I performed to accomplish the task.

In my environment the Exchange databases are located on the D: drive.

  1. Dismount the database in question via the Exchange Management Console

  2. Via the command line, move to directory C:\Program Files\Exchange Server\Bin

  3. Test the information Store of the server. (my server is named MailLady)

    isinteg.exe -s MailLady -test allfoldertests


  4. Type the number of the database and hit Enter. Confirm with Y and then Enter again

  5. If all tests pass then run an integrity check on the database

    eseutil.exe /g " D:\Exchange Databases\Mailbox Database.edb" /t "D:\Exchange Databases\Temp\temper.edb"


  6. If that passes then run a defrag of the database

    eseutil.exe /d " D:\Exchange Databases\Mailbox Database.edb" /t "D:\Exchange Databases\Temp\temper.edb"


  7. After that finishes then mount the database via the Exchange Management Console

By default the eseutil command creates a temporary database inside the Bin directory on the system drive. Since my Exchange Server didn't have that much free room on the system drive I had to use the /t switch to move the temp database to a drive with more room.

Thursday, May 13, 2010

C# Ping Status

One of the networks I manage needed a quick cheap solution for monitoring if a few servers were up. Came up with a C# Windows Service application that pings the servers every 15 minutes. If the ping fails for a system it will wait another 5 seconds and try it again. If both fail it will add it to a report that is emailed to the network admins. Below is the code for the test console app.


--------C# Test Console App Code-----------
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Mail;
using System.Data;


namespace PING
{
class Program
{
static void Main(string[] args)
{
//Int for Counting Failed Pings
int pingFail = 0;

//String Builder for Email Message
StringBuilder stbFail = new StringBuilder();

//Hashtable for Server Name and IP Addresses
Hashtable servers = new Hashtable();

//Server Name is Key and IP Address is Value
servers.Add("Server1", "192.168.xxx.xxx");
servers.Add("Server2", "192.168.xxx.xxx");
servers.Add("Server3", "192.168.xxx.xxx");
servers.Add("Server4", "192.168.xxx.xxx");
servers.Add("Server5", "192.168.xxx.xxx");
servers.Add("Server6", "192.168.xxx.xxx");
servers.Add("Firewall1", "192.168.xxx.xxx");
servers.Add("Firewall2", "192.168.xxx.xxx");
servers.Add("Transwall1", "192.168.xxx.xxx");


foreach (DictionaryEntry de in servers)
{
//Ping Server IP. If It Fails Ping Again Five Seconds Later
if (!PingCheck(de.Value.ToString()))
{
//Pausing for Five Seconds
System.Threading.Thread.Sleep(5000);

//Second Ping Check on Failed IP
if (!PingCheck(de.Value.ToString()))
{
//Increment Verified Fail and Add Server Info to Report
pingFail++;
stbFail.AppendLine(de.Key.ToString() + " at " + de.Value.ToString() + " is down");
}

}

}

//Email Failed Pings to Network Admin(s)
if (pingFail > 0)
{
//Create Mail Message and Send
MailAddress maFrom = new MailAddress("notifyingsystem@mydomain.edu");
MailAddress maTo = new MailAddress("guycomingintooffice@mydomain.edu");
MailMessage message = new MailMessage(maFrom, maTo);
message.Subject = "Failed Ping Report";
message.IsBodyHtml = false;
message.Body = stbFail.ToString();
SmtpClient mail = new SmtpClient();
mail.Host = "smtp.mydomain.edu";
mail.Send(message);
}
}

static bool PingCheck(string strAddr)
{
bool pingStatus = false;
Ping pingSender = new Ping();
PingOptions options = new PingOptions();
options.DontFragment = true;
string data = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
byte[] buffer = Encoding.ASCII.GetBytes(data);
int timeout = 120;
PingReply replyPing = pingSender.Send(strAddr, timeout, buffer, options);

if (replyPing.Status == IPStatus.Success)
{
pingStatus = true;
}

return pingStatus;
}

}
}

Monday, May 3, 2010

DHCP Reservations via PowerShell and Exported .CSV Leases File

Ran into an issue with having to transfer DHCP reservations from one stand alone Windows 2008 server to a Windows 2008 R2 server. When I tried the export and import netsh commands they failed. Not wanting to manually create the whole class C worth of reservations again I came up with this more efficient method.

Basically, here are the steps: log onto the old DHCP server and export the current leases to a .csv file. Copy that file over to the new DHCP server. Place the PowerShell script (code listed below) into the same directory as the .csv file. Then run the script and watch the happiness.


Found the idea for the Add-Content part via another site. PowerShell is such a interesting creature.


#-------------Code from dhcpRes.ps1-----------------------------------------------------------

# IP Address of the Current DHCP Server Running the Script
$server = "192.168.2.1"

# The Scope IP Address
$scope = "192.168.2.0"

# Netsh Commands File
$commands = "dhcp.txt"

# Exported .CSV File of DHCP Leases from Other DHCP Server
$leases = import-csv "dhcp.csv"

$leases | % {
add-content -path $commands -value "dhcp server $server scope $scope add reservedip $($_.'Client IP Address') $($_.'Unique ID') `"$($_.'Unique ID')`""
}

netsh exec $commands


#End of Code

Friday, February 12, 2010

Windows 2008 TS RemoteApp

Last month I pushed out a legacy application using Windows 2008 Terminal Services RemoteApp. I was very pleased with how easy it was and I won't go into setting up RemoteApp since there is more than enough documentation online for that; however, I will give a couple of points to consider.
  1. RemoteApp opens on the primary monitor and cannot be moved to another
  2. Disable the user screen saver on the terminal server. Otherwise, a user that leaves the RemoteApp up but idle will lock out their session on the server and they will need to restart the RemoteApp.
  3. Since closing the RemoteApp won't log the user off the terminal server, limit the user's sessions on the server. This can be done either through a group policy or RemoteApp settings on the server.
Numbers 2 and 3 can be done easily via group policy. Here are the settings I applied to the terminal server.

Computer Configuration / Policies / Administrative Templates / System / Group Policy
User Group Policy loopback processing mode = Enabled (Mode - Merge)

Computer Configuration / Policies / Administrative Templates / Windows Components / Terminal Services / Terminal Server / Session Time Limits
Set time limit for active but idle Terminal Services sessions = Enabled (Idle session limit - 16 hours)
Set time limit for active Terminal Services sessions = Enabled (Active Session limit - 16 hours)
Set time limit for disconnected sessions = Enabled (End a disconnected session - 1 hour)
Set time limit for logoff of RemoteApp sessions = Enabled (RemoteApp session logoff delay - 30 minutes)
Terminate session when time limits are reached = Enabled

User Configuration / Policies / Administrative Templates / Control Panel / Display
Screen Saver = Disabled

Wednesday, January 27, 2010

Fun C# ASP.NET Page for Lotto Numbers

To lighten the mood in my office, I came up with fun C# ASP.NET page to randomly display lotto numbers. It's configured for the Cali lotto format but you can easily modify it for whatever state your in. Enjoy.

using System;
using System.Web;
using System.Text;

public partial class numbers : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{

}

protected void GetLottoNumbers(object sender, EventArgs e)
{
ArrayList arlNum = new ArrayList();
Random RandomClass = new Random();

while (arlNum.Count < 5)
{
int g = RandomClass.Next(1, 56);
if (!arlNum.Contains(g))
{
arlNum.Add(g);
}
}

arlNum.Sort();

pnlNum.Visible = true;
lblN1.Text = arlNum[0].ToString();
lblN2.Text = arlNum[1].ToString();
lblN3.Text = arlNum[2].ToString();
lblN4.Text = arlNum[3].ToString();
lblN5.Text = arlNum[4].ToString();
lblN6.Text = RandomClass.Next(1, 46).ToString();
btnNumbers.Text = "Get Another Set";
}


}


-----------------------Portion of numbers.aspx------------------------------

<h2>IT Retirement Numbers</h2>
<hr />
<p><strong>Would you like to see some IT retirement numbers?</strong></p>

<asp:Button ID="btnNumbers" runat="server" Text="Get Numbers" OnClick="GetLottoNumbers" />

<asp:Panel ID="pnlNum" runat="server" Visible="false">

<br />
Here you go...

<asp:Label ID="lblN1" runat="server" Width="20" />

<asp:Label ID="lblN2" runat="server" Width="20" />

<asp:Label ID="lblN3" runat="server" Width="20" />

<asp:Label ID="lblN4" runat="server" Width="20" />

<asp:Label ID="lblN5" runat="server" Width="20" />

and mega number
<asp:Label ID="lblN6" runat="server" Width="20" />
</asp:Panel>

Friday, January 22, 2010

OpenBSD Transparent Firewall for Server Room Switch

Below is the rule set for an OpenBSD transparent firewall to protect servers on the same switch from unauthorized hosts on the local network. This ruleset assumes that there is a network firewall in place and only filters on MAC addresses of the local network clients and devices.

The firewall is setup with three network interfaces and sits between the server room network access port and the switch for the server room. The third interface is needed for remote ssh access and is plugged into a regular port on the switch.

Here is a link to my old post on MAC filtering using a Bridge and Packet Tagging



#############################################################
# Macros and Tables
#############################################################

# Interfaces
switch_if = "bge0"
nap_if = "bge1"
ssh_if = "em0"

############################################################
# Logging, Timeouts, Limits, Interface skips, Scrubs
############################################################

# Set logging interface
set loginterface $nap_if

# Revised - Adaptive Set higher state limits
set timeout { adaptive.start 10000, adaptive.end 110000 }
set limit states 100000
set timeout interval 10

# Normalize all incoming/outgoing traffic to prevent malformed packets
match in all scrub (no-df)

# Don't filter on loopback interface or ssh_if
set skip on lo0
set skip on em0

###########################################################
# Rules
###########################################################

# Block Traffic from Unauthorized Hosts into Servers
block in log on $nap_if all label "block in"

# Allow All Traffic on Switch Interface
pass in quick on $switch_if all
pass out quick on $switch_if all

# Allow All Traffic From Servers Behind Switch to Rest of Network
pass out quick on $nap_if all

# Allow Traffic from Known Good Mac Addresses into Servers
pass in quick on $nap_if all tagged goodmac

# Allowing Broadcast UDP into Servers
pass in quick on $nap_if proto udp to any port { 67 68 137 138 1900 3702 }

Tuesday, January 12, 2010

Manually Rotating OpenBSD PF Logs

While installing a new OpenBSD transparent bridge, the need came up to view with Wireshark a relatively new pf log file. Thanks to some colleagues at work I was able to accomplish this task by two quick commands.

$ su root

# newsyslog /var/log/pflog

Another way to do this is a simple tcpdump command.

$ sudo tcpdump -nettti pflog0 -w pfdumpfile