VeeamZip Hyper-V Backup

Veeam Backup & Replication drops down into VeeamZip mode if you don’t have a licence key. But it’ll still provide some handy functionality – I’m using it to take a basic backup of all the VMs on a Hyper-V host at a remote site, just in case the (rather crusty old) hardware dies.

There’s no scheduling in the free Veeam backup product, but you can write a PowerShell script and use Windows Task Scheduler to run it, which is what I’ve done. I’m backing up all powered on VMs on a particular host to a UNC path on a physical server.

Add-PSSnapin VeeamPSSnapin
$VMs = Find-VBRHvEntity -Name * -Server HVHost01
$VMs.Count
foreach($VM in $VMs){
    if($VM.PowerState -eq "PoweredOn"){
        Write-Host ("Backing up "+$VM.Name+"...") -ForegroundColor Gray -NoNewline
        try{
            $Result = Start-VBRZip -Entity $VM -Folder "\\FileServer\Veeam\Backups" -Compression 5 -AutoDelete In1Week
            if($Result.Result -ne "Failed"){
                Write-Host "Done" -ForegroundColor Green
                # You could use Send-MailMessage here to get email notification of a successful backup
            }
            else{
                Write-Host "Failed" -ForegroundColor Red
            }
        }
        catch{
            Write-Host "Error" -ForegroundColor Red
            $Error[0]
        }
    }
}

I created a domain admin account in Active Directory to use as a service account for Veeam, and used this to run the scheduled task too. The task needs to be “Run with highest privileges”.

If you get the error:

06/07/2016 10:13:10 :: Error: Access is denied.
--tr:Error code: 0x00000005
Cannot create folder. Folder path: [\\FileServer\Veeam\Backups].
--tr:FC: Failed to create directory. Directory path: [\\FileServer\Veeam\Backups].
--tr:Failed to call DoRpc. CmdName: [FcCreateDir].
Access is denied.
Cannot create folder. Folder path: [\\FileServer\Veeam\Backups].

It’s probably because the Veeam B&R server authenticates to the UNC path using its local system account, so you need to grant that computer account access to the share and NTFS permissions on the server holding the shared folder, e.g. VBRServer$

Posted in PowerShell, veeam | Tagged , , , , , , , | Leave a comment

SMTP email diagnostics and info – troubleshoot email not received

Every now and then somebody will contact you via a method that they wouldn’t normally use and say something like “did you get the email I sent to you a few days ago”. If the answer to this is “no, I did not receive your email” then the following might be useful.

SMTP (Simple Mail Transport Protocol) servers, classically, should never blackhole email. To blackhole an email message, years ago, was a bad thing and meant that your mail server, or the recipient’s mail server was probably malfunctioning. A receiving SMTP server should either accept and deliver an email, or return a message to the sending server explaining why it was unable to deliver the email. Likewise, a sending SMTP server should either successfully transmit an email to a destination mail server, or deliver an NDR (non-delivery report) back to the user who tried to send the email.

Of course that was before spam became a problem. Now it is standard practice to silently drop emails in certain circumstances. However this does occasionally lead to the problems described at the start of this article. Spam is simply such a huge volume of email now that it would take significant extra server resource to deal with it according to the original “proper” SMTP methodology. You also don’t necessarily want a spammer’s mail server to know if an address they’ve tried to send to is legitimate or not – if they know it exists, or just that a particular internet server is an SMTP server, they’ll likely just send more junk to it.

Diagnosis and troubleshooting

So how to diagnose the “never received” email problem?

Firstly, ask the sender if they received an NDR. If they did, their mail system will usually have provided a log of the conversation when it was trying to talk to your mail system, and this will often be quite helpful.

If they never received an NDR, check your mail system logs to see if you can see any trace of their mail system trying to connect to your mail system. Many companies route all their email though a third party spam/malware filter (e.g. Symantec Email Security.cloud, Microsoft Exchange Online Protection), so this is a good place to start – if you can’t see any emails being received from your sender’s email address there then you can rule out any problems with your internal mail servers.

You can also use online tools such a the Microsoft Remote Connectivity Analyser or MX Toolbox to check that your mail servers (or a third party’s) are configured correctly. From a command prompt (on Windows) you can also get your MX records:

nslookup -type=mx rcmtech.co.uk 8.8.8.8

where 8.8.8.8 is a Google public DNS server, you can change this to use any DNS server you like.

Has the sender been blacklisted?

If a sender’s domain sends spam, or too much spam, it might be blacklisted. You can check this by using MX Toolbox and/or talking to your third party spam filter vendor. If a domain is blacklisted, spam filtering systems will frequently silently drop all (or most) mail send out from it.

Not all failures are bad

When using these tools, it helps to know a bit about how MX record preference values work, and tricks that mail filtering companies use to try and cut down on the amount of spam they have to process. Your MX (mail exchanger) DNS record will usually have more than one entry, because you’ll (ideally) have a primary mail server (or cluster of servers) and one or more lower priority servers in case your primary server is unavailable.

A sending SMTP server will use the lowest preference number server first. It will only use a server with a higher preference number if all lower preference number servers are unavailable or reject the message/communication attempt.

In the case of MessageLabs, the server addresses are actually server clusters. Also, the clusterna names are all spam traps, and will never accept any email. This is because spammers apparently often deliberately send to higher preference number servers because historically they might have no or less spam filtering applied to them, and they would normally only be used on the rare occasions when the primary server (lowest/lower preference number) was unavailable. No correctly configured/normally functioning sending mail server would ever pick one of the “a” servers. This is important to know because some SMTP testing tools will test all servers in the MX records for a domain, and so now we know that in the case of messagelabs.com servers, we can expect a failure from the clusterna server, but not from the clustern one!

Posted in Exchange | Tagged , , , , , , , , , , , , , , | Leave a comment

PowerShell: Change Hyper-V VM VLAN after Live Migration

One of my old Hyper-V hosts has its virtual switch uplink NICs connected to access ports rather than trunk ports. My other hosts all have trunked uplinks, which means that the VMs need to have a VLAN ID specified to connect them onto the correct VLAN.

I’m gradually moving VMs off the old host, but want to minimise downtime and down’t want to do it out of hours. The problem is that as soon as the VM has finished its Live Migration onto the new host, it stops being able to talk to the network, due to the VLAN ID not being set.

So I wrote this script to monitor the new host for the presence of the VM that’s being migrated, and as soon as it sees it, to set the VLAN ID to the correct value.

$HVHost = "RCMHV01"
$VMName = "OldVM01"
$SwitchName = "LAN Switch"
$VlanID = 250

$Finished = $false

Write-Host "Waiting for $VMName to move onto $HVHost"
while($Finished -ne $true){
    $VMs = Get-VM -ComputerName $HVHost
    if($VMs.Name -contains $VMName){
        Write-Host "Migrated, waiting for Status to be OK"
        while((Get-VM -ComputerName $HVHost -Name $VMName).PrimaryOperationalStatus -ne "Ok"){
            Start-Sleep -Seconds 1
        }
        $VM = Get-VM -ComputerName $HVHost -Name $VMName
        $VMNICs = Get-VMNetworkAdapter -VM $VM
        foreach($VMNIC in $VMNICs){
            if($VMNIC.SwitchName -eq $SwitchName){
                Write-Host "Configure VMNIC"
                Set-VMNetworkAdapterVlan -VMNetworkAdapter $VMNIC -VlanId $VlanID -Access
                $Finished = $true
            }
        }

    }
}
Posted in Hyper-V, PowerShell | Tagged , , , , , , | Leave a comment

Send notification email from SCCM 2012 Task Sequence

I wanted to be able to send an email from a step in a SCCM 2012 OS Deployment (OSD) task sequence. This was so that I could be notified when the task sequence had completed successfully.

The account used to send the email needed to be a specific account, as otherwise Exchange would reject the message. I’d already created a sccm.notifications@rcmtech.co.uk account in Active Directory and a mailbox for it in Exchange.

I thought I’d just use a Run Command Line step, and run PowerShell.exe specifying a very basic script file on the command line containing a Send-MailMessage cmdlet. That fails to run with an error though, and the Run PowerShell Script step doesn’t have a “Run this step as the following account” option.

So I reverted to “good old” VBScript. This is a script that sends an email using CDO.Message:

Const cdoNTLM = 2 'NTLM
Set oMessage = CreateObject("CDO.Message") 
Dim sComputerName, sOSDComputerName, sSubject, sTextBody
Dim oShell
Set oShell = CreateObject("WScript.Shell")
sSubject = "Build Complete %COMPUTERNAME%"
sSubject = oShell.ExpandEnvironmentStrings(sSubject)
oMessage.Subject = sSubject
sTextBody = "Build Complete "&Now
oMessage.TextBody = sTextBody
oMessage.From = "sccm.notifications@rcmtech.co.uk"
oMessage.To = "robin@rcmtech.co.uk"
oMessage.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
oMessage.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "mail.rcmtech.co.uk"
oMessage.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
oMessage.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate") = cdoNTLM
oMessage.Configuration.Fields.Update
oMessage.Send

Save that into a file called EmailBuildComplete.vbs.

I then put this script file into an SCCM Package, and distributed it to my distribution points. At the end of the OSD task sequence, I then added a Run Command Line step called Send Email Notification, containing the following command line:

cscript.exe //nologo EmailBuildComplete.vbs

and set the step to run as my sccm.notifications account.

Posted in sccm, Scripting, Windows | Tagged , , , , , , , , , | Leave a comment

SCCM 2012 PXE-E55: ProxyDHCP service did not reply to request on port 4011

Had this today, didn’t have any of #60, #66 or #67 DHCP options set that might have been conflicting (per Microsoft guidelines).

I was able to build Hyper-V VMs at the site where the problem distribution point was, but PCs weren’t building, giving the error:

PXE-E55: ProxyDHCP service did not reply to request on port 4011

I then checked the SMSPXE.log file which is found on the distribution point on the path D:\SMS_DP$\sms\logs (drive letter might be different, hopefully you’re not using the C drive…)

I saw warnings and messages similar to:

Warning: Matching Processor Architecture Boot Image (0) not found
F8:CA:B8:22:A6:53, 4C4C4544-0051-3610-8030-B3C04F443732: Not serviced.

I checked the two boot images in the SCCM console under Software Library – Overview – Operating Systems – Boot Images. The Boot Image (x64) was distributed to all my DPs, but Boot Image (x86) was missing from the one at the site with the PXE problems.

I distributed the x86 boot image to the distribution point it was missing from, and once that had completed I saw it being picked up in smspxe.log:

Found new image RCM000BF
Opening image file D:\RemoteInstall\SMSImages\RCM000BF\boot.RCM000BF.wim
Found Image file: D:\RemoteInstall\SMSImages\RCM000BF\boot.RCM000BF.wim
PackageID: RCM000BF
ProductName: Microsoft® Windows® Operating System
Architecture: 0
Description: Microsoft Windows PE (x86)
Version:
Creator:
SystemDir: WINDOWS
Closing image file D:\RemoteInstall\SMSImages\RCM000BF\boot.RCM000BF.wim

PXE boot of the failing clients is now working.

Posted in sccm | Tagged , , , , , , , , , , , , , , , | Leave a comment

Standard user launching a command with elevated credentials

I needed standard users to be able to run certain executables with administrator credentials, but ideally without wanting to give them an administrator account and password, and certainly without adding them to the Administrators group. I also needed a log of the commands run with elevated credentials, which is what led me to this method.

I’m using the Application event log and the Task Scheduler. The problem with this method is that when Task Scheduler launches a process as a different user to that currently logged on on the console, the launched process cannot interact with the desktop. Sadly there’s no way around this that I’m away of, which is a shame.

This method might still be useful though if the users just need to run command line utilities and can redirect the output to a text or log file.

Step One – Create a new event source

This allows us to filter out events easily later, and makes the logged commands easy to find. From an Administrator PowerShell prompt issue the following command:

New-EventLog -LogName Application -Source "RunElevated"

Step Two – Create a scheduled task

Open Task Scheduler, create a basic task called RunElevated.
The trigger is When a specific event is logged.
The log is Application, the source is RunElevated, the Event ID is 1.
The action is Start a program.
For Program/script we’re using the full path to powershell.exe: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
The argument is a PowerShell one liner to pick the event Message data out of the most recent RunElevated event to be logged to the Application event log, and execute the data:

&(Get-WinEvent -FilterHashtable @{logname='application'; providername='RunElevated'} -MaxEvents 1).Message

Finally, edit the new scheduled task and choose the administrator account that you want the task to run as, select Run whether user is logged on or not and Run with highest privileges. When you click OK you’ll be prompted for the account’s password.

Step three

Now, as a regular user, we’re going to write a command line to the Application event log using PowerShell:

Write-EventLog -LogName Application -Source "RunElevated" -EntryType Information -EventId 1 -Message "C:\windows\system32\notepad.exe"

This gives us an event that looks like this:

Log Name:      Application
Source:        RunElevated
Date:          31/05/2016 14:29:55
Event ID:      1
Task Category: (1)
Level:         Information
Keywords:      Classic
User:          N/A
Computer:      Laptop001.rcmtech.co.uk
Description:
C:\windows\system32\notepad.exe

The task should trigger and you’ll see notepad running (hidden) as the admin user you specified when creating the scheduled task. Note terribly handy, but somebody might have a use for this method!

Posted in PowerShell, Windows | Tagged , , , , , , , , , , , , , , , , , | Leave a comment

PowerShell: Active Directory User to SID and SID to User

I was recently asked to find the username associated with a particular Active Directory SID (technically I was given the RID).

This is actually pretty easy in PowerShell, and quite intuitive using basic AD cmdlets.

Get the user for a given RID:

Get-ADUser -Filter * | Select-Object -Property SID,Name | Where-Object -Property SID -like "*-6640"

Get the SID for a given user:

Get-ADUser -Identity ad.user | Select-Object -Property Name,SID
Posted in PowerShell, Windows | Tagged , , , , , , , | 1 Comment

PowerShell Script to download latest SysInternals tools

The SysInternals tools are pretty much a must-have for any IT Pro, but they get updated randomly and I always like to have the latest versions. You can run them from the live site, but I like to have them stored within my network as not everything has internet access.

This script will copy all the tools to the specified folder. Run it as a scheduled task.

$DestinationFolder = "C:\sysint"

Write-Host "Connecting"
New-PSDrive -Name SysInt -PSProvider FileSystem -Root \\live.sysinternals.com\Tools
$Files = Get-ChildItem -Path SysInt:\ -Recurse

Write-Host "Copying"
$Copied = 0
foreach($File in $Files){
    Write-Progress -Activity "Update SysInt" -Status $File.Name -PercentComplete ($Copied / $Files.Count * 100)
    Copy-Item -Path $File.FullName -Destination $DestinationFolder -Force
    $Copied++
}
Write-Progress -Activity "Update SysInt" -Completed

Write-Host "Tidying up"
Remove-PSDrive -Name SysInt -PSProvider FileSystem

Enjoy!

Note that if you want to run this on Windows Server you need to enable Desktop Experience and then start the WebClient service, this is to enable the Windows WebDAV client functionality. If you don’t want to set the service to autostart you could modify the script to start the service at the beginning and stop it at the end.

Posted in PowerShell, Windows | Tagged , , , , , , , , | Leave a comment

AppLocker Executable policy breaks Windows 10 Jump Lists

Jump lists, very handy. You’ve pinned a piece of software to the taskbar, and then you can right-click the icon and get a list of pinned and/or recently used files or connections.

I recently enabled AppLocker executable policy and applied it to my Windows 10 (2015 LTSB) PC. I just enabled the default rules, so everyone is allowed to run stuff from Program Files and Windows folders, and administrators can run anything.

Once that had kicked in, as an unwanted side effect, I noticed that the jump lists had stopped working. On looking in the AppLocker event log I saw the following entry:

Log Name: Microsoft-Windows-AppLocker/Packaged app-Execution
Source: Microsoft-Windows-AppLocker
Date: 22/03/2016 11:40:41
Event ID: 8027
Task Category: None
Level: Error
Keywords:
User: RCMTECH\Robin
Computer: PC01.rcmtech.co.uk
Description:
No packaged apps can be executed while Exe rules are being enforced and no Packaged app rules have been configured.

There was one of these logged every time I right-clicked on a pinned app on the taskbar.

So rather like the event description hints at, I created a default AppLocker rule under Packaged app Rules: Allow Everyone to run all signed packaged apps, and once that had applied to my PC, jump lists are working again.

What’s interesting is that I have not enabled Packaged app Rules: they’re not being enforced, the “Configured” box is not ticked (whereas it is for Executable rules).

Posted in Security, Windows | Tagged , , , , , , , , , , , , , , , | Leave a comment

Send SMTP email with authentication from PowerShell

Email is a good way to send notifications from your PowerShell scripts, and it’s super easy. You just need an SMTP server, and use Send-MailMessage:

Send-MailMessage -From "testscript@rcmtech.co.uk" -To "robin@rcmtech.co.uk" -Subject "Something interesting just happened" -Body "Here's the details about the interesting thing" -SmtpServer smtp.rcmtech.co.uk

You can even omit the -SmtpServer bit if you’ve previously set the $PSEmailServer preference variable.

However, what if you don’t have your own internal mailserver, and the only one available needs credentials? Many ISPs require authenticated SMTP now. Sure, Send-MailMessage has a -Credentials options, but these need to be in the form of a System.Management.Automation.PSCredential object. You can use Get-Credential to generate one of these:

Get-Credential -Message "Cough up" -Username "your_username"

But Get-Credential doesn’t have an option to accept the password as plain text, and storing a password as plain text is bad practice anyway. Thus Get-Credential, in the form used above, will create the right kind of object that you can feed into Send-MailMessage, but it does it in the wrong kind of way – via a pop up a box for you to type your password into, which isn’t that handy for use in unattended scripting.

So the clever way to do this is to create yourself an encrypted password file. You can do this as follows:

Read-Host -AsSecureString | ConvertFrom-SecureString | Out-File -FilePath username@domain.net.securestring

Run the above, enter the password (which will be obscured with asterisks as you type it), and hit <Enter>. Now you’ve got a text file with an encrypted password in it. How does this work? Read-Host prompts for text, because we’ve used the -AsSecureString switch it returns the text entered as a System.Security.SecureString object. We then pass this to ConvertFrom-SecureString which takes that object and spits it out as text, encrypted with Windows Data Protection API (DPAPI). You can also use 128, 192 or 256-bit AES encryption.

So now we have the password in a file, and can use this to create a PSCredential object:

New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "username@myisp.net",(Get-Content -Path username@myisp.net.securestring | ConvertTo-SecureString)

So now shove the whole lot together, on one line (because we can, and bigger is better, right?):

Send-MailMessage -From "username@myisp.net" -To "robin@rcmtech.co.uk" -Subject "Something interesting just happened" -Body "Here's the details about the interesting thing" -SmtpServer smtp.myisp.net -Port 587 -Credential (New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "username@myisp.net",(Get-Content -Path username@myisp.net.securestring | ConvertTo-SecureString))

But to make it easier to interpret, here’s the same thing broken down with variables:

$PSEmailServer = "smtp.myisp.net"
$SMTPPort = 587
$SMTPUsername = "username@myisp.net"
$EncryptedPasswordFile = "username@myisp.net.securestring"
$SecureStringPassword = Get-Content -Path $EncryptedPasswordFile | ConvertTo-SecureString
$EmailCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $SMTPUsername,$SecureStringPassword
$MailTo = "robin@rcmtech.co.uk"
$MailFrom = "username@myisp.net"
$MailSubject = "Something interesting just happened"
$MailBody = "Here's the details about the interesting thing"
Send-MailMessage -From $MailFrom -To $MailTo -Subject $MailSubject -Body $MailBody -Port $SMTPPort -Credential $EmailCredential

If your SMTP server requires it, you can also add -UseSsl to Send-MailMessage.

Posted in PowerShell | Tagged , , , , , , , , , , , , , , , , , , | Leave a comment