Tag Archives: Useful

Perl IP Address Range Merger

If like me you maintain a number of IP address blacklists for various purposes (websites, firewalls, etc) then you probably find yourself thinking, from time to time, I wonder how many of these ranges overlap and could be merged down to clean these lists up a bit. I was hoping that there would be a nice, easy way to do this with Powershell but it doesn’t seem like there is.

Turns out there are some nice Perl libraries to help with this process in the form of Net::CIDR and its children. While my Perl is pretty dreadful, the following script will nonetheless take a collection of xxx.xxx.xxx.xxx-xxx.xxx.xxx.xxx style IP ranges, merge them down and output them to a file in the same format. You can also easily modify it to convert to/from CIDR-formatted address ranges, single addresses or any combination of the three; the full documentation for the Net::CIDR::Lite module is available on CPAN.

Obviously it requires Net::CIDR::Lite to be present on your system.

#!/usr/bin/perl -w
 
use Net::CIDR::Lite;
 
open(MYFILE, '>>data.txt');
 
my $cidr = Net::CIDR::Lite->new();
 
while (<DATA>) {
	chomp;
	$cidr->add_range($_);
}
 
for $r ( $cidr->list_range() ) {
	print MYFILE "$r\n";
}
 
close (MYFILE);
 
__DATA__
1.0.1.0 - 1.0.3.255
1.0.1.0 - 1.0.2.255
1.0.2.0 - 1.0.3.255

Disable NTFS Permissions Inheritance

The following is the Powershell equivalent of unticking the box below for the folder “C:\temp”:

NTFS Permissions Inheritance

$acl = get-acl "C:\temp"
$acl.SetAccessRuleProtection($true,$true)
$acl | set-acl

Note that SetAccessRuleProtection takes two boolean arguments; the first turns inheritance on ($False) or off ($True) and the second determines whether the previously inherited permissions are retained ($True) or removed ($False).

Test RDP Connectivity with Powershell

Very simply returns True or False for a given list of hostnames or IP addresses depending on whether or not it can connect to TCP/3389 – a successful connection does not mean that you will be able to login, of course. If you’re running RDP on a non-standard port, you’ll need to adjust the script appropriately.

param(
     [parameter(Mandatory=$true,ValueFromPipeline=$true)][string[]]$computername
     )
 
$results = @()
 
foreach($name in $computername){
 
        $result = "" | select Name,RDP
        $result.name = $name
 
        try{
           $socket = New-Object Net.Sockets.TcpClient($name, 3389)
           if($socket -eq $null){
                 $result.RDP = $false
           }else{
                 $result.RDP = $true
                 $socket.close()
           }
        }
        catch{
                 $result.RDP = $false
        }
        $results += $result
}
 
return $results

Powershell One-Liners

These two are useful if you’re writing scripts which require certain modules (such as ActiveDirectory) or snapins (such as SQL, Exchange or VMware) to be present on the local system and you want to check for them before executing the bulk of the script.

Check if a given Module (In this instance “ActiveDirectory”) is present on a system:

if($(Get-Module -ListAvailable) -match "ActiveDirectory"){"Module Present"}else{"Module Not Present"}

Check if a given Snapin (In this instance “VMware.VimAutomation.Core”) is present on a system:

if($(Get-PSSnapin -Registered) -match "VMware.VimAutomation.Core"){"Snapin Present"}else{"Snapin Not Present"}

Some of the most common snapins are:

  • VMware PowerCLI: VMware.VimAutomation.Core
  • Exchange 2007: Microsoft.Exchange.Management.Powershell.Admin
  • Exchange 2010: Microsoft.Exchange.Management.Powershell.E2010
  • SQL: SqlServerCmdletSnapin100 & SqlServerProviderSnapin100

Changing Printer Drivers En Masse

If you need to change the drivers for a large number of printers, such as on a print server, then you can use the following Powershell to do it. Set $driver to the name of the driver you wish to set and $pattern to match for the printers you wish to affect (so you don’t change the driver on printers you don’t want to).

Note: This script will run pretty quickly, but depending on the number of printers it may take upwards of 10 minutes for Windows to do all the background processing associated with the driver changes. Keep an eye out for a bunch of rundll32.exe processes which will spawn; once they close themselves down the changes should be complete.

$driver = "HP Universal Printing PCL 6 (v5.4)"
$pattern = "HP"
 
$printers = gwmi win32_printer
 
foreach($printer in $printers){
        $name = $printer.name
        if($name -match $pattern){
                & rundll32 printui.dll PrintUIEntry /Xs /n $name DriverName $driver
        }
}

Failover Cluster Fails To Fail Over

If you have a 2008/R2 failover cluster then it’s possible you may come across the following errors at some point after an unplanned failover:

Unable to obtain the primary cluster name identity token

An attempt has been made to operate on an impersonation token by a thread that is not currently impersonating a client

As a result, your clustered resources may refuse to start.

Now, assuming that you haven’t done something stupid, like deleting the cluster computer account from AD, you should be able to resolve this problem by right-clicking on the failed CNO on the Summary page of the Failover Cluster Manager, go to “More Options” and then “Repair Active Directory Object”. You should then be able to start all the cluster resources successfully. Thanks to wonhchoi.com for pointing me in the right direction.

As to what might have caused this problem in the first place? Well that’s still something of a mystery to me at the moment…

Am I an Administrator?

Powershell. Returns True or False. Simple.

(New-Object System.Security.Principal.WindowsPrincipal([System.Security.Principal.WindowsIdentity]::GetCurrent())).IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)

Tunneling CIFS over SSH in Windows 7

SSH is great; SSH port forwarding is really great, but forwarding CIFS over SSH in Windows is a huge pain in the arse, especially in Vista/Windows 7. Thankfully I came across this handy guide, which walks you through the process: http://www.nikhef.nl/~janjust/CifsOverSSH/VistaLoopback.html

To summarise (in case the page ceases to exist):

  1. Run hdwwiz.exe and add a Microsoft Loopback Adaptor
  2. Edit the properties of the new adaptor and disable all protocols except IPv4
  3. Edit the properties of the IPv4 protocol and set the IP address to a private range that won’t conflict with any ranges you’re working with, such as 10.255.255.1
  4. Set the Interface Metric to 9999
  5. Disable NetBIOS over TCP/IP
  6. Run sc config smb start= demand to disable autostart of the SMB service
  7. Run netsh interface portproxy add v4tov4 listenaddress=10.255.255.1 listenport=445 connectaddress=10.255.255.1 connectport=44445 to create a portproxy rule that redirects traffic to port 445.
  8. Create a scheduled task to run net start smb when any user logs in
  9. Reboot
  10. Set up a Local tunnelling rule in your SSH client with a source of 10.255.255.1:44445 and a destination of <hostname>:445 (where is the hostname of the remote machine you’re working with)

You should now be able to connect to SMB shares using \\10.255.255.1\<sharename> (see below for a note about name resolution).

As an addendum, I found that I had to use a local account to run the Scheduled Task (SYSTEM in this instance) because my I’m using my laptop from remote sites without access to my domain, so if I try and use a domain account it can’t authenticate against a DC when it tries to run.

If you want to access more than one machine on the remote network (and the required SSH server config is in place to allow port forwarding to those machines), then you can simply add another IP address to the Loopback interface and create a new portproxy rule for it using a different port (such as 44446), then add a new port forwarding rule for it in your SSH client.

Also, if you want name resolution to work, there’s a handy hack you might be able to make use of (which will explain the existence of my previous post about the Windows name resolution process). You can add the hostnames and pseudo-IP addresses to your lmhosts file, which should permit you to resolve those hosts while tunnelling, without breaking your resolution when connecting to them locally (Because windows will try DNS/NetBIOS broadcast before looking at the lmhosts file). If you do this, you will be asked to authenticate the first time you connect to each machine due to the name/address mismatch.

To undo the changes:

  1. Run sc config smb start= auto to set the smb service to start automatically again
  2. Run netsh interface portproxy delete v4tov4 listenaddress=10.255.255.1 listenport=445 to remove the portproxy rule (change as needed to remove any additional ones)
  3. Open Device Manager and delete the Loopback Interface
  4. Open Scheduled Tasks and delete the SMB Startup task

The 7 Stages of Windows Name Resolution

You’d be surprised how many people don’t know this and how rarely that matters (OK, probably not that surprised). This is the process Windows uses to resolve names to IP addresses, it can be useful when troubleshooting name resolution issues or in the few edge cases where you need the same hostname to resolve to different addresses depending on where you are:

  1. Windows checks whether the host name is the same as the local host name.
  2. DNS cache (This includes the Hosts file)
  3. DNS servers (If configured)
  4. NetBIOS cache
  5. WINS servers (If configured)
  6. NetBIOS broadcast (If enabled)
  7. Lmhosts file (If present)

Note: If the host name is 16 characters or longer or an FQDN, Windows does not try to resolve the host name using NetBIOS/WINS/LmHosts.

Decode UserAccountControl Values With Powershell

One of the most annoying things when working with Powershell and AD accounts is the UserAccountControl value. This value is what determines settings such as whether or not the account is locked out, disabled, requires a smartcard for authentication, uses reversible encryption for its password, etc. The default is 512 (NORMAL_ACCOUNT) but there are all kinds of weird and wonderful combinations that can turn up depending on how the account is configured and when you’re trying to (for example) find all the accounts that are set to USE_DES_KEY_ONLY then having so many different possible values (any number that could have 2097152 as part of its makeup) makes it a pain to work out.

Thankfully, someone has solved this problem in a relatively simple manner; I first came across it here: http://bsonposh.com/archives/288 and it is listed in all its glory below. It takes a single argument, which is the UAC value for an account and will return a list of all the flags that apply to that value. So, for example, plugging in a value of 66048 will give an output of:
NORMAL_ACCOUNT
DONT_EXPIRE_PASSWORD
.

param
([int]$value)
$flags = @("","ACCOUNTDISABLE","", "HOMEDIR_REQUIRED",
"LOCKOUT", "PASSWD_NOTREQD","PASSWD_CANT_CHANGE", "ENCRYPTED_TEXT_PWD_ALLOWED",
"TEMP_DUPLICATE_ACCOUNT", "NORMAL_ACCOUNT", "","INTERDOMAIN_TRUST_ACCOUNT", "WORKSTATION_TRUST_ACCOUNT",
"SERVER_TRUST_ACCOUNT", "", "", "DONT_EXPIRE_PASSWORD", "MNS_LOGON_ACCOUNT", "SMARTCARD_REQUIRED",
"TRUSTED_FOR_DELEGATION", "NOT_DELEGATED","USE_DES_KEY_ONLY", "DONT_REQ_PREAUTH",
"PASSWORD_EXPIRED", "TRUSTED_TO_AUTH_FOR_DELEGATION")
1..($flags.length) | ? {$value -band [math]::Pow(2,$_)} | % { $flags[$_] }